Created
May 31, 2017 17:32
-
-
Save k3idii/653133550e854476be7aeb6cf2b16203 to your computer and use it in GitHub Desktop.
The power of struct && the power of file-like io ;-)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct | |
import os | |
def glue_ex(parts, delim='', preproc=None): | |
if preproc: | |
if isinstance(preproc, list): | |
for fn in preproc: | |
parts = map(fn, parts) | |
elif callable(preproc): | |
parts = map(preproc, parts) | |
return delim.join(parts) | |
def unpack_ex(fmt, data, into=None): | |
size = struct.calcsize(fmt) | |
if len(data) < size: | |
raise Exception("unpack_ex: too few bytes to unpack !") | |
parts = struct.unpack(fmt, data) | |
if not parts: | |
return None | |
if not into: | |
return parts | |
if len(parts) > len(into): | |
raise Exception("unpack_ex: too many values unpacked !") | |
return dict((into[i], parts[i]) for i in range(len(parts))) | |
def hex_dump_fd(fd, bytes=16, title=None, head=True): | |
S = ' \n' | |
if head: | |
if title: | |
S += " .----[ %s ]----- \n" % title | |
S += "| offset ascii hex \n" | |
p = fd.tell() # save | |
fd.seek(0) # rewind | |
fmt = "| 0x%08X %-" + str(bytes) + "s \t %s\n" | |
while True: | |
of = fd.tell() | |
chunk = fd.read(bytes) | |
hx = '' | |
ch = '' | |
for c in list(chunk): | |
ch += c if ord(c) >= 32 and ord(c) < 127 else '.' | |
hx += "%02X " % ord(c) | |
S += fmt % (of, ch, hx) | |
if len(chunk) < bytes: | |
break | |
S += "| 0x%08X \n" % fd.tell() | |
S += "`-- \n" | |
fd.seek(p) | |
return S | |
class StructIO(object): | |
_fd = None | |
prefix = "" | |
def __init__(self, fd): | |
self._fd = fd | |
def __getattr__(self, e): | |
res = getattr(self._fd, e, None) | |
return res | |
def read_n(self, n): | |
d = self._fd.read(n) | |
if not d or len(d) < n: | |
raise Exception("Read error : need %d bytes, got %d " % (n, len(d))) | |
return d | |
def read_fmt(self, fmt="", into=None, untuple_single=True): | |
fmt = self.prefix + fmt | |
sz = struct.calcsize(fmt) | |
d = self.read_n(sz) | |
ret = unpack_ex(fmt, d, into) | |
if untuple_single and into is None and len(ret) == 1: | |
return ret[0] | |
return ret | |
def read_single_fmt(self, fmt): | |
fmt = self.prefix + fmt | |
v = self.read_fmt(fmt) | |
if v: | |
return v[0] | |
else: | |
return None | |
def read_the_rest(self): | |
n = self.available_bytes() | |
return self._fd.read_n(n) | |
def peek(self, size): | |
p = self._fd.tell() | |
r = self.read_n(size) | |
self._fd.seek(p) | |
return r | |
def append(self, data): | |
p = self._fd.tell() | |
self._fd.seek(0, os.SEEK_END) | |
self._fd.write(data) | |
self._fd.seek(p) | |
def append_fmt(self, fmt, *a): | |
return self._fd.append(struct.pack(fmt, *a)) | |
def write_fmt(self, fmt, *a): | |
return self._fd.write(struct.pack(fmt, *a)) | |
def read_all(self): | |
p = self._fd.tell() | |
self._fd.seek(0) | |
v = self._fd.read() | |
self._fd.seek(p) | |
return v | |
def available_bytes(self): | |
org = self._fd.tell() | |
self._fd.seek(0, os.SEEK_END) | |
end = self._fd.tell() | |
self._fd.seek(org) | |
return end - org | |
def get_pos(self): | |
return self._fd.tell() | |
def hex_dump(self, *a, **kw): | |
return hex_dump_fd(self._fd, *a, **kw) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment