def alloc_buffer(count): """ Returns a (raw_buffer, gc_buffer, case_num) triple, allocated with count bytes. The raw_buffer can be safely passed to a native function which expects it to not move. Call str_from_buffer with the returned values to get a safe high-level string. When the garbage collector cooperates, this allows for the process to be performed without an extra copy. Make sure to call keep_buffer_alive_until_here on the returned values. """ new_buf = mallocfn(count) pinned = 0 if rgc.can_move(new_buf): if rgc.pin(new_buf): pinned = 1 else: raw_buf = lltype.malloc(TYPEP.TO, count, flavor='raw') return raw_buf, new_buf, 2 # # following code is executed if: # - rgc.can_move(data) and rgc.pin(data) both returned true # - rgc.can_move(data) returned false data_start = cast_ptr_to_adr(new_buf) + \ offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0) return cast(TYPEP, data_start), new_buf, pinned
def str_from_buffer(raw_buf, gc_buf, case_num, allocated_size, needed_size): """ Converts from a pair returned by alloc_buffer to a high-level string. The returned string will be truncated to needed_size. """ assert allocated_size >= needed_size if allocated_size != needed_size: from rpython.rtyper.lltypesystem.lloperation import llop if llop.shrink_array(lltype.Bool, gc_buf, needed_size): pass # now 'gc_buf' is smaller else: gc_buf = mallocfn(needed_size) case_num = 2 if case_num == 2: copy_raw_to_string(raw_buf, gc_buf, 0, needed_size) return hlstrtype(gc_buf)
def charpsize2str(cp, size): ll_str = mallocfn(size) copy_raw_to_string(cp, ll_str, 0, size) result = hlstrtype(ll_str) assert result is not None return result