# Copyright (c) 2011-2015 Rusty Wagner
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from BinaryData import *
class _ParserState:
def __init__(self, data, ofs):
self.data = data
self.offset = ofs
class Array:
def __init__(self, state, count):
self._state = state
self.elements = []
for i in range(0, count):
self.elements += [Structure(state.data, state)]
def append(self):
self.elements.append(Structure(self._state.data, self._state))
def getStart(self):
start = None
for i in self.elements:
if (start == None) or (i.getStart() < start):
start = i.getStart()
if start == None:
return 0
return start
def getSize(self):
start = self.getStart()
end = None
for i in self.elements:
if (end == None) or ((i.getStart() + i.getSize()) > end):
end = i.getStart() + i.getSize()
if end == None:
return 0
return end - start
def complete(self):
for i in self.elements:
i.complete()
def __getitem__(self, index):
return self.elements[index]
def __len__(self):
return len(self.elements)
class Structure:
def __init__(self, data, state = None):
self._data = data
self._state = state
if state == None:
self._state = _ParserState(data, 0)
self._names = {}
self._order = []
self._start = {}
self._size = {}
self._type = {}
def seek(self, ofs):
self._state.offset = ofs
def struct(self, name, id = None):
if id == None:
id = name
result = Structure(self._data, self._state)
self.__dict__[id] = result
self._names[id] = name
self._type[id] = "struct"
self._order += [id]
return result
def array(self, count, name, id = None):
if id == None:
id = name
result = Array(self._state, count)
self.__dict__[id] = result
self._names[id] = name
self._type[id] = "array"
self._order += [id]
return result
def bytes(self, count, name, id = None):
if id == None:
id = name
result = self._data.read(self._state.offset, count)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = count
self._type[id] = "bytes"
self._order += [id]
self._state.offset += count
return result
def uint8(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint8(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 1
self._type[id] = "uint8"
self._order += [id]
self._state.offset += 1
return result
def uint16(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint16(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 2
self._type[id] = "uint16"
self._order += [id]
self._state.offset += 2
return result
def uint32(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint32(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 4
self._type[id] = "uint32"
self._order += [id]
self._state.offset += 4
return result
def uint64(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint64(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 8
self._type[id] = "uint64"
self._order += [id]
self._state.offset += 8
return result
def uint16_le(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint16_le(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 2
self._type[id] = "uint16_le"
self._order += [id]
self._state.offset += 2
return result
def uint32_le(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint32_le(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 4
self._type[id] = "uint32_le"
self._order += [id]
self._state.offset += 4
return result
def uint64_le(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint64_le(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 8
self._type[id] = "uint64_le"
self._order += [id]
self._state.offset += 8
return result
def uint16_be(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint16_be(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 2
self._type[id] = "uint16_be"
self._order += [id]
self._state.offset += 2
return result
def uint32_be(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint32_be(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 4
self._type[id] = "uint32_be"
self._order += [id]
self._state.offset += 4
return result
def uint64_be(self, name, id = None):
if id == None:
id = name
result = self._data.read_uint64_be(self._state.offset)
self.__dict__[id] = result
self._names[id] = name
self._start[id] = self._state.offset
self._size[id] = 8
self._type[id] = "uint64_be"
self._order += [id]
self._state.offset += 8
return result
def getStart(self):
self.complete()
start = None
for i in self._order:
if (start == None) or (self._start[i] < start):
start = self._start[i]
return start
def getSize(self):
start = self.getStart()
end = None
for i in self._order:
if (end == None) or ((self._start[i] + self._size[i]) > end):
end = self._start[i] + self._size[i]
if end == None:
return None
return end - start
def complete(self):
for i in self._order:
if (not self._start.has_key(i)) or (not self._size.has_key(i)):
self.__dict__[i].complete()
self._start[i] = self.__dict__[i].getStart()
self._size[i] = self.__dict__[i].getSize()