Author: Armin Rigo <[email protected]>
Branch: ffi-backend
Changeset: r55757:f49e20cfb0b1
Date: 2012-06-22 19:02 +0200
http://bitbucket.org/pypy/pypy/changeset/f49e20cfb0b1/

Log:    (arigo, fijal around) General progress.

diff --git a/pypy/module/_ffi_backend/cdataobj.py 
b/pypy/module/_ffi_backend/cdataobj.py
--- a/pypy/module/_ffi_backend/cdataobj.py
+++ b/pypy/module/_ffi_backend/cdataobj.py
@@ -1,10 +1,11 @@
+import operator
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.objectmodel import keepalive_until_here
-from pypy.rlib import rgc
+from pypy.rlib.objectmodel import keepalive_until_here, specialize
+from pypy.rlib import objectmodel, rgc
 
 from pypy.module._ffi_backend import misc
 
@@ -18,7 +19,7 @@
         assert lltype.typeOf(cdata) == rffi.CCHARP
         assert isinstance(ctype, ctypeobj.W_CType)
         self.space = space
-        self.cdata = cdata
+        self._cdata = cdata    # don't forget keepalive_until_here!
         self.ctype = ctype
 
     def repr(self):
@@ -29,10 +30,10 @@
         return ''
 
     def nonzero(self):
-        return self.space.wrap(bool(self.cdata))
+        return self.space.wrap(bool(self._cdata))
 
     def int(self):
-        w_result = self.ctype.int(self.cdata)
+        w_result = self.ctype.int(self._cdata)
         keepalive_until_here(self)
         return w_result
 
@@ -44,40 +45,71 @@
         return w_result
 
     def float(self):
-        w_result = self.ctype.float(self.cdata)
+        w_result = self.ctype.float(self._cdata)
         keepalive_until_here(self)
         return w_result
 
     def str(self):
-        w_result = self.ctype.try_str(self.cdata)
+        w_result = self.ctype.try_str(self._cdata)
         keepalive_until_here(self)
         return w_result or self.repr()
 
+    @specialize.arg(2)
+    def _cmp(self, w_other, cmp):
+        space = self.space
+        cdata1 = self._cdata
+        other = space.interpclass_w(w_other)
+        if isinstance(other, W_CData):
+            cdata2 = other._cdata
+        elif space.is_w(w_other, space.w_None):
+            cdata2 = lltype.nullptr(rffi.CCHARP.TO)
+        else:
+            return space.w_NotImplemented
+        return space.newbool(cmp(cdata1, cdata2))
+
+    def eq(self, w_other): return self._cmp(w_other, operator.eq)
+    def ne(self, w_other): return self._cmp(w_other, operator.ne)
+
+    def hash(self):
+        h = (objectmodel.compute_identity_hash(self.ctype) ^
+             rffi.cast(lltype.Signed, self._cdata))
+        return self.space.wrap(h)
+
+    def getitem(self, w_index):
+        from pypy.module._ffi_backend import ctypeobj
+        space = self.space
+        i = space.getindex_w(w_index, space.w_IndexError)
+        self.ctype._check_subscript_index(self, i)
+        citem = self.ctype.ctypeitem
+        w_o = citem.convert_to_object(rffi.ptradd(self._cdata, i * citem.size))
+        keepalive_until_here(self)
+        return w_o
+
     def read_raw_signed_data(self):
-        result = misc.read_raw_signed_data(self.cdata, self.ctype.size)
+        result = misc.read_raw_signed_data(self._cdata, self.ctype.size)
         keepalive_until_here(self)
         return result
 
     def read_raw_unsigned_data(self):
-        result = misc.read_raw_unsigned_data(self.cdata, self.ctype.size)
+        result = misc.read_raw_unsigned_data(self._cdata, self.ctype.size)
         keepalive_until_here(self)
         return result
 
     def write_raw_integer_data(self, source):
-        misc.write_raw_integer_data(self.cdata, source, self.ctype.size)
+        misc.write_raw_integer_data(self._cdata, source, self.ctype.size)
         keepalive_until_here(self)
 
     def read_raw_float_data(self):
-        result = misc.read_raw_float_data(self.cdata, self.ctype.size)
+        result = misc.read_raw_float_data(self._cdata, self.ctype.size)
         keepalive_until_here(self)
         return result
 
     def write_raw_float_data(self, source):
-        misc.write_raw_float_data(self.cdata, source, self.ctype.size)
+        misc.write_raw_float_data(self._cdata, source, self.ctype.size)
         keepalive_until_here(self)
 
     def convert_to_object(self):
-        w_obj = self.ctype.convert_to_object(self.cdata)
+        w_obj = self.ctype.convert_to_object(self._cdata)
         keepalive_until_here(self)
         return w_obj
 
@@ -90,7 +122,7 @@
 
     @rgc.must_be_light_finalizer
     def __del__(self):
-        lltype.free(self.cdata, flavor='raw')
+        lltype.free(self._cdata, flavor='raw')
 
 
 class W_CDataOwn(W_CDataOwnFromCasted):
@@ -108,9 +140,9 @@
     __long__ = interp2app(W_CData.long),
     __float__ = interp2app(W_CData.float),
     __str__ = interp2app(W_CData.str),
+    __eq__ = interp2app(W_CData.eq),
+    __ne__ = interp2app(W_CData.ne),
+    __hash__ = interp2app(W_CData.hash),
+    __getitem__ = interp2app(W_CData.getitem),
     )
 W_CData.acceptable_as_base_class = False
