cpython: 6707637f68ca (original) (raw)
Mercurial > cpython
changeset 83807:6707637f68ca
Issue #14596: The struct.Struct() objects now use more compact implementation. [#14596]
Serhiy Storchaka storchaka@gmail.com | |
---|---|
date | Fri, 17 May 2013 10:49:44 +0300 |
parents | 27cc0e0b7637 |
children | 9ff8b6d4d479 |
files | Lib/test/test_struct.py Misc/NEWS Modules/_struct.c |
diffstat | 3 files changed, 99 insertions(+), 87 deletions(-)[+] [-] Lib/test/test_struct.py 9 Misc/NEWS 2 Modules/_struct.c 175 |
line wrap: on
line diff
--- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -8,7 +8,6 @@ import sys from test import support ISBIGENDIAN = sys.byteorder == "big" -IS32BIT = sys.maxsize == 0x7fffffff integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N' byteorders = '', '@', '=', '<', '>', '!' @@ -538,10 +537,6 @@ class StructTest(unittest.TestCase): hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2) self.assertRaises(struct.error, struct.calcsize, hugecount2)
- if IS32BIT:
def test_crasher(self):[](#l1.16)
self.assertRaises(MemoryError, struct.pack, "357913941b", "a")[](#l1.17)
- def test_trailing_counter(self): store = array.array('b', b' '*100) @@ -578,7 +573,7 @@ class StructTest(unittest.TestCase): # The size of 'PyStructObject' totalsize = support.calcobjsize('2n3P') # The size taken up by the 'formatcode' dynamic array
totalsize += struct.calcsize('P2n0P') * (number_of_codes + 1)[](#l1.26)
totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)[](#l1.27) support.check_sizeof(self, struct.Struct(format_str), totalsize)[](#l1.28)
@support.cpython_only @@ -589,7 +584,7 @@ class StructTest(unittest.TestCase): self.check_sizeof('B' * 1234, 1234) self.check_sizeof('fd', 2) self.check_sizeof('xxxxxxxxxxxxxx', 0)
self.check_sizeof('100H', 100)[](#l1.35)
self.check_sizeof('100H', 1)[](#l1.36) self.check_sizeof('187s', 1)[](#l1.37) self.check_sizeof('20p', 1)[](#l1.38) self.check_sizeof('0s', 1)[](#l1.39)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -91,6 +91,8 @@ Core and Builtins Library ------- +- Issue #14596: The struct.Struct() objects now use more compact implementation. +
- Issue #17981: Closed socket on error in SysLogHandler.
- Issue #17964: Fix os.sysconf(): the return type of the C sysconf() function
--- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -26,6 +26,7 @@ typedef struct _formatcode { const struct _formatdef *fmtdef; Py_ssize_t offset; Py_ssize_t size;
} formatcode; /* Struct object interface */ @@ -1263,7 +1264,7 @@ prepare_s(PyStructObject *self) const char *s; const char *fmt; char c;
fmt = PyBytes_AS_STRING(self->s_format); @@ -1272,6 +1273,7 @@ prepare_s(PyStructObject *self) s = fmt; size = 0; len = 0;
@@ -1301,9 +1303,9 @@ prepare_s(PyStructObject self) switch (c) { case 's': / fall through */
case 'p': len++; break;[](#l3.32)
case 'p': len++; ncodes++; break;[](#l3.33) case 'x': break;[](#l3.34)
default: len += num; break;[](#l3.35)
default: len += num; if (num) ncodes++; break;[](#l3.36) }[](#l3.37)
itemsize = e->size; @@ -1318,14 +1320,14 @@ prepare_s(PyStructObject self) } / check for overflow */
- if ((ncodes + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) { PyErr_NoMemory(); return -1; } self->s_size = size; self->s_len = len;
- codes = PyMem_MALLOC((ncodes + 1) * sizeof(formatcode)); if (codes == NULL) { PyErr_NoMemory(); return -1;
@@ -1357,23 +1359,24 @@ prepare_s(PyStructObject *self) codes->offset = size; codes->size = num; codes->fmtdef = e;
codes->repeat = 1;[](#l3.61) codes++;[](#l3.62) size += num;[](#l3.63) } else if (c == 'x') {[](#l3.64) size += num;[](#l3.65)
} else {[](#l3.66)
while (--num >= 0) {[](#l3.67)
codes->offset = size;[](#l3.68)
codes->size = e->size;[](#l3.69)
codes->fmtdef = e;[](#l3.70)
codes++;[](#l3.71)
size += e->size;[](#l3.72)
}[](#l3.73)
} else if (num) {[](#l3.74)
codes->offset = size;[](#l3.75)
codes->size = e->size;[](#l3.76)
codes->fmtdef = e;[](#l3.77)
codes->repeat = num;[](#l3.78)
codes++;[](#l3.79)
} codes->fmtdef = NULL; codes->offset = size; codes->size = 0;size += e->size * num;[](#l3.80) }[](#l3.81)
- codes->repeat = 0;
return 0; @@ -1462,22 +1465,26 @@ s_unpack_internal(PyStructObject *soself return NULL; for (code = soself->s_codes; code->fmtdef != NULL; code++) {
PyObject *v;[](#l3.94) const formatdef *e = code->fmtdef;[](#l3.95) const char *res = startfrom + code->offset;[](#l3.96)
if (e->format == 's') {[](#l3.97)
v = PyBytes_FromStringAndSize(res, code->size);[](#l3.98)
} else if (e->format == 'p') {[](#l3.99)
Py_ssize_t n = *(unsigned char*)res;[](#l3.100)
if (n >= code->size)[](#l3.101)
n = code->size - 1;[](#l3.102)
v = PyBytes_FromStringAndSize(res + 1, n);[](#l3.103)
} else {[](#l3.104)
v = e->unpack(res, e);[](#l3.105)
Py_ssize_t j = code->repeat;[](#l3.106)
while (j--) {[](#l3.107)
PyObject *v;[](#l3.108)
if (e->format == 's') {[](#l3.109)
v = PyBytes_FromStringAndSize(res, code->size);[](#l3.110)
} else if (e->format == 'p') {[](#l3.111)
Py_ssize_t n = *(unsigned char*)res;[](#l3.112)
if (n >= code->size)[](#l3.113)
n = code->size - 1;[](#l3.114)
v = PyBytes_FromStringAndSize(res + 1, n);[](#l3.115)
} else {[](#l3.116)
v = e->unpack(res, e);[](#l3.117)
}[](#l3.118)
if (v == NULL)[](#l3.119)
goto fail;[](#l3.120)
PyTuple_SET_ITEM(result, i++, v);[](#l3.121)
res += code->size;[](#l3.122) }[](#l3.123)
if (v == NULL)[](#l3.124)
goto fail;[](#l3.125)
} return result; @@ -1716,62 +1723,67 @@ s_pack_internal(PyStructObject *soself, memset(buf, '\0', soself->s_size); i = offset; for (code = soself->s_codes; code->fmtdef != NULL; code++) {PyTuple_SET_ITEM(result, i++, v);[](#l3.126)
Py_ssize_t n;[](#l3.134)
PyObject *v = PyTuple_GET_ITEM(args, i++);[](#l3.135) const formatdef *e = code->fmtdef;[](#l3.136) char *res = buf + code->offset;[](#l3.137)
if (e->format == 's') {[](#l3.138)
int isstring;[](#l3.139)
void *p;[](#l3.140)
isstring = PyBytes_Check(v);[](#l3.141)
if (!isstring && !PyByteArray_Check(v)) {[](#l3.142)
PyErr_SetString(StructError,[](#l3.143)
"argument for 's' must be a bytes object");[](#l3.144)
return -1;[](#l3.145)
}[](#l3.146)
if (isstring) {[](#l3.147)
n = PyBytes_GET_SIZE(v);[](#l3.148)
p = PyBytes_AS_STRING(v);[](#l3.149)
}[](#l3.150)
else {[](#l3.151)
n = PyByteArray_GET_SIZE(v);[](#l3.152)
p = PyByteArray_AS_STRING(v);[](#l3.153)
Py_ssize_t j = code->repeat;[](#l3.154)
while (j--) {[](#l3.155)
PyObject *v = PyTuple_GET_ITEM(args, i++);[](#l3.156)
if (e->format == 's') {[](#l3.157)
Py_ssize_t n;[](#l3.158)
int isstring;[](#l3.159)
void *p;[](#l3.160)
isstring = PyBytes_Check(v);[](#l3.161)
if (!isstring && !PyByteArray_Check(v)) {[](#l3.162)
PyErr_SetString(StructError,[](#l3.163)
"argument for 's' must be a bytes object");[](#l3.164)
return -1;[](#l3.165)
}[](#l3.166)
if (isstring) {[](#l3.167)
n = PyBytes_GET_SIZE(v);[](#l3.168)
p = PyBytes_AS_STRING(v);[](#l3.169)
}[](#l3.170)
else {[](#l3.171)
n = PyByteArray_GET_SIZE(v);[](#l3.172)
p = PyByteArray_AS_STRING(v);[](#l3.173)
}[](#l3.174)
if (n > code->size)[](#l3.175)
n = code->size;[](#l3.176)
if (n > 0)[](#l3.177)
memcpy(res, p, n);[](#l3.178)
} else if (e->format == 'p') {[](#l3.179)
Py_ssize_t n;[](#l3.180)
int isstring;[](#l3.181)
void *p;[](#l3.182)
isstring = PyBytes_Check(v);[](#l3.183)
if (!isstring && !PyByteArray_Check(v)) {[](#l3.184)
PyErr_SetString(StructError,[](#l3.185)
"argument for 'p' must be a bytes object");[](#l3.186)
return -1;[](#l3.187)
}[](#l3.188)
if (isstring) {[](#l3.189)
n = PyBytes_GET_SIZE(v);[](#l3.190)
p = PyBytes_AS_STRING(v);[](#l3.191)
}[](#l3.192)
else {[](#l3.193)
n = PyByteArray_GET_SIZE(v);[](#l3.194)
p = PyByteArray_AS_STRING(v);[](#l3.195)
}[](#l3.196)
if (n > (code->size - 1))[](#l3.197)
n = code->size - 1;[](#l3.198)
if (n > 0)[](#l3.199)
memcpy(res + 1, p, n);[](#l3.200)
if (n > 255)[](#l3.201)
n = 255;[](#l3.202)
*res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);[](#l3.203)
} else {[](#l3.204)
if (e->pack(res, v, e) < 0) {[](#l3.205)
if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError))[](#l3.206)
PyErr_SetString(StructError,[](#l3.207)
"long too large to convert to int");[](#l3.208)
return -1;[](#l3.209)
}[](#l3.210) }[](#l3.211)
if (n > code->size)[](#l3.212)
n = code->size;[](#l3.213)
if (n > 0)[](#l3.214)
memcpy(res, p, n);[](#l3.215)
} else if (e->format == 'p') {[](#l3.216)
int isstring;[](#l3.217)
void *p;[](#l3.218)
isstring = PyBytes_Check(v);[](#l3.219)
if (!isstring && !PyByteArray_Check(v)) {[](#l3.220)
PyErr_SetString(StructError,[](#l3.221)
"argument for 'p' must be a bytes object");[](#l3.222)
return -1;[](#l3.223)
}[](#l3.224)
if (isstring) {[](#l3.225)
n = PyBytes_GET_SIZE(v);[](#l3.226)
p = PyBytes_AS_STRING(v);[](#l3.227)
}[](#l3.228)
else {[](#l3.229)
n = PyByteArray_GET_SIZE(v);[](#l3.230)
p = PyByteArray_AS_STRING(v);[](#l3.231)
}[](#l3.232)
if (n > (code->size - 1))[](#l3.233)
n = code->size - 1;[](#l3.234)
if (n > 0)[](#l3.235)
memcpy(res + 1, p, n);[](#l3.236)
if (n > 255)[](#l3.237)
n = 255;[](#l3.238)
*res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);[](#l3.239)
} else {[](#l3.240)
if (e->pack(res, v, e) < 0) {[](#l3.241)
if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError))[](#l3.242)
PyErr_SetString(StructError,[](#l3.243)
"long too large to convert to int");[](#l3.244)
return -1;[](#l3.245)
}[](#l3.246)