Author: Philip Jenvey <[email protected]>
Branch: py3k
Changeset: r83695:3bc87fc47479
Date: 2016-04-15 16:10 -0700
http://bitbucket.org/pypy/pypy/changeset/3bc87fc47479/
Log: merge default
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
@@ -48,6 +48,7 @@
'from_buffer': 'func.from_buffer',
'string': 'func.string',
+ 'rawstring': 'func.rawstring',
'buffer': 'cbuffer.buffer',
'memmove': 'func.memmove',
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
@@ -7,11 +7,12 @@
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef
-from rpython.rtyper.lltypesystem import rffi
+from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.rarithmetic import ovfcheck
from pypy.module._cffi_backend import cdataobj
from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
+from pypy.module._cffi_backend import ctypeprim
class W_CTypeArray(W_CTypePtrOrArray):
@@ -108,6 +109,21 @@
def typeoffsetof_index(self, index):
return self.ctptr.typeoffsetof_index(index)
+ def rawstring(self, w_cdata):
+ if isinstance(self.ctitem, ctypeprim.W_CTypePrimitive):
+ space = self.space
+ length = w_cdata.get_array_length()
+ if self.ctitem.size == rffi.sizeof(lltype.Char):
+ with w_cdata as ptr:
+ s = rffi.charpsize2str(ptr, length)
+ return space.wrapbytes(s)
+ elif self.is_unichar_ptr_or_array():
+ with w_cdata as ptr:
+ cdata = rffi.cast(rffi.CWCHARP, ptr)
+ u = rffi.wcharpsize2unicode(cdata, length)
+ return space.wrap(u)
+ return W_CTypePtrOrArray.rawstring(self, w_cdata)
+
class W_CDataIter(W_Root):
_immutable_fields_ = ['ctitem', 'cdata', '_stop'] # but not '_next'
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
@@ -127,6 +127,12 @@
raise oefmt(space.w_TypeError,
"string(): unexpected cdata '%s' argument", self.name)
+ def rawstring(self, cdataobj):
+ space = self.space
+ raise oefmt(space.w_TypeError,
+ "expected a 'char[]' or 'uint8_t[]' or 'int8_t[]' "
+ "or 'wchar_t[]', got '%s'", self.name)
+
def add(self, cdata, i):
space = self.space
raise oefmt(space.w_TypeError, "cannot add a cdata '%s' and a number",
diff --git a/pypy/module/_cffi_backend/ffi_obj.py
b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -542,6 +542,21 @@
return w_cdata.ctype.string(w_cdata, maxlen)
+ @unwrap_spec(w_cdata=W_CData)
+ def descr_rawstring(self, w_cdata):
+ """\
+Convert a cdata that is an array of 'char' or 'wchar_t' to
+a byte or unicode string. Unlike ffi.string(), it does not stop
+at the first null.
+
+Note that if you have a pointer and an explicit length, you
+can use 'p[0:length]' to make an array view. This is similar to
+the construct 'list(p[0:length])', which returns a list of chars/
+unichars/ints/floats."""
+ #
+ return w_cdata.ctype.rawstring(w_cdata)
+
+
def descr_sizeof(self, w_arg):
"""\
Return the size in bytes of the argument.
@@ -736,6 +751,7 @@
new_allocator = interp2app(W_FFIObject.descr_new_allocator),
new_handle = interp2app(W_FFIObject.descr_new_handle),
offsetof = interp2app(W_FFIObject.descr_offsetof),
+ rawstring = interp2app(W_FFIObject.descr_rawstring),
sizeof = interp2app(W_FFIObject.descr_sizeof),
string = interp2app(W_FFIObject.descr_string),
typeof = interp2app(W_FFIObject.descr_typeof),
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
@@ -78,6 +78,12 @@
# ____________________________________________________________
+@unwrap_spec(w_cdata=cdataobj.W_CData)
+def rawstring(space, w_cdata):
+ return w_cdata.ctype.rawstring(w_cdata)
+
+# ____________________________________________________________
+
def _get_types(space):
return space.newtuple([space.gettypefor(cdataobj.W_CData),
space.gettypefor(ctypeobj.W_CType)])
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
@@ -3514,3 +3514,22 @@
d = {}
_get_common_types(d)
assert d['bool'] == '_Bool'
+
+def test_rawstring():
+ BChar = new_primitive_type("char")
+ BArray = new_array_type(new_pointer_type(BChar), 10) # char[10]
+ p = newp(BArray, "abc\x00def")
+ assert rawstring(p) == "abc\x00def\x00\x00\x00"
+ assert rawstring(p[1:6]) == "bc\x00de"
+ BWChar = new_primitive_type("wchar_t")
+ BArray = new_array_type(new_pointer_type(BWChar), 10) # wchar_t[10]
+ p = newp(BArray, u"abc\x00def")
+ assert rawstring(p) == u"abc\x00def\x00\x00\x00"
+ assert rawstring(p[1:6]) == u"bc\x00de"
+ BChar = new_primitive_type("uint8_t")
+ BArray = new_array_type(new_pointer_type(BChar), 10) # uint8_t[10]
+ p = newp(BArray, [65 + i for i in range(10)])
+ assert rawstring(p) == "ABCDEFGHIJ"
+ #
+ py.test.raises(TypeError, rawstring, "foobar")
+ py.test.raises(TypeError, rawstring, p + 1)
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -476,3 +476,16 @@
for i in range(5):
raises(ValueError, ffi.init_once, do_init, "tag")
assert seen == [1] * (i + 1)
+
+ def test_rawstring(self):
+ import _cffi_backend as _cffi1_backend
+ ffi = _cffi1_backend.FFI()
+ p = ffi.new("char[]", "abc\x00def")
+ assert ffi.rawstring(p) == "abc\x00def\x00"
+ assert ffi.rawstring(p[1:6]) == "bc\x00de"
+ p = ffi.new("wchar_t[]", u"abc\x00def")
+ assert ffi.rawstring(p) == u"abc\x00def\x00"
+ assert ffi.rawstring(p[1:6]) == u"bc\x00de"
+ #
+ raises(TypeError, ffi.rawstring, "foobar")
+ raises(TypeError, ffi.rawstring, p + 1)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit