1import sys
2from . import model
3from .error import FFIError
4
5
6COMMON_TYPES = {}
7
8try:
9    # fetch "bool" and all simple Windows types
10    from _cffi_backend import _get_common_types
11    _get_common_types(COMMON_TYPES)
12except ImportError:
13    pass
14
15COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE')
16COMMON_TYPES['bool'] = '_Bool'    # in case we got ImportError above
17
18for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
19    if _type.endswith('_t'):
20        COMMON_TYPES[_type] = _type
21del _type
22
23_CACHE = {}
24
25def resolve_common_type(parser, commontype):
26    try:
27        return _CACHE[commontype]
28    except KeyError:
29        cdecl = COMMON_TYPES.get(commontype, commontype)
30        if not isinstance(cdecl, str):
31            result, quals = cdecl, 0    # cdecl is already a BaseType
32        elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
33            result, quals = model.PrimitiveType(cdecl), 0
34        elif cdecl == 'set-unicode-needed':
35            raise FFIError("The Windows type %r is only available after "
36                           "you call ffi.set_unicode()" % (commontype,))
37        else:
38            if commontype == cdecl:
39                raise FFIError(
40                    "Unsupported type: %r.  Please look at "
41        "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations "
42                    "and file an issue if you think this type should really "
43                    "be supported." % (commontype,))
44            result, quals = parser.parse_type_and_quals(cdecl)   # recursive
45
46        assert isinstance(result, model.BaseTypeByIdentity)
47        _CACHE[commontype] = result, quals
48        return result, quals
49
50
51# ____________________________________________________________
52# extra types for Windows (most of them are in commontypes.c)
53
54
55def win_common_types():
56    return {
57        "UNICODE_STRING": model.StructType(
58            "_UNICODE_STRING",
59            ["Length",
60             "MaximumLength",
61             "Buffer"],
62            [model.PrimitiveType("unsigned short"),
63             model.PrimitiveType("unsigned short"),
64             model.PointerType(model.PrimitiveType("wchar_t"))],
65            [-1, -1, -1]),
66        "PUNICODE_STRING": "UNICODE_STRING *",
67        "PCUNICODE_STRING": "const UNICODE_STRING *",
68
69        "TBYTE": "set-unicode-needed",
70        "TCHAR": "set-unicode-needed",
71        "LPCTSTR": "set-unicode-needed",
72        "PCTSTR": "set-unicode-needed",
73        "LPTSTR": "set-unicode-needed",
74        "PTSTR": "set-unicode-needed",
75        "PTBYTE": "set-unicode-needed",
76        "PTCHAR": "set-unicode-needed",
77        }
78
79if sys.platform == 'win32':
80    COMMON_TYPES.update(win_common_types())
81