def convert_bitfield_from_object(self, cdata, w_ob): ctype = self.ctype space = ctype.space # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: raise oefmt(space.w_OverflowError, "value %d outside the range allowed by the bit field " "width: %d <= x <= %d", value, fmin, fmax) rawmask = ((r_ulonglong(1) << self.bitsize) - 1) << self.bitshift rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) if is_signed: misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) else: misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size)
def convert_bitfield_from_object(self, cdata, w_ob): ctype = self.ctype space = ctype.space # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: raise oefmt( space.w_OverflowError, "value %d outside the range allowed by the bit field " "width: %d <= x <= %d", value, fmin, fmax) rawmask = ((r_ulonglong(1) << self.bitsize) - 1) << self.bitshift rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) if is_signed: misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) else: misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size)
def test_it_reads_a_bool_from_buffer(self, space): w_bool_type = ffitype.BoolRWStrategy() size = w_bool_type.typesize data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') misc.write_raw_unsigned_data(data, False, size) w_res = w_bool_type.read(space, data) assert not space.is_true(w_res) lltype.free(data, flavor='raw')
def test_it_reads_a_bool_from_buffer(self, space): w_bool_type = ffitype.BoolRWStrategy() size = w_bool_type.typesize data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') misc.write_raw_unsigned_data(data, False, size) w_res = w_bool_type.read(space, data) assert not space.is_true(w_res) lltype.free(data, flavor='raw')
def rcall(self, funcaddr, args): assert self.cif_descr self = jit.promote(self) # no checking of len(args) needed, as calls in this context are not dynamic # The following code is functionally similar to W_CTypeFunc._call, but its # implementation is tailored to the restricted use (include memory handling) # of the CAPI calls. space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) obj = args[i] argtype = self.fargs[i] # the following is clumsy, but the data types used as arguments are # very limited, so it'll do for now if obj.tc == 'l': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned) misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) elif obj.tc == 'h': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned) misc.write_raw_unsigned_data( data, rffi.cast(rffi.ULONG, obj._handle), argtype.size) elif obj.tc == 'p': assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp else: # only other use is sring assert obj.tc == 's' n = len(obj._string) assert raw_string == rffi.cast(rffi.CCHARP, 0) # XXX could use rffi.get_nonmovingbuffer_final_null() raw_string = rffi.str2charp(obj._string) data = rffi.cast(rffi.CCHARPP, data) data[0] = raw_string jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) # this wrapping is unnecessary, but the assumption is that given the # immediate unwrapping, the round-trip is removed w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: if raw_string != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string) lltype.free(buffer, flavor='raw') return w_res
def convert_from_object(self, cdata, w_ob): if self.value_fits_ulong: value = misc.as_unsigned_long(self.space, w_ob, strict=True) if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) misc.write_raw_unsigned_data(cdata, value, self.size) else: self._convert_from_object_longlong(cdata, w_ob)
def test_it_reads_a_string_from_buffer(self, space): w_string_type = ffitype.StringRWStrategy() size = w_string_type.typesize data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') raw_str = rffi.str2charp("test") misc.write_raw_unsigned_data(data, raw_str, size) w_res = w_string_type.read(space, data) assert space.is_kind_of(w_res, space.w_string) assert self.unwrap(space, w_res) == "test" lltype.free(data, flavor='raw')
def test_it_reads_a_pointer_from_buffer(self, space): w_pointer_type = ffitype.PointerRWStrategy() size = w_pointer_type.typesize data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') raw_ptr = rffi.cast(lltype.Unsigned, 12) misc.write_raw_unsigned_data(data, raw_ptr, size) w_res = w_pointer_type.read(space, data) w_pointer_class = space.execute("FFI::Pointer") assert space.is_kind_of(w_res, w_pointer_class) assert self.unwrap(space, space.send(w_res, 'address')) == 12
def test_it_reads_a_string_from_buffer(self, space): w_string_type = ffitype.StringRWStrategy() size = w_string_type.typesize data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') raw_str = rffi.str2charp("test") misc.write_raw_unsigned_data(data, raw_str, size) w_res = w_string_type.read(space, data) assert space.is_kind_of(w_res, space.w_string) assert self.unwrap(space, w_res) == "test" lltype.free(data, flavor='raw')
def test_it_reads_a_pointer_from_buffer(self, space): w_pointer_type = ffitype.PointerRWStrategy() size = w_pointer_type.typesize data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') raw_ptr = rffi.cast(lltype.Unsigned, 12) misc.write_raw_unsigned_data(data, raw_ptr, size) w_res = w_pointer_type.read(space, data) w_pointer_class = space.execute("FFI::Pointer") assert space.is_kind_of(w_res, w_pointer_class) assert self.unwrap(space, space.send(w_res, 'address')) == 12
def rcall(self, funcaddr, args): assert self.cif_descr self = jit.promote(self) # no checking of len(args) needed, as calls in this context are not dynamic # The following code is functionally similar to W_CTypeFunc._call, but its # implementation is tailored to the restricted use (include memory handling) # of the CAPI calls. space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) obj = args[i] argtype = self.fargs[i] # the following is clumsy, but the data types used as arguments are # very limited, so it'll do for now if obj.tc == 'l': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned) misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) elif obj.tc == 'h': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned) misc.write_raw_unsigned_data(data, rffi.cast(rffi.ULONG, obj._handle), argtype.size) elif obj.tc == 'p': assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp else: # only other use is sring assert obj.tc == 's' n = len(obj._string) assert raw_string == rffi.cast(rffi.CCHARP, 0) # XXX could use rffi.get_nonmovingbuffer_final_null() raw_string = rffi.str2charp(obj._string) data = rffi.cast(rffi.CCHARPP, data) data[0] = raw_string jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) # this wrapping is unnecessary, but the assumption is that given the # immediate unwrapping, the round-trip is removed w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: if raw_string != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string) lltype.free(buffer, flavor='raw') return w_res
def test_it_reads_unsigned_types_to_buffer(self, space): for t in [ ffitype.UINT8, ffitype.UINT16, ffitype.UINT32, ffitype.UINT64, ffitype.ULONG ]: w_unsigned_type = ffitype.UnsignedRWStrategy(t) size = w_unsigned_type.typesize # make new buffer for every t data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') misc.write_raw_unsigned_data(data, 42, size) w_res = w_unsigned_type.read(space, data) assert self.unwrap(space, w_res) == 42 lltype.free(data, flavor='raw')
def test_it_reads_unsigned_types_to_buffer(self, space): for t in [ffitype.UINT8, ffitype.UINT16, ffitype.UINT32, ffitype.UINT64, ffitype.ULONG]: w_unsigned_type = ffitype.UnsignedRWStrategy(t) size = w_unsigned_type.typesize # make new buffer for every t data = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') misc.write_raw_unsigned_data(data, 42, size) w_res = w_unsigned_type.read(space, data) assert self.unwrap(space, w_res) == 42 lltype.free(data, flavor='raw')
def write_raw_unsigned_data(self, source): misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self)
def write(self, space, data, w_arg): arg = space.int_w(w_arg) misc.write_raw_unsigned_data(data, arg, self.typesize)
def write(self, space, data, w_arg): w_arg = self._convert_to_NULL_if_nil(space, w_arg) arg = Coerce.ffi_pointer(space, w_arg) arg = rffi.cast(lltype.Unsigned, arg) misc.write_raw_unsigned_data(data, arg, self.typesize)
def write(self, space, data, w_arg): arg = space.str_w(w_arg) arg = rffi.str2charp(arg) arg = rffi.cast(lltype.Unsigned, arg) misc.write_raw_unsigned_data(data, arg, self.typesize)
def convert_from_object(self, cdata, w_ob): ordinal = self._convert_to_charN_t(w_ob) misc.write_raw_unsigned_data(cdata, ordinal, self.size)
def _convert_from_object_longlong(self, cdata, w_ob): # in its own function: LONGLONG may make the whole function jit-opaque value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) misc.write_raw_unsigned_data(cdata, value, self.size)
def write_raw_unsigned_data(self, source): with self as ptr: misc.write_raw_unsigned_data(ptr, source, self.ctype.size)
def rcall(self, funcaddr, args): assert self.cif_descr self = jit.promote(self) # no checking of len(args) needed, as calls in this context are not dynamic # The following code is functionally similar to W_CTypeFunc._call, but its # implementation is tailored to the restricted use (include memory handling) # of the CAPI calls. space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size raw_string1 = rffi.cast(rffi.CCHARP, 0) raw_string2 = rffi.cast(rffi.CCHARP, 0) # have max two in any CAPI buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) obj = args[i] argtype = self.fargs[i] # the following is clumsy, but the data types used as arguments are # very limited, so it'll do for now if obj.tc == 'h': misc.write_raw_unsigned_data( data, rffi.cast(rffi.SIZE_T, obj._scope), argtype.size) elif obj.tc == 'm': misc.write_raw_signed_data( data, rffi.cast(rffi.INTPTR_T, obj._method), argtype.size) elif obj.tc == 'o': # additional cast of void* to intptr_t required for 32b (or intmask fails) misc.write_raw_signed_data( data, rffi.cast(rffi.INTPTR_T, rffi.cast(rffi.VOIDP, obj._object)), argtype.size) elif obj.tc == 'u': misc.write_raw_unsigned_data( data, rffi.cast(rffi.SIZE_T, obj._index), argtype.size) elif obj.tc == 'i': misc.write_raw_signed_data(data, rffi.cast(rffi.INT, obj._int), argtype.size) elif obj.tc == 'd': misc.write_raw_float_data( data, rffi.cast(rffi.DOUBLE, obj._double), argtype.size) elif obj.tc == 'p': assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp elif obj.tc == 's': n = len(obj._string) data = rffi.cast(rffi.CCHARPP, data) if raw_string1 == rffi.cast(rffi.CCHARP, 0): # XXX could use rffi.get_nonmovingbuffer_final_null() raw_string1 = rffi.str2charp(obj._string) data[0] = raw_string1 else: assert raw_string2 == rffi.cast(rffi.CCHARP, 0) raw_string2 = rffi.str2charp(obj._string) data[0] = raw_string2 else: # only other use is voidp assert obj.tc == 'p' assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) # this wrapping is unnecessary, but the assumption is that given the # immediate unwrapping, the round-trip is removed w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: if raw_string1 != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string1) if raw_string2 != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string2) lltype.free(buffer, flavor='raw') return w_res
def write(self, data): misc.write_raw_unsigned_data(data, rffi.cast(rffi.CCHARP, self.heap), rffi.sizeof(clibffi.FFI_CLOSUREP))
def write_raw_unsigned_data(self, source): with self as ptr: misc.write_raw_unsigned_data(ptr, source, self.ctype.size)
def write_raw_unsigned_data(self, source): misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self)