Armin Rigo avatar Armin Rigo committed 8656485

Fix issue #32: turn types like "size_t" into primitive types from the
point of view of CFFI.

Comments (0)

Files changed (9)

c/_cffi_backend.c

 
 /************************************************************/
 
-static PyObject *b_nonstandard_integer_types(PyObject *self, PyObject *noarg)
-{
-#define UNSIGNED   0x1000
-    static const struct descr_s { const char *name; int size; } types[] = {
-        { "int8_t",        1 },
-        { "uint8_t",       1 | UNSIGNED },
-        { "int16_t",       2 },
-        { "uint16_t",      2 | UNSIGNED },
-        { "int32_t",       4 },
-        { "uint32_t",      4 | UNSIGNED },
-        { "int64_t",       8 },
-        { "uint64_t",      8 | UNSIGNED },
-
-        { "intptr_t",      sizeof(intptr_t) },
-        { "uintptr_t",     sizeof(uintptr_t) | UNSIGNED },
-        { "ptrdiff_t",     sizeof(ptrdiff_t) },
-        { "size_t",        sizeof(size_t) | UNSIGNED },
-        { "ssize_t",       sizeof(ssize_t) },
-        { NULL }
-    };
-#undef UNSIGNED
-    const struct descr_s *ptypes;
-    PyObject *d;
-
-    d = PyDict_New();
-    if (d == NULL)
-        return NULL;
-
-    for (ptypes=types; ptypes->name; ptypes++) {
-        int err;
-        PyObject *obj = PyInt_FromLong(ptypes->size);
-        if (obj == NULL)
-            goto error;
-        err = PyDict_SetItemString(d, ptypes->name, obj);
-        Py_DECREF(obj);
-        if (err != 0)
-            goto error;
-    }
-    return d;
-
- error:
-    Py_DECREF(d);
-    return NULL;
-}
-
 static PyObject *b_new_primitive_type(PyObject *self, PyObject *args)
 {
 #define ENUM_PRIMITIVE_TYPES                                    \
        EPTYPE(d, double, CT_PRIMITIVE_FLOAT )                   \
        EPTYPE(ld, long double, CT_PRIMITIVE_FLOAT | CT_IS_LONGDOUBLE ) \
        ENUM_PRIMITIVE_TYPES_WCHAR                               \
-       EPTYPE(b, _Bool, CT_PRIMITIVE_UNSIGNED | CT_IS_BOOL )
+       EPTYPE(b, _Bool, CT_PRIMITIVE_UNSIGNED | CT_IS_BOOL )    \
+     /* the following types are not primitive in the C sense */ \
+       EPTYPE(i8, int8_t, CT_PRIMITIVE_SIGNED)                  \
+       EPTYPE(u8, uint8_t, CT_PRIMITIVE_UNSIGNED)               \
+       EPTYPE(i16, int16_t, CT_PRIMITIVE_SIGNED)                \
+       EPTYPE(u16, uint16_t, CT_PRIMITIVE_UNSIGNED)             \
+       EPTYPE(i32, int32_t, CT_PRIMITIVE_SIGNED)                \
+       EPTYPE(u32, uint32_t, CT_PRIMITIVE_UNSIGNED)             \
+       EPTYPE(i64, int64_t, CT_PRIMITIVE_SIGNED)                \
+       EPTYPE(u64, uint64_t, CT_PRIMITIVE_UNSIGNED)             \
+       EPTYPE(ip, intptr_t, CT_PRIMITIVE_SIGNED)                \
+       EPTYPE(up, uintptr_t, CT_PRIMITIVE_UNSIGNED)             \
+       EPTYPE(pd, ptrdiff_t, CT_PRIMITIVE_SIGNED)               \
+       EPTYPE(sz, size_t, CT_PRIMITIVE_UNSIGNED)                \
+       EPTYPE(ssz, ssize_t, CT_PRIMITIVE_SIGNED)
 
 #ifdef HAVE_WCHAR_H
 # define ENUM_PRIMITIVE_TYPES_WCHAR                             \
 }
 
 static PyMethodDef FFIBackendMethods[] = {
-    {"nonstandard_integer_types", b_nonstandard_integer_types, METH_NOARGS},
     {"load_library", b_load_library, METH_VARARGS},
     {"new_primitive_type", b_new_primitive_type, METH_VARARGS},
     {"new_pointer_type", b_new_pointer_type, METH_VARARGS},
     return NULL;
 }
 
