[pypy-commit] pypy faster-rstruct-2: add a new Buffer.typed_read method, which does the same as the current strstorage.py: the idea is that this will be implemented by all Buffer subclasses for which it makes sense (e.g. ByteArrayBuffer can use the same gc_load_indexed approach as StringBuffer; and raw buffers should be able to use raw_load or similar). Copy the logic and the tests from strstorage.py, which will be deleted later
antocuni
pypy.commits at gmail.com
Wed May 3 13:10:57 EDT 2017
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: faster-rstruct-2
Changeset: r91177:19988cc7db57
Date: 2017-05-03 19:06 +0200
http://bitbucket.org/pypy/pypy/changeset/19988cc7db57/
Log: add a new Buffer.typed_read method, which does the same as the
current strstorage.py: the idea is that this will be implemented by
all Buffer subclasses for which it makes sense (e.g. ByteArrayBuffer
can use the same gc_load_indexed approach as StringBuffer; and raw
buffers should be able to use raw_load or similar). Copy the logic
and the tests from strstorage.py, which will be deleted later
diff --git a/rpython/rlib/buffer.py b/rpython/rlib/buffer.py
--- a/rpython/rlib/buffer.py
+++ b/rpython/rlib/buffer.py
@@ -1,11 +1,23 @@
"""
Buffer protocol support.
"""
+from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.rtyper.lltypesystem.rstr import STR
+from rpython.rtyper.annlowlevel import llstr
+from rpython.rlib.objectmodel import specialize
from rpython.rlib import jit
from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr,
nonmoving_raw_ptr_for_resizable_list)
+class CannotRead(Exception):
+ """
+ Exception raised by Buffer.typed_read in case it is not possible to
+ accomplish the request. This might be because it is not supported by the
+ specific type of buffer, or because of alignment issues.
+ """
+
class Buffer(object):
"""Abstract base class for buffers."""
_attrs_ = ['readonly']
@@ -80,6 +92,12 @@
def releasebuffer(self):
pass
+ #@specialize.??
+ def typed_read(self, TP, byte_offset):
+ raise CannotRead
+
+
+
class StringBuffer(Buffer):
_attrs_ = ['readonly', 'value']
_immutable_ = True
@@ -115,6 +133,19 @@
# may still raise ValueError on some GCs
return rffi.get_raw_address_of_string(self.value)
+ #@specialize.??
+ def typed_read(self, TP, byte_offset):
+ # WARNING: the 'byte_offset' is, as its name says, measured in bytes;
+ # however, it should be aligned for TP, otherwise on some platforms this
+ # code will crash!
+ lls = llstr(self.value)
+ base_ofs = (llmemory.offsetof(STR, 'chars') +
+ llmemory.itemoffsetof(STR.chars, 0))
+ scale_factor = llmemory.sizeof(lltype.Char)
+ return llop.gc_load_indexed(TP, lls, byte_offset,
+ scale_factor, base_ofs)
+
+
class SubBuffer(Buffer):
_attrs_ = ['buffer', 'offset', 'size', 'readonly']
_immutable_ = True
diff --git a/rpython/rlib/test/test_buffer.py b/rpython/rlib/test/test_buffer.py
--- a/rpython/rlib/test/test_buffer.py
+++ b/rpython/rlib/test/test_buffer.py
@@ -1,3 +1,6 @@
+import struct
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.rarithmetic import r_singlefloat
from rpython.rlib.buffer import StringBuffer, SubBuffer, Buffer
from rpython.annotator.annrpython import RPythonAnnotator
from rpython.annotator.model import SomeInteger
@@ -71,3 +74,43 @@
assert addr[0] == b'h'
assert addr[4] == b'o'
assert addr[6] == b'w'
+
+
+class BaseTypedReadTest:
+
+ def test_signed(self):
+ buf = struct.pack('@ll', 42, 43)
+ size = struct.calcsize('@l')
+ assert self.read(lltype.Signed, buf, 0) == 42
+ assert self.read(lltype.Signed, buf, size) == 43
+
+ def test_short(self):
+ buf = struct.pack('@hh', 42, 43)
+ size = struct.calcsize('@h')
+ x = self.read(rffi.SHORT, buf, 0)
+ assert int(x) == 42
+ x = self.read(rffi.SHORT, buf, size)
+ assert int(x) == 43
+
+ def test_float(self):
+ buf = struct.pack('@dd', 12.3, 45.6)
+ size = struct.calcsize('@d')
+ assert self.read(lltype.Float, buf, 0) == 12.3
+ assert self.read(lltype.Float, buf, size) == 45.6
+
+ def test_singlefloat(self):
+ buf = struct.pack('@ff', 12.3, 45.6)
+ size = struct.calcsize('@f')
+ x = self.read(lltype.SingleFloat, buf, 0)
+ assert x == r_singlefloat(12.3)
+ x = self.read(lltype.SingleFloat, buf, size)
+ assert x == r_singlefloat(45.6)
+
+
+class TestTypedReadDirect(BaseTypedReadTest):
+
+ def read(self, TYPE, data, offset):
+ buf = StringBuffer(data)
+ return buf.typed_read(TYPE, offset)
+
+
More information about the pypy-commit
mailing list