10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi######################################################################
20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#  This file should be kept compatible with Python 2.3, see PEP 291. #
30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi######################################################################
40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys
50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom ctypes import *
60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi_array_type = type(Array)
80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _other_endian(typ):
100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """Return the type with the 'other' byte order.  Simple types like
110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    c_int and so on already have __ctype_be__ and __ctype_le__
120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes which contain the types, for more complicated types
130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    arrays and structures are supported.
140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """
150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # check _OTHER_ENDIAN attribute (present if typ is primitive type)
160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if hasattr(typ, _OTHER_ENDIAN):
170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return getattr(typ, _OTHER_ENDIAN)
180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # if typ is array
190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if isinstance(typ, _array_type):
200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _other_endian(typ._type_) * typ._length_
210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # if typ is structure
220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if issubclass(typ, Structure):
230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return typ
240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    raise TypeError("This type does not support other endian: %s" % typ)
250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass _swapped_meta(type(Structure)):
270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setattr__(self, attrname, value):
280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if attrname == "_fields_":
290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            fields = []
300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for desc in value:
310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                name = desc[0]
320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                typ = desc[1]
330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                rest = desc[2:]
340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                fields.append((name, _other_endian(typ)) + rest)
350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            value = fields
360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        super(_swapped_meta, self).__setattr__(attrname, value)
370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi################################################################
390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Note: The Structure metaclass checks for the *presence* (not the
410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# value!) of a _swapped_bytes_ attribute to determine the bit order in
420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# structures containing bit fields.
430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif sys.byteorder == "little":
450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _OTHER_ENDIAN = "__ctype_be__"
460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    LittleEndianStructure = Structure
480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    class BigEndianStructure(Structure):
500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """Structure with big endian byte order"""
510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        __metaclass__ = _swapped_meta
520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _swappedbytes_ = None
530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yielif sys.byteorder == "big":
550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _OTHER_ENDIAN = "__ctype_le__"
560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    BigEndianStructure = Structure
580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    class LittleEndianStructure(Structure):
590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """Structure with little endian byte order"""
600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        __metaclass__ = _swapped_meta
610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _swappedbytes_ = None
620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yielse:
640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    raise RuntimeError("Invalid byteorder")
65