14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport unittest
24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom ctypes import *
34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport re, sys
44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif sys.byteorder == "little":
64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    THIS_ENDIAN = "<"
74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    OTHER_ENDIAN = ">"
84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoelse:
94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    THIS_ENDIAN = ">"
104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    OTHER_ENDIAN = "<"
114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef normalize(format):
134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # Remove current endian specifier and white space from a format
144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # string
154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    if format is None:
164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return ""
174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    format = format.replace(OTHER_ENDIAN, THIS_ENDIAN)
184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    return re.sub(r"\s", "", format)
194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Test(unittest.TestCase):
214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_native_types(self):
234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        for tp, fmt, shape, itemtp in native_types:
244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            ob = tp()
254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            v = memoryview(ob)
264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            try:
274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(normalize(v.format), normalize(fmt))
284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                if shape is not None:
294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    self.assertEqual(len(v), shape[0])
304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                else:
314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(v.itemsize, sizeof(itemtp))
334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(v.shape, shape)
344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # ctypes object always have a non-strided memory block
354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(v.strides, None)
364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # they are always read/write
374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertFalse(v.readonly)
384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                if v.shape:
404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    n = 1
414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    for dim in v.shape:
424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        n = n * dim
434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    self.assertEqual(n * v.itemsize, len(v.tobytes()))
444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            except:
454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # so that we can see the failing type
464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                print(tp)
474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                raise
484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_endian_types(self):
504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        for tp, fmt, shape, itemtp in endian_types:
514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            ob = tp()
524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            v = memoryview(ob)
534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            try:
544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(v.format, fmt)
554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                if shape is not None:
564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    self.assertEqual(len(v), shape[0])
574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                else:
584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(v.itemsize, sizeof(itemtp))
604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(v.shape, shape)
614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # ctypes object always have a non-strided memory block
624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(v.strides, None)
634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # they are always read/write
644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertFalse(v.readonly)
654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                if v.shape:
674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    n = 1
684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    for dim in v.shape:
694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        n = n * dim
704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    self.assertEqual(n, len(v))
714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            except:
724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # so that we can see the failing type
734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                print(tp)
744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                raise
754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# define some structure classes
774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Point(Structure):
794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _fields_ = [("x", c_long), ("y", c_long)]
804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PackedPoint(Structure):
824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _pack_ = 2
834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _fields_ = [("x", c_long), ("y", c_long)]
844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Point2(Structure):
864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    pass
874adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoPoint2._fields_ = [("x", c_long), ("y", c_long)]
884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass EmptyStruct(Structure):
904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _fields_ = []
914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass aUnion(Union):
934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _fields_ = [("a", c_int)]
944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Incomplete(Structure):
964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    pass
974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Complete(Structure):
994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    pass
1004adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoPComplete = POINTER(Complete)
1014adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoComplete._fields_ = [("a", c_long)]
1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao################################################################
1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# This table contains format strings as they look on little endian
1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# machines.  The test replaces '<' with '>' on big endian machines.
1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaonative_types = [
1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # type                      format                  shape           calc itemsize
1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ## simple types
1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_char,                    "<c",                   None,           c_char),
1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_byte,                    "<b",                   None,           c_byte),
1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_ubyte,                   "<B",                   None,           c_ubyte),
1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_short,                   "<h",                   None,           c_short),
1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_ushort,                  "<H",                   None,           c_ushort),
1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # c_int and c_uint may be aliases to c_long
1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #(c_int,                     "<i",                   None,           c_int),
1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #(c_uint,                    "<I",                   None,           c_uint),
1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_long,                    "<l",                   None,           c_long),
1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_ulong,                   "<L",                   None,           c_ulong),
1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # c_longlong and c_ulonglong are aliases on 64-bit platforms
1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #(c_longlong,                "<q",                   None,           c_longlong),
1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #(c_ulonglong,               "<Q",                   None,           c_ulonglong),
1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_float,                   "<f",                   None,           c_float),
1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_double,                  "<d",                   None,           c_double),
1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # c_longdouble may be an alias to c_double
1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_bool,                    "<?",                   None,           c_bool),
1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (py_object,                 "<O",                   None,           py_object),
1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ## pointers
1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(c_byte),           "&<b",                  None,           POINTER(c_byte)),
1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(POINTER(c_long)),  "&&<l",                 None,           POINTER(POINTER(c_long))),
1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ## arrays and pointers
1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_double * 4,              "(4)<d",                (4,),           c_double),
1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (c_float * 4 * 3 * 2,       "(2,3,4)<f",            (2,3,4),        c_float),
1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(c_short) * 2,      "(2)&<h",               (2,),           POINTER(c_short)),
1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(c_short) * 2 * 3,  "(3,2)&<h",             (3,2,),         POINTER(c_short)),
1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(c_short * 2),      "&(2)<h",               None,           POINTER(c_short)),
1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ## structures and unions
1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (Point,                     "T{<l:x:<l:y:}",        None,           Point),
1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # packed structures do not implement the pep
1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (PackedPoint,               "B",                    None,           PackedPoint),
1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (Point2,                    "T{<l:x:<l:y:}",        None,           Point2),
1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (EmptyStruct,               "T{}",                  None,           EmptyStruct),
1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # the pep does't support unions
1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (aUnion,                    "B",                    None,           aUnion),
1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ## pointer to incomplete structure
1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (Incomplete,                "B",                    None,           Incomplete),
1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(Incomplete),       "&B",                   None,           POINTER(Incomplete)),
1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # 'Complete' is a structure that starts incomplete, but is completed after the
1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # pointer type to it has been created.
1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (Complete,                  "T{<l:a:}",             None,           Complete),
1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # Unfortunately the pointer format string is not fixed...
1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(Complete),         "&B",                   None,           POINTER(Complete)),
1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ## other
1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # function signatures are not implemented
1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (CFUNCTYPE(None),           "X{}",                  None,           CFUNCTYPE(None)),
1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ]
1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass BEPoint(BigEndianStructure):
1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _fields_ = [("x", c_long), ("y", c_long)]
1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass LEPoint(LittleEndianStructure):
1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _fields_ = [("x", c_long), ("y", c_long)]
1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao################################################################
1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# This table contains format strings as they really look, on both big
1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# and little endian machines.
1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoendian_types = [
1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (BEPoint,                   "T{>l:x:>l:y:}",        None,           BEPoint),
1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (LEPoint,                   "T{<l:x:<l:y:}",        None,           LEPoint),
1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(BEPoint),          "&T{>l:x:>l:y:}",       None,           POINTER(BEPoint)),
1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    (POINTER(LEPoint),          "&T{<l:x:<l:y:}",       None,           POINTER(LEPoint)),
1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ]
1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif __name__ == "__main__":
1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    unittest.main()
197