-
-
-def check_cdata(space, w_obj):
-    return space.is_w(space.type(w_obj), space.gettypefor(W_CData))
diff --git a/pypy/module/_ffi_backend/ctypeobj.py 
b/pypy/module/_ffi_backend/ctypeobj.py
--- a/pypy/module/_ffi_backend/ctypeobj.py
+++ b/pypy/module/_ffi_backend/ctypeobj.py
@@ -4,6 +4,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.objectmodel import keepalive_until_here
 
 from pypy.module._ffi_backend import cdataobj, misc
 
@@ -44,6 +45,13 @@
     def convert_to_object(self, cdata):
         raise NotImplementedError
 
+    def convert_from_object(self, cdata, w_ob):
+        raise NotImplementedError
+
+    def _check_subscript_index(self, w_cdata, i):
+        space = self.space
+        raise OperationError(xxx)
+
     def try_str(self, cdata):
         return None
 
@@ -55,7 +63,11 @@
         return name, name_position
 
 
-class W_CTypePointer(W_CType):
+class W_CTypePtrOrArray(W_CType):
+    pass
+
+
+class W_CTypePointer(W_CTypePtrOrArray):
 
     def __init__(self, space, ctypeitem):
         name, name_position = ctypeitem.insert_name(' *', 2)
@@ -64,7 +76,18 @@
         self.ctypeitem = ctypeitem
 
     def cast(self, w_ob):
-        xxx
+        space = self.space
+        ob = space.interpclass_w(w_ob)
+        if (isinstance(ob, cdataobj.W_CData) and
+                isinstance(ob.ctype, W_CTypePtrOrArray)):
+            value = ob._cdata
+        elif space.is_w(w_ob, space.w_None):
+            value = lltype.nullptr(rffi.CCHARP.TO)
+        else:
+            xxx
+            value = misc.as_unsigned_long_long(space, w_ob, strict=False)
+            value = rffi.cast(rffi.CCHARP, value)
+        return cdataobj.W_CData(space, value, self)
 
     def newp(self, w_init):
         space = self.space
@@ -73,8 +96,18 @@
             xxx
         if isinstance(citem, W_CTypePrimitiveChar):
             xxx
-        w_cdata = cdataobj.W_CDataOwn(space, citem.size, self)
-        return w_cdata
+        cdata = cdataobj.W_CDataOwn(space, citem.size, self)
+        if not space.is_w(w_init, space.w_None):
+            citem.convert_from_object(cdata._cdata, w_init)
+            keepalive_until_here(cdata)
+        return cdata
+
+    def _check_subscript_index(self, w_cdata, i):
+        if isinstance(w_cdata, cdataobj.W_CDataOwn) and i != 0:
+            space = self.space
+            raise operationerrfmt(space.w_IndexError,
+                                  "cdata '%s' can only be indexed by 0",
+                                  self.name)
 
 
 class W_CTypePrimitive(W_CType):
@@ -90,7 +123,8 @@
 
     def cast(self, w_ob):
         space = self.space
-        if cdataobj.check_cdata(space, w_ob):
+        ob = space.interpclass_w(w_ob)
+        if isinstance(ob, cdataobj.W_CData):
             xxx
         elif space.isinstance_w(w_ob, space.w_str):
             value = self.cast_single_char(w_ob)
@@ -135,6 +169,12 @@
         else:
             return self.space.wrap(value)    # r_longlong => on 32-bit, 'long'
 
+    def convert_from_object(self, cdata, w_ob):
+        value = misc.as_long_long(self.space, w_ob)
+        # xxx enums
+        misc.write_raw_integer_data(cdata, value, self.size)
+        # xxx overflow
+
 
 class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
 
@@ -157,7 +197,8 @@
 
     def cast(self, w_ob):
         space = self.space
-        if cdataobj.check_cdata(space, w_ob):
+        ob = space.interpclass_w(w_ob)
+        if isinstance(ob, cdataobj.W_CData):
             xxx
         elif space.isinstance_w(w_ob, space.w_str):
             value = self.cast_single_char(w_ob)
@@ -186,7 +227,3 @@
     __repr__ = interp2app(W_CType.repr),
     )
 W_CType.acceptable_as_base_class = False
-
-
-def check_ctype(space, w_obj):
-    return space.is_w(space.type(w_obj), space.gettypefor(W_CType))
diff --git a/pypy/module/_ffi_backend/func.py b/pypy/module/_ffi_backend/func.py
--- a/pypy/module/_ffi_backend/func.py
+++ b/pypy/module/_ffi_backend/func.py
@@ -21,13 +21,12 @@
 # ____________________________________________________________
 
 def sizeof(space, w_obj):
-    if cdataobj.check_cdata(space, w_obj):
+    ob = space.interpclass_w(w_obj)
+    if isinstance(ob, cdataobj.W_CData):
         # xxx CT_ARRAY
-        w_cdata = space.interp_w(cdataobj.W_CData, w_obj)
-        size = w_cdata.ctype.size
-    elif ctypeobj.check_ctype(space, w_obj):
-        w_ctype = space.interp_w(ctypeobj.W_CType, w_obj)
-        size = w_ctype.size
+        size = ob.ctype.size
+    elif isinstance(ob, ctypeobj.W_CType):
+        size = ob.size
         if size < 0:
             raise operationerrfmt(space.w_ValueError,
                                   "ctype '%s' is of unknown size",
diff --git a/pypy/module/_ffi_backend/misc.py b/pypy/module/_ffi_backend/misc.py
--- a/pypy/module/_ffi_backend/misc.py
+++ b/pypy/module/_ffi_backend/misc.py
@@ -86,7 +86,7 @@
 
 # ____________________________________________________________
 
-def as_long_long(space, w_ob, strict):
+def as_long_long(space, w_ob):
     # (possibly) convert and cast a Python object to a long long.
     # This version accepts a Python int too, and does convertions from
     # other types of objects.  It refuses floats.
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to