diff options
author | Christian Heimes <christian@cheimes.de> | 2008-01-04 03:06:10 (GMT) |
---|---|---|
committer | Christian Heimes <christian@cheimes.de> | 2008-01-04 03:06:10 (GMT) |
commit | a34706f101a16eef8e36054d1f405f794d53ac79 (patch) | |
tree | c644a54978563e860c623f96c087a761e6a5776a /Modules/_struct.c | |
parent | bccd63c389d72d22882264b8e9cf6e8e5911106c (diff) | |
download | cpython-a34706f101a16eef8e36054d1f405f794d53ac79.zip cpython-a34706f101a16eef8e36054d1f405f794d53ac79.tar.gz cpython-a34706f101a16eef8e36054d1f405f794d53ac79.tar.bz2 |
Merged revisions 59680-59695 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r59686 | guido.van.rossum | 2008-01-04 00:54:04 +0100 (Fri, 04 Jan 2008) | 2 lines
Bug #1301: fixed a bad assert in _tkinter.
........
r59687 | raymond.hettinger | 2008-01-04 01:01:15 +0100 (Fri, 04 Jan 2008) | 3 lines
Finish-up the struct module optimizations started at the Iceland NFS sprint.
........
r59688 | christian.heimes | 2008-01-04 01:04:52 +0100 (Fri, 04 Jan 2008) | 1 line
Fixed #1687: plistlib.py restricts <integer> to Python int when writing
........
r59689 | christian.heimes | 2008-01-04 01:37:34 +0100 (Fri, 04 Jan 2008) | 1 line
Bug #1481296: Fixed long(float('nan'))!=0L.
........
r59691 | andrew.kuchling | 2008-01-04 02:15:50 +0100 (Fri, 04 Jan 2008) | 1 line
Markup fixes; grammar tweaks
........
r59692 | andrew.kuchling | 2008-01-04 02:16:12 +0100 (Fri, 04 Jan 2008) | 1 line
Add items
........
r59694 | christian.heimes | 2008-01-04 02:48:50 +0100 (Fri, 04 Jan 2008) | 1 line
Fixed math.copysign() on Windows
........
r59695 | christian.heimes | 2008-01-04 03:03:25 +0100 (Fri, 04 Jan 2008) | 1 line
Filled in some XXX comments
........
Diffstat (limited to 'Modules/_struct.c')
-rw-r--r-- | Modules/_struct.c | 239 |
1 files changed, 236 insertions, 3 deletions
diff --git a/Modules/_struct.c b/Modules/_struct.c index 3c02bc9..278b035 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1464,11 +1464,28 @@ s_init(PyObject *self, PyObject *args, PyObject *kwds) assert(PyStruct_Check(self)); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:Struct", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Struct", kwlist, &o_format)) return -1; - Py_INCREF(o_format); + if (PyUnicode_Check(o_format)) { + o_format = PyUnicode_AsASCIIString(o_format); + if (o_format == NULL) + return -1; + } + /* XXX support buffer interface, too */ + else { + Py_INCREF(o_format); + } + + if (!PyString_Check(o_format)) { + Py_DECREF(o_format); + PyErr_Format(PyExc_TypeError, + "Struct() argument 1 must be bytes, not %.200s", + Py_TYPE(o_format)->tp_name); + return -1; + } + Py_XDECREF(soself->s_format); soself->s_format = o_format; @@ -1861,12 +1878,226 @@ PyTypeObject PyStructType = { PyObject_Del, /* tp_free */ }; + +/* ---- Standalone functions ---- */ + +#define MAXCACHE 100 +static PyObject *cache = NULL; + +static PyObject * +cache_struct(PyObject *fmt) +{ + PyObject * s_object; + + if (cache == NULL) { + cache = PyDict_New(); + if (cache == NULL) + return NULL; + } + + s_object = PyDict_GetItem(cache, fmt); + if (s_object != NULL) { + Py_INCREF(s_object); + return s_object; + } + + s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL); + if (s_object != NULL) { + if (PyDict_Size(cache) >= MAXCACHE) + PyDict_Clear(cache); + /* Attempt to cache the result */ + if (PyDict_SetItem(cache, fmt, s_object) == -1) + PyErr_Clear(); + } + return s_object; +} + +PyDoc_STRVAR(clearcache_doc, +"Clear the internal cache."); + +static PyObject * +clearcache(PyObject *self) +{ + if (cache != NULL) + PyDict_Clear(cache); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(calcsize_doc, +"Return size of C struct described by format string fmt."); + +static PyObject * +calcsize(PyObject *self, PyObject *fmt) +{ + Py_ssize_t n; + PyObject *s_object = cache_struct(fmt); + if (s_object == NULL) + return NULL; + n = ((PyStructObject *)s_object)->s_size; + Py_DECREF(s_object); + return PyLong_FromSsize_t(n); +} + +PyDoc_STRVAR(pack_doc, +"Return string containing values v1, v2, ... packed according to fmt."); + +static PyObject * +pack(PyObject *self, PyObject *args) +{ + PyObject *s_object, *fmt, *newargs, *result; + Py_ssize_t n = PyTuple_GET_SIZE(args); + + if (n == 0) { + PyErr_SetString(PyExc_TypeError, "missing format argument"); + return NULL; + } + fmt = PyTuple_GET_ITEM(args, 0); + newargs = PyTuple_GetSlice(args, 1, n); + if (newargs == NULL) + return NULL; + + s_object = cache_struct(fmt); + if (s_object == NULL) { + Py_DECREF(newargs); + return NULL; + } + result = s_pack(s_object, newargs); + Py_DECREF(newargs); + Py_DECREF(s_object); + return result; +} + +PyDoc_STRVAR(pack_into_doc, +"Pack the values v1, v2, ... according to fmt.\n\ +Write the packed bytes into the writable buffer buf starting at offset."); + +static PyObject * +pack_into(PyObject *self, PyObject *args) +{ + PyObject *s_object, *fmt, *newargs, *result; + Py_ssize_t n = PyTuple_GET_SIZE(args); + + if (n == 0) { + PyErr_SetString(PyExc_TypeError, "missing format argument"); + return NULL; + } + fmt = PyTuple_GET_ITEM(args, 0); + newargs = PyTuple_GetSlice(args, 1, n); + if (newargs == NULL) + return NULL; + + s_object = cache_struct(fmt); + if (s_object == NULL) { + Py_DECREF(newargs); + return NULL; + } + result = s_pack_into(s_object, newargs); + Py_DECREF(newargs); + Py_DECREF(s_object); + return result; +} + +PyDoc_STRVAR(unpack_doc, +"Unpack the string containing packed C structure data, according to fmt.\n\ +Requires len(string) == calcsize(fmt)."); + +static PyObject * +unpack(PyObject *self, PyObject *args) +{ + PyObject *s_object, *fmt, *inputstr, *result; + + if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr)) + return NULL; + + s_object = cache_struct(fmt); + if (s_object == NULL) + return NULL; + result = s_unpack(s_object, inputstr); + Py_DECREF(s_object); + return result; +} + +PyDoc_STRVAR(unpack_from_doc, +"Unpack the buffer, containing packed C structure data, according to\n\ +fmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt)."); + +static PyObject * +unpack_from(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *s_object, *fmt, *newargs, *result; + Py_ssize_t n = PyTuple_GET_SIZE(args); + + if (n == 0) { + PyErr_SetString(PyExc_TypeError, "missing format argument"); + return NULL; + } + fmt = PyTuple_GET_ITEM(args, 0); + newargs = PyTuple_GetSlice(args, 1, n); + if (newargs == NULL) + return NULL; + + s_object = cache_struct(fmt); + if (s_object == NULL) { + Py_DECREF(newargs); + return NULL; + } + result = s_unpack_from(s_object, newargs, kwds); + Py_DECREF(newargs); + Py_DECREF(s_object); + return result; +} + +static struct PyMethodDef module_functions[] = { + {"_clearcache", (PyCFunction)clearcache, METH_NOARGS, clearcache_doc}, + {"calcsize", calcsize, METH_O, calcsize_doc}, + {"pack", pack, METH_VARARGS, pack_doc}, + {"pack_into", pack_into, METH_VARARGS, pack_into_doc}, + {"unpack", unpack, METH_VARARGS, unpack_doc}, + {"unpack_from", (PyCFunction)unpack_from, + METH_VARARGS|METH_KEYWORDS, unpack_from_doc}, + {NULL, NULL} /* sentinel */ +}; + + /* Module initialization */ +PyDoc_STRVAR(module_doc, +"Functions to convert between Python values and C structs.\n\ +Python strings are used to hold the data representing the C struct\n\ +and also as format strings to describe the layout of data in the C struct.\n\ +\n\ +The optional first format char indicates byte order, size and alignment:\n\ + @: native order, size & alignment (default)\n\ + =: native order, std. size & alignment\n\ + <: little-endian, std. size & alignment\n\ + >: big-endian, std. size & alignment\n\ + !: same as >\n\ +\n\ +The remaining chars indicate types of args and must match exactly;\n\ +these can be preceded by a decimal repeat count:\n\ + x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\ + h:short; H:unsigned short; i:int; I:unsigned int;\n\ + l:long; L:unsigned long; f:float; d:double.\n\ +Special cases (preceding decimal count indicates length):\n\ + s:string (array of char); p: pascal string (with count byte).\n\ +Special case (only available in native format):\n\ + P:an integer type that is wide enough to hold a pointer.\n\ +Special case (not in native mode unless 'long long' in platform C):\n\ + q:long long; Q:unsigned long long\n\ +Whitespace between formats is ignored.\n\ +\n\ +The variable struct.error is an exception raised on errors.\n"); + PyMODINIT_FUNC init_struct(void) { - PyObject *m = Py_InitModule("_struct", NULL); + PyObject *ver, *m; + + ver = PyString_FromString("0.2"); + if (ver == NULL) + return; + + m = Py_InitModule3("_struct", module_functions, module_doc); if (m == NULL) return; @@ -1947,6 +2178,8 @@ init_struct(void) Py_INCREF((PyObject*)&PyStructType); PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType); + PyModule_AddObject(m, "__version__", ver); + PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1); #ifdef PY_STRUCT_OVERFLOW_MASKING PyModule_AddIntConstant(m, "_PY_STRUCT_OVERFLOW_MASKING", 1); |