[pypy-svn] r34499 - in pypy/dist/pypy/rlib: . test

arigo at codespeak.net arigo at codespeak.net
Sat Nov 11 19:47:57 CET 2006


Author: arigo
Date: Sat Nov 11 19:47:57 2006
New Revision: 34499

Modified:
   pypy/dist/pypy/rlib/rctypesobject.py
   pypy/dist/pypy/rlib/test/test_rctypesobject.py
Log:
Some extra getters and setters for arrays of char.


Modified: pypy/dist/pypy/rlib/rctypesobject.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypesobject.py	(original)
+++ pypy/dist/pypy/rlib/rctypesobject.py	Sat Nov 11 19:47:57 2006
@@ -94,6 +94,7 @@
         return llmemory.cast_adr_to_ptr(self.addr, lltype.Ptr(CDATATYPE))
     ll_ref._annspecialcase_ = 'specialize:arg(1)'
 
+# ____________________________________________________________
 
 _primitive_cache = {}
 def Primitive(TYPE):
@@ -121,16 +122,16 @@
 rc_int = Primitive(lltype.Signed)
 rc_char = Primitive(lltype.Char)
 
+# ____________________________________________________________
 
 class _RCTypesStringData(object):
-    ARRAYTYPE    = lltype.Array(lltype.Char, hints={'nolength': True})
-    FIRSTITEMOFS = llmemory.ArrayItemsOffset(ARRAYTYPE)
-    ITEMOFS      = llmemory.sizeof(lltype.Char)
+    ARRAYTYPE = lltype.FixedSizeArray(lltype.Char, 1)
+    ITEMOFS   = llmemory.sizeof(lltype.Char)
     
     def __init__(self, string):
-        rawsize = self.FIRSTITEMOFS + self.ITEMOFS * (len(string) + 1)
+        rawsize = self.ITEMOFS * (len(string) + 1)
         self.addr = llmemory.raw_malloc(rawsize)
-        a = self.addr + self.FIRSTITEMOFS
+        a = self.addr
         for i in range(len(string)):
             a.char[0] = string[i]
             a += self.ITEMOFS
@@ -138,25 +139,32 @@
     def __del__(self):
         llmemory.raw_free(self.addr)
 
+def strlen(p):
+    n = 0
+    while p[n] != '\x00':
+        n += 1
+    return n
+
+def strnlen(p, n_max):
+    n = 0
+    while n < n_max and p[n] != '\x00':
+        n += 1
+    return n
+
+def charp2string(p, length):
+    lst = ['\x00'] * length
+    for i in range(length):
+        lst[i] = p[i]
+    return ''.join(lst)
+
 class RCTypesCharP(RCTypesObject):
     LLTYPE = lltype.Ptr(_RCTypesStringData.ARRAYTYPE)
 
-    def strlen(self):
-        ptr = self.ll_ref(RCTypesCharP.CDATATYPE)
-        a = ptr[0]
-        n = 0
-        while a[n] != '\x00':
-            n += 1
-        return n
-
     def get_value(self):
-        length = self.strlen()
         ptr = self.ll_ref(RCTypesCharP.CDATATYPE)
-        a = ptr[0]
-        lst = ['\x00'] * length
-        for i in range(length):
-            lst[i] = a[i]
-        return ''.join(lst)
+        p = ptr[0]
+        length = strlen(p)
+        return charp2string(p, length)
 
     def set_value(self, string):
         data = _RCTypesStringData(string)
@@ -166,6 +174,7 @@
 
 rc_char_p = RCTypesCharP
 
+# ____________________________________________________________
 
 def RPointer(contentscls):
     """Build and return a new RCTypesPointer class."""
@@ -209,6 +218,7 @@
     return p
 pointer._annspecialcase_ = 'specialize:argtype(0)'
 
+# ____________________________________________________________
 
 def RStruct(c_name, fields, c_external=False):
     """Build and return a new RCTypesStruct class."""
@@ -249,6 +259,7 @@
         make_accessors(name)
     return RCTypesStruct
 
+# ____________________________________________________________
 
 def RFixedArray(itemcls, fixedsize):
     """Build and return a new RCTypesFixedArray class."""
@@ -276,6 +287,30 @@
                 subblock = self.memblock.addoffset(itemcls.num_keepalives * n)
                 return itemcls(subaddr, subblock)
 
+            if itemcls is rc_char:
+                # special methods for arrays of chars
+                def _as_ll_charptr(self):
+                    ptr = self.ll_ref(ARRAYTYPE)
+                    return lltype.direct_arrayitems(ptr)
+
+                def get_value(self):
+                    p = self._as_ll_charptr()
+                    n = strnlen(p, fixedsize)
+                    return charp2string(p, n)
+
+                def set_value(self, string):
+                    p = self._as_ll_charptr()
+                    for i in range(fixedsize):
+                        if i < len(string):
+                            p[i] = string[i]
+                        else:
+                            p[i] = '\x00'
+                            break
+
+                def get_raw(self):
+                    p = self._as_ll_charptr()
+                    return charp2string(p, fixedsize)
+
         setattr(itemcls, key, RCTypesFixedArray)
         return RCTypesFixedArray
 RFixedArray._annspecialcase_ = 'specialize:memo'

Modified: pypy/dist/pypy/rlib/test/test_rctypesobject.py
==============================================================================
--- pypy/dist/pypy/rlib/test/test_rctypesobject.py	(original)
+++ pypy/dist/pypy/rlib/test/test_rctypesobject.py	Sat Nov 11 19:47:57 2006
@@ -116,6 +116,24 @@
         res = self.do(func)
         assert res == 26
 
+    def test_char_array(self):
+        def func():
+            a = RFixedArray(rc_char, 10).allocate()
+            for i in range(6):
+                a.ref(i).set_value("hello!"[i])
+            assert a.get_value() == "hello!"
+            a.set_value("foo")
+            assert a.get_value() == "foo"
+            raw = ''.join([a.ref(i).get_value() for i in range(10)])
+            assert raw == "foo\x00o!\x00\x00\x00\x00"
+            assert raw == a.get_raw()
+            a.set_value("0123456789")
+            assert a.get_raw() == "0123456789"
+            assert a.get_value() == "0123456789"
+            return 1
+        res = self.do(func)
+        assert res == 1
+
 
 class TestLLInterpreted(TestBasic):
     POLICY = AnnotatorPolicy()



More information about the Pypy-commit mailing list