-#define _cffi_to_c_PRIMITIVE(TARGETNAME, TARGET)        \
-static TARGET _cffi_to_c_##TARGETNAME(PyObject *obj) {  \
-    PY_LONG_LONG tmp = _my_PyLong_AsLongLong(obj);      \
-    if (tmp != (TARGET)tmp && !PyErr_Occurred())        \
-        return (TARGET)_convert_overflow(obj, #TARGET); \
-    return (TARGET)tmp;                                 \
+#define _cffi_to_c_SIGNED_FN(RETURNTYPE, SIZE)                          \
+static RETURNTYPE _cffi_to_c_i##SIZE(PyObject *obj) {                   \
+    PY_LONG_LONG tmp = _my_PyLong_AsLongLong(obj);                      \
+    if ((tmp > (PY_LONG_LONG)((1ULL<<(SIZE-1)) - 1)) ||                 \
+        (tmp < (PY_LONG_LONG)(-(1ULL<<(SIZE-1)))))                      \
+        if (!PyErr_Occurred())                                          \
+            return (RETURNTYPE)_convert_overflow(obj, #SIZE "-bit int"); \
+    return (RETURNTYPE)tmp;                                             \
 }
 
-_cffi_to_c_PRIMITIVE(signed_char,    signed char)
-_cffi_to_c_PRIMITIVE(unsigned_char,  unsigned char)
-_cffi_to_c_PRIMITIVE(short,          short)
-_cffi_to_c_PRIMITIVE(unsigned_short, unsigned short)
-#if SIZEOF_INT == SIZEOF_LONG
-#define _cffi_to_c_int           _cffi_to_c_long
-#define _cffi_to_c_unsigned_int  _cffi_to_c_unsigned_long
-#else
-_cffi_to_c_PRIMITIVE(int,            int)
-_cffi_to_c_PRIMITIVE(unsigned_int,   unsigned int)
-#endif
-_cffi_to_c_PRIMITIVE(long,           long)
-
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
-static unsigned long _cffi_to_c_unsigned_long(PyObject *obj)
-{
-    unsigned PY_LONG_LONG value = _my_PyLong_AsUnsignedLongLong(obj, 1);
-    if (value != (unsigned long)value)
-        return (unsigned long)_convert_overflow(obj, "unsigned long");
-    return (unsigned long)value;
+#define _cffi_to_c_UNSIGNED_FN(RETURNTYPE, SIZE)                        \
+static RETURNTYPE _cffi_to_c_u##SIZE(PyObject *obj) {                   \
+    unsigned PY_LONG_LONG tmp = _my_PyLong_AsUnsignedLongLong(obj, 1);  \
+    if (tmp > ~(((unsigned PY_LONG_LONG)-2) << (SIZE-1)))               \
+        if (!PyErr_Occurred())                                          \
+            return (RETURNTYPE)_convert_overflow(obj,                   \
+                                   #SIZE "-bit unsigned int");          \
+    return (RETURNTYPE)tmp;                                             \
 }
-#else
-#  define _cffi_to_c_unsigned_long _cffi_to_c_unsigned_long_long
-#endif
-
-#define _cffi_to_c_long_long _my_PyLong_AsLongLong
-
-static unsigned PY_LONG_LONG _cffi_to_c_unsigned_long_long(PyObject *obj)
-{
-    return _my_PyLong_AsUnsignedLongLong(obj, 1);
-}
+
+_cffi_to_c_SIGNED_FN(int, 8)
+_cffi_to_c_SIGNED_FN(int, 16)
+_cffi_to_c_SIGNED_FN(int, 32)
+_cffi_to_c_SIGNED_FN(PY_LONG_LONG, 64)
+_cffi_to_c_UNSIGNED_FN(int, 8)
+_cffi_to_c_UNSIGNED_FN(int, 16)
+_cffi_to_c_UNSIGNED_FN(unsigned int, 32)
+_cffi_to_c_UNSIGNED_FN(unsigned PY_LONG_LONG, 64)
 
 static char _cffi_to_c_char(PyObject *obj)
 {
 
 static void *cffi_exports[] = {
     _cffi_to_c_char_p,
-    _cffi_to_c_signed_char,
-    _cffi_to_c_unsigned_char,
-    _cffi_to_c_short,
-    _cffi_to_c_unsigned_short,
-    _cffi_to_c_int,
-    _cffi_to_c_unsigned_int,
-    _cffi_to_c_long,
-    _cffi_to_c_unsigned_long,
+    _cffi_to_c_i8,
+    _cffi_to_c_u8,
+    _cffi_to_c_i16,
+    _cffi_to_c_u16,
+    _cffi_to_c_i32,
+    _cffi_to_c_u32,
+    _cffi_to_c_i64,
+    _cffi_to_c_u64,
     _cffi_to_c_char,
     _cffi_from_c_pointer,
     _cffi_to_c_pointer,
 #endif
     _cffi_to_c_long_double,
     _cffi_to_c__Bool,
-    _cffi_to_c_long_long,
-    _cffi_to_c_unsigned_long_long,
 };
 
 /************************************************************/
         RTLD_NOLOAD
         RTLD_DEEPBIND
 
-def test_nonstandard_integer_types():
-    d = nonstandard_integer_types()
-    assert type(d) is dict
-    assert 'char' not in d
-    assert d['size_t'] in (0x1004, 0x1008)
-    assert d['size_t'] == d['ssize_t'] + 0x1000
-
 def test_new_primitive_type():
     py.test.raises(KeyError, new_primitive_type, "foo")
     p = new_primitive_type("signed char")
     #
     res = GetLastError()
     assert res == 42
+
+def test_nonstandard_integer_types():
+    for typename in ['int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t',
+                     'uint32_t', 'int64_t', 'uint64_t', 'intptr_t',
+                     'uintptr_t', 'ptrdiff_t', 'size_t', 'ssize_t']:
+        new_primitive_type(typename)    # works
             if name.startswith('RTLD_'):
                 setattr(self, name, getattr(backend, name))
         #
-        lines = ['typedef struct _IO_FILE FILE;']
-        by_size = {}
-        for cname in ['long long', 'long', 'int', 'short', 'char']:
-            by_size[self.sizeof(cname)] = cname
-        for name, size in self._backend.nonstandard_integer_types().items():
-            if size & 0x1000:   # unsigned
-                equiv = 'unsigned %s'
-                size &= ~0x1000
-            else:
-                equiv = 'signed %s'
-            lines.append('typedef %s %s;' % (equiv % by_size[size], name))
-        self.cdef('\n'.join(lines))
+        self.cdef('typedef struct _IO_FILE FILE;')
         del self._cdefsources[:]
         #
         self.NULL = self.cast("void *", 0)

cffi/backend_ctypes.py

         'float': ctypes.c_float,
         'double': ctypes.c_double,
         '_Bool': ctypes.c_bool,
-    }
+        }
+
+    for _name in ['unsigned long long', 'unsigned long',
+                  'unsigned int', 'unsigned short', 'unsigned char']:
+        _size = ctypes.sizeof(PRIMITIVE_TYPES[_name])
+        PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name]
+        if _size == ctypes.sizeof(ctypes.c_void_p):
+            PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name]
+        if _size == ctypes.sizeof(ctypes.c_size_t):
+            PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name]
+
+    for _name in ['long long', 'long', 'int', 'short', 'signed char']:
+        _size = ctypes.sizeof(PRIMITIVE_TYPES[_name])
+        PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name]
+        if _size == ctypes.sizeof(ctypes.c_void_p):
+            PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name]
+            PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name]
+        if _size == ctypes.sizeof(ctypes.c_size_t):
+            PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name]
+
 
     def __init__(self):
         self.RTLD_LAZY = 0   # not supported anyway by ctypes
     def _get_types(self):
         return CTypesData, CTypesType
 
-    def nonstandard_integer_types(self):
-        UNSIGNED = 0x1000
-        result = {}
-        for name in ['long long', 'long', 'int', 'short', 'char']:
-            size = ctypes.sizeof(self.PRIMITIVE_TYPES[name])
-            result['int%d_t' % (8*size)] = size
-            result['uint%d_t' % (8*size)] = size | UNSIGNED
-            if size == ctypes.sizeof(ctypes.c_void_p):
-                result['intptr_t'] = size
-                result['uintptr_t'] = size | UNSIGNED
-                result['ptrdiff_t'] = result['intptr_t']
-            if size == ctypes.sizeof(ctypes.c_size_t):
-                result['size_t'] = size | UNSIGNED
-                result['ssize_t'] = size
-        return result
-
     def load_library(self, path, flags=0):
         cdll = ctypes.CDLL(path, flags)
         return CTypesLibrary(self, cdll)
     return csource.replace('...', ' __dotdotdot__ '), macros
 
 class Parser(object):
+    TYPEDEFS = sorted(
+        [_name for _name in model.PrimitiveType.ALL_PRIMITIVE_TYPES
+               if _name.endswith('_t')])
+
     def __init__(self):
         self._declarations = {}
         self._anonymous_counter = 0
         # internals of CParser...  the following registers the
         # typedefs, because their presence or absence influences the
         # parsing itself (but what they are typedef'ed to plays no role)
