def _accept_integral(self, meth): space = self.space w_obj = self.accept_obj_arg() if (space.isinstance_w(w_obj, space.w_int) or space.isinstance_w(w_obj, space.w_long)): w_index = w_obj else: w_index = None if space.lookup(w_obj, '__index__'): try: w_index = space.index(w_obj) except OperationError as e: if not e.match(space, space.w_TypeError): raise pass if w_index is None and space.lookup(w_obj, '__int__'): if space.isinstance_w(w_obj, space.w_float): msg = "integer argument expected, got float" else: msg = "integer argument expected, got non-integer" \ " (implicit conversion using __int__ is deprecated)" space.warn(space.newtext(msg), space.w_DeprecationWarning) w_index = space.int( w_obj) # wrapped float -> wrapped int or long if w_index is None: raise StructError("cannot convert argument to integer") method = getattr(space, meth) try: return method(w_index) except OperationError as e: if e.match(self.space, self.space.w_OverflowError): raise StructError("argument out of range") raise
def accept_obj_arg(self): try: w_obj = self.args_w[self.args_index] except IndexError: raise StructError("struct format requires more arguments") self.args_index += 1 return w_obj
def read(self, count): end = self.inputpos + count if end > len(self.input): raise StructError("unpack str size too short for format") s = self.input[self.inputpos : end] self.inputpos = end return s
def read(self, count): end = self.pos + count if end > self.length: raise StructError("unpack str size too short for format") s = self.buf.getslice(self.pos, end, 1, count) self.pos = end return s
def pack_unichar(fmtiter): unistr = fmtiter.accept_unicode_arg() if len(unistr) != 1: raise StructError("expected a unicode string of length 1") c = unistr[0] # string->char conversion for the annotator unichar.pack_unichar(c, fmtiter.wbuf, fmtiter.pos) fmtiter.advance(unichar.UNICODE_SIZE)
def pack_unichar(fmtiter): utf8, lgt = fmtiter.accept_unicode_arg() if lgt != 1: raise StructError("expected a unicode string of length 1") uchr = rutf8.codepoint_at_pos(utf8, 0) unichar.pack_codepoint(uchr, fmtiter.wbuf, fmtiter.pos) fmtiter.advance(unichar.UNICODE_SIZE)
def pack_char(fmtiter): string = fmtiter.accept_str_arg() if len(string) != 1: raise StructError("expected a string of length 1") c = string[0] # string->char conversion for the annotator fmtiter.wbuf.setitem(fmtiter.pos, c) fmtiter.advance(1)
def unpack_pascal(fmtiter, count): if count == 0: raise StructError("bad '0p' in struct format") data = fmtiter.read(count) end = 1 + ord(data[0]) if end > count: end = count fmtiter.appendobj(data[1:end])
def accept_float_arg(self): w_obj = self.accept_obj_arg() try: return self.space.float_w(w_obj) except OperationError as e: if e.match(self.space, self.space.w_TypeError): raise StructError("required argument is not a float") raise
def skip(self, count): # assumption: UnpackFormatIterator only iterates over # flat structures (continous memory) either: forward (index # grows) or reverse if self.strides: assert len(self.strides) == 1 count = self.strides[0] end = self.pos + count if end > self.length: raise StructError("unpack str size too short for format") self.pos = end
def pack_pascal(fmtiter, count): string = fmtiter.accept_str_arg() prefix = len(string) if prefix >= count: prefix = count - 1 if prefix < 0: raise StructError("bad '0p' in struct format") if prefix > 255: prefix = 255 fmtiter.wbuf.setitem(fmtiter.pos, chr(prefix)) fmtiter.advance(1) _pack_string(fmtiter, string, count - 1)
def pack_int(fmtiter): method = getattr(fmtiter, accept_method) value = method() if not min <= value <= max: raise StructError(errormsg) if fmtiter.bigendian: for i in unroll_revrange_size: x = (value >> (8*i)) & 0xff fmtiter.result.append(chr(x)) else: for i in unroll_revrange_size: fmtiter.result.append(chr(value & 0xff)) value >>= 8
def pack_pascal(fmtiter, count): string = fmtiter.accept_str_arg() prefix = len(string) if prefix >= count: prefix = count - 1 if prefix < 0: raise StructError("bad '0p' in struct format") if prefix > 255: prefixchar = '\xff' else: prefixchar = chr(prefix) fmtiter.result.append(prefixchar) fmtiter.result.append_slice(string, 0, prefix) fmtiter.result.append_multiple_char('\x00', count - (1 + prefix))
def _accept_integral(self, meth): space = self.space w_obj = self.accept_obj_arg() if space.isinstance_w(w_obj, space.w_int): w_index = w_obj else: w_index = None if space.lookup(w_obj, '__index__'): try: w_index = space.index(w_obj) except OperationError as e: if not e.match(space, space.w_TypeError): raise pass if w_index is None: raise StructError("required argument is not an integer") method = getattr(space, meth) try: return method(w_index) except OperationError as e: if e.match(self.space, self.space.w_OverflowError): raise StructError("argument out of range") raise
def _accept_integral(self, meth): space = self.space w_obj = self.accept_obj_arg() if space.isinstance_w(w_obj, space.w_int): w_index = w_obj else: w_index = None if space.lookup(w_obj, '__index__'): try: w_index = space.index(w_obj) except OperationError, e: if not e.match(space, space.w_TypeError): raise pass if w_index is None: raise StructError("required argument is not an integer")
def pack_int(fmtiter): method = getattr(fmtiter, accept_method) value = method() if not min <= value <= max: raise StructError(errormsg) # if pack_fastpath(TYPE)(fmtiter, value): return # pos = fmtiter.pos + size - 1 if fmtiter.bigendian: for i in unroll_revrange_size: x = (value >> (8 * i)) & 0xff fmtiter.wbuf.setitem(pos - i, chr(x)) else: for i in unroll_revrange_size: fmtiter.wbuf.setitem(pos - i, chr(value & 0xff)) value >>= 8 fmtiter.advance(size)
def align(self, mask): pad = (-self.totalsize) & mask try: self.totalsize = ovfcheck(self.totalsize + pad) except OverflowError: raise StructError("total struct size too long")
def operate(self, fmtdesc, repetitions): try: size = ovfcheck(fmtdesc.size * repetitions) self.totalsize = ovfcheck(self.totalsize + size) except OverflowError: raise StructError("total struct size too long")
def interpret(self, fmt): # decode the byte order, size and alignment based on the 1st char table = unroll_native_fmtdescs self.bigendian = native_is_bigendian index = 0 if len(fmt) > 0: c = fmt[0] index = 1 if c == '@': pass elif c == '=': table = unroll_standard_fmtdescs elif c == '<': table = unroll_standard_fmtdescs self.bigendian = False elif c == '>' or c == '!': table = unroll_standard_fmtdescs self.bigendian = True else: index = 0 # interpret the format string, # calling self.operate() for each format unit while index < len(fmt): c = fmt[index] index += 1 if c.isspace(): continue if c.isdigit(): repetitions = ord(c) - ord('0') while True: if index == len(fmt): raise StructError("incomplete struct format") c = fmt[index] index += 1 if not c.isdigit(): break try: repetitions = ovfcheck(repetitions * 10) repetitions = ovfcheck(repetitions + (ord(c) - ord('0'))) except OverflowError: raise StructError("overflow in item count") assert repetitions >= 0 else: repetitions = 1 for fmtdesc in table: if c == fmtdesc.fmtchar: if self._operate_is_specialized_: if fmtdesc.alignment > 1: self.align(fmtdesc.mask) self.operate(fmtdesc, repetitions) break else: if c == '\0': raise StructError("embedded null character") raise StructError("bad char in struct format") if not self._operate_is_specialized_: if fmtdesc.alignment > 1: self.align(fmtdesc.mask) self.operate(fmtdesc, repetitions) self.finished()
def pack_unichar(fmtiter): unistr = fmtiter.accept_unicode_arg() if len(unistr) != 1: raise StructError("expected a unicode string of length 1") c = unistr[0] # string->char conversion for the annotator unichar.pack_unichar(c, fmtiter.result)
def finished(self): value = self.pos if self.strides and self.strides[0] < 0: value = -self.pos if value != self.length: raise StructError("unpack str size too long for format")
def finished(self): if self.pos != self.length: raise StructError("unpack str size too long for format")
def advance(self, count): if not self.can_advance(count): raise StructError("unpack str size too short for format") self.pos += count
def finished(self): if self.args_index != len(self.args_w): raise StructError("too many arguments for struct format")
class PackFormatIterator(FormatIterator): def __init__(self, space, args_w, size): self.space = space self.args_w = args_w self.args_index = 0 self.result = StringBuilder(size) # This *should* be always unroll safe, the only way to get here is by # unroll the interpret function, which means the fmt is const, and thus # this should be const (in theory ;) @jit.unroll_safe @specialize.arg(1) def operate(self, fmtdesc, repetitions): if fmtdesc.needcount: fmtdesc.pack(self, repetitions) else: for i in range(repetitions): fmtdesc.pack(self) _operate_is_specialized_ = True @jit.unroll_safe def align(self, mask): pad = (-self.result.getlength()) & mask self.result.append_multiple_char('\x00', pad) def finished(self): if self.args_index != len(self.args_w): raise StructError("too many arguments for struct format") def accept_obj_arg(self): try: w_obj = self.args_w[self.args_index] except IndexError: raise StructError("struct format requires more arguments") self.args_index += 1 return w_obj def accept_int_arg(self): return self._accept_integral("int_w") def accept_uint_arg(self): return self._accept_integral("uint_w") def accept_longlong_arg(self): return self._accept_integral("r_longlong_w") def accept_ulonglong_arg(self): return self._accept_integral("r_ulonglong_w") @specialize.arg(1) def _accept_integral(self, meth): space = self.space w_obj = self.accept_obj_arg() if (space.isinstance_w(w_obj, space.w_int) or space.isinstance_w(w_obj, space.w_long)): w_index = w_obj else: w_index = None if space.lookup(w_obj, '__index__'): try: w_index = space.index(w_obj) except OperationError, e: if not e.match(space, space.w_TypeError): raise pass if w_index is None and space.lookup(w_obj, '__int__'): if space.isinstance_w(w_obj, space.w_float): msg = "integer argument expected, got float" else: msg = "integer argument expected, got non-integer" \ " (implicit conversion using __int__ is deprecated)" space.warn(space.wrap(msg), space.w_DeprecationWarning) w_index = space.int( w_obj) # wrapped float -> wrapped int or long if w_index is None: raise StructError("cannot convert argument to integer") method = getattr(space, meth) try: return method(w_index) except OperationError as e: if e.match(self.space, self.space.w_OverflowError): raise StructError("argument out of range") raise
def pack_char(fmtiter): string = fmtiter.accept_str_arg() if len(string) != 1: raise StructError("expected a string of length 1") c = string[0] # string->char conversion for the annotator fmtiter.result.append(c)