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 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 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 pack_int(fmtiter): method = getattr(fmtiter, accept_method) value = method() if check_range: if value < min or 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 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 += string[:prefix] for i in range(1 + prefix, count): fmtiter.result.append('\x00')
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): if self.inputpos != len(self.input): raise StructError('unpack str size too long for format')
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: 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 finished(self): if self.args_index != len(self.args_w): raise StructError("too many arguments for struct format")
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)