1 import sys 2 from ctypes import * 3 4 _array_type = type(Array) 5 6 def _other_endian(typ): 7 """Return the type with the 'other' byte order. Simple types like 8 c_int and so on already have __ctype_be__ and __ctype_le__ 9 attributes which contain the types, for more complicated types 10 arrays and structures are supported. 11 """ 12 # check _OTHER_ENDIAN attribute (present if typ is primitive type) 13 if hasattr(typ, _OTHER_ENDIAN): 14 return getattr(typ, _OTHER_ENDIAN) 15 # if typ is array 16 if isinstance(typ, _array_type): 17 return _other_endian(typ._type_) * typ._length_ 18 # if typ is structure 19 if issubclass(typ, Structure): 20 return typ 21 raise TypeError("This type does not support other endian: %s" % typ) 22 23 class _swapped_meta(type(Structure)): 24 def __setattr__(self, attrname, value): 25 if attrname == "_fields_": 26 fields = [] 27 for desc in value: 28 name = desc[0] 29 typ = desc[1] 30 rest = desc[2:] 31 fields.append((name, _other_endian(typ)) + rest) 32 value = fields 33 super().__setattr__(attrname, value) 34 35 ################################################################ 36 37 # Note: The Structure metaclass checks for the *presence* (not the 38 # value!) of a _swapped_bytes_ attribute to determine the bit order in 39 # structures containing bit fields. 40 41 if sys.byteorder == "little": 42 _OTHER_ENDIAN = "__ctype_be__" 43 44 LittleEndianStructure = Structure 45 46 class BigEndianStructure(Structure, metaclass=_swapped_meta): 47 """Structure with big endian byte order""" 48 __slots__ = () 49 _swappedbytes_ = None 50 51 elif sys.byteorder == "big": 52 _OTHER_ENDIAN = "__ctype_le__" 53 54 BigEndianStructure = Structure 55 class LittleEndianStructure(Structure, metaclass=_swapped_meta): 56 """Structure with little endian byte order""" 57 __slots__ = () 58 _swappedbytes_ = None 59 60 else: 61 raise RuntimeError("Invalid byteorder") 62