-        csourcelines = ['typedef int wchar_t;']
+        typenames = self.TYPEDEFS[:]
         for name in sorted(self._declarations):
             if name.startswith('typedef '):
-                csourcelines.append('typedef int %s;' % (name[8:],))
+                typenames.append(name[8:])
+        csourcelines = ['typedef int %s;' % typename for typename in typenames]
         csourcelines.append('typedef int __dotdotdot__;')
         csource, macros = _preprocess(csource)
         csourcelines.append(csource)
 class PrimitiveType(BaseType):
     _attrs_ = ('name',)
 
+    ALL_PRIMITIVE_TYPES = {
+        'char':               'c',
+        'short':              'i',
+        'int':                'i',
+        'long':               'i',
+        'long long':          'i',
+        'signed char':        'i',
+        'unsigned char':      'u',
+        'unsigned short':     'u',
+        'unsigned int':       'u',
+        'unsigned long':      'u',
+        'unsigned long long': 'u',
+        'float':              'f',
+        'double':             'f',
+        'long double':        'f',
+        'wchar_t':            'c',
+        '_Bool':              'u',
+        # the following types are not primitive in the C sense
+        'int8_t':             'i',
+        'uint8_t':            'u',
+        'int16_t':            'i',
+        'uint16_t':           'u',
+        'int32_t':            'i',
+        'uint32_t':           'u',
+        'int64_t':            'i',
+        'uint64_t':           'u',
+        'intptr_t':           'i',
+        'uintptr_t':          'u',
+        'ptrdiff_t':          'i',
+        'size_t':             'u',
+        'ssize_t':            'i',
+        }
+
     def __init__(self, name):
+        assert name in self.ALL_PRIMITIVE_TYPES
         self.name = name
 
     def _get_c_name(self, replace_with):
         return self.name + replace_with
 
     def is_char_type(self):
-        return self.name in ('char', 'wchar_t')
+        return self.ALL_PRIMITIVE_TYPES[self.name] == 'c'
     def is_signed_type(self):
-        return self.is_integer_type() and not self.is_unsigned_type()
+        return self.ALL_PRIMITIVE_TYPES[self.name] == 'i'
     def is_unsigned_type(self):
-        return self.name.startswith('unsigned ')
+        return self.ALL_PRIMITIVE_TYPES[self.name] == 'u'
     def is_integer_type(self):
