Skip to content

Commit a32421d

Browse files
Support combined.
1 parent ab60716 commit a32421d

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

Include/descrobject.h

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,24 +81,23 @@ struct PyMemberDef {
8181

8282
#define Py_T_SSIZE Py_T_PYSSIZET
8383
#define Py_T_SIZE 21
84-
85-
#define Py_T_INT8 22
86-
#define Py_T_UINT8 23
87-
#define Py_T_INT16 24
88-
#define Py_T_UINT16 25
89-
#define Py_T_INT32 26
90-
#define Py_T_UINT32 27
91-
#define Py_T_INT64 28
92-
#define Py_T_UINT64 29
93-
94-
#define Py_T_INTPTR 30
95-
#define Py_T_UINTPTR 31
84+
#define Py_T_INTPTR 22
85+
#define Py_T_UINTPTR 23
9686
#ifdef MS_WINDOWS
9787
# define Py_T_OFF Py_T_LONGLONG
9888
#else
99-
# define Py_T_OFF 32
89+
# define Py_T_OFF 24
10090
#endif
101-
#define Py_T_PID 33
91+
#define Py_T_PID 25
92+
93+
#define Py_T_INT8 0x100|0x1
94+
#define Py_T_UINT8 0x100|0x2
95+
#define Py_T_INT16 0x104|0x1
96+
#define Py_T_UINT16 0x104|0x2
97+
#define Py_T_INT32 0x108|0x1
98+
#define Py_T_UINT32 0x108|0x2
99+
#define Py_T_INT64 0x110|0x1
100+
#define Py_T_UINT64 0x110|0x2
102101

103102
/* Flags */
104103
#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))
@@ -192,18 +192,22 @@ def test_size(self):
192192
def test_int8(self):
193193
self._test_int_range('T_INT8', -2**7, 2**7-1)
194194
self._test_int_range('T_UINT8', 0, 2**8-1, negvalueerror=ValueError)
195+
self._test_int_range('T_XINT8', -2**7, 2**8-1, wrap=True)
195196

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

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

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

208212
def test_intptr(self):
209213
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
@@ -69,12 +73,16 @@ static struct PyMemberDef test_members_newapi[] = {
6973
{"T_CHAR", Py_T_CHAR, offsetof(test_structmembers, structmembers.char_member), 0, NULL},
7074
{"T_INT8", Py_T_INT8, offsetof(test_structmembers, structmembers.int8_member), 0, NULL},
7175
{"T_UINT8", Py_T_UINT8, offsetof(test_structmembers, structmembers.uint8_member), 0, NULL},
76+
{"T_XINT8", Py_T_INT8|Py_T_UINT8, offsetof(test_structmembers, structmembers.xint8_member), 0, NULL},
7277
{"T_INT16", Py_T_INT16, offsetof(test_structmembers, structmembers.int16_member), 0, NULL},
7378
{"T_UINT16", Py_T_UINT16, offsetof(test_structmembers, structmembers.uint16_member), 0, NULL},
79+
{"T_XINT16", Py_T_INT16|Py_T_UINT16, offsetof(test_structmembers, structmembers.xint16_member), 0, NULL},
7480
{"T_INT32", Py_T_INT32, offsetof(test_structmembers, structmembers.int32_member), 0, NULL},
7581
{"T_UINT32", Py_T_UINT32, offsetof(test_structmembers, structmembers.uint32_member), 0, NULL},
82+
{"T_XINT32", Py_T_INT32|Py_T_UINT32, offsetof(test_structmembers, structmembers.xint32_member), 0, NULL},
7683
{"T_INT64", Py_T_INT64, offsetof(test_structmembers, structmembers.int64_member), 0, NULL},
7784
{"T_UINT64", Py_T_UINT64, offsetof(test_structmembers, structmembers.uint64_member), 0, NULL},
85+
{"T_XINT64", Py_T_INT64|Py_T_UINT64, offsetof(test_structmembers, structmembers.xint64_member), 0, NULL},
7886
{"T_INTPTR", Py_T_INTPTR, offsetof(test_structmembers, structmembers.intptr_member), 0, NULL},
7987
{"T_UINTPTR", Py_T_UINTPTR, offsetof(test_structmembers, structmembers.uintptr_member), 0, NULL},
8088
{"T_OFF", Py_T_OFF, offsetof(test_structmembers, structmembers.off_member), 0, NULL},

Python/structmember.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,24 +121,28 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
121121
v = Py_NewRef(Py_None);
122122
break;
123123
case Py_T_INT8:
124+
case Py_T_INT8|Py_T_UINT8:
124125
v = PyLong_FromLong(*(int8_t*)addr);
125126
break;
126127
case Py_T_UINT8:
127128
v = PyLong_FromUnsignedLong(*(uint8_t*)addr);
128129
break;
129130
case Py_T_INT16:
131+
case Py_T_INT16|Py_T_UINT16:
130132
v = PyLong_FromLong(*(int16_t*)addr);
131133
break;
132134
case Py_T_UINT16:
133135
v = PyLong_FromUnsignedLong(*(uint16_t*)addr);
134136
break;
135137
case Py_T_INT32:
138+
case Py_T_INT32|Py_T_UINT32:
136139
v = PyLong_FromLong(*(int32_t*)addr);
137140
break;
138141
case Py_T_UINT32:
139142
v = PyLong_FromUnsignedLong(*(uint32_t*)addr);
140143
break;
141144
case Py_T_INT64:
145+
case Py_T_INT64|Py_T_UINT64:
142146
v = PyLong_FromLongLong(*(int64_t*)addr);
143147
break;
144148
case Py_T_UINT64:
@@ -199,6 +203,20 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
199203
} \
200204
} while (0)
201205

