mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
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 ........
This commit is contained in:
parent
bccd63c389
commit
a34706f101
9 changed files with 305 additions and 26 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue