[pypy-svn] r52333 - in pypy/branch/buffer/pypy/module/_rawffi: . test
arigo at codespeak.net
arigo at codespeak.net
Sun Mar 9 15:09:01 CET 2008
Author: arigo
Date: Sun Mar 9 15:08:59 2008
New Revision: 52333
Modified:
pypy/branch/buffer/pypy/module/_rawffi/array.py
pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py
Log:
A useful extension to arrays of shape 'c': buffer-like slicing,
because this can be implemented kind-of-efficiently.
Modified: pypy/branch/buffer/pypy/module/_rawffi/array.py
==============================================================================
--- pypy/branch/buffer/pypy/module/_rawffi/array.py (original)
+++ pypy/branch/buffer/pypy/module/_rawffi/array.py Sun Mar 9 15:08:59 2008
@@ -113,7 +113,8 @@
self.length))
descr_repr.unwrap_spec = ['self', ObjSpace]
- # XXX don't allow negative indexes, nor slices
+ # This only allows non-negative indexes. Arrays of shape 'c' also
+ # support simple slices.
def setitem(self, space, num, w_value):
if not self.ll_buffer:
@@ -122,7 +123,17 @@
raise OperationError(space.w_IndexError, space.w_None)
unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.itemtp,
w_value)
- setitem.unwrap_spec = ['self', ObjSpace, int, W_Root]
+
+ def descr_setitem(self, space, w_index, w_value):
+ try:
+ num = space.int_w(w_index)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ self.setslice(space, w_index, w_value)
+ else:
+ self.setitem(space, num, w_value)
+ descr_setitem.unwrap_spec = ['self', ObjSpace, W_Root, W_Root]
def getitem(self, space, num):
if not self.ll_buffer:
@@ -131,7 +142,17 @@
raise OperationError(space.w_IndexError, space.w_None)
return wrap_value(space, get_elem, self.ll_buffer, num,
self.shape.itemtp)
- getitem.unwrap_spec = ['self', ObjSpace, int]
+
+ def descr_getitem(self, space, w_index):
+ try:
+ num = space.int_w(w_index)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ return self.getslice(space, w_index)
+ else:
+ return self.getitem(space, num)
+ descr_getitem.unwrap_spec = ['self', ObjSpace, W_Root]
def getlength(self, space):
return space.wrap(self.length)
@@ -147,11 +168,59 @@
_, itemsize, _ = self.shape.itemtp
return itemsize * self.length
+ def decodeslice(self, space, w_slice):
+ if not space.is_true(space.isinstance(w_slice, space.w_slice)):
+ return OperationError(space.w_TypeError,
+ space.wrap('index must be int or slice'))
+ letter, _, _ = self.shape.itemtp
+ if letter != 'c':
+ raise OperationError(space.w_TypeError,
+ space.wrap("only 'c' arrays support slicing"))
+ w_start = space.getattr(w_slice, space.wrap('start'))
+ w_stop = space.getattr(w_slice, space.wrap('stop'))
+ w_step = space.getattr(w_slice, space.wrap('step'))
+
+ if space.is_w(w_start, space.w_None):
+ start = 0
+ else:
+ start = space.int_w(w_start)
+ if space.is_w(w_stop, space.w_None):
+ stop = self.length
+ else:
+ stop = space.int_w(w_stop)
+ if not space.is_w(w_step, space.w_None):
+ step = space.int_w(w_step)
+ if step != 1:
+ raise OperationError(space.w_ValueError,
+ space.wrap("no step support"))
+ if not (0 <= start <= stop <= self.length):
+ raise OperationError(space.w_ValueError,
+ space.wrap("slice out of bounds"))
+ if not self.ll_buffer:
+ raise segfault_exception(space, "accessing a freed array")
+ return start, stop
+
+ def getslice(self, space, w_slice):
+ start, stop = self.decodeslice(space, w_slice)
+ ll_buffer = self.ll_buffer
+ result = [ll_buffer[i] for i in range(start, stop)]
+ return space.wrap(''.join(result))
+
+ def setslice(self, space, w_slice, w_value):
+ start, stop = self.decodeslice(space, w_slice)
+ value = space.bufferstr_w(w_value)
+ if start + len(value) != stop:
+ raise OperationError(space.w_ValueError,
+ space.wrap("cannot resize array"))
+ ll_buffer = self.ll_buffer
+ for i in range(len(value)):
+ ll_buffer[start + i] = value[i]
+
W_ArrayInstance.typedef = TypeDef(
'ArrayInstance',
__repr__ = interp2app(W_ArrayInstance.descr_repr),
- __setitem__ = interp2app(W_ArrayInstance.setitem),
- __getitem__ = interp2app(W_ArrayInstance.getitem),
+ __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
+ __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
__len__ = interp2app(W_ArrayInstance.getlength),
__buffer__ = interp2app(W_ArrayInstance.descr_buffer),
buffer = GetSetProperty(W_ArrayInstance.getbuffer),
@@ -174,8 +243,8 @@
W_ArrayInstanceAutoFree.typedef = TypeDef(
'ArrayInstanceWithFree',
__repr__ = interp2app(W_ArrayInstance.descr_repr),
- __setitem__ = interp2app(W_ArrayInstance.setitem),
- __getitem__ = interp2app(W_ArrayInstance.getitem),
+ __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
+ __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
__len__ = interp2app(W_ArrayInstance.getlength),
__buffer__ = interp2app(W_ArrayInstance.descr_buffer),
buffer = GetSetProperty(W_ArrayInstance.getbuffer),
Modified: pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py
==============================================================================
--- pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py (original)
+++ pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py Sun Mar 9 15:08:59 2008
@@ -180,6 +180,17 @@
dupaptr.free()
dupa.free()
+ def test_chararray_as_bytebuffer(self):
+ # a useful extension to arrays of shape 'c': buffer-like slicing
+ import _rawffi
+ A = _rawffi.Array('c')
+ buf = A(10, autofree=True)
+ buf[0] = '*'
+ assert buf[1:5] == '\x00' * 4
+ buf[7:] = 'abc'
+ assert buf[9] == 'c'
+ assert buf[:8] == '*' + '\x00'*6 + 'a'
+
def test_returning_str(self):
import _rawffi
lib = _rawffi.CDLL(self.lib_name)
More information about the Pypy-commit
mailing list