Author: Richard Plangger <[email protected]>
Branch: strbuf-as-buffer
Changeset: r88982:15b144ea1d4d
Date: 2016-12-09 12:04 +0100
http://bitbucket.org/pypy/pypy/changeset/15b144ea1d4d/

Log:    a new approach to get the raw address to a string

diff --git a/rpython/rlib/buffer.py b/rpython/rlib/buffer.py
--- a/rpython/rlib/buffer.py
+++ b/rpython/rlib/buffer.py
@@ -78,15 +78,12 @@
         return [1]
 
 class StringBuffer(Buffer):
-    __slots__ = ['value', 'charlist']
+    __slots__ = ['value', '__weakref__']
     _immutable_ = True
 
     def __init__(self, value):
         self.value = value
         self.readonly = True
-        # the not initialized list of chars, copied from value
-        # as soon as get_raw_address is called
-        self.charlist = None
 
     def getlength(self):
         return len(self.value)
@@ -111,12 +108,8 @@
         return Buffer.getslice(self, start, stop, step, size)
 
     def get_raw_address(self):
-        if not self.charlist:
-            data = [c for c in self.value]
-            self.charlist = resizable_list_supporting_raw_ptr(data)
-        return nonmoving_raw_ptr_for_resizable_list(self.charlist)
-
-
+        from rpython.rtyper.lltypesystem import rffi
+        return rffi.get_raw_address_of_string(self, self.value)
 
 class SubBuffer(Buffer):
     __slots__ = ['buffer', 'offset', 'size']
diff --git a/rpython/rtyper/lltypesystem/rffi.py 
b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -754,6 +754,53 @@
 SIGNED = lltype.Signed
 SIGNEDP = lltype.Ptr(lltype.Array(SIGNED, hints={'nolength': True}))
 
+
+class RawBytes(object):
+    # literal copy of _cffi_backend/func.py
+    def __init__(self, string):
+        self.ptr = str2charp(string, track_allocation=False)
+    def __del__(self):
+        free_charp(self.ptr, track_allocation=False)
+
+from rpython.rlib import rweakref
+from rpython.rlib.buffer import Buffer
+_STR_WDICT = rweakref.RWeakKeyDictionary(Buffer, RawBytes)
+
[email protected]_look_inside
+def get_raw_address_of_string(key, string):
+    """Returns a 'char *' that is valid as long as the key object is alive.
+    Two calls to to this function are guaranteed to return the same pointer.
+
+    The extra parameter key is necessary to create a weak reference.
+    The buffer of the returned pointer (if object is young) lives as long
+    as key is alive. If key goes out of scope, the buffer will eventually
+    be freed. `string` cannot go out of scope until the RawBytes object
+    referencing it goes out of scope.
+    """
+    from rpython.rtyper.annlowlevel import llstr
+    from rpython.rtyper.lltypesystem.rstr import STR
+    from rpython.rtyper.lltypesystem import llmemory
+    from rpython.rlib import rgc
+
+    global _STR_WDICT
+    rawbytes = _STR_WDICT.get(key)
+    if rawbytes is None:
+        if we_are_translated() and not rgc.can_move(string):
+            lldata = llstr(string)
+            data_start = (llmemory.cast_ptr_to_adr(lldata) +
+                          offsetof(STR, 'chars') +
+                          llmemory.itemoffsetof(STR.chars, 0))
+            data_start = cast(CCHARP, data_start)
+            data_start[len(string)] = '\x00'   # write the final extra null
+            return data_start
+        rawbytes = RawBytes(string)
+        _STR_WDICT.set(key, rawbytes)
+    return rawbytes.ptr
+
+
+
+
+
 # various type mapping
 
 # conversions between str and char*
@@ -876,6 +923,7 @@
     get_nonmovingbuffer._always_inline_ = 'try' # get rid of the returned tuple
     get_nonmovingbuffer._annenforceargs_ = [strtype]
 
+
     @jit.dont_look_inside
     def get_nonmovingbuffer_final_null(data):
         tup = get_nonmovingbuffer(data)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to