Skip to content

Instantly share code, notes, and snippets.

@k3idii
Created May 31, 2017 17:32
Show Gist options
  • Save k3idii/653133550e854476be7aeb6cf2b16203 to your computer and use it in GitHub Desktop.
Save k3idii/653133550e854476be7aeb6cf2b16203 to your computer and use it in GitHub Desktop.
The power of struct && the power of file-like io ;-)
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