def get_raw_address_of_string(space, w_x): """Special case for ffi.from_buffer(string). Returns a 'char *' that is valid as long as the string object is alive. Two calls to ffi.from_buffer(same_string) are guaranteed to return the same pointer. """ from rpython.rtyper.annlowlevel import llstr from rpython.rtyper.lltypesystem.rstr import STR from rpython.rtyper.lltypesystem import llmemory from rpython.rlib import rgc cache = space.fromcache(RawBytesCache) rawbytes = cache.wdict.get(w_x) if rawbytes is None: data = space.bytes_w(w_x) if (we_are_translated() and not rgc.can_move(data) and not rgc.must_split_gc_address_space()): lldata = llstr(data) data_start = (llmemory.cast_ptr_to_adr(lldata) + rffi.offsetof(STR, 'chars') + llmemory.itemoffsetof(STR.chars, 0)) data_start = rffi.cast(rffi.CCHARP, data_start) data_start[len(data)] = '\x00' # write the final extra null return data_start rawbytes = RawBytes(data) cache.wdict.set(w_x, rawbytes) return rawbytes.ptr
def copy_string_contents(src, dst, srcstart, dststart, length): """Copies 'length' characters from the 'src' string to the 'dst' string, starting at position 'srcstart' and 'dststart'.""" # xxx Warning: don't try to do this at home. It relies on a lot # of details to be sure that it works correctly in all cases. # Notably: no GC operation at all from the first cast_ptr_to_adr() # because it might move the strings. The keepalive_until_here() # are obscurely essential to make sure that the strings stay alive # longer than the raw_memcopy(). assert length >= 0 ll_assert(srcstart >= 0, "copystrc: negative srcstart") ll_assert(srcstart + length <= len(src.chars), "copystrc: src ovf") ll_assert(dststart >= 0, "copystrc: negative dststart") ll_assert(dststart + length <= len(dst.chars), "copystrc: dst ovf") # # If the 'split_gc_address_space' option is set, we must copy # manually, character-by-character if rgc.must_split_gc_address_space(): i = 0 while i < length: dst.chars[dststart + i] = src.chars[srcstart + i] i += 1 return # # # from here, no GC operations can happen asrc = _get_raw_buf(SRC_TP, src, srcstart) adst = _get_raw_buf(DST_TP, dst, dststart) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(CHAR_TP) * length) # end of "no GC" section keepalive_until_here(src) keepalive_until_here(dst)
def copy_string_to_raw(src, ptrdst, srcstart, length): """ Copies 'length' characters from the 'src' string to the 'ptrdst' buffer, starting at position 'srcstart'. 'ptrdst' must be a non-gc Array of Char. """ # xxx Warning: same note as above apply: don't do this at home assert length >= 0 # # If the 'split_gc_address_space' option is set, we must copy # manually, character-by-character if rgc.must_split_gc_address_space(): i = 0 while i < length: ptrdst[i] = src.chars[srcstart + i] i += 1 return # # from here, no GC operations can happen asrc = _get_raw_buf(SRC_TP, src, srcstart) adst = llmemory.cast_ptr_to_adr(ptrdst) adst = adst + llmemory.itemoffsetof(typeOf(ptrdst).TO, 0) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(CHAR_TP) * length) # end of "no GC" section keepalive_until_here(src)
def ll_string2list(RESLIST, src): length = len(src.chars) lst = RESLIST.ll_newlist(length) dst = lst.ll_items() SRC = typeOf(src).TO # STR or UNICODE DST = typeOf(dst).TO # GcArray assert DST.OF is SRC.chars.OF # # If the 'split_gc_address_space' option is set, we must copy # manually, character-by-character if rgc.must_split_gc_address_space(): i = 0 while i < length: dst[i] = src.chars[i] i += 1 return lst # # from here, no GC operations can happen asrc = llmemory.cast_ptr_to_adr(src) + (llmemory.offsetof( SRC, 'chars') + llmemory.itemoffsetof(SRC.chars, 0)) adst = llmemory.cast_ptr_to_adr(dst) + llmemory.itemoffsetof(DST, 0) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(DST.OF) * length) # end of "no GC" section keepalive_until_here(src) keepalive_until_here(dst) return lst
def ll_populate_list_from_raw_array(ll_list, src_ptr, length): ll_list._ll_resize(length) if rgc.must_split_gc_address_space(): for i in range(length): ll_list.ll_setitem_fast(i, src_ptr[i]) return ITEM = lltype.typeOf(src_ptr).TO.OF size = llmemory.sizeof(ITEM) * length # start of no-GC section src_adr = get_raw_buf(src_ptr) dst_adr = get_raw_buf(ll_list.ll_items()) llmemory.raw_memcopy(src_adr, dst_adr, size)
def ll_copy_list_to_raw_array(ll_list, dst_ptr): if rgc.must_split_gc_address_space(): for i in range(ll_list.ll_length()): dst_ptr[i] = ll_list.ll_getitem_fast(i) return # this code is delicate: we must ensure that there are no GC operations # around the call to raw_memcopy # ITEM = lltype.typeOf(dst_ptr).TO.OF size = llmemory.sizeof(ITEM) * ll_list.ll_length() # start of no-GC section src_adr = get_raw_buf(ll_list.ll_items()) dst_adr = get_raw_buf(dst_ptr) llmemory.raw_memcopy(src_adr, dst_adr, size)
def copy_raw_to_string(ptrsrc, dst, dststart, length): # xxx Warning: same note as above apply: don't do this at home assert length >= 0 # # If the 'split_gc_address_space' option is set, we must copy # manually, character-by-character if rgc.must_split_gc_address_space(): i = 0 while i < length: dst.chars[dststart + i] = ptrsrc[i] i += 1 return # # from here, no GC operations can happen adst = _get_raw_buf(SRC_TP, dst, dststart) asrc = llmemory.cast_ptr_to_adr(ptrsrc) asrc = asrc + llmemory.itemoffsetof(typeOf(ptrsrc).TO, 0) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(CHAR_TP) * length) # end of "no GC" section keepalive_until_here(dst)
def hide_reveal(): if rgc.must_split_gc_address_space(): return hide_reveal_slow else: return hide_reveal_fast