diff options
Diffstat (limited to 'external/construct/lib')
-rw-r--r-- | external/construct/lib/__init__.py | 5 | ||||
-rw-r--r-- | external/construct/lib/__init__.pyc | bin | 0 -> 700 bytes | |||
-rw-r--r-- | external/construct/lib/binary.py | 187 | ||||
-rw-r--r-- | external/construct/lib/binary.pyc | bin | 0 -> 7551 bytes | |||
-rw-r--r-- | external/construct/lib/bitstream.py | 81 | ||||
-rw-r--r-- | external/construct/lib/bitstream.pyc | bin | 0 -> 4227 bytes | |||
-rw-r--r-- | external/construct/lib/container.py | 224 | ||||
-rw-r--r-- | external/construct/lib/container.pyc | bin | 0 -> 11401 bytes | |||
-rw-r--r-- | external/construct/lib/expr.py | 166 | ||||
-rw-r--r-- | external/construct/lib/expr.pyc | bin | 0 -> 12000 bytes | |||
-rw-r--r-- | external/construct/lib/hex.py | 46 | ||||
-rw-r--r-- | external/construct/lib/hex.pyc | bin | 0 -> 3081 bytes | |||
-rw-r--r-- | external/construct/lib/py3compat.py | 70 | ||||
-rw-r--r-- | external/construct/lib/py3compat.pyc | bin | 0 -> 3600 bytes |
14 files changed, 779 insertions, 0 deletions
diff --git a/external/construct/lib/__init__.py b/external/construct/lib/__init__.py new file mode 100644 index 0000000..2d533e8 --- /dev/null +++ b/external/construct/lib/__init__.py @@ -0,0 +1,5 @@ +from construct.lib.binary import int_to_bin, bin_to_int, swap_bytes, encode_bin, decode_bin +from construct.lib.bitstream import BitStreamReader, BitStreamWriter +from construct.lib.container import (Container, FlagsContainer, ListContainer, + LazyContainer) +from construct.lib.hex import HexString, hexdump diff --git a/external/construct/lib/__init__.pyc b/external/construct/lib/__init__.pyc Binary files differnew file mode 100644 index 0000000..6eda7eb --- /dev/null +++ b/external/construct/lib/__init__.pyc diff --git a/external/construct/lib/binary.py b/external/construct/lib/binary.py new file mode 100644 index 0000000..c5ef9b3 --- /dev/null +++ b/external/construct/lib/binary.py @@ -0,0 +1,187 @@ +import six +from construct.lib.py3compat import int2byte + + +if six.PY3: + def int_to_bin(number, width = 32): + r""" + Convert an integer into its binary representation in a bytes object. + Width is the amount of bits to generate. If width is larger than the actual + amount of bits required to represent number in binary, sign-extension is + used. If it's smaller, the representation is trimmed to width bits. + Each "bit" is either '\x00' or '\x01'. The MSBit is first. + + Examples: + + >>> int_to_bin(19, 5) + b'\x01\x00\x00\x01\x01' + >>> int_to_bin(19, 8) + b'\x00\x00\x00\x01\x00\x00\x01\x01' + """ + number = int(number) + if number < 0: + number += 1 << width + i = width - 1 + bits = bytearray(width) + while number and i >= 0: + bits[i] = number & 1 + number >>= 1 + i -= 1 + return bytes(bits) + + # heavily optimized for performance + def bin_to_int(bits, signed = False): + r""" + Logical opposite of int_to_bin. Both '0' and '\x00' are considered zero, + and both '1' and '\x01' are considered one. Set sign to True to interpret + the number as a 2-s complement signed integer. + """ + bits = "".join("01"[b & 1] for b in bits) + if signed and bits[0] == "1": + bits = bits[1:] + bias = 1 << len(bits) + else: + bias = 0 + return int(bits, 2) - bias + + _char_to_bin = [0] * 256 + _bin_to_char = {} + for i in range(256): + ch = int2byte(i) + bin = int_to_bin(i, 8) + # Populate with for both keys i and ch, to support Python 2 & 3 + _char_to_bin[i] = bin + _bin_to_char[bin] = ord(ch) + + def encode_bin(data): + """ + Create a binary representation of the given b'' object. Assume 8-bit + ASCII. Example: + + >>> encode_bin('ab') + b"\x00\x01\x01\x00\x00\x00\x00\x01\x00\x01\x01\x00\x00\x00\x01\x00" + """ + return six.b("").join(_char_to_bin[int(ch)] for ch in data) + + def decode_bin(data): + if len(data) & 7: + raise ValueError("Data length must be a multiple of 8") + i = 0 + j = 0 + l = len(data) // 8 + arr = bytearray(l) + while j < l: + arr[j] = _bin_to_char[data[i:i+8]] + i += 8 + j += 1 + return arr + + def swap_bytes(bits, bytesize=8): + r""" + Bits is a b'' object containing a binary representation. Assuming each + bytesize bits constitute a bytes, perform a endianness byte swap. Example: + + >>> swap_bytes(b'00011011', 2) + b'11100100' + """ + i = 0 + l = len(bits) + output = [six.b("")] * ((l // bytesize) + 1) + j = len(output) - 1 + while i < l: + output[j] = bits[i : i + bytesize] + i += bytesize + j -= 1 + return six.b("").join(output) + +else: + + def int_to_bin(number, width = 32): + r""" + Convert an integer into its binary representation in a bytes object. + Width is the amount of bits to generate. If width is larger than the actual + amount of bits required to represent number in binary, sign-extension is + used. If it's smaller, the representation is trimmed to width bits. + Each "bit" is either '\x00' or '\x01'. The MSBit is first. + + Examples: + + >>> int_to_bin(19, 5) + '\x01\x00\x00\x01\x01' + >>> int_to_bin(19, 8) + '\x00\x00\x00\x01\x00\x00\x01\x01' + """ + if number < 0: + number += 1 << width + i = width - 1 + bits = ["\x00"] * width + while number and i >= 0: + bits[i] = "\x00\x01"[number & 1] + number >>= 1 + i -= 1 + return "".join(bits) + + # heavily optimized for performance + def bin_to_int(bits, signed = False): + r""" + Logical opposite of int_to_bin. Both '0' and '\x00' are considered zero, + and both '1' and '\x01' are considered one. Set sign to True to interpret + the number as a 2-s complement signed integer. + """ + bits = "".join("01"[ord(b) & 1] for b in bits) + if signed and bits[0] == "1": + bits = bits[1:] + bias = 1 << len(bits) + else: + bias = 0 + return int(bits, 2) - bias + + _char_to_bin = [0] * 256 + _bin_to_char = {} + for i in range(256): + ch = int2byte(i) + bin = int_to_bin(i, 8) + # Populate with for both keys i and ch, to support Python 2 & 3 + _char_to_bin[i] = bin + _bin_to_char[bin] = ch + + def encode_bin(data): + """ + Create a binary representation of the given b'' object. Assume 8-bit + ASCII. Example: + + >>> encode_bin('ab') + b"\x00\x01\x01\x00\x00\x00\x00\x01\x00\x01\x01\x00\x00\x00\x01\x00" + """ + return "".join(_char_to_bin[ord(ch)] for ch in data) + + def decode_bin(data): + if len(data) & 7: + raise ValueError("Data length must be a multiple of 8") + i = 0 + j = 0 + l = len(data) // 8 + chars = [""] * l + while j < l: + chars[j] = _bin_to_char[data[i:i+8]] + i += 8 + j += 1 + return "".join(chars) + + def swap_bytes(bits, bytesize=8): + r""" + Bits is a b'' object containing a binary representation. Assuming each + bytesize bits constitute a bytes, perform a endianness byte swap. Example: + + >>> swap_bytes(b'00011011', 2) + b'11100100' + """ + i = 0 + l = len(bits) + output = [""] * ((l // bytesize) + 1) + j = len(output) - 1 + while i < l: + output[j] = bits[i : i + bytesize] + i += bytesize + j -= 1 + return "".join(output) diff --git a/external/construct/lib/binary.pyc b/external/construct/lib/binary.pyc Binary files differnew file mode 100644 index 0000000..1614005 --- /dev/null +++ b/external/construct/lib/binary.pyc diff --git a/external/construct/lib/bitstream.py b/external/construct/lib/bitstream.py new file mode 100644 index 0000000..3b51f66 --- /dev/null +++ b/external/construct/lib/bitstream.py @@ -0,0 +1,81 @@ +import six +from construct.lib.binary import encode_bin, decode_bin + +try: + bytes +except NameError: + bytes = str + +class BitStreamReader(object): + __slots__ = ["substream", "buffer", "total_size"] + + def __init__(self, substream): + self.substream = substream + self.total_size = 0 + self.buffer = six.b("") + + def close(self): + if self.total_size % 8 != 0: + raise ValueError("total size of read data must be a multiple of 8", + self.total_size) + + def tell(self): + return self.substream.tell() + + def seek(self, pos, whence = 0): + self.buffer = six.b("") + self.total_size = 0 + self.substream.seek(pos, whence) + + def read(self, count): + if count < 0: + raise ValueError("count cannot be negative") + + l = len(self.buffer) + if count == 0: + data = six.b("") + elif count <= l: + data = self.buffer[:count] + self.buffer = self.buffer[count:] + else: + data = self.buffer + count -= l + count_bytes = count // 8 + if count & 7: + count_bytes += 1 + buf = encode_bin(self.substream.read(count_bytes)) + data += buf[:count] + self.buffer = buf[count:] + self.total_size += len(data) + return data + +class BitStreamWriter(object): + __slots__ = ["substream", "buffer", "pos"] + + def __init__(self, substream): + self.substream = substream + self.buffer = [] + self.pos = 0 + + def close(self): + self.flush() + + def flush(self): + raw = decode_bin(six.b("").join(self.buffer)) + self.substream.write(raw) + self.buffer = [] + self.pos = 0 + + def tell(self): + return self.substream.tell() + self.pos // 8 + + def seek(self, pos, whence = 0): + self.flush() + self.substream.seek(pos, whence) + + def write(self, data): + if not data: + return + if not isinstance(data, bytes): + raise TypeError("data must be a string, not %r" % (type(data),)) + self.buffer.append(data) diff --git a/external/construct/lib/bitstream.pyc b/external/construct/lib/bitstream.pyc Binary files differnew file mode 100644 index 0000000..8ea4399 --- /dev/null +++ b/external/construct/lib/bitstream.pyc diff --git a/external/construct/lib/container.py b/external/construct/lib/container.py new file mode 100644 index 0000000..f04d037 --- /dev/null +++ b/external/construct/lib/container.py @@ -0,0 +1,224 @@ +""" +Various containers. +""" + +def recursion_lock(retval, lock_name = "__recursion_lock__"): + def decorator(func): + def wrapper(self, *args, **kw): + if getattr(self, lock_name, False): + return retval + setattr(self, lock_name, True) + try: + return func(self, *args, **kw) + finally: + setattr(self, lock_name, False) + wrapper.__name__ = func.__name__ + return wrapper + return decorator + +class Container(dict): + """ + A generic container of attributes. + + Containers are the common way to express parsed data. + """ + __slots__ = ["__keys_order__"] + + def __init__(self, **kw): + object.__setattr__(self, "__keys_order__", []) + for k, v in kw.items(): + self[k] = v + def __getattr__(self, name): + try: + return self[name] + except KeyError: + raise AttributeError(name) + def __setitem__(self, key, val): + if key not in self: + self.__keys_order__.append(key) + dict.__setitem__(self, key, val) + def __delitem__(self, key): + dict.__delitem__(self, key) + self.__keys_order__.remove(key) + + __delattr__ = __delitem__ + __setattr__ = __setitem__ + + def clear(self): + dict.clear(self) + del self.__keys_order__[:] + def pop(self, key, *default): + val = dict.pop(self, key, *default) + self.__keys_order__.remove(key) + return val + def popitem(self): + k, v = dict.popitem(self) + self.__keys_order__.remove(k) + return k, v + + def update(self, seq, **kw): + if hasattr(seq, "keys"): + for k in seq.keys(): + self[k] = seq[k] + else: + for k, v in seq: + self[k] = v + dict.update(self, kw) + + def copy(self): + inst = self.__class__() + inst.update(self.iteritems()) + return inst + + __update__ = update + __copy__ = copy + + def __iter__(self): + return iter(self.__keys_order__) + iterkeys = __iter__ + def itervalues(self): + return (self[k] for k in self.__keys_order__) + def iteritems(self): + return ((k, self[k]) for k in self.__keys_order__) + def keys(self): + return self.__keys_order__ + def values(self): + return list(self.itervalues()) + def items(self): + return list(self.iteritems()) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, dict.__repr__(self)) + + @recursion_lock("<...>") + def __pretty_str__(self, nesting = 1, indentation = " "): + attrs = [] + ind = indentation * nesting + for k, v in self.iteritems(): + if not k.startswith("_"): + text = [ind, k, " = "] + if hasattr(v, "__pretty_str__"): + text.append(v.__pretty_str__(nesting + 1, indentation)) + else: + text.append(repr(v)) + attrs.append("".join(text)) + if not attrs: + return "%s()" % (self.__class__.__name__,) + attrs.insert(0, self.__class__.__name__ + ":") + return "\n".join(attrs) + + __str__ = __pretty_str__ + + +class FlagsContainer(Container): + """ + A container providing pretty-printing for flags. + + Only set flags are displayed. + """ + + @recursion_lock("<...>") + def __pretty_str__(self, nesting = 1, indentation = " "): + attrs = [] + ind = indentation * nesting + for k in self.keys(): + v = self[k] + if not k.startswith("_") and v: + attrs.append(ind + k) + if not attrs: + return "%s()" % (self.__class__.__name__,) + attrs.insert(0, self.__class__.__name__+ ":") + return "\n".join(attrs) + + +class ListContainer(list): + """ + A container for lists. + """ + __slots__ = ["__recursion_lock__"] + + def __str__(self): + return self.__pretty_str__() + + @recursion_lock("[...]") + def __pretty_str__(self, nesting = 1, indentation = " "): + if not self: + return "[]" + ind = indentation * nesting + lines = ["["] + for elem in self: + lines.append("\n") + lines.append(ind) + if hasattr(elem, "__pretty_str__"): + lines.append(elem.__pretty_str__(nesting + 1, indentation)) + else: + lines.append(repr(elem)) + lines.append("\n") + lines.append(indentation * (nesting - 1)) + lines.append("]") + return "".join(lines) + + +class LazyContainer(object): + + __slots__ = ["subcon", "stream", "pos", "context", "_value"] + + def __init__(self, subcon, stream, pos, context): + self.subcon = subcon + self.stream = stream + self.pos = pos + self.context = context + self._value = NotImplemented + + def __eq__(self, other): + try: + return self._value == other._value + except AttributeError: + return False + + def __ne__(self, other): + return not (self == other) + + def __str__(self): + return self.__pretty_str__() + + def __pretty_str__(self, nesting = 1, indentation = " "): + if self._value is NotImplemented: + text = "<unread>" + elif hasattr(self._value, "__pretty_str__"): + text = self._value.__pretty_str__(nesting, indentation) + else: + text = str(self._value) + return "%s: %s" % (self.__class__.__name__, text) + + def read(self): + self.stream.seek(self.pos) + return self.subcon._parse(self.stream, self.context) + + def dispose(self): + self.subcon = None + self.stream = None + self.context = None + self.pos = None + + def _get_value(self): + if self._value is NotImplemented: + self._value = self.read() + return self._value + + value = property(_get_value) + + has_value = property(lambda self: self._value is not NotImplemented) + + + +if __name__ == "__main__": + c = Container(x=5) + c.y = 8 + c.z = 9 + c.w = 10 + c.foo = 5 + + print (c) + + diff --git a/external/construct/lib/container.pyc b/external/construct/lib/container.pyc Binary files differnew file mode 100644 index 0000000..690afbb --- /dev/null +++ b/external/construct/lib/container.pyc diff --git a/external/construct/lib/expr.py b/external/construct/lib/expr.py new file mode 100644 index 0000000..783c947 --- /dev/null +++ b/external/construct/lib/expr.py @@ -0,0 +1,166 @@ +import operator + +if not hasattr(operator, "div"): + operator.div = operator.truediv + + +opnames = { + operator.add : "+", + operator.sub : "-", + operator.mul : "*", + operator.div : "/", + operator.floordiv : "//", + operator.mod : "+", + operator.pow : "**", + operator.xor : "^", + operator.lshift : "<<", + operator.rshift : ">>", + operator.and_ : "and", + operator.or_ : "or", + operator.not_ : "not", + operator.neg : "-", + operator.pos : "+", + operator.contains : "in", + operator.gt : ">", + operator.ge : ">=", + operator.lt : "<", + operator.le : "<=", + operator.eq : "==", + operator.ne : "!=", +} + + +class ExprMixin(object): + __slots__ = () + def __add__(self, other): + return BinExpr(operator.add, self, other) + def __sub__(self, other): + return BinExpr(operator.sub, self, other) + def __mul__(self, other): + return BinExpr(operator.mul, self, other) + def __floordiv__(self, other): + return BinExpr(operator.floordiv, self, other) + def __truediv__(self, other): + return BinExpr(operator.div, self, other) + __div__ = __floordiv__ + def __mod__(self, other): + return BinExpr(operator.mod, self, other) + def __pow__(self, other): + return BinExpr(operator.pow, self, other) + def __xor__(self, other): + return BinExpr(operator.xor, self, other) + def __rshift__(self, other): + return BinExpr(operator.rshift, self, other) + def __lshift__(self, other): + return BinExpr(operator.rshift, self, other) + def __and__(self, other): + return BinExpr(operator.and_, self, other) + def __or__(self, other): + return BinExpr(operator.or_, self, other) + + def __radd__(self, other): + return BinExpr(operator.add, other, self) + def __rsub__(self, other): + return BinExpr(operator.sub, other, self) + def __rmul__(self, other): + return BinExpr(operator.mul, other, self) + def __rfloordiv__(self, other): + return BinExpr(operator.floordiv, other, self) + def __rtruediv__(self, other): + return BinExpr(operator.div, other, self) + __rdiv__ = __rfloordiv__ + def __rmod__(self, other): + return BinExpr(operator.mod, other, self) + def __rpow__(self, other): + return BinExpr(operator.pow, other, self) + def __rxor__(self, other): + return BinExpr(operator.xor, other, self) + def __rrshift__(self, other): + return BinExpr(operator.rshift, other, self) + def __rlshift__(self, other): + return BinExpr(operator.rshift, other, self) + def __rand__(self, other): + return BinExpr(operator.and_, other, self) + def __ror__(self, other): + return BinExpr(operator.or_, other, self) + + def __neg__(self): + return UniExpr(operator.neg, self) + def __pos__(self): + return UniExpr(operator.pos, self) + def __invert__(self): + return UniExpr(operator.not_, self) + __inv__ = __invert__ + + def __contains__(self, other): + return BinExpr(operator.contains, self, other) + def __gt__(self, other): + return BinExpr(operator.gt, self, other) + def __ge__(self, other): + return BinExpr(operator.ge, self, other) + def __lt__(self, other): + return BinExpr(operator.lt, self, other) + def __le__(self, other): + return BinExpr(operator.le, self, other) + def __eq__(self, other): + return BinExpr(operator.eq, self, other) + def __ne__(self, other): + return BinExpr(operator.ne, self, other) + + +class UniExpr(ExprMixin): + __slots__ = ["op", "operand"] + def __init__(self, op, operand): + self.op = op + self.operand = operand + def __repr__(self): + return "%s %r" % (opnames[self.op], self.operand) + def __call__(self, context): + operand = self.operand(context) if callable(self.operand) else self.operand + return self.op(operand) + + +class BinExpr(ExprMixin): + __slots__ = ["op", "lhs", "rhs"] + def __init__(self, op, lhs, rhs): + self.op = op + self.lhs = lhs + self.rhs = rhs + def __repr__(self): + return "(%r %s %r)" % (self.lhs, opnames[self.op], self.rhs) + def __call__(self, context): + lhs = self.lhs(context) if callable(self.lhs) else self.lhs + rhs = self.rhs(context) if callable(self.rhs) else self.rhs + return self.op(lhs, rhs) + + +class Path(ExprMixin): + __slots__ = ["__name", "__parent"] + def __init__(self, name, parent = None): + self.__name = name + self.__parent = parent + def __repr__(self): + if self.__parent is None: + return self.__name + return "%r.%s" % (self.__parent, self.__name) + def __call__(self, context): + if self.__parent is None: + return context + context2 = self.__parent(context) + return context2[self.__name] + def __getattr__(self, name): + return Path(name, self) + + +# let the magic begin! +this = Path("this") + + +if __name__ == "__main__": + x = ~((this.foo * 2 + 3 << 2) % 11) + print (x) + print (x({"foo" : 7})) + + + + diff --git a/external/construct/lib/expr.pyc b/external/construct/lib/expr.pyc Binary files differnew file mode 100644 index 0000000..14e1ca2 --- /dev/null +++ b/external/construct/lib/expr.pyc diff --git a/external/construct/lib/hex.py b/external/construct/lib/hex.py new file mode 100644 index 0000000..62fd3c7 --- /dev/null +++ b/external/construct/lib/hex.py @@ -0,0 +1,46 @@ +from construct.lib.py3compat import byte2int, int2byte, bytes2str + + +# Map an integer in the inclusive range 0-255 to its string byte representation +_printable = dict((i, ".") for i in range(256)) +_printable.update((i, bytes2str(int2byte(i))) for i in range(32, 128)) + + +def hexdump(data, linesize): + """ + data is a bytes object. The returned result is a string. + """ + prettylines = [] + if len(data) < 65536: + fmt = "%%04X %%-%ds %%s" + else: + fmt = "%%08X %%-%ds %%s" + fmt = fmt % (3 * linesize - 1,) + for i in range(0, len(data), linesize): + line = data[i : i + linesize] + hextext = " ".join('%02x' % byte2int(b) for b in line) + rawtext = "".join(_printable[byte2int(b)] for b in line) + prettylines.append(fmt % (i, str(hextext), str(rawtext))) + return prettylines + + +try: + basecls = bytes +except NameError: + basecls = str + +class HexString(basecls): + """ + Represents bytes that will be hex-dumped to a string when its string + representation is requested. + """ + def __init__(self, data, linesize = 16): + self.linesize = linesize + def __new__(cls, data, *args, **kwargs): + return basecls.__new__(cls, data) + def __str__(self): + if not self: + return "''" + return "\n" + "\n".join(hexdump(self, self.linesize)) + + diff --git a/external/construct/lib/hex.pyc b/external/construct/lib/hex.pyc Binary files differnew file mode 100644 index 0000000..bc766fa --- /dev/null +++ b/external/construct/lib/hex.pyc diff --git a/external/construct/lib/py3compat.py b/external/construct/lib/py3compat.py new file mode 100644 index 0000000..4a52c29 --- /dev/null +++ b/external/construct/lib/py3compat.py @@ -0,0 +1,70 @@ +#------------------------------------------------------------------------------- +# py3compat.py +# +# Some Python2&3 compatibility code +#------------------------------------------------------------------------------- +import sys +PY3 = sys.version_info[0] == 3 + + +if PY3: + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + + def bchr(i): + """ When iterating over b'...' in Python 2 you get single b'_' chars + and in Python 3 you get integers. Call bchr to always turn this + to single b'_' chars. + """ + return bytes((i,)) + + def u(s): + return s + + def int2byte(i): + return bytes((i,)) + + def byte2int(b): + return b + + def str2bytes(s): + return s.encode("latin-1") + + def str2unicode(s): + return s + + def bytes2str(b): + return b.decode('latin-1') + + def decodebytes(b, encoding): + return bytes(b, encoding) + + advance_iterator = next + +else: + import cStringIO + StringIO = BytesIO = cStringIO.StringIO + + int2byte = chr + byte2int = ord + bchr = lambda i: i + + def u(s): + return unicode(s, "unicode_escape") + + def str2bytes(s): + return s + + def str2unicode(s): + return unicode(s, "unicode_escape") + + def bytes2str(b): + return b + + def decodebytes(b, encoding): + return b.decode(encoding) + + def advance_iterator(it): + return it.next() + diff --git a/external/construct/lib/py3compat.pyc b/external/construct/lib/py3compat.pyc Binary files differnew file mode 100644 index 0000000..4f06b7b --- /dev/null +++ b/external/construct/lib/py3compat.pyc |