-        return not self.is_float_type() and not self.is_char_type()
+        return self.ALL_PRIMITIVE_TYPES[self.name] in 'iu'
     def is_float_type(self):
-        return self.name in ('double', 'float')
+        return self.ALL_PRIMITIVE_TYPES[self.name] == 'f'
 
     def build_backend_type(self, ffi, finishlist):
         return global_cache(self, ffi, 'new_primitive_type', self.name)

cffi/vengine_cpy.py

     def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
         extraarg = ''
         if isinstance(tp, model.PrimitiveType):
-            converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
+            if tp.is_integer_type() and tp.name != '_Bool':
+                if tp.is_signed_type():
+                    converter = '_cffi_to_c_SIGNED'
+                else:
+                    converter = '_cffi_to_c_UNSIGNED'
+                extraarg = ', %s' % tp.name
+            else:
+                converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
             errvalue = '-1'
         #
         elif isinstance(tp, model.PointerType):
 
     def _convert_expr_from_c(self, tp, var):
         if isinstance(tp, model.PrimitiveType):
-            if tp.name != 'long double':
+            if tp.is_integer_type():
+                if tp.is_signed_type():
+                    return '_cffi_from_c_SIGNED(%s, %s)' % (var, tp.name)
+                else:
+                    return '_cffi_from_c_UNSIGNED(%s, %s)' % (var, tp.name)
+            elif tp.name != 'long double':
                 return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var)
             else:
                 return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
 
 #define _cffi_from_c_double PyFloat_FromDouble
 #define _cffi_from_c_float PyFloat_FromDouble
-#define _cffi_from_c_signed_char PyInt_FromLong
-#define _cffi_from_c_short PyInt_FromLong
-#define _cffi_from_c_int PyInt_FromLong
 #define _cffi_from_c_long PyInt_FromLong
-#define _cffi_from_c_unsigned_char PyInt_FromLong
-#define _cffi_from_c_unsigned_short PyInt_FromLong
-#define _cffi_from_c_unsigned_long PyLong_FromUnsignedLong
-#define _cffi_from_c_unsigned_long_long PyLong_FromUnsignedLongLong
-#define _cffi_from_c__Bool PyInt_FromLong
-
-#if SIZEOF_INT < SIZEOF_LONG
-#  define _cffi_from_c_unsigned_int PyInt_FromLong
-#else
-#  define _cffi_from_c_unsigned_int PyLong_FromUnsignedLong
-#endif
-
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
-#  define _cffi_from_c_long_long PyLong_FromLongLong
-#else
-#  define _cffi_from_c_long_long PyInt_FromLong
-#endif
+#define _cffi_from_c_ulong PyLong_FromUnsignedLong
+#define _cffi_from_c_longlong PyLong_FromLongLong
+#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong
 
 #define _cffi_to_c_double PyFloat_AsDouble
 #define _cffi_to_c_float PyFloat_AsDouble
 
