[pypy-commit] pypy ffi-backend: Test and implementation of ffi.buffer().
arigo
noreply at buildbot.pypy.org
Sat Jul 7 14:27:41 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r55965:8c71371063a6
Date: 2012-07-07 14:27 +0200
http://bitbucket.org/pypy/pypy/changeset/8c71371063a6/
Log: Test and implementation of ffi.buffer().
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -27,4 +27,5 @@
'typeof': 'func.typeof',
'offsetof': 'func.offsetof',
'_getfields': 'func._getfields',
+ 'buffer': 'cbuffer.buffer',
}
diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -0,0 +1,49 @@
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.buffer import RWBuffer
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.rpython.lltypesystem import rffi
+from pypy.module._cffi_backend import cdataobj, ctypeptr
+
+
+class LLBuffer(RWBuffer):
+
+ def __init__(self, raw_cdata, size):
+ self.raw_cdata = raw_cdata
+ self.size = size
+
+ def getlength(self):
+ return self.size
+
+ def getitem(self, index):
+ return self.raw_cdata[index]
+
+ def setitem(self, index, char):
+ self.raw_cdata[index] = char
+
+ def get_raw_address(self):
+ return self.raw_cdata
+
+ def getslice(self, start, stop, step, size):
+ if step == 1:
+ return rffi.charpsize2str(rffi.ptradd(self.raw_cdata, start), size)
+ return RWBuffer.getslice(self, start, stop, step, size)
+
+ def setslice(self, start, string):
+ raw_cdata = rffi.ptradd(self.raw_cdata, start)
+ for i in range(len(string)):
+ raw_cdata[i] = string[i]
+
+
+ at unwrap_spec(cdata=cdataobj.W_CData, size=int)
+def buffer(space, cdata, size=-1):
+ if not isinstance(cdata.ctype, ctypeptr.W_CTypePtrOrArray):
+ raise operationerrfmt(space.w_TypeError,
+ "expected a pointer or array cdata, got '%s'",
+ cdata.ctype.name)
+ if size < 0:
+ size = cdata._sizeof()
+ if size < 0:
+ raise operationerrfmt(space.w_TypeError,
+ "don't know the size pointed to by '%s'",
+ cdata.ctype.name)
+ return space.wrap(LLBuffer(cdata._cdata, size))
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
@@ -208,6 +208,9 @@
assert length >= 0
return length
+ def _sizeof(self):
+ return self.ctype.size
+
class W_CDataApplevelOwning(W_CData):
"""This is the abstract base class for classes that are of the app-level
@@ -247,12 +250,15 @@
W_CDataNewOwning.__init__(self, space, size, ctype)
self.length = length
- def _owning_num_bytes(self):
+ def _sizeof(self):
from pypy.module._cffi_backend import ctypearray
ctype = self.ctype
assert isinstance(ctype, ctypearray.W_CTypeArray)
return self.length * ctype.ctitem.size
+ def _owning_num_bytes(self):
+ return self._sizeof()
+
def get_array_length(self):
return self.length
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -36,10 +36,7 @@
def sizeof(space, w_obj):
ob = space.interpclass_w(w_obj)
if isinstance(ob, cdataobj.W_CData):
- if isinstance(ob, cdataobj.W_CDataNewOwningLength):
- size = ob._owning_num_bytes()
- else:
- size = ob.ctype.size
+ size = ob._sizeof()
elif isinstance(ob, ctypeobj.W_CType):
size = ob.size
if size < 0:
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1346,3 +1346,24 @@
assert (p < s) is (p <= s) is (s > p) is (s >= p)
assert (p > s) is (p >= s) is (s < p) is (s <= p)
assert (p < s) ^ (p > s)
+
+def test_buffer():
+ BChar = new_primitive_type("char")
+ BCharArray = new_array_type(new_pointer_type(BChar), None)
+ c = newp(BCharArray, "hi there")
+ buf = buffer(c)
+ assert str(buf) == "hi there\x00"
+ assert len(buf) == len("hi there\x00")
+ assert buf[0] == 'h'
+ assert buf[2] == ' '
+ assert list(buf) == ['h', 'i', ' ', 't', 'h', 'e', 'r', 'e', '\x00']
+ buf[2] = '-'
+ assert c[2] == '-'
+ assert str(buf) == "hi-there\x00"
+ buf[:2] = 'HI'
+ assert str(c) == 'HI-there'
+ assert buf[:4:2] == 'H-'
+ if '__pypy__' not in sys.builtin_module_names:
+ # XXX pypy doesn't support the following assignment so far
+ buf[:4:2] = 'XY'
+ assert str(c) == 'XIYthere'
More information about the pypy-commit
mailing list