def extend_data(data, length, offset): """Extend data using a length and an offset.""" if length >= offset: new_data = data[-offset:] * (alignValue(length, offset) // offset) return data + new_data[:length] else: return data + data[-offset:-offset + length]
def __init__(self, *args): FieldSet.__init__(self, *args) self._size = (8 + alignValue(self["size"].value, 2)) * 8 tag = self["type"].value if tag in self.TAG_INFO: self._name, self._description, self._parser = self.TAG_INFO[tag] else: self._parser = None
def __init__(self, *args, **kw): FieldSet.__init__(self, *args, **kw) try: self._name, self.handler, self._description = self.TAG_INFO[self["tag"].value] except KeyError: self.handler = None size = self["size"] self._size = size.address + size.size + alignValue(size.value, 2) * 8
def createFields(self): if self.has_all_byte: yield Enum(UInt8(self, "all_defined"), {0: 'False', 1: 'True'}) if self['all_defined'].value: return nbytes = alignValue(self.num, 8) // 8 ctr = 0 for i in xrange(nbytes): for j in reversed(xrange(8)): yield Bit(self, "bit[%d]" % (ctr + j)) ctr += 8
def setCheckedSizes(self, size): # First set size so that end is aligned, if needed self.real_size = size size *= 8 if self.ALIGN: size = alignValue(self.absolute_address + size, 8 * self.ALIGN) \ - self.absolute_address if self._parent._size: if self._parent.current_size + size > self._parent._size: size = self._parent._size - self._parent.current_size self._size = size
def hexadecimal(field): """ Convert an integer to hexadecimal in lower case. Returns unicode string. >>> hexadecimal(type("", (), dict(value=412, size=16))) u'0x019c' >>> hexadecimal(type("", (), dict(value=0, size=32))) u'0x00000000' """ assert hasattr(field, "value") and hasattr(field, "size") size = field.size padding = alignValue(size, 4) // 4 pattern = u"0x%%0%ux" % padding return pattern % field.value
def __init__(self, *args, **kw): FieldSet.__init__(self, *args, **kw) self._size = (8 + alignValue(self["size"].value, 2)) * 8 tag = self["tag"].value if tag in self.TAG_INFO: self.tag_info = self.TAG_INFO[tag] if tag == "LIST": subtag = self["subtag"].value if subtag in self.subtag_info: info = self.subtag_info[subtag] self.tag_info = (info[0], None, info[1]) self._name = self.tag_info[0] self._description = self.tag_info[2] else: self.tag_info = ("field[]", None, None)
def readBits(self, address, nbits, endian): assert endian in (BIG_ENDIAN, LITTLE_ENDIAN, MIDDLE_ENDIAN) if endian is MIDDLE_ENDIAN: # read an aligned chunk of words wordaddr, remainder = divmod(address, 16) wordnbits = alignValue(remainder + nbits, 16) _, data, missing = self.read(wordaddr * 16, wordnbits) shift = remainder else: shift, data, missing = self.read(address, nbits) if missing: raise ReadStreamError(nbits, address) value = str2long(data, endian) if endian in (BIG_ENDIAN, MIDDLE_ENDIAN): value >>= len(data) * 8 - shift - nbits else: value >>= shift return value & (1 << nbits) - 1
def createFields(self): yield String(self, "signature", 4, "8BIM signature", charset="ASCII") if self["signature"].value != "8BIM": raise ParserError("Stream doesn't look like 8BIM item (wrong signature)!") yield textHandler(UInt16(self, "tag"), hexadecimal) if self.stream.readBytes(self.absolute_address + self.current_size, 4) != "\0\0\0\0": yield PascalString8(self, "name") size = 2 + (self["name"].size // 8) % 2 yield NullBytes(self, "name_padding", size) else: yield String(self, "name", 4, strip="\0") yield UInt16(self, "size") size = alignValue(self["size"].value, 2) if not size: return if self.handler: if issubclass(self.handler, FieldSet): yield self.handler(self, "content", size=size * 8) else: yield self.handler(self, "content") else: yield RawBytes(self, "content", size)
def __init__(self, parent, name): FieldSet.__init__(self, parent, name) self._size = alignValue(self["size"].value, 4) * 8
def __init__(self, parent, name, is_32bit=True): FieldSet.__init__(self, parent, name) self._size = alignValue(self["size"].value, 4) * 8 self.is_32bit = is_32bit
def __init__(self, parent, name, width, pixel_class): FieldSet.__init__(self, parent, name) self._pixel = pixel_class self._width = width self._size = alignValue(self._width * self._pixel.static_size, 32)
def __init__(self, parent, name, format, description=None, strip=None, charset=None, nbytes=None, truncate=None): Bytes.__init__(self, parent, name, 1, description) # Is format valid? assert format in self.VALID_FORMATS # Store options self._format = format self._strip = strip self._truncate = truncate # Check charset and compute character size in bytes # (or None when it's not possible to guess character size) if not charset or charset in self.CHARSET_8BIT: self._character_size = 1 # one byte per character elif charset in self.UTF_CHARSET: self._character_size = None else: raise FieldError("Invalid charset for %s: \"%s\"" % (self.path, charset)) self._charset = charset # It is a fixed string? if nbytes is not None: assert self._format == "fixed" # Arbitrary limits, just to catch some bugs... if not (1 <= nbytes <= 0xffff): raise FieldError("Invalid string size for %s: %s" % (self.path, nbytes)) self._content_size = nbytes # content length in bytes self._size = nbytes * 8 self._content_offset = 0 else: # Format with a suffix: Find the end of the string if self._format in self.SUFFIX_FORMAT: self._content_offset = 0 # Choose the suffix suffix = self.suffix_str # Find the suffix length = self._parent.stream.searchBytesLength( suffix, False, self.absolute_address) if length is None: raise FieldError( "Unable to find end of string %s (format %s)!" % (self.path, self._format)) if 1 < len(suffix): # Fix length for little endian bug with UTF-xx charset: # u"abc" -> "a\0b\0c\0\0\0" (UTF-16-LE) # search returns length=5, whereas real lenght is 6 length = alignValue(length, len(suffix)) # Compute sizes self._content_size = length # in bytes self._size = (length + len(suffix)) * 8 # Format with a prefix: Read prefixed length in bytes else: assert self._format in self.PASCAL_FORMATS # Get the prefix size prefix_size = self.PASCAL_FORMATS[self._format] self._content_offset = prefix_size # Read the prefix and compute sizes value = self._parent.stream.readBits(self.absolute_address, prefix_size * 8, self._parent.endian) self._content_size = value # in bytes self._size = (prefix_size + value) * 8 # For UTF-16 and UTF-32, choose the right charset using BOM if self._charset in self.UTF_CHARSET: # Charset requires a BOM? bomsize, endian = self.UTF_CHARSET[self._charset] if endian == "BOM": # Read the BOM value nbytes = bomsize // 8 bom = self._parent.stream.readBytes(self.absolute_address, nbytes) # Choose right charset using the BOM bom_endian = self.UTF_BOM[bomsize] if bom not in bom_endian: raise FieldError("String %s has invalid BOM (%s)!" % (self.path, repr(bom))) self._charset = bom_endian[bom] self._content_size -= nbytes self._content_offset += nbytes # Compute length in character if possible if self._character_size: self._length = self._content_size // self._character_size else: self._length = None