]> granicus.if.org Git - python/commitdiff
Bug #1563759: struct.unpack doens't support buffer protocol objects
authorRaymond Hettinger <python@rcn.com>
Thu, 5 Apr 2007 18:00:03 +0000 (18:00 +0000)
committerRaymond Hettinger <python@rcn.com>
Thu, 5 Apr 2007 18:00:03 +0000 (18:00 +0000)
Lib/test/test_struct.py
Modules/_struct.c

index f5019bf192a85fabe0fdc58c11d1c297b01e0da5..ea3a5187cf6fb12bfd8dc362d3b98d7e7b7da539 100644 (file)
@@ -614,11 +614,19 @@ def test_pack_into_fn():
     assertRaises(struct.error, pack_into, small_buf, 0, test_string)
     assertRaises(struct.error, pack_into, small_buf, 2, test_string)
 
+def test_unpack_with_buffer():
+    # SF bug 1563759: struct.unpack doens't support buffer protocol objects
+    data1 = array.array('B', '\x12\x34\x56\x78')
+    data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
+    for data in [data1, data2]:
+        value, = struct.unpack('>I', data)
+        vereq(value, 0x12345678)
 
 # Test methods to pack and unpack from buffers rather than strings.
 test_unpack_from()
 test_pack_into()
 test_pack_into_fn()
+test_unpack_with_buffer()
 
 def test_bool():
     for prefix in tuple("<>!=")+('',):
index 059d98867da0449a1beb45e7a5f9b4de1f97bed4..a4c82f765331c62d1a545afa27be90ecc87c2f86 100644 (file)
@@ -1534,17 +1534,35 @@ strings.");
 static PyObject *
 s_unpack(PyObject *self, PyObject *inputstr)
 {
+       char *start;
+       Py_ssize_t len;
+       PyObject *args=NULL, *result;
        PyStructObject *soself = (PyStructObject *)self;
        assert(PyStruct_Check(self));
        assert(soself->s_codes != NULL);
-       if (inputstr == NULL || !PyString_Check(inputstr) ||
-               PyString_GET_SIZE(inputstr) != soself->s_size) {
-               PyErr_Format(StructError,
-                       "unpack requires a string argument of length %zd",
-                       soself->s_size);
-               return NULL;
+       if (inputstr == NULL)
+               goto fail;
+       if (PyString_Check(inputstr) &&
+               PyString_GET_SIZE(inputstr) == soself->s_size) {
+                       return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
        }
-       return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
+       args = PyTuple_Pack(1, inputstr);
+       if (args == NULL)
+               return NULL;
+       if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len))
+               goto fail;
+       if (soself->s_size != len)
+               goto fail;
+       result = s_unpack_internal(soself, start);
+       Py_DECREF(args);
+       return result;
+
+fail:
+       Py_XDECREF(args);
+       PyErr_Format(StructError,
+               "unpack requires a string argument of length %zd",
+               soself->s_size);
+       return NULL;
 }
 
 PyDoc_STRVAR(s_unpack_from__doc__,