Commits

Armin Rigo committed 1feeb5b

char.

Comments (0)

Files changed (2)

ffi/backend_ctypes.py

 class CTypesData(object):
 
     @staticmethod
-    def _import(value):
+    def _to_ctypes(value):
         raise TypeError
 
     @staticmethod
-    def _export(ctypes_value):
+    def _from_ctypes(ctypes_value):
         raise TypeError
 
     @classmethod
 class CTypesBackend(BackendBase):
 
     PRIMITIVE_TYPES = {
+        'char': ctypes.c_char,
         'short': ctypes.c_short,
         'int': ctypes.c_int,
         'long': ctypes.c_long,
         return CTypesLibrary(cdll)
 
     def new_primitive_type(self, name):
-        # XXX integer types only
         ctype = self.PRIMITIVE_TYPES[name]
-        is_signed = (ctype(-1).value == -1)
+        if name == 'char':
+            pass
+        else:
+            # integer types
+            is_signed = (ctype(-1).value == -1)
         #
         class CTypesInt(CTypesData):
             _ctype = ctype
 
             def __init__(self, value):
                 if value is None:
-                    value = 0
+                    if name == 'char':
+                        value = '\x00'
+                    else:
+                        value = 0
                 elif ctype(value).value != value:
                     raise OverflowError("%r out of range: %d" %
                                         (name, value))
                 self._value = value
 
             def __int__(self):
+                if name == 'char':
+                    return ord(self._value)
                 return self._value
 
-            def __nonzero__(self):   return self._value
-            def __lt__(self, other): return self._value <  other
-            def __le__(self, other): return self._value <= other
+            __nonzero__ = __int__
+
             def __eq__(self, other): return self._value == other
             def __ne__(self, other): return self._value != other
-            def __gt__(self, other): return self._value >  other
-            def __ge__(self, other): return self._value >= other
             def __hash__(self):      return hash(self._value)
+            def __lt__(self, other): raise TypeError("unorderable type")
+            def __le__(self, other): raise TypeError("unorderable type")
+            def __gt__(self, other): raise TypeError("unorderable type")
+            def __ge__(self, other): raise TypeError("unorderable type")
 
             @staticmethod
-            def _import(x):
+            def _to_ctypes(x):
+                if name == 'char':
+                    if isinstance(x, str) and len(x) == 1:
+                        return x
+                    if isinstance(x, CTypesInt):    # <CData <char>>
+                        return x._value
+                    raise TypeError("character expected, got %s" %
+                                    type(x).__name__)
+                #
                 if not isinstance(x, (int, long)):
                     if isinstance(x, CTypesData):
                         x = int(x)
                     else:
                         raise OverflowError("%s: integer out of bounds" % name)
                 return x
-            _export = staticmethod(_identity)
+            _from_ctypes = staticmethod(_identity)
         #
         CTypesInt._fix_class()
         return CTypesInt
                             self._address == other._address)
 
             def __getitem__(self, index):
-                return BItem._export(self._as_ctype_ptr[index])
+                return BItem._from_ctypes(self._as_ctype_ptr[index])
 
             def __setitem__(self, index, value):
-                self._as_ctype_ptr[index] = BItem._import(value)
+                self._as_ctype_ptr[index] = BItem._to_ctypes(value)
 
             @staticmethod
-            def _import(value):
+            def _to_ctypes(value):
                 return ctypes.cast(value._convert_to_address_of(BItem),
                                    CTypesPtr._ctype)
 
             @staticmethod
-            def _export(ctypes_ptr):
+            def _from_ctypes(ctypes_ptr):
                 self = CTypesPtr.__new__(CTypesPtr)
                 self._address = ctypes.addressof(ctypes_ptr.contents)
                 self._as_ctype_ptr = ctypes_ptr
                     for i, value in enumerate(init):
                         self[i] = value
 
+            def __len__(self):
+                return len(self._blob)
+
             def __getitem__(self, index):
                 if not (0 <= index < len(self._blob)):
                     raise IndexError
-                return BItem._export(self._blob[index])
+                return BItem._from_ctypes(self._blob[index])
 
             def __setitem__(self, index, value):
                 if not (0 <= index < len(self._blob)):
                     raise IndexError
-                self._blob[index] = BItem._import(value)
+                self._blob[index] = BItem._to_ctypes(value)
 
             def _convert_to_address_of(self, BClass):
                 if BItem is BClass:
                     return CTypesData._convert_to_address_of(self, BClass)
 
             @staticmethod
-            def _export(ctypes_array):
+            def _from_ctypes(ctypes_array):
                 self = CTypesArray.__new__(CTypesArray)
                 self._blob = ctypes_array
                 return self

testing/backend_tests.py

         assert not bool(ffi.new("short", 0))
         assert n != ffi.new("short", 123)
         assert hash(n) == hash(-123)
-        assert n < -122
-        assert n <= -123
-        assert n > -124
-        assert n >= -123
-        assert not (n < -123)
-        assert not (n <= -124)
-        assert not (n > -123)
-        assert not (n >= -122)
+        assert int(n) == -123 and type(int(n)) is int
+        py.test.raises(TypeError, "n < -122")
+        py.test.raises(TypeError, "n <= -123")
+        py.test.raises(TypeError, "n > -124")
+        py.test.raises(TypeError, "n >= -123")
+        py.test.raises(TypeError, "n >= n")
 
     def test_new_array_no_arg(self):
         ffi = FFI(backend=self.Backend())
         a = p[3]
         assert repr(a) == "<cdata 'int *'>"
         assert a[0] == 99
+
+    def test_char(self):
+        ffi = FFI(backend=self.Backend())
+        assert int(ffi.new("char", "\xff")) == 0xFF
+        assert int(ffi.new("char")) == 0
+        assert bool(ffi.new("char", "\x80"))
+        assert not bool(ffi.new("char"))
+        py.test.raises(TypeError, ffi.new, "char", 32)
+        p = ffi.new("char[]", ['a', 'b', '\x9c'])
+        assert len(p) == 3
+        assert p[0] == 'a'
+        assert p[1] == 'b'
+        assert p[2] == '\x9c'
+        p[0] = '\xff'
+        assert p[0] == '\xff'
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.