]> granicus.if.org Git - python/commitdiff
[Backport of r52452]
authorMartin v. Löwis <martin@v.loewis.de>
Fri, 27 Oct 2006 06:17:21 +0000 (06:17 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Fri, 27 Oct 2006 06:17:21 +0000 (06:17 +0000)
Patch #1549049: Rewrite type conversion in structmember.
Fixes #1545696 and #1566140.

The new warnings have been omitted in the backport.

Lib/test/test_structmembers.py [new file with mode: 0644]
Misc/NEWS
Modules/_testcapimodule.c
Python/structmember.c

diff --git a/Lib/test/test_structmembers.py b/Lib/test/test_structmembers.py
new file mode 100644 (file)
index 0000000..7fcf785
--- /dev/null
@@ -0,0 +1,48 @@
+from _testcapi import test_structmembersType, \
+    CHAR_MAX, CHAR_MIN, UCHAR_MAX, \
+    SHRT_MAX, SHRT_MIN, USHRT_MAX, \
+    INT_MAX, INT_MIN, UINT_MAX, \
+    LONG_MAX, LONG_MIN, ULONG_MAX
+
+import warnings, exceptions, unittest, test.test_warnings
+from test import test_support
+
+ts=test_structmembersType(1,2,3,4,5,6,7,8,9.99999,10.1010101010)
+
+class ReadWriteTests(unittest.TestCase):
+    def test_types(self):
+        ts.T_BYTE=CHAR_MAX
+        self.assertEquals(ts.T_BYTE, CHAR_MAX)
+        ts.T_BYTE=CHAR_MIN
+        self.assertEquals(ts.T_BYTE, CHAR_MIN)
+        ts.T_UBYTE=UCHAR_MAX
+        self.assertEquals(ts.T_UBYTE, UCHAR_MAX)
+
+        ts.T_SHORT=SHRT_MAX
+        self.assertEquals(ts.T_SHORT, SHRT_MAX)
+        ts.T_SHORT=SHRT_MIN
+        self.assertEquals(ts.T_SHORT, SHRT_MIN)
+        ts.T_USHORT=USHRT_MAX
+        self.assertEquals(ts.T_USHORT, USHRT_MAX)
+
+        ts.T_INT=INT_MAX
+        self.assertEquals(ts.T_INT, INT_MAX)
+        ts.T_INT=INT_MIN
+        self.assertEquals(ts.T_INT, INT_MIN)
+        ts.T_UINT=UINT_MAX
+        self.assertEquals(ts.T_UINT, UINT_MAX)
+
+        ts.T_LONG=LONG_MAX
+        self.assertEquals(ts.T_LONG, LONG_MAX)
+        ts.T_LONG=LONG_MIN
+        self.assertEquals(ts.T_LONG, LONG_MIN)
+        ts.T_ULONG=ULONG_MAX
+        self.assertEquals(ts.T_ULONG, ULONG_MAX)
+
+def test_main(verbose=None):
+    test_support.run_unittest(
+        ReadWriteTests
+        )
+
+if __name__ == "__main__":
+    test_main(verbose=True)
index 8b822e9d7557f0f7a7526036f93fc5b14174e7fd..c79a55ab7edad92172d24315fc35d067b88c14e2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 2.5.1c1?
 Core and builtins
 -----------------
 
+- Patch #1549049: Support long values in structmember.
+
 - Bug #1545497: when given an explicit base, int() did ignore NULs
   embedded in the string to convert.
 
index f5f3ab23bdcb07e51dd5465e8b7c8b76559621a1..0236c838e063597e988c2e901ef242231c023cbf 100644 (file)
@@ -6,6 +6,8 @@
  */
 
 #include "Python.h"
+#include <values.h>
+#include "structmember.h"
 
 #ifdef WITH_THREAD
 #include "pythread.h"
@@ -35,13 +37,13 @@ raiseTestError(const char* test_name, const char* msg)
    platforms have these hardcoded.  Better safe than sorry.
 */
 static PyObject*
-sizeof_error(const char* fatname, const char* typename,
+sizeof_error(const char* fatname, const char* typname,
         int expected, int got)
 {
        char buf[1024];
        PyOS_snprintf(buf, sizeof(buf),
                "%.200s #define == %d but sizeof(%.200s) == %d",
-               fatname, expected, typename, got);
+               fatname, expected, typname, got);
        PyErr_SetString(TestError, buf);
        return (PyObject*)NULL;
 }
@@ -615,7 +617,7 @@ _make_call(void *callable)
 {
        PyObject *rc;
        PyGILState_STATE s = PyGILState_Ensure();
-       rc = PyObject_CallFunction(callable, "");
+       rc = PyObject_CallFunction((PyObject *)callable, "");
        Py_XDECREF(rc);
        PyGILState_Release(s);
 }
@@ -756,6 +758,105 @@ static PyMethodDef TestMethods[] = {
 
 #define AddSym(d, n, f, v) {PyObject *o = f(v); PyDict_SetItemString(d, n, o); Py_DECREF(o);}
 
+typedef struct {
+       char byte_member;
+       unsigned char ubyte_member;
+       short short_member;
+       unsigned short ushort_member;
+       int int_member;
+       unsigned int uint_member;
+       long long_member;
+       unsigned long ulong_member;
+       float float_member;
+       double double_member;
+} all_structmembers;
+
+typedef struct {
+    PyObject_HEAD
+       all_structmembers structmembers;
+} test_structmembers;
+
+static struct PyMemberDef test_members[] = {
+       {"T_BYTE", T_BYTE, offsetof(test_structmembers, structmembers.byte_member), 0, NULL},
+       {"T_UBYTE", T_UBYTE, offsetof(test_structmembers, structmembers.ubyte_member), 0, NULL},
+       {"T_SHORT", T_SHORT, offsetof(test_structmembers, structmembers.short_member), 0, NULL},
+       {"T_USHORT", T_USHORT, offsetof(test_structmembers, structmembers.ushort_member), 0, NULL},
+       {"T_INT", T_INT, offsetof(test_structmembers, structmembers.int_member), 0, NULL},
+       {"T_UINT", T_UINT, offsetof(test_structmembers, structmembers.uint_member), 0, NULL},
+       {"T_LONG", T_LONG, offsetof(test_structmembers, structmembers.long_member), 0, NULL},
+       {"T_ULONG", T_ULONG, offsetof(test_structmembers, structmembers.ulong_member), 0, NULL},
+       {"T_FLOAT", T_FLOAT, offsetof(test_structmembers, structmembers.float_member), 0, NULL},
+       {"T_DOUBLE", T_DOUBLE, offsetof(test_structmembers, structmembers.double_member), 0, NULL},
+       {NULL}
+};
+
+
+static PyObject *test_structmembers_new(PyTypeObject *type, PyObject *args, PyObject *kwargs){
+       static char *keywords[]={"T_BYTE", "T_UBYTE", "T_SHORT", "T_USHORT", "T_INT", "T_UINT",
+               "T_LONG", "T_ULONG", "T_FLOAT", "T_DOUBLE", NULL};
+       test_structmembers *ob=PyObject_New(test_structmembers, type);
+       if (ob==NULL)
+               return NULL;
+       memset(&ob->structmembers, 0, sizeof(all_structmembers));
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|bBhHiIlkfd", keywords,
+               &ob->structmembers.byte_member, &ob->structmembers.ubyte_member,
+               &ob->structmembers.short_member, &ob->structmembers.ushort_member,
+               &ob->structmembers.int_member, &ob->structmembers.uint_member, 
+               &ob->structmembers.long_member, &ob->structmembers.ulong_member,
+               &ob->structmembers.float_member, &ob->structmembers.double_member)){
+               Py_DECREF(ob);
+               return NULL;
+               }
+       return (PyObject *)ob;
+}
+
+static void test_structmembers_free(PyObject *ob){
+       PyObject_FREE(ob);
+}
+
+static PyTypeObject test_structmembersType = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+       "test_structmembersType",
+       sizeof(test_structmembers),     /* tp_basicsize */
+       0,                              /* tp_itemsize */
+       test_structmembers_free,        /* destructor tp_dealloc */
+       0,                              /* tp_print */
+       0,                              /* tp_getattr */
+       0,                              /* tp_setattr */
+       0,                              /* tp_compare */
+       0,                              /* tp_repr */
+       0,                              /* tp_as_number */
+       0,                              /* tp_as_sequence */
+       0,                              /* tp_as_mapping */
+       0,                              /* tp_hash */
+       0,                              /* tp_call */
+       0,                              /* tp_str */
+       PyObject_GenericGetAttr,
+       PyObject_GenericSetAttr,
+       0,                              /* tp_as_buffer */
+       0,                              /* tp_flags */
+       "Type containing all structmember types",
+       0,                              /* traverseproc tp_traverse */
+       0,                              /* tp_clear */
+       0,                              /* tp_richcompare */
+       0,                              /* tp_weaklistoffset */
+       0,                              /* tp_iter */
+       0,                              /* tp_iternext */
+       0,                              /* tp_methods */
+       test_members,   /* tp_members */
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       test_structmembers_new,                 /* tp_new */
+};
+
+
 PyMODINIT_FUNC
 init_testcapi(void)
 {
@@ -765,16 +866,28 @@ init_testcapi(void)
        if (m == NULL)
                return;
 
+       test_structmembersType.ob_type=&PyType_Type;
+       Py_INCREF(&test_structmembersType);
+       PyModule_AddObject(m, "test_structmembersType", (PyObject *)&test_structmembersType);
+
+       PyModule_AddObject(m, "CHAR_MAX", PyInt_FromLong(CHAR_MAX));
+       PyModule_AddObject(m, "CHAR_MIN", PyInt_FromLong(CHAR_MIN));
        PyModule_AddObject(m, "UCHAR_MAX", PyInt_FromLong(UCHAR_MAX));
+       PyModule_AddObject(m, "SHRT_MAX", PyInt_FromLong(SHRT_MAX));
+       PyModule_AddObject(m, "SHRT_MIN", PyInt_FromLong(SHRT_MIN));
        PyModule_AddObject(m, "USHRT_MAX", PyInt_FromLong(USHRT_MAX));
+       PyModule_AddObject(m, "INT_MAX",  PyLong_FromLong(INT_MAX));
+       PyModule_AddObject(m, "INT_MIN",  PyLong_FromLong(INT_MIN));
        PyModule_AddObject(m, "UINT_MAX",  PyLong_FromUnsignedLong(UINT_MAX));
-       PyModule_AddObject(m, "ULONG_MAX", PyLong_FromUnsignedLong(ULONG_MAX));
-       PyModule_AddObject(m, "INT_MIN", PyInt_FromLong(INT_MIN));
-       PyModule_AddObject(m, "LONG_MIN", PyInt_FromLong(LONG_MIN));
-       PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyInt_FromSsize_t(PY_SSIZE_T_MIN));
-       PyModule_AddObject(m, "INT_MAX", PyInt_FromLong(INT_MAX));
        PyModule_AddObject(m, "LONG_MAX", PyInt_FromLong(LONG_MAX));