+#define _cffi_from_c_SIGNED(x, type)                                     \
+    (sizeof(type) <= sizeof(long) ? PyInt_FromLong(x) :                  \
+                                    PyLong_FromLongLong(x))
+#define _cffi_from_c_UNSIGNED(x, type)                                   \
+    (sizeof(type) < sizeof(long) ? PyInt_FromLong(x) :                   \
+     sizeof(type) == sizeof(long) ? PyLong_FromUnsignedLong(x) :         \
+                                    PyLong_FromUnsignedLongLong(x))
+
+#define _cffi_to_c_SIGNED(o, type)                                       \
+    (sizeof(type) == 1 ? _cffi_to_c_i8(o) :                              \
+     sizeof(type) == 2 ? _cffi_to_c_i16(o) :                             \
+     sizeof(type) == 4 ? _cffi_to_c_i32(o) :                             \
+     sizeof(type) == 8 ? _cffi_to_c_i64(o) :                             \
+     (Py_FatalError("unsupported size for type " #type), 0))
+#define _cffi_to_c_UNSIGNED(o, type)                                     \
+    (sizeof(type) == 1 ? _cffi_to_c_u8(o) :                              \
+     sizeof(type) == 2 ? _cffi_to_c_u16(o) :                             \
+     sizeof(type) == 4 ? _cffi_to_c_u32(o) :                             \
+     sizeof(type) == 8 ? _cffi_to_c_u64(o) :                             \
+     (Py_FatalError("unsupported size for type " #type), 0))
+
 #define _cffi_to_c_char_p                                                \
                  ((char *(*)(PyObject *))_cffi_exports[0])
-#define _cffi_to_c_signed_char                                           \
-                 ((signed char(*)(PyObject *))_cffi_exports[1])
-#define _cffi_to_c_unsigned_char                                         \
-                 ((unsigned char(*)(PyObject *))_cffi_exports[2])
-#define _cffi_to_c_short                                                 \
-                 ((short(*)(PyObject *))_cffi_exports[3])
-#define _cffi_to_c_unsigned_short                                        \
-                 ((unsigned short(*)(PyObject *))_cffi_exports[4])
-#define _cffi_to_c_int                                                   \
+#define _cffi_to_c_i8                                                    \
+                 ((int(*)(PyObject *))_cffi_exports[1])
+#define _cffi_to_c_u8                                                    \
+                 ((int(*)(PyObject *))_cffi_exports[2])
+#define _cffi_to_c_i16                                                   \
+                 ((int(*)(PyObject *))_cffi_exports[3])
+#define _cffi_to_c_u16                                                   \
+                 ((int(*)(PyObject *))_cffi_exports[4])
+#define _cffi_to_c_i32                                                   \
                  ((int(*)(PyObject *))_cffi_exports[5])
-#define _cffi_to_c_unsigned_int                                          \
+#define _cffi_to_c_u32                                                   \
                  ((unsigned int(*)(PyObject *))_cffi_exports[6])
-#define _cffi_to_c_long                                                  \
-                 ((long(*)(PyObject *))_cffi_exports[7])
-#define _cffi_to_c_unsigned_long                                         \
-                 ((unsigned long(*)(PyObject *))_cffi_exports[8])
+#define _cffi_to_c_i64                                                   \
+                 ((long long(*)(PyObject *))_cffi_exports[7])
+#define _cffi_to_c_u64                                                   \
+                 ((unsigned long long(*)(PyObject *))_cffi_exports[8])
 #define _cffi_to_c_char                                                  \
                  ((char(*)(PyObject *))_cffi_exports[9])
 #define _cffi_from_c_pointer                                             \
     ((long double(*)(PyObject *))_cffi_exports[21])
 #define _cffi_to_c__Bool                                                 \
     ((_Bool(*)(PyObject *))_cffi_exports[22])
-#define _cffi_to_c_long_long                                             \
-                 ((long long(*)(PyObject *))_cffi_exports[23])
-#define _cffi_to_c_unsigned_long_long                                    \
-                 ((unsigned long long(*)(PyObject *))_cffi_exports[24])
-#define _CFFI_NUM_EXPORTS 25
+#define _CFFI_NUM_EXPORTS 23
 
 typedef struct _ctypedescr CTypeDescrObject;
 

doc/source/index.rst

    ``static char *const FOO;``).
 
 Currently, finding automatically the size of an integer type is not
-supported.  You need to declare them with ``typedef int myint;`` or
-``typedef long myint;`` or ``typedef long long myint;`` or their
-unsigned equivalent.  Depending on the usage, the C compiler might give
-warnings if you misdeclare ``myint`` as the wrong type even if it is
-equivalent on this platform (e.g. using ``long`` instead of ``long
-long`` or vice-versa on 64-bit Linux).
+supported.  You need to declare them with ``typedef EXACTTYPE myint;``.
+The ``EXACTTYPE`` might be a built-in C type like ``int`` or ``unsigned
+long long``, or one of the standard integer types like ``size_t`` (see
+the complete list above__).
+
+.. __: `Declaring types and functions`_
 
 Note that ``verify()`` is meant to call C libraries that are *not* using
 ``#include <Python.h>``.  The C functions are called without the GIL,

testing/test_verify.py

             py.test.skip("don't know the very exact precision of 'long double'")
 
 
-all_integer_types = ['short', 'int', 'long', 'long long',
-                     'signed char', 'unsigned char',
-                     'unsigned short', 'unsigned int',
-                     'unsigned long', 'unsigned long long']
-all_signed_integer_types = [_typename for _typename in all_integer_types
-                                      if not _typename.startswith('unsigned ')]
-all_unsigned_integer_types = [_typename for _typename in all_integer_types
-                                        if _typename.startswith('unsigned ')]
-all_float_types = ['float', 'double']
+all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES
+all_signed_integer_types = sorted(tp for tp in all_primitive_types
+                                     if all_primitive_types[tp] == 'i')
+all_unsigned_integer_types = sorted(tp for tp in all_primitive_types
+                                       if all_primitive_types[tp] == 'u')
+all_float_types = sorted(tp for tp in all_primitive_types
+                            if all_primitive_types[tp] == 'f')
 
 def test_primitive_category():
-    for typename in all_integer_types + all_float_types + ['char', 'wchar_t']:
+    for typename in all_primitive_types:
         tp = model.PrimitiveType(typename)
-        assert tp.is_char_type() == (typename in ('char', 'wchar_t'))
-        assert tp.is_signed_type() == (typename in all_signed_integer_types)
-        assert tp.is_unsigned_type()== (typename in all_unsigned_integer_types)
-        assert tp.is_integer_type() == (typename in all_integer_types)
-        assert tp.is_float_type() == (typename in all_float_types)
+        C = tp.is_char_type()
+        U = tp.is_unsigned_type()
+        S = tp.is_signed_type()
+        F = tp.is_float_type()
+        I = tp.is_integer_type()
+        assert C == (typename in ('char', 'wchar_t'))
+        assert U == (typename.startswith('unsigned ') or
+                     typename == '_Bool' or typename == 'size_t' or
+                     typename == 'uintptr_t' or typename.startswith('uint'))
+        assert F == (typename in ('float', 'double', 'long double'))
+        assert S + U + F + C == 1      # one and only one of them is true
+        assert I == (S or U)
 
 def test_all_integer_and_float_types():
-    for typename in all_integer_types + all_float_types:
-        ffi = FFI()
-        ffi.cdef("%s foo(%s);" % (typename, typename))
-        lib = ffi.verify("%s foo(%s x) { return x+1; }" % (typename, typename))
-        assert lib.foo(42) == 43
+    typenames = []
+    for typename in all_primitive_types:
+        if (all_primitive_types[typename] == 'c' or
+            typename == '_Bool' or typename == 'long double'):
+            pass
+        else:
+            typenames.append(typename)
+    #
+    ffi = FFI()
+    ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
+                       for tp in typenames]))
+    lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return x+1; }" %
+                                (tp, tp.replace(' ', '_'), tp)
+                                for tp in typenames]))
+    for typename in typenames:
+        foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
+        assert foo(42) == 43
         if sys.version < '3':
-            assert lib.foo(long(44)) == 45
-        assert lib.foo(ffi.cast(typename, 46)) == 47
-        py.test.raises(TypeError, lib.foo, ffi.NULL)
+            assert foo(long(44)) == 45
+        assert foo(ffi.cast(typename, 46)) == 47
+        py.test.raises(TypeError, foo, ffi.NULL)
         #
         # check for overflow cases
-        if typename in all_float_types:
+        if all_primitive_types[typename] == 'f':
             continue
         for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
                       2**5, 2**10, 2**20, 2**40, 2**80]:
             overflows = int(ffi.cast(typename, value)) != value
             if overflows:
-                py.test.raises(OverflowError, lib.foo, value)
+                py.test.raises(OverflowError, foo, value)
             else:
-                assert lib.foo(value) == value + 1
+                assert foo(value) == value + 1
 
-def test_nonstandard_integer_types():
+def test_var_signed_integer_types():
     ffi = FFI()
-    lst = ffi._backend.nonstandard_integer_types().items()
-    lst = sorted(lst)
-    verify_lines = []
-    for key, value in lst:
-        ffi.cdef("static const int expected_%s;" % key)
-        verify_lines.append("static const int expected_%s =" % key)
-        verify_lines.append("    sizeof(%s) | (((%s)-1) <= 0 ? 0 : 0x1000);"
-                            % (key, key))
-    lib = ffi.verify('\n'.join(verify_lines))
-    for key, value in lst:
-        assert getattr(lib, 'expected_%s' % key) == value
+    lst = all_signed_integer_types
+    csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
+                         for tp in lst])
+    ffi.cdef(csource)
+    lib = ffi.verify(csource)
+    for tp in lst:
+        varname = 'somevar_%s' % tp.replace(' ', '_')
+        sz = ffi.sizeof(tp)
+        max = (1 << (8*sz-1)) - 1
+        min = -(1 << (8*sz-1))
+        setattr(lib, varname, max)
+        assert getattr(lib, varname) == max
+        setattr(lib, varname, min)
+        assert getattr(lib, varname) == min
+        py.test.raises(OverflowError, setattr, lib, varname, max+1)
+        py.test.raises(OverflowError, setattr, lib, varname, min-1)
+
+def test_var_unsigned_integer_types():
+    ffi = FFI()
+    lst = all_unsigned_integer_types
+    csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
+                         for tp in lst])
+    ffi.cdef(csource)
+    lib = ffi.verify(csource)
+    for tp in lst:
+        varname = 'somevar_%s' % tp.replace(' ', '_')
+        sz = ffi.sizeof(tp)
+        if tp != '_Bool':
+            max = (1 << (8*sz)) - 1
+        else:
+            max = 1
+        setattr(lib, varname, max)
+        assert getattr(lib, varname) == max
+        setattr(lib, varname, 0)
+        assert getattr(lib, varname) == 0
+        py.test.raises(OverflowError, setattr, lib, varname, max+1)
+        py.test.raises(OverflowError, setattr, lib, varname, -1)
+
+def test_fn_signed_integer_types():
+    ffi = FFI()
+    lst = all_signed_integer_types
+    cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
+                         for tp in lst])
+    ffi.cdef(cdefsrc)
+    verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
+                           (tp, tp.replace(' ', '_'), tp) for tp in lst])
+    lib = ffi.verify(verifysrc)
+    for tp in lst:
+        fnname = 'somefn_%s' % tp.replace(' ', '_')
+        sz = ffi.sizeof(tp)
+        max = (1 << (8*sz-1)) - 1
+        min = -(1 << (8*sz-1))
+        fn = getattr(lib, fnname)
+        assert fn(max) == max
+        assert fn(min) == min
+        py.test.raises(OverflowError, fn, max + 1)
+        py.test.raises(OverflowError, fn, min - 1)
+
+def test_fn_unsigned_integer_types():
+    ffi = FFI()
+    lst = all_unsigned_integer_types
+    cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
+                         for tp in lst])
+    ffi.cdef(cdefsrc)
+    verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
+                           (tp, tp.replace(' ', '_'), tp) for tp in lst])
+    lib = ffi.verify(verifysrc)
+    for tp in lst:
+        fnname = 'somefn_%s' % tp.replace(' ', '_')
+        sz = ffi.sizeof(tp)
+        if tp != '_Bool':
+            max = (1 << (8*sz)) - 1
+        else:
+            max = 1
+        fn = getattr(lib, fnname)
+        assert fn(max) == max
+        assert fn(0) == 0
+        py.test.raises(OverflowError, fn, max + 1)
+        py.test.raises(OverflowError, fn, -1)
 
 def test_char_type():
     ffi = FFI()
                                  "%s != %s" % (typename, real))
 
 def test_struct_bad_sized_integer():
-    for typename in all_signed_integer_types:
-        for real in all_signed_integer_types:
+    for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
+        for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
             _check_field_match(typename, real, "by_size")
 
 def test_struct_bad_sized_float():
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.