Author: Armin Rigo <[email protected]>
Branch: stmgc-c8
Changeset: r78257:350b6a396e7a
Date: 2015-06-23 12:50 +0200
http://bitbucket.org/pypy/pypy/changeset/350b6a396e7a/
Log: Support the common primitive types in unsafe_write()
diff --git a/pypy/module/_cffi_backend/ctypeprim.py
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -184,12 +184,16 @@
value = misc.read_raw_signed_data(cdata, self.size)
return self.space.wrap(value) # r_longlong => on 32-bit, 'long'
+ def _convert_to_long(self, w_ob):
+ value = misc.as_long(self.space, w_ob)
+ if self.value_smaller_than_long:
+ if value != misc.signext(value, self.size):
+ self._overflow(w_ob)
+ return value
+
def convert_from_object(self, cdata, w_ob):
if self.value_fits_long:
- value = misc.as_long(self.space, w_ob)
- if self.value_smaller_than_long:
- if value != misc.signext(value, self.size):
- self._overflow(w_ob)
+ value = self._convert_to_long(w_ob)
misc.write_raw_signed_data(cdata, value, self.size)
else:
self._convert_from_object_longlong(cdata, w_ob)
@@ -261,12 +265,16 @@
def cast_to_int(self, cdata):
return self.convert_to_object(cdata)
+ def _convert_to_ulong(self, w_ob):
+ value = misc.as_unsigned_long(self.space, w_ob, strict=True)
+ if self.value_fits_long:
+ if value > self.vrangemax:
+ self._overflow(w_ob)
+ return value
+
def convert_from_object(self, cdata, w_ob):
if self.value_fits_ulong:
- value = misc.as_unsigned_long(self.space, w_ob, strict=True)
- if self.value_fits_long:
- if value > self.vrangemax:
- self._overflow(w_ob)
+ value = self._convert_to_ulong(w_ob)
misc.write_raw_unsigned_data(cdata, value, self.size)
else:
self._convert_from_object_longlong(cdata, w_ob)
@@ -373,9 +381,12 @@
value = misc.read_raw_float_data(cdata, self.size)
return self.space.wrap(value)
+ def _convert_to_double(self, w_ob):
+ space = self.space
+ return space.float_w(space.float(w_ob))
+
def convert_from_object(self, cdata, w_ob):
- space = self.space
- value = space.float_w(space.float(w_ob))
+ value = self._convert_to_double(w_ob)
misc.write_raw_float_data(cdata, value, self.size)
def unpack_list_of_float_items(self, w_cdata):
diff --git a/pypy/module/pypystm/__init__.py b/pypy/module/pypystm/__init__.py
--- a/pypy/module/pypystm/__init__.py
+++ b/pypy/module/pypystm/__init__.py
@@ -30,5 +30,5 @@
'queue': 'queue.W_Queue',
'Empty': 'space.fromcache(queue.Cache).w_Empty',
- 'unsafe_write_int32': 'unsafe_op.unsafe_write_int32',
+ 'unsafe_write': 'unsafe_op.unsafe_write',
}
diff --git a/pypy/module/pypystm/test/test_unsafe_op.py
b/pypy/module/pypystm/test/test_unsafe_op.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypystm/test/test_unsafe_op.py
@@ -0,0 +1,62 @@
+import pypy.module._cffi_backend.misc # side-effects
+
+
+class AppTestUnsafeOp:
+ spaceconfig = dict(usemodules=['pypystm', '_cffi_backend'])
+
+ def test_unsafe_write_char(self):
+ import pypystm, _cffi_backend
+ BChar = _cffi_backend.new_primitive_type('char')
+ BCharP = _cffi_backend.new_pointer_type(BChar)
+ x = _cffi_backend.newp(_cffi_backend.new_array_type(BCharP, 2))
+ pypystm.unsafe_write(x, 0, 'A')
+ pypystm.unsafe_write(x, 1, '\xAA')
+ assert x[0] == 'A'
+ assert x[1] == '\xAA'
+
+ def test_unsafe_write_int32(self):
+ import pypystm, _cffi_backend
+ BInt32 = _cffi_backend.new_primitive_type('int32_t')
+ BInt32P = _cffi_backend.new_pointer_type(BInt32)
+ x = _cffi_backend.newp(_cffi_backend.new_array_type(BInt32P, 2))
+ pypystm.unsafe_write(x, 0, -0x01020304)
+ pypystm.unsafe_write(x, 1, -0x05060708)
+ assert x[0] == -0x01020304
+ assert x[1] == -0x05060708
+
+ def test_unsafe_write_uint64(self):
+ import pypystm, _cffi_backend
+ BUInt64 = _cffi_backend.new_primitive_type('uint64_t')
+ BUInt64P = _cffi_backend.new_pointer_type(BUInt64)
+ x = _cffi_backend.newp(_cffi_backend.new_array_type(BUInt64P, 2))
+ pypystm.unsafe_write(x, 0, 0x0102030411223344)
+ pypystm.unsafe_write(x, 1, 0xF506070855667788)
+ assert x[0] == 0x0102030411223344
+ assert x[1] == 0xF506070855667788
+
+ def test_unsafe_write_unsupported_case(self):
+ import pypystm, _cffi_backend
+ BUniChar = _cffi_backend.new_primitive_type('wchar_t')
+ BUniCharP = _cffi_backend.new_pointer_type(BUniChar)
+ x = _cffi_backend.newp(_cffi_backend.new_array_type(BUniCharP, 2))
+ raises(TypeError, pypystm.unsafe_write, x, 0, u'X')
+
+ def test_unsafe_write_float(self):
+ import pypystm, _cffi_backend
+ BFloat = _cffi_backend.new_primitive_type('float')
+ BFloatP = _cffi_backend.new_pointer_type(BFloat)
+ x = _cffi_backend.newp(_cffi_backend.new_array_type(BFloatP, 2))
+ pypystm.unsafe_write(x, 0, 12.25)
+ pypystm.unsafe_write(x, 1, -42.0)
+ assert x[0] == 12.25
+ assert x[1] == -42.0
+
+ def test_unsafe_write_double(self):
+ import pypystm, _cffi_backend
+ BDouble = _cffi_backend.new_primitive_type('double')
+ BDoubleP = _cffi_backend.new_pointer_type(BDouble)
+ x = _cffi_backend.newp(_cffi_backend.new_array_type(BDoubleP, 2))
+ pypystm.unsafe_write(x, 0, 12.25)
+ pypystm.unsafe_write(x, 1, -42.0)
+ assert x[0] == 12.25
+ assert x[1] == -42.0
diff --git a/pypy/module/pypystm/unsafe_op.py b/pypy/module/pypystm/unsafe_op.py
--- a/pypy/module/pypystm/unsafe_op.py
+++ b/pypy/module/pypystm/unsafe_op.py
@@ -1,15 +1,75 @@
from pypy.interpreter.gateway import unwrap_spec
-from pypy.module._cffi_backend import cdataobj
+from pypy.interpreter.error import oefmt
+from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypeprim, misc
from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.objectmodel import specialize
-UNSAFE_INT = lltype.Struct('UNSAFE_INT', ('x', rffi.INT),
[email protected]()
+def get_unsafe_type_ptr(TP):
+ UNSAFE = lltype.Struct('UNSAFE', ('x', TP),
hints = {'stm_dont_track_raw_accesses': True})
-UNSAFE_INT_P = lltype.Ptr(UNSAFE_INT)
+ return rffi.CArrayPtr(UNSAFE)
-@unwrap_spec(w_cdata=cdataobj.W_CData, index=int, value='c_int')
-def unsafe_write_int32(space, w_cdata, index, value):
- with w_cdata as ptr:
- ptr = rffi.cast(UNSAFE_INT_P, rffi.ptradd(ptr, index * 4))
- ptr.x = rffi.cast(rffi.INT, value)
+def unsafe_write_raw_signed_data(w_cdata, index, source, size):
+ with w_cdata as target:
+ for TP, _ in misc._prim_signed_types:
+ if size == rffi.sizeof(TP):
+ TPP = get_unsafe_type_ptr(TP)
+ rffi.cast(TPP, target)[index].x = rffi.cast(TP, source)
+ return
+ raise NotImplementedError("bad integer size")
+
+def unsafe_write_raw_unsigned_data(w_cdata, index, source, size):
+ with w_cdata as target:
+ for TP, _ in misc._prim_unsigned_types:
+ if size == rffi.sizeof(TP):
+ TPP = get_unsafe_type_ptr(TP)
+ rffi.cast(TPP, target)[index].x = rffi.cast(TP, source)
+ return
+ raise NotImplementedError("bad integer size")
+
+def unsafe_write_raw_float_data(w_cdata, index, source, size):
+ with w_cdata as target:
+ for TP, _ in misc._prim_float_types:
+ if size == rffi.sizeof(TP):
+ TPP = get_unsafe_type_ptr(TP)
+ rffi.cast(TPP, target)[index].x = rffi.cast(TP, source)
+ return
+ raise NotImplementedError("bad float size")
+
+
+@unwrap_spec(w_cdata=cdataobj.W_CData, index=int)
+def unsafe_write(space, w_cdata, index, w_value):
+ ctype = w_cdata.ctype
+ if not isinstance(ctype, ctypeptr.W_CTypePtrOrArray):
+ raise oefmt(space.w_TypeError,
+ "expected a cdata of type pointer or array")
+ ctitem = ctype.ctitem
+
+ if isinstance(ctitem, ctypeprim.W_CTypePrimitiveChar):
+ charvalue = ctitem._convert_to_char(w_value)
+ unsafe_write_raw_signed_data(w_cdata, index, ord(charvalue), size=1)
+ return
+
+ if isinstance(ctitem, ctypeprim.W_CTypePrimitiveSigned):
+ if ctitem.value_fits_long:
+ value = ctitem._convert_to_long(w_value)
+ unsafe_write_raw_signed_data(w_cdata, index, value, ctitem.size)
+ return
+
+ if isinstance(ctitem, ctypeprim.W_CTypePrimitiveUnsigned):
+ if ctitem.value_fits_ulong:
+ value = ctitem._convert_to_ulong(w_value)
+ unsafe_write_raw_unsigned_data(w_cdata, index, value, ctitem.size)
+ return
+
+ if isinstance(ctitem, ctypeprim.W_CTypePrimitiveFloat):
+ if not isinstance(ctitem, ctypeprim.W_CTypePrimitiveLongDouble):
+ value = ctitem._convert_to_double(w_value)
+ unsafe_write_raw_float_data(w_cdata, index, value, ctitem.size)
+ return
+
+ raise oefmt(space.w_TypeError, "unsupported type in unsafe_write(): '%s'",
+ ctitem.name)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit