summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2011-07-13 19:43:18 (GMT)
committerVictor Stinner <victor.stinner@haypocalc.com>2011-07-13 19:43:18 (GMT)
commit6636121950a08de9d437cc2d76ac272cdceb7ecc (patch)
tree1519bd4609f357a6027ae22e8bdc0939a0f7ca9e /Lib
parentcb4ae815b5db6c9339c7c77e1d45e850ed76e497 (diff)
downloadcpython-6636121950a08de9d437cc2d76ac272cdceb7ecc.zip
cpython-6636121950a08de9d437cc2d76ac272cdceb7ecc.tar.gz
cpython-6636121950a08de9d437cc2d76ac272cdceb7ecc.tar.bz2
Close #4376: ctypes now supports nested structures in a endian different than
the parent structure. Patch by Vlad Riscutia.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/ctypes/_endian.py16
-rw-r--r--Lib/ctypes/test/test_byteswap.py38
2 files changed, 36 insertions, 18 deletions
diff --git a/Lib/ctypes/_endian.py b/Lib/ctypes/_endian.py
index b48bda5..721b0d1 100644
--- a/Lib/ctypes/_endian.py
+++ b/Lib/ctypes/_endian.py
@@ -7,14 +7,18 @@ def _other_endian(typ):
"""Return the type with the 'other' byte order. Simple types like
c_int and so on already have __ctype_be__ and __ctype_le__
attributes which contain the types, for more complicated types
- only arrays are supported.
+ arrays and structures are supported.
"""
- try:
+ # check _OTHER_ENDIAN attribute (present if typ is primitive type)
+ if hasattr(typ, _OTHER_ENDIAN):
return getattr(typ, _OTHER_ENDIAN)
- except AttributeError:
- if type(typ) == _array_type:
- return _other_endian(typ._type_) * typ._length_
- raise TypeError("This type does not support other endian: %s" % typ)
+ # if typ is array
+ if isinstance(typ, _array_type):
+ return _other_endian(typ._type_) * typ._length_
+ # if typ is structure
+ if issubclass(typ, Structure):
+ return typ
+ raise TypeError("This type does not support other endian: %s" % typ)
class _swapped_meta(type(Structure)):
def __setattr__(self, attrname, value):
diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py
index 83cb667..3366ba6 100644
--- a/Lib/ctypes/test/test_byteswap.py
+++ b/Lib/ctypes/test/test_byteswap.py
@@ -185,18 +185,32 @@ class Test(unittest.TestCase):
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])
def test_struct_struct(self):
- # Nested structures with different byte order not (yet) supported
- if sys.byteorder == "little":
- base = BigEndianStructure
- else:
- base = LittleEndianStructure
-
- class T(Structure):
- _fields_ = [("a", c_int),
- ("b", c_int)]
- class S(base):
- pass
- self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
+ # nested structures with different byteorders
+
+ # create nested structures with given byteorders and set memory to data
+ def set_structures(endianness, nested_endianness, data):
+ class NestedStructure(nested_endianness):
+ _fields_ = [("x", c_uint32),
+ ("y", c_uint32)]
+
+ class TestStructure(endianness):
+ _fields_ = [("point", NestedStructure)]
+
+ self.assertEqual(len(data), sizeof(TestStructure))
+ return cast(data, POINTER(TestStructure))[0]
+
+ for nested, data in (
+ (BigEndianStructure, b'\0\0\0\1\0\0\0\2'),
+ (LittleEndianStructure, b'\1\0\0\0\2\0\0\0'),
+ ):
+ for parent in (
+ BigEndianStructure,
+ LittleEndianStructure,
+ Structure,
+ ):
+ s = set_structures(parent, nested, data)
+ self.assertEqual(s.point.x, 1)
+ self.assertEqual(s.point.y, 2)
def test_struct_fields_2(self):
# standard packing in struct uses no alignment.