import os import ctypes import struct class BinaryReader: def __init__(self, buf, endian="<"): self.buf = buf self.endian = endian self.seek(0, 2) self.size = self.tell() self.seek(0) def read(self, *args): return self.buf.read(*args) def seek(self, *args): return self.buf.seek(*args) def tell(self): return self.buf.tell() def finished(self): return self.tell() == self.size def read_string(self, maxlen=0): r = [] start = self.tell() while maxlen == 0 or len(r) <= maxlen: c = self.read(1) if not c: raise ValueError("Unterminated string starting at %d" % (start)) if c == b"\0": break r.append(c) return b"".join(r) def struct_calcsize(self, fmt): return struct.calcsize(fmt) def read_struct(self, fmt, endian=None): fmt = (endian or self.endian) + fmt; fmtlen = struct.calcsize(fmt) data = self.read(fmtlen) if len(data) != fmtlen: raise ValueError("Not enough bytes left in buffer to read struct") return struct.unpack(fmt, data) def read_struct_into(self, dest, fmt, endian=None): fields = self.read_struct(fmt, endian=endian) fields = list(fields) + [None] * (len(dest._fields) - len(fields)) return dest._make(fields) def read_type(self, type_fmt, endian=None): r = self.read_struct(type_fmt, endian=endian) if len(r) != 1: raise ValueError("Format %r did not describe a single type" % (type_fmt)) return r[0] class LibraryNotFoundException(OSError): pass def load_lib(*names): for name in names: try: libname = ctypes.util.find_library(name) if libname: return ctypes.CDLL(libname) else: dll_path = os.path.join(os.getcwd(), "lib%s.dll" % (name)) return ctypes.CDLL(dll_path) except OSError: pass raise LibraryNotFoundException("Could not load the library %r" % (names[0]))