206+
#define SET_COMBINED_INT(N) do { \
207+
Py_ssize_t bytes = PyLong_AsNativeBytes(v, addr, (N), \
208+
Py_ASNATIVEBYTES_NATIVE_ENDIAN | \
209+
Py_ASNATIVEBYTES_ALLOW_INDEX | \
210+
Py_ASNATIVEBYTES_UNSIGNED_BUFFER); \
211+
if (bytes < 0) { \
212+
return -1; \
213+
} \
214+
if ((size_t)bytes > (N)) { \
215+
PyErr_SetString(PyExc_OverflowError, "int too big to convert"); \
216+
return -1; \
217+
} \
218+
} while (0)
219+
202220
int
203221
PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
204222
{
@@ -446,24 +464,36 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
446464
case Py_T_UINT8:
447465
SET_UNSIGNED_INT(1);
448466
break;
467+
case Py_T_INT8|Py_T_UINT8:
468+
SET_COMBINED_INT(1);
469+
break;
449470
case Py_T_INT16:
450471
SET_SIGNED_INT(2);
451472
break;
452473
case Py_T_UINT16:
453474
SET_UNSIGNED_INT(2);
454475
break;
476+
case Py_T_INT16|Py_T_UINT16:
477+
SET_COMBINED_INT(2);
478+
break;
455479
case Py_T_INT32:
456480
SET_SIGNED_INT(4);
457481
break;
458482
case Py_T_UINT32:
459483
SET_UNSIGNED_INT(4);
460484
break;
485+
case Py_T_INT32|Py_T_UINT32:
486+
SET_COMBINED_INT(4);
487+
break;
461488
case Py_T_INT64:
462489
SET_SIGNED_INT(8);
463490
break;
464491
case Py_T_UINT64:
465492
SET_UNSIGNED_INT(8);
466493
break;
494+
case Py_T_INT64|Py_T_UINT64:
495+
SET_COMBINED_INT(8);
496+
break;
467497
case Py_T_INTPTR:
468498
SET_SIGNED_INT(sizeof(intptr_t));
469499
break;

0 commit comments

Comments
 (0)