+       PyModule_AddObject(m, "LONG_MIN", PyInt_FromLong(LONG_MIN));
+       PyModule_AddObject(m, "ULONG_MAX", PyLong_FromUnsignedLong(ULONG_MAX));
+       PyModule_AddObject(m, "FLT_MAX", PyFloat_FromDouble(FLT_MAX));
+       PyModule_AddObject(m, "FLT_MIN", PyFloat_FromDouble(FLT_MIN));
+       PyModule_AddObject(m, "DBL_MAX", PyFloat_FromDouble(DBL_MAX));
+       PyModule_AddObject(m, "DBL_MIN", PyFloat_FromDouble(DBL_MIN));
        PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyInt_FromSsize_t(PY_SSIZE_T_MAX));
+       PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyInt_FromSsize_t(PY_SSIZE_T_MIN));
 
        TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
        Py_INCREF(TestError);
index 54eb0556f7aa6aa1a9367e82683252f7c6d8e685..03934c0c844929872f7ea9a293898a2fbf48b534 100644 (file)
@@ -62,29 +62,28 @@ PyMember_GetOne(const char *addr, PyMemberDef *l)
        addr += l->offset;
        switch (l->type) {
        case T_BYTE:
-               v = PyInt_FromLong(
-                       (long) (((*(char*)addr & 0xff) ^ 0x80) - 0x80));
+               v = PyInt_FromLong(*(char*)addr);
                break;
        case T_UBYTE:
-               v = PyInt_FromLong((long) *(char*)addr & 0xff);
+               v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
                break;
        case T_SHORT:
-               v = PyInt_FromLong((long) *(short*)addr);
+               v = PyInt_FromLong(*(short*)addr);
                break;
        case T_USHORT:
-               v = PyInt_FromLong((long) *(unsigned short*)addr);
+               v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
                break;
        case T_INT:
-               v = PyInt_FromLong((long) *(int*)addr);
+               v = PyInt_FromLong(*(int*)addr);
                break;
        case T_UINT:
-               v = PyInt_FromLong((long) *(unsigned int*)addr);
+               v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
                break;
        case T_LONG:
                v = PyInt_FromLong(*(long*)addr);
                break;
        case T_ULONG:
-               v = PyLong_FromDouble((double) *(unsigned long*)addr);
+               v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
                break;
        case T_FLOAT:
                v = PyFloat_FromDouble((double)*(float*)addr);
@@ -175,68 +174,91 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
        }
        addr += l->offset;
        switch (l->type) {
-       case T_BYTE:
-       case T_UBYTE:
-               if (!PyInt_Check(v)) {
-                       PyErr_BadArgument();
+       case T_BYTE:{
+               long long_val;
+               long_val = PyInt_AsLong(v);
+               if ((long_val == -1) && PyErr_Occurred())
                        return -1;
-               }
-               *(char*)addr = (char) PyInt_AsLong(v);
+               *(char*)addr = (char)long_val;
                break;
-       case T_SHORT:
-       case T_USHORT:
-               if (!PyInt_Check(v)) {
-                       PyErr_BadArgument();
-                       return -1;
                }
-               *(short*)addr = (short) PyInt_AsLong(v);
+       case T_UBYTE:{
+               long long_val;
+               long_val = PyInt_AsLong(v);
+               if ((long_val == -1) && PyErr_Occurred())
+                       return -1;
+               *(unsigned char*)addr = (unsigned char)long_val;
                break;
-       case T_UINT:
-       case T_INT:
-               if (!PyInt_Check(v)) {
-                       PyErr_BadArgument();
+               }
+       case T_SHORT:{
+               long long_val;
+               long_val = PyInt_AsLong(v);
+               if ((long_val == -1) && PyErr_Occurred())
                        return -1;
+               *(short*)addr = (short)long_val;
+               break;
                }
-               *(int*)addr = (int) PyInt_AsLong(v);
+       case T_USHORT:{
+               long long_val;
+               long_val = PyInt_AsLong(v);
+               if ((long_val == -1) && PyErr_Occurred())
+                       return -1;
+               *(unsigned short*)addr = (unsigned short)long_val;
                break;
-       case T_LONG:
-               if (!PyInt_Check(v)) {
-                       PyErr_BadArgument();
+               }
+       case T_INT:{
+               long long_val;
+               long_val = PyInt_AsLong(v);
+               if ((long_val == -1) && PyErr_Occurred())
                        return -1;
+               *(int *)addr = (int)long_val;
+               break;
+               }
+       case T_UINT:{
+               unsigned long ulong_val;
+               ulong_val = PyLong_AsUnsignedLong(v);
+               if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
+                       /* XXX: For compatibility, accept negative int values
+                          as well. */
+                       PyErr_Clear();
+                       ulong_val = PyLong_AsLong(v);
+                       if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
+                               return -1;
                }
-               *(long*)addr = PyInt_AsLong(v);
+               *(unsigned int *)addr = (unsigned int)ulong_val;
                break;
-       case T_ULONG:
-               if (PyInt_Check(v))
-                       *(long*)addr = PyInt_AsLong(v);
-               else if (PyLong_Check(v))
-                       *(long*)addr = PyLong_AsLong(v);
-               else {
-                       PyErr_BadArgument();
+               }
+       case T_LONG:{
+               *(long*)addr = PyLong_AsLong(v);
+               if ((*(long*)addr == -1) && PyErr_Occurred())
                        return -1;
+               break;
+               }
+       case T_ULONG:{
+               *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
+               if ((*(unsigned long*)addr == (unsigned long)-1)
+                   && PyErr_Occurred()) {
+                       /* XXX: For compatibility, accept negative int values
+                          as well. */
+                       PyErr_Clear();
+                       *(unsigned long*)addr = PyLong_AsLong(v);
+                       if ((*(unsigned long*)addr == (unsigned int)-1) && PyErr_Occurred())
+                               return -1;
                }
                break;
-       case T_FLOAT:
-               if (PyInt_Check(v))
-                       *(float*)addr =
-                               (float) PyInt_AsLong(v);
-               else if (PyFloat_Check(v))
-                       *(float*)addr =
-                               (float) PyFloat_AsDouble(v);
-               else {
-                       PyErr_BadArgument();
-                       return -1;
                }
+       case T_FLOAT:{
+               double double_val;
+               double_val = PyFloat_AsDouble(v);
+               if ((double_val == -1) && PyErr_Occurred())
+                       return -1;
+               *(float*)addr = (float)double_val;
                break;
+               }
        case T_DOUBLE:
-               if (PyInt_Check(v))
-                       *(double*)addr = (double) PyInt_AsLong(v);
-               else if (PyFloat_Check(v))
-                       *(double*)addr = PyFloat_AsDouble(v);
-               else {
-                       PyErr_BadArgument();
+               *(double*)addr = PyFloat_AsDouble(v);
+               if ((*(double*)addr == -1) && PyErr_Occurred())
                        return -1;
-               }
                break;
        case T_OBJECT:
        case T_OBJECT_EX: