summaryrefslogtreecommitdiff
path: root/external/construct/lib/binary.py
diff options
context:
space:
mode:
Diffstat (limited to 'external/construct/lib/binary.py')
-rw-r--r--external/construct/lib/binary.py187
1 files changed, 187 insertions, 0 deletions
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)