def get_new_array_length(self, w_value): space = self.space if (space.isinstance_w(w_value, space.w_list) or space.isinstance_w(w_value, space.w_tuple)): return (w_value, space.int_w(space.len(w_value))) elif space.isinstance_w(w_value, space.w_bytes): # from a string, we add the null terminator s = space.bytes_w(w_value) return (w_value, len(s) + 1) elif space.isinstance_w(w_value, space.w_unicode): from pypy.module._cffi_backend import wchar_helper u = space.unicode_w(w_value) if self.ctitem.size == 2: length = wchar_helper.unicode_size_as_char16(u) else: length = wchar_helper.unicode_size_as_char32(u) return (w_value, length + 1) else: try: explicitlength = space.getindex_w(w_value, space.w_OverflowError) except OperationError as e: if e.match(space, space.w_TypeError): raise oefmt(space.w_TypeError, "expected new array length or list/tuple/str, " "not %T", w_value) raise if explicitlength < 0: raise oefmt(space.w_ValueError, "negative array length") return (space.w_None, explicitlength)
def _prepare_pointer_call_argument(self, w_init, cdata, keepalives, i): space = self.space if self.accept_str and space.isinstance_w(w_init, space.w_bytes): # special case to optimize strings passed to a "char *" argument value = space.bytes_w(w_init) if isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveBool): self._must_be_string_of_zero_or_one(value) keepalives[i] = value buf, buf_flag = rffi.get_nonmovingbuffer_final_null(value) rffi.cast(rffi.CCHARPP, cdata)[0] = buf return ord(buf_flag) # 4, 5 or 6 # if (space.isinstance_w(w_init, space.w_list) or space.isinstance_w(w_init, space.w_tuple)): length = space.int_w(space.len(w_init)) elif space.isinstance_w(w_init, space.w_bytes): # from a string, we add the null terminator s = space.bytes_w(w_init) length = len(s) + 1 elif space.isinstance_w(w_init, space.w_unicode): from pypy.module._cffi_backend import wchar_helper u = space.unicode_w(w_init) if self.ctitem.size == 2: length = wchar_helper.unicode_size_as_char16(u) else: length = wchar_helper.unicode_size_as_char32(u) length += 1 elif self.is_file: result = self.prepare_file(w_init) if result: rffi.cast(rffi.CCHARPP, cdata)[0] = result return 2 return 0 else: return 0 itemsize = self.ctitem.size if itemsize <= 0: if isinstance(self.ctitem, ctypevoid.W_CTypeVoid): itemsize = 1 else: return 0 try: datasize = ovfcheck(length * itemsize) except OverflowError: raise oefmt(space.w_OverflowError, "array size would overflow a ssize_t") result = lltype.malloc(rffi.CCHARP.TO, datasize, flavor='raw', zero=True) try: self.convert_array_from_object(result, w_init) except Exception: lltype.free(result, flavor='raw') raise rffi.cast(rffi.CCHARPP, cdata)[0] = result return 1
def convert_array_from_object(self, cdata, w_ob): space = self.space if (space.isinstance_w(w_ob, space.w_list) or space.isinstance_w(w_ob, space.w_tuple)): if self.ctitem.pack_list_of_items(cdata, w_ob): # fast path pass else: self._convert_array_from_listview(cdata, space.listview(w_ob)) elif self.accept_str: if not space.isinstance_w(w_ob, space.w_bytes): raise self._convert_error("str or list or tuple", w_ob) s = space.bytes_w(w_ob) n = len(s) if self.length >= 0 and n > self.length: raise oefmt( space.w_IndexError, "initializer string is too long for '%s' (got %d " "characters)", self.name, n) if isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveBool): self._must_be_string_of_zero_or_one(s) copy_string_to_raw(llstr(s), cdata, 0, n) if n != self.length: cdata[n] = '\x00' elif isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar): from pypy.module._cffi_backend import wchar_helper if not space.isinstance_w(w_ob, space.w_unicode): raise self._convert_error("unicode or list or tuple", w_ob) s = space.unicode_w(w_ob) if self.ctitem.size == 2: n = wchar_helper.unicode_size_as_char16(s) else: n = wchar_helper.unicode_size_as_char32(s) if self.length >= 0 and n > self.length: raise oefmt( space.w_IndexError, "initializer unicode string is too long for '%s' " "(got %d characters)", self.name, n) add_final_zero = (n != self.length) if self.ctitem.size == 2: try: wchar_helper.unicode_to_char16(s, cdata, n, add_final_zero) except wchar_helper.OutOfRange as e: raise oefmt( self.space.w_ValueError, "unicode character ouf of range for " "conversion to char16_t: %s", hex(e.ordinal)) else: wchar_helper.unicode_to_char32(s, cdata, n, add_final_zero) else: raise self._convert_error("list or tuple", w_ob)