[pypy-svn] r73379 - in pypy/branch/cpython-extension/pypy/module/cpyext: . test

fijal at codespeak.net fijal at codespeak.net
Sun Apr 4 20:18:43 CEST 2010


Author: fijal
Date: Sun Apr  4 20:18:41 2010
New Revision: 73379

Modified:
   pypy/branch/cpython-extension/pypy/module/cpyext/stringobject.py
   pypy/branch/cpython-extension/pypy/module/cpyext/test/test_stringobject.py
Log:
test and fix _PyString_Resize


Modified: pypy/branch/cpython-extension/pypy/module/cpyext/stringobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/stringobject.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/stringobject.py	Sun Apr  4 20:18:41 2010
@@ -8,6 +8,17 @@
 
 PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_str")
 
+def new_empty_str(space, length):
+    py_str = lltype.malloc(PyStringObject.TO, flavor='raw')
+    py_str.c_ob_refcnt = 1
+    
+    buflen = length + 1
+    py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
+    py_str.c_buffer[buflen-1] = '\0'
+    py_str.c_size = length
+    py_str.c_ob_type = make_ref(space, space.w_str)
+    return py_str    
+
 @cpython_api_c()
 def PyString_FromFormatV():
     pass
@@ -19,16 +30,7 @@
         ptr = make_ref(space, space.wrap(s))
         return rffi.cast(PyStringObject, ptr)
     else:
-        py_str = lltype.malloc(PyStringObject.TO, flavor='raw')
-        py_str.c_ob_refcnt = 1
-        
-        buflen = length + 1
-        py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
-        py_str.c_buffer[buflen-1] = '\0'
-        py_str.c_size = length
-        py_str.c_ob_type = make_ref(space, space.w_str)
-        
-        return py_str
+        return new_empty_str(space, length)
 
 @cpython_api([rffi.CCHARP], PyObject)
 def PyString_FromString(space, char_p):
@@ -69,13 +71,23 @@
     This function used an int type for newsize. This might
     require changes in your code for properly supporting 64-bit systems."""
     # XXX always create a new string so far
-    w_s = from_ref(space, ref[0])
+    py_str = rffi.cast(PyStringObject, ref[0])
+    if not py_str.c_buffer:
+        raise OperationError(space.w_SystemError, space.wrap(
+            "_PyString_Resize called on already created string"))
     try:
-        ptr = make_ref(space, space.wrap(space.str_w(w_s)[:newsize]))
-    except:
+        py_newstr = new_empty_str(space, newsize)
+    except MemoryError:
         Py_DecRef(space, ref[0])
-        ref[0] = lltype.nullptr(PyStringObject) 
+        ref[0] = lltype.nullptr(PyObject)
         raise
+    to_cp = newsize
+    oldsize = py_str.c_size
+    if oldsize < newsize:
+        to_cp = oldsize
+    for i in range(to_cp):
+        py_newstr.c_buffer[i] = py_str.c_buffer[i]
+    py_newstr.c_buffer[newsize] = '\x00'
     Py_DecRef(space, ref[0])
-    ref[0] = ptr
+    ref[0] = rffi.cast(PyObject, py_newstr)
     return 0

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_stringobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_stringobject.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_stringobject.py	Sun Apr  4 20:18:41 2010
@@ -1,15 +1,12 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.stringobject import new_empty_str
+from pypy.module.cpyext.api import PyStringObject, PyObjectP, PyObject
 
 import py
 import sys
 
-#class TestObject(BaseApiTest):
-#    def test_Size(self, space, api):
-#        s = space.wrap("test")
-#        assert api.PyString_Size(s) == 4
-
 class AppTestStringObject(AppTestCpythonExtensionBase):
     def test_stringobject(self):
         module = self.import_extension('foo', [
@@ -128,3 +125,26 @@
             ''')
         res = module.test_string_format_v(1, "xyz")
         print res
+
+class TestString(BaseApiTest):
+    def test_string_resize(self, space, api):
+        py_str = new_empty_str(space, 10)
+        ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        py_str.c_buffer[0] = 'a'
+        py_str.c_buffer[1] = 'b'
+        py_str.c_buffer[2] = 'c'
+        ar[0] = rffi.cast(PyObject, py_str)
+        api._PyString_Resize(ar, 3)
+        py_str = rffi.cast(PyStringObject, ar[0])
+        assert py_str.c_size == 3
+        assert py_str.c_buffer[1] == 'b'
+        assert py_str.c_buffer[3] == '\x00'
+        # the same for growing
+        ar[0] = rffi.cast(PyObject, py_str)
+        api._PyString_Resize(ar, 10)
+        py_str = rffi.cast(PyStringObject, ar[0])
+        assert py_str.c_size == 10
+        assert py_str.c_buffer[1] == 'b'
+        assert py_str.c_buffer[10] == '\x00'
+        lltype.free(ar, flavor='raw')
+        



More information about the Pypy-commit mailing list