Author: Armin Rigo <ar...@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] + + +@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' _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit