77 lines
1.8 KiB
Python
77 lines
1.8 KiB
Python
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]))
|