Skip to content

Commit 34eee62

Browse files
Support combined types.
1 parent 75645e1 commit 34eee62

File tree

4 files changed

+30
-10
lines changed

4 files changed

+30
-10
lines changed

Include/descrobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct PyMemberDef {
7979
#define Py_T_PYSSIZET 19 /* Py_ssize_t */
8080
#define _Py_T_NONE 20 // Deprecated. Value is always None.
8181

82-
#define Py_T_INTEGER(type) ((sizeof(type) << 8) | (_Py_IS_TYPE_SIGNED(type) ? 0 : 1))
82+
#define Py_T_INTEGER(type) ((sizeof(type) << 8) | (_Py_IS_TYPE_SIGNED(type) ? 1 : 2))
8383

8484
/* Flags */
8585
#define Py_READONLY 1

Lib/test/test_capi/test_structmembers.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ def _test_overflow(self, name, value, error=OverflowError):
6969
self.assertRaises(error, setattr, ts, name, value)
7070

7171
def _test_int_range(self, name, minval, maxval, *, hardlimit=None,
72-
indexlimit=None, negvalueerror=OverflowError):
72+
indexlimit=None, negvalueerror=OverflowError, wrap=False):
7373
if hardlimit is None:
7474
hardlimit = (minval, maxval)
7575
ts = self.ts
7676
self._test_write(name, minval)
77-
self._test_write(name, maxval)
77+
self._test_write(name, maxval, -1 if wrap else maxval)
7878
hardminval, hardmaxval = hardlimit
7979
self._test_overflow(name, hardminval-1, error=negvalueerror)
8080
self._test_overflow(name, hardmaxval+1)
@@ -92,7 +92,7 @@ def _test_int_range(self, name, minval, maxval, *, hardlimit=None,
9292
self.assertRaises(TypeError, setattr, ts, name, Index(maxval))
9393
else:
9494
self._test_write(name, Index(minval), minval)
95-
self._test_write(name, Index(maxval), maxval)
95+
self._test_write(name, Index(maxval), -1 if wrap else maxval)
9696
self._test_overflow(name, Index(hardminval-1), error=negvalueerror)
9797
self._test_overflow(name, Index(hardmaxval+1))
9898
self._test_overflow(name, Index(2**1000))
@@ -191,18 +191,22 @@ def test_size(self):
191191
def test_int8(self):
192192
self._test_int_range('T_INT8', -2**7, 2**7-1)
193193
self._test_int_range('T_UINT8', 0, 2**8-1, negvalueerror=ValueError)
194+
self._test_int_range('T_XINT8', -2**7, 2**8-1, wrap=True)
194195

195196
def test_int16(self):
196197
self._test_int_range('T_INT16', -2**15, 2**15-1)
197198
self._test_int_range('T_UINT16', 0, 2**16-1, negvalueerror=ValueError)
199+
self._test_int_range('T_XINT16', -2**15, 2**16-1, wrap=True)
198200

199201
def test_int32(self):
200202
self._test_int_range('T_INT32', -2**31, 2**31-1)
201203
self._test_int_range('T_UINT32', 0, 2**32-1, negvalueerror=ValueError)
204+
self._test_int_range('T_XINT32', -2**31, 2**32-1, wrap=True)
202205

203206
def test_int64(self):
204207
self._test_int_range('T_INT64', -2**63, 2**63-1)
205208
self._test_int_range('T_UINT64', 0, 2**64-1, negvalueerror=ValueError)
209+
self._test_int_range('T_XINT64', -2**63, 2**64-1, wrap=True)
206210

207211
def test_intptr(self):
208212
bits = 8*SIZEOF_INTPTR_T

Modules/_testcapi/structmember.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,16 @@ typedef struct {
2626
char char_member;
2727
int8_t int8_member;
2828
uint8_t uint8_member;
29+
uint8_t xint8_member;
2930
int16_t int16_member;
3031
uint16_t uint16_member;
32+
uint16_t xint16_member;
3133
int32_t int32_member;
3234
uint32_t uint32_member;
35+
uint32_t xint32_member;
3336
int64_t int64_member;
3437
uint64_t uint64_member;
38+
uint64_t xint64_member;
3539
intptr_t intptr_member;
3640
uintptr_t uintptr_member;
3741
#ifdef MS_WINDOWS
@@ -68,12 +72,16 @@ static struct PyMemberDef test_members_newapi[] = {
6872
{"T_CHAR", Py_T_CHAR, offsetof(test_structmembers, structmembers.char_member), 0, NULL},
6973
{"T_INT8", Py_T_INTEGER(int8_t), offsetof(test_structmembers, structmembers.int8_member), 0, NULL},
7074
{"T_UINT8", Py_T_INTEGER(uint8_t), offsetof(test_structmembers, structmembers.uint8_member), 0, NULL},
75+
{"T_XINT8", Py_T_INTEGER(int8_t)|Py_T_INTEGER(uint8_t), offsetof(test_structmembers, structmembers.xint8_member), 0, NULL},
7176
{"T_INT16", Py_T_INTEGER(int16_t), offsetof(test_structmembers, structmembers.int16_member), 0, NULL},
7277
{"T_UINT16", Py_T_INTEGER(uint16_t), offsetof(test_structmembers, structmembers.uint16_member), 0, NULL},
78+
{"T_XINT16", Py_T_INTEGER(int16_t)|Py_T_INTEGER(uint16_t), offsetof(test_structmembers, structmembers.xint16_member), 0, NULL},
7379
{"T_INT32", Py_T_INTEGER(int32_t), offsetof(test_structmembers, structmembers.int32_member), 0, NULL},
7480
{"T_UINT32", Py_T_INTEGER(uint32_t), offsetof(test_structmembers, structmembers.uint32_member), 0, NULL},
81+
{"T_XINT32", Py_T_INTEGER(int32_t)|Py_T_INTEGER(uint32_t), offsetof(test_structmembers, structmembers.xint32_member), 0, NULL},
7582
{"T_INT64", Py_T_INTEGER(int64_t), offsetof(test_structmembers, structmembers.int64_member), 0, NULL},
7683
{"T_UINT64", Py_T_INTEGER(uint64_t), offsetof(test_structmembers, structmembers.uint64_member), 0, NULL},
84+
{"T_XINT64", Py_T_INTEGER(int64_t)|Py_T_INTEGER(uint64_t), offsetof(test_structmembers, structmembers.xint64_member), 0, NULL},
7785
{"T_INTPTR", Py_T_INTEGER(intptr_t), offsetof(test_structmembers, structmembers.intptr_member), 0, NULL},
7886
{"T_UINTPTR", Py_T_INTEGER(uintptr_t), offsetof(test_structmembers, structmembers.uintptr_member), 0, NULL},
7987
#ifdef MS_WINDOWS

Python/structmember.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,20 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
118118
v = Py_NewRef(Py_None);
119119
break;
120120
default:
121-
if (l->type > 0xff && l->type <= 0xffff && (l->type & (0xff & ~0x01)) == 0) {
121+
if (l->type > 0xff && l->type <= 0xffff && (l->type & (0xff & ~0x03)) == 0) {
122122
Py_ssize_t size = l->type >> 8;
123-
if (l->type & 0x01) {
123+
if ((l->type & 0x03) == 1) {
124+
v = PyLong_FromNativeBytes(addr, size, -1);
125+
break;
126+
}
127+
else if ((l->type & 0x03) == 2) {
124128
v = PyLong_FromUnsignedNativeBytes(addr, size, -1);
129+
break;
125130
}
126-
else {
131+
else if ((l->type & 0x03) == 3) {
127132
v = PyLong_FromNativeBytes(addr, size, -1);
133+
break;
128134
}
129-
break;
130135
}
131136
PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
132137
v = NULL;
@@ -374,14 +379,17 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
374379
break;
375380
}
376381
default:
377-
if (l->type > 0xff && l->type <= 0xffff && (l->type & (0xff & ~0x01)) == 0) {
382+
if (l->type > 0xff && l->type <= 0xffff && (l->type & (0xff & ~0x03)) == 0) {
378383
Py_ssize_t size = l->type >> 8;
379384
int flags = Py_ASNATIVEBYTES_NATIVE_ENDIAN
380385
| Py_ASNATIVEBYTES_ALLOW_INDEX;
381-
if (l->type & 0x01) {
386+
if ((l->type & 0x03) == 2) {
382387
flags |= Py_ASNATIVEBYTES_UNSIGNED_BUFFER
383388
| Py_ASNATIVEBYTES_REJECT_NEGATIVE;
384389
}
390+
else if ((l->type & 0x03) == 3) {
391+
flags |= Py_ASNATIVEBYTES_UNSIGNED_BUFFER;
392+
}
385393
Py_ssize_t bytes = PyLong_AsNativeBytes(v, addr, size, flags);
386394
if (bytes < 0) {
387395
return -1;

0 commit comments

Comments
 (0)