Author: Antonio Cuni <[email protected]>
Branch: fast_cffi_list_init
Changeset: r67293:b25eb074c18b
Date: 2013-10-10 15:55 +0200
http://bitbucket.org/pypy/pypy/changeset/b25eb074c18b/

Log:    add a fast path to convert a cffi long[] array to a list

diff --git a/pypy/module/_cffi_backend/cdataobj.py 
b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -282,6 +282,9 @@
     def iter(self):
         return self.ctype.iter(self)
 
+    def unpackiterable_int(self, space):
+        return self.ctype.unpackiterable_int(self)
+
     @specialize.argtype(1)
     def write_raw_signed_data(self, source):
         misc.write_raw_signed_data(self._cdata, source, self.ctype.size)
diff --git a/pypy/module/_cffi_backend/ctypearray.py 
b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -105,6 +105,16 @@
     def iter(self, cdata):
         return W_CDataIter(self.space, self.ctitem, cdata)
 
+    def unpackiterable_int(self, cdata):
+        from rpython.rlib.rarray import populate_list_from_raw_array
+        if self.ctitem.is_long():
+            res = []
+            buf = rffi.cast(rffi.LONGP, cdata._cdata)
+            length = cdata.get_array_length()
+            populate_list_from_raw_array(res, buf, length)
+            return res
+        return None
+
     def get_vararg_type(self):
         return self.ctptr
 
diff --git a/pypy/module/_cffi_backend/ctypeobj.py 
b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -163,6 +163,9 @@
                               "cdata '%s' does not support iteration",
                               self.name)
 
+    def unpackiterable_int(self, cdata):
+        return None
+
     def get_vararg_type(self):
         return self
 
diff --git a/pypy/module/_cffi_backend/test/test_extra.py 
b/pypy/module/_cffi_backend/test/test_extra.py
--- a/pypy/module/_cffi_backend/test/test_extra.py
+++ b/pypy/module/_cffi_backend/test/test_extra.py
@@ -2,7 +2,7 @@
 from pypy.module._cffi_backend import misc
 from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
 
-class AppTestFastPath(object):
+class AppTest_fast_path_from_list(object):
     spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO'))
 
     def setup_method(self, meth):
@@ -34,3 +34,40 @@
         assert buf[1] == 2.2
         assert buf[2] == 3.3
 
+
+class AppTest_fast_path_to_list(object):
+    spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO'))
+
+    def setup_method(self, meth):
+        from pypy.interpreter import gateway
+        from rpython.rlib import rarray
+        #
+        self.count = 0
+        def get_count(*args):
+            return self.space.wrap(self.count)
+        self.w_get_count = self.space.wrap(gateway.interp2app(get_count))
+        #
+        original = rarray.populate_list_from_raw_array
+        def populate_list_from_raw_array(*args):
+            self.count += 1
+            return original(*args)
+        self._original = original
+        rarray.populate_list_from_raw_array = populate_list_from_raw_array
+
+
+    def teardown_method(self, meth):
+        from rpython.rlib import rarray
+        rarray.populate_list_from_raw_array = self._original
+
+    def test_list_int(self):
+        import _cffi_backend
+        LONG = _cffi_backend.new_primitive_type('long')
+        P_LONG = _cffi_backend.new_pointer_type(LONG)
+        LONG_ARRAY = _cffi_backend.new_array_type(P_LONG, 3)
+        buf = _cffi_backend.newp(LONG_ARRAY)
+        buf[0] = 1
+        buf[1] = 2
+        buf[2] = 3
+        lst = list(buf)
+        assert lst == [1, 2, 3]
+        assert self.get_count() == 1
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -950,6 +950,8 @@
             return
 
         intlist = space.listview_int(w_iterable)
+        if intlist is None:
+            intlist = space.unpackiterable_int(w_iterable)
         if intlist is not None:
             w_list.strategy = strategy = space.fromcache(IntegerListStrategy)
             # need to copy because intlist can share with w_iterable
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to