[pypy-commit] lang-smalltalk default: implemented c_layout for BytesObject
lwassermann
noreply at buildbot.pypy.org
Thu Jun 20 13:05:28 CEST 2013
Author: Lars Wassermann <lars.wassermann at gmail.com>
Branch:
Changeset: r467:469aa663812c
Date: 2013-06-19 16:36 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/469aa663812c/
Log: implemented c_layout for BytesObject added immutable hint for _size
diff --git a/spyvm/interpreter_proxy.py b/spyvm/interpreter_proxy.py
--- a/spyvm/interpreter_proxy.py
+++ b/spyvm/interpreter_proxy.py
@@ -240,6 +240,8 @@
# return a list with values (?) of w_objects variable-parts
if isinstance(w_object, model.W_WordsObject):
return w_object.convert_to_c_layout()
+ elif isinstance(w_object, model.W_BytesObject):
+ return rffi.cast(sqIntArrayPtr, w_object.convert_to_c_layout())
else:
raise ProxyFunctionFailed
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -709,16 +709,19 @@
return w_result
class W_BytesObject(W_AbstractObjectWithClassReference):
- _attrs_ = ['bytes']
+ _attrs_ = ['bytes', 'c_bytes', '_size']
+ _immutable_fields_ = ['_size']
def __init__(self, space, w_class, size):
W_AbstractObjectWithClassReference.__init__(self, space, w_class)
assert isinstance(size, int)
self.bytes = ['\x00'] * size
+ self._size = size
def fillin(self, space, g_self):
self.s_class = g_self.get_class().as_class_get_penumbra(space)
self.bytes = g_self.get_bytes()
+ self._size = len(self.bytes)
self.hash = g_self.get_hash()
self.space = space
@@ -729,11 +732,19 @@
self.setchar(index0, chr(space.unwrap_int(w_value)))
def getchar(self, n0):
- return self.bytes[n0]
+ if self.bytes is not None:
+ return self.bytes[n0]
+ else:
+ if n0 >= self._size:
+ raise IndexError
+ return self.c_bytes[n0]
def setchar(self, n0, character):
assert len(character) == 1
- self.bytes[n0] = character
+ if self.bytes is not None:
+ self.bytes[n0] = character
+ else:
+ self.c_bytes[n0] = character
def short_at0(self, space, index0):
byte_index0 = index0 * 2
@@ -755,7 +766,7 @@
self.setchar(byte_index0 + 1, chr(byte1))
def size(self):
- return len(self.bytes)
+ return self._size
def __str__(self):
return self.as_string()
@@ -765,7 +776,10 @@
className='W_BytesObject', additionalInformation=self.as_string())
def as_string(self):
- return "".join(self.bytes)
+ if self.bytes is not None:
+ return "".join(self.bytes)
+ else:
+ return "".join([self.c_bytes[i] for i in range(self.size())])
def invariant(self):
if not W_AbstractObjectWithClassReference.invariant(self):
@@ -779,11 +793,24 @@
# XXX this sounds very wrong to me
if not isinstance(other, W_BytesObject):
return False
- return self.bytes == other.bytes
+ if self.bytes is not None and other.bytes is not None:
+ return self.bytes == other.bytes
+ else:
+ size = self.size()
+ if size != other.size():
+ return False
+ for i in range(size):
+ if self.getchar(i) != other.getchar(i):
+ return False
+ return True
def clone(self, space):
- w_result = W_BytesObject(self.space, self.getclass(space), len(self.bytes))
- w_result.bytes = list(self.bytes)
+ size = self.size()
+ w_result = W_BytesObject(self.space, self.getclass(space), size)
+ if self.bytes is not None:
+ w_result.bytes = list(self.bytes)
+ else:
+ w_result.bytes = [self.c_bytes[i] for i in range(size)]
return w_result
def unwrap_uint(self, space):
@@ -799,6 +826,19 @@
def is_array_object(self):
return True
+ def convert_to_c_layout(self):
+ if self.bytes is None:
+ return self.c_bytes
+ else:
+ size = self.size()
+ c_bytes = self.c_bytes = rffi.str2charp(self.bytes)
+ self.bytes = None
+ return c_bytes
+
+ def __del__(self):
+ if self.bytes is None:
+ rffi.free_charp(self.c_bytes)
+
class W_WordsObject(W_AbstractObjectWithClassReference):
_attrs_ = ['words', 'c_words', '_size']
_immutable_fields_ = ['_size']
diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py
--- a/spyvm/test/test_model.py
+++ b/spyvm/test/test_model.py
@@ -49,6 +49,19 @@
assert w_bytes.getchar(0) == "\x00"
py.test.raises(IndexError, lambda: w_bytes.getchar(20))
+def test_c_bytes_object():
+ w_class = mockclass(space, 0, format=shadow.BYTES)
+ w_bytes = w_class.as_class_get_shadow(space).new(20)
+ w_bytes.convert_to_c_layout()
+ assert w_bytes.getclass(space).is_same_object(w_class)
+ assert w_bytes.size() == 20
+ assert w_class.as_class_get_shadow(space).instsize() == 0
+ assert w_bytes.getchar(3) == "\x00"
+ w_bytes.setchar(3, "\xAA")
+ assert w_bytes.getchar(3) == "\xAA"
+ assert w_bytes.getchar(0) == "\x00"
+ py.test.raises(IndexError, lambda: w_bytes.getchar(20))
+
def test_word_object():
w_class = mockclass(space, 0, format=shadow.WORDS)
w_bytes = w_class.as_class_get_shadow(space).new(20)
More information about the pypy-commit
mailing list