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