pycrate/pycrate_core/utils_py3.py

2117 lines
76 KiB
Python

# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# *
# * Copyright 2016. Benoit Michau. ANSSI.
# *
# * This library is free software; you can redistribute it and/or
# * modify it under the terms of the GNU Lesser General Public
# * License as published by the Free Software Foundation; either
# * version 2.1 of the License, or (at your option) any later version.
# *
# * This library is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# * Lesser General Public License for more details.
# *
# * You should have received a copy of the GNU Lesser General Public
# * License along with this library; if not, write to the Free Software
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# * MA 02110-1301 USA
# *
# *--------------------------------------------------------
# * File Name : pycrate_core/utils_py3.py
# * Created : 2016-02-11
# * Authors : Benoit Michau
# *--------------------------------------------------------
#*/
#
# All basic conversion function in native Python should be handled here
#
import sys
from struct import pack, unpack
from functools import reduce, partial
# use gmpy for handling very large integers
try:
from gmpy import mpz
except ImportError:
try:
from gmpy2 import mpz
except ImportError:
# just use Python large integer handling (which is slow)
_WITH_MPZ = False
else:
_WITH_MPZ = True
_MPZ_T = type(mpz(0))
else:
_WITH_MPZ = True
_MPZ_T = type(mpz(0))
#------------------------------------------------------------------------------#
# Python3 oddities
#------------------------------------------------------------------------------#
python_version = sys.version_info[0]
# no more long type in Python3
if _WITH_MPZ:
integer_types = (int, _MPZ_T)
else:
integer_types = (int, )
# str are different than bytes in Python3
bytes_types = (bytes, )
# unicode is defined in Python2 and not in Python3
str_types = (str, )
# there is no NoneType in types anymore
NoneType = type(None)
# defines a bchr() which returns a bytes instance to mimic Python2 chr()
bchr = partial(pack, 'B')
#------------------------------------------------------------------------------#
# Pycrate generic error
#------------------------------------------------------------------------------#
class PycrateErr(Exception):
pass
#------------------------------------------------------------------------------#
# bit list functions
#------------------------------------------------------------------------------#
ARRTOBIT_LUT = {
0: (0, 0, 0, 0, 0, 0, 0, 0),
1: (0, 0, 0, 0, 0, 0, 0, 1),
2: (0, 0, 0, 0, 0, 0, 1, 0),
3: (0, 0, 0, 0, 0, 0, 1, 1),
4: (0, 0, 0, 0, 0, 1, 0, 0),
5: (0, 0, 0, 0, 0, 1, 0, 1),
6: (0, 0, 0, 0, 0, 1, 1, 0),
7: (0, 0, 0, 0, 0, 1, 1, 1),
8: (0, 0, 0, 0, 1, 0, 0, 0),
9: (0, 0, 0, 0, 1, 0, 0, 1),
10: (0, 0, 0, 0, 1, 0, 1, 0),
11: (0, 0, 0, 0, 1, 0, 1, 1),
12: (0, 0, 0, 0, 1, 1, 0, 0),
13: (0, 0, 0, 0, 1, 1, 0, 1),
14: (0, 0, 0, 0, 1, 1, 1, 0),
15: (0, 0, 0, 0, 1, 1, 1, 1),
16: (0, 0, 0, 1, 0, 0, 0, 0),
17: (0, 0, 0, 1, 0, 0, 0, 1),
18: (0, 0, 0, 1, 0, 0, 1, 0),
19: (0, 0, 0, 1, 0, 0, 1, 1),
20: (0, 0, 0, 1, 0, 1, 0, 0),
21: (0, 0, 0, 1, 0, 1, 0, 1),
22: (0, 0, 0, 1, 0, 1, 1, 0),
23: (0, 0, 0, 1, 0, 1, 1, 1),
24: (0, 0, 0, 1, 1, 0, 0, 0),
25: (0, 0, 0, 1, 1, 0, 0, 1),
26: (0, 0, 0, 1, 1, 0, 1, 0),
27: (0, 0, 0, 1, 1, 0, 1, 1),
28: (0, 0, 0, 1, 1, 1, 0, 0),
29: (0, 0, 0, 1, 1, 1, 0, 1),
30: (0, 0, 0, 1, 1, 1, 1, 0),
31: (0, 0, 0, 1, 1, 1, 1, 1),
32: (0, 0, 1, 0, 0, 0, 0, 0),
33: (0, 0, 1, 0, 0, 0, 0, 1),
34: (0, 0, 1, 0, 0, 0, 1, 0),
35: (0, 0, 1, 0, 0, 0, 1, 1),
36: (0, 0, 1, 0, 0, 1, 0, 0),
37: (0, 0, 1, 0, 0, 1, 0, 1),
38: (0, 0, 1, 0, 0, 1, 1, 0),
39: (0, 0, 1, 0, 0, 1, 1, 1),
40: (0, 0, 1, 0, 1, 0, 0, 0),
41: (0, 0, 1, 0, 1, 0, 0, 1),
42: (0, 0, 1, 0, 1, 0, 1, 0),
43: (0, 0, 1, 0, 1, 0, 1, 1),
44: (0, 0, 1, 0, 1, 1, 0, 0),
45: (0, 0, 1, 0, 1, 1, 0, 1),
46: (0, 0, 1, 0, 1, 1, 1, 0),
47: (0, 0, 1, 0, 1, 1, 1, 1),
48: (0, 0, 1, 1, 0, 0, 0, 0),
49: (0, 0, 1, 1, 0, 0, 0, 1),
50: (0, 0, 1, 1, 0, 0, 1, 0),
51: (0, 0, 1, 1, 0, 0, 1, 1),
52: (0, 0, 1, 1, 0, 1, 0, 0),
53: (0, 0, 1, 1, 0, 1, 0, 1),
54: (0, 0, 1, 1, 0, 1, 1, 0),
55: (0, 0, 1, 1, 0, 1, 1, 1),
56: (0, 0, 1, 1, 1, 0, 0, 0),
57: (0, 0, 1, 1, 1, 0, 0, 1),
58: (0, 0, 1, 1, 1, 0, 1, 0),
59: (0, 0, 1, 1, 1, 0, 1, 1),
60: (0, 0, 1, 1, 1, 1, 0, 0),
61: (0, 0, 1, 1, 1, 1, 0, 1),
62: (0, 0, 1, 1, 1, 1, 1, 0),
63: (0, 0, 1, 1, 1, 1, 1, 1),
64: (0, 1, 0, 0, 0, 0, 0, 0),
65: (0, 1, 0, 0, 0, 0, 0, 1),
66: (0, 1, 0, 0, 0, 0, 1, 0),
67: (0, 1, 0, 0, 0, 0, 1, 1),
68: (0, 1, 0, 0, 0, 1, 0, 0),
69: (0, 1, 0, 0, 0, 1, 0, 1),
70: (0, 1, 0, 0, 0, 1, 1, 0),
71: (0, 1, 0, 0, 0, 1, 1, 1),
72: (0, 1, 0, 0, 1, 0, 0, 0),
73: (0, 1, 0, 0, 1, 0, 0, 1),
74: (0, 1, 0, 0, 1, 0, 1, 0),
75: (0, 1, 0, 0, 1, 0, 1, 1),
76: (0, 1, 0, 0, 1, 1, 0, 0),
77: (0, 1, 0, 0, 1, 1, 0, 1),
78: (0, 1, 0, 0, 1, 1, 1, 0),
79: (0, 1, 0, 0, 1, 1, 1, 1),
80: (0, 1, 0, 1, 0, 0, 0, 0),
81: (0, 1, 0, 1, 0, 0, 0, 1),
82: (0, 1, 0, 1, 0, 0, 1, 0),
83: (0, 1, 0, 1, 0, 0, 1, 1),
84: (0, 1, 0, 1, 0, 1, 0, 0),
85: (0, 1, 0, 1, 0, 1, 0, 1),
86: (0, 1, 0, 1, 0, 1, 1, 0),
87: (0, 1, 0, 1, 0, 1, 1, 1),
88: (0, 1, 0, 1, 1, 0, 0, 0),
89: (0, 1, 0, 1, 1, 0, 0, 1),
90: (0, 1, 0, 1, 1, 0, 1, 0),
91: (0, 1, 0, 1, 1, 0, 1, 1),
92: (0, 1, 0, 1, 1, 1, 0, 0),
93: (0, 1, 0, 1, 1, 1, 0, 1),
94: (0, 1, 0, 1, 1, 1, 1, 0),
95: (0, 1, 0, 1, 1, 1, 1, 1),
96: (0, 1, 1, 0, 0, 0, 0, 0),
97: (0, 1, 1, 0, 0, 0, 0, 1),
98: (0, 1, 1, 0, 0, 0, 1, 0),
99: (0, 1, 1, 0, 0, 0, 1, 1),
100: (0, 1, 1, 0, 0, 1, 0, 0),
101: (0, 1, 1, 0, 0, 1, 0, 1),
102: (0, 1, 1, 0, 0, 1, 1, 0),
103: (0, 1, 1, 0, 0, 1, 1, 1),
104: (0, 1, 1, 0, 1, 0, 0, 0),
105: (0, 1, 1, 0, 1, 0, 0, 1),
106: (0, 1, 1, 0, 1, 0, 1, 0),
107: (0, 1, 1, 0, 1, 0, 1, 1),
108: (0, 1, 1, 0, 1, 1, 0, 0),
109: (0, 1, 1, 0, 1, 1, 0, 1),
110: (0, 1, 1, 0, 1, 1, 1, 0),
111: (0, 1, 1, 0, 1, 1, 1, 1),
112: (0, 1, 1, 1, 0, 0, 0, 0),
113: (0, 1, 1, 1, 0, 0, 0, 1),
114: (0, 1, 1, 1, 0, 0, 1, 0),
115: (0, 1, 1, 1, 0, 0, 1, 1),
116: (0, 1, 1, 1, 0, 1, 0, 0),
117: (0, 1, 1, 1, 0, 1, 0, 1),
118: (0, 1, 1, 1, 0, 1, 1, 0),
119: (0, 1, 1, 1, 0, 1, 1, 1),
120: (0, 1, 1, 1, 1, 0, 0, 0),
121: (0, 1, 1, 1, 1, 0, 0, 1),
122: (0, 1, 1, 1, 1, 0, 1, 0),
123: (0, 1, 1, 1, 1, 0, 1, 1),
124: (0, 1, 1, 1, 1, 1, 0, 0),
125: (0, 1, 1, 1, 1, 1, 0, 1),
126: (0, 1, 1, 1, 1, 1, 1, 0),
127: (0, 1, 1, 1, 1, 1, 1, 1),
128: (1, 0, 0, 0, 0, 0, 0, 0),
129: (1, 0, 0, 0, 0, 0, 0, 1),
130: (1, 0, 0, 0, 0, 0, 1, 0),
131: (1, 0, 0, 0, 0, 0, 1, 1),
132: (1, 0, 0, 0, 0, 1, 0, 0),
133: (1, 0, 0, 0, 0, 1, 0, 1),
134: (1, 0, 0, 0, 0, 1, 1, 0),
135: (1, 0, 0, 0, 0, 1, 1, 1),
136: (1, 0, 0, 0, 1, 0, 0, 0),
137: (1, 0, 0, 0, 1, 0, 0, 1),
138: (1, 0, 0, 0, 1, 0, 1, 0),
139: (1, 0, 0, 0, 1, 0, 1, 1),
140: (1, 0, 0, 0, 1, 1, 0, 0),
141: (1, 0, 0, 0, 1, 1, 0, 1),
142: (1, 0, 0, 0, 1, 1, 1, 0),
143: (1, 0, 0, 0, 1, 1, 1, 1),
144: (1, 0, 0, 1, 0, 0, 0, 0),
145: (1, 0, 0, 1, 0, 0, 0, 1),
146: (1, 0, 0, 1, 0, 0, 1, 0),
147: (1, 0, 0, 1, 0, 0, 1, 1),
148: (1, 0, 0, 1, 0, 1, 0, 0),
149: (1, 0, 0, 1, 0, 1, 0, 1),
150: (1, 0, 0, 1, 0, 1, 1, 0),
151: (1, 0, 0, 1, 0, 1, 1, 1),
152: (1, 0, 0, 1, 1, 0, 0, 0),
153: (1, 0, 0, 1, 1, 0, 0, 1),
154: (1, 0, 0, 1, 1, 0, 1, 0),
155: (1, 0, 0, 1, 1, 0, 1, 1),
156: (1, 0, 0, 1, 1, 1, 0, 0),
157: (1, 0, 0, 1, 1, 1, 0, 1),
158: (1, 0, 0, 1, 1, 1, 1, 0),
159: (1, 0, 0, 1, 1, 1, 1, 1),
160: (1, 0, 1, 0, 0, 0, 0, 0),
161: (1, 0, 1, 0, 0, 0, 0, 1),
162: (1, 0, 1, 0, 0, 0, 1, 0),
163: (1, 0, 1, 0, 0, 0, 1, 1),
164: (1, 0, 1, 0, 0, 1, 0, 0),
165: (1, 0, 1, 0, 0, 1, 0, 1),
166: (1, 0, 1, 0, 0, 1, 1, 0),
167: (1, 0, 1, 0, 0, 1, 1, 1),
168: (1, 0, 1, 0, 1, 0, 0, 0),
169: (1, 0, 1, 0, 1, 0, 0, 1),
170: (1, 0, 1, 0, 1, 0, 1, 0),
171: (1, 0, 1, 0, 1, 0, 1, 1),
172: (1, 0, 1, 0, 1, 1, 0, 0),
173: (1, 0, 1, 0, 1, 1, 0, 1),
174: (1, 0, 1, 0, 1, 1, 1, 0),
175: (1, 0, 1, 0, 1, 1, 1, 1),
176: (1, 0, 1, 1, 0, 0, 0, 0),
177: (1, 0, 1, 1, 0, 0, 0, 1),
178: (1, 0, 1, 1, 0, 0, 1, 0),
179: (1, 0, 1, 1, 0, 0, 1, 1),
180: (1, 0, 1, 1, 0, 1, 0, 0),
181: (1, 0, 1, 1, 0, 1, 0, 1),
182: (1, 0, 1, 1, 0, 1, 1, 0),
183: (1, 0, 1, 1, 0, 1, 1, 1),
184: (1, 0, 1, 1, 1, 0, 0, 0),
185: (1, 0, 1, 1, 1, 0, 0, 1),
186: (1, 0, 1, 1, 1, 0, 1, 0),
187: (1, 0, 1, 1, 1, 0, 1, 1),
188: (1, 0, 1, 1, 1, 1, 0, 0),
189: (1, 0, 1, 1, 1, 1, 0, 1),
190: (1, 0, 1, 1, 1, 1, 1, 0),
191: (1, 0, 1, 1, 1, 1, 1, 1),
192: (1, 1, 0, 0, 0, 0, 0, 0),
193: (1, 1, 0, 0, 0, 0, 0, 1),
194: (1, 1, 0, 0, 0, 0, 1, 0),
195: (1, 1, 0, 0, 0, 0, 1, 1),
196: (1, 1, 0, 0, 0, 1, 0, 0),
197: (1, 1, 0, 0, 0, 1, 0, 1),
198: (1, 1, 0, 0, 0, 1, 1, 0),
199: (1, 1, 0, 0, 0, 1, 1, 1),
200: (1, 1, 0, 0, 1, 0, 0, 0),
201: (1, 1, 0, 0, 1, 0, 0, 1),
202: (1, 1, 0, 0, 1, 0, 1, 0),
203: (1, 1, 0, 0, 1, 0, 1, 1),
204: (1, 1, 0, 0, 1, 1, 0, 0),
205: (1, 1, 0, 0, 1, 1, 0, 1),
206: (1, 1, 0, 0, 1, 1, 1, 0),
207: (1, 1, 0, 0, 1, 1, 1, 1),
208: (1, 1, 0, 1, 0, 0, 0, 0),
209: (1, 1, 0, 1, 0, 0, 0, 1),
210: (1, 1, 0, 1, 0, 0, 1, 0),
211: (1, 1, 0, 1, 0, 0, 1, 1),
212: (1, 1, 0, 1, 0, 1, 0, 0),
213: (1, 1, 0, 1, 0, 1, 0, 1),
214: (1, 1, 0, 1, 0, 1, 1, 0),
215: (1, 1, 0, 1, 0, 1, 1, 1),
216: (1, 1, 0, 1, 1, 0, 0, 0),
217: (1, 1, 0, 1, 1, 0, 0, 1),
218: (1, 1, 0, 1, 1, 0, 1, 0),
219: (1, 1, 0, 1, 1, 0, 1, 1),
220: (1, 1, 0, 1, 1, 1, 0, 0),
221: (1, 1, 0, 1, 1, 1, 0, 1),
222: (1, 1, 0, 1, 1, 1, 1, 0),
223: (1, 1, 0, 1, 1, 1, 1, 1),
224: (1, 1, 1, 0, 0, 0, 0, 0),
225: (1, 1, 1, 0, 0, 0, 0, 1),
226: (1, 1, 1, 0, 0, 0, 1, 0),
227: (1, 1, 1, 0, 0, 0, 1, 1),
228: (1, 1, 1, 0, 0, 1, 0, 0),
229: (1, 1, 1, 0, 0, 1, 0, 1),
230: (1, 1, 1, 0, 0, 1, 1, 0),
231: (1, 1, 1, 0, 0, 1, 1, 1),
232: (1, 1, 1, 0, 1, 0, 0, 0),
233: (1, 1, 1, 0, 1, 0, 0, 1),
234: (1, 1, 1, 0, 1, 0, 1, 0),
235: (1, 1, 1, 0, 1, 0, 1, 1),
236: (1, 1, 1, 0, 1, 1, 0, 0),
237: (1, 1, 1, 0, 1, 1, 0, 1),
238: (1, 1, 1, 0, 1, 1, 1, 0),
239: (1, 1, 1, 0, 1, 1, 1, 1),
240: (1, 1, 1, 1, 0, 0, 0, 0),
241: (1, 1, 1, 1, 0, 0, 0, 1),
242: (1, 1, 1, 1, 0, 0, 1, 0),
243: (1, 1, 1, 1, 0, 0, 1, 1),
244: (1, 1, 1, 1, 0, 1, 0, 0),
245: (1, 1, 1, 1, 0, 1, 0, 1),
246: (1, 1, 1, 1, 0, 1, 1, 0),
247: (1, 1, 1, 1, 0, 1, 1, 1),
248: (1, 1, 1, 1, 1, 0, 0, 0),
249: (1, 1, 1, 1, 1, 0, 0, 1),
250: (1, 1, 1, 1, 1, 0, 1, 0),
251: (1, 1, 1, 1, 1, 0, 1, 1),
252: (1, 1, 1, 1, 1, 1, 0, 0),
253: (1, 1, 1, 1, 1, 1, 0, 1),
254: (1, 1, 1, 1, 1, 1, 1, 0),
255: (1, 1, 1, 1, 1, 1, 1, 1)
}
BYTETOBIT_LUT = {
b'\x00': (0, 0, 0, 0, 0, 0, 0, 0),
b'\x01': (0, 0, 0, 0, 0, 0, 0, 1),
b'\x02': (0, 0, 0, 0, 0, 0, 1, 0),
b'\x03': (0, 0, 0, 0, 0, 0, 1, 1),
b'\x04': (0, 0, 0, 0, 0, 1, 0, 0),
b'\x05': (0, 0, 0, 0, 0, 1, 0, 1),
b'\x06': (0, 0, 0, 0, 0, 1, 1, 0),
b'\x07': (0, 0, 0, 0, 0, 1, 1, 1),
b'\x08': (0, 0, 0, 0, 1, 0, 0, 0),
b'\t': (0, 0, 0, 0, 1, 0, 0, 1),
b'\n': (0, 0, 0, 0, 1, 0, 1, 0),
b'\x0b': (0, 0, 0, 0, 1, 0, 1, 1),
b'\x0c': (0, 0, 0, 0, 1, 1, 0, 0),
b'\r': (0, 0, 0, 0, 1, 1, 0, 1),
b'\x0e': (0, 0, 0, 0, 1, 1, 1, 0),
b'\x0f': (0, 0, 0, 0, 1, 1, 1, 1),
b'\x10': (0, 0, 0, 1, 0, 0, 0, 0),
b'\x11': (0, 0, 0, 1, 0, 0, 0, 1),
b'\x12': (0, 0, 0, 1, 0, 0, 1, 0),
b'\x13': (0, 0, 0, 1, 0, 0, 1, 1),
b'\x14': (0, 0, 0, 1, 0, 1, 0, 0),
b'\x15': (0, 0, 0, 1, 0, 1, 0, 1),
b'\x16': (0, 0, 0, 1, 0, 1, 1, 0),
b'\x17': (0, 0, 0, 1, 0, 1, 1, 1),
b'\x18': (0, 0, 0, 1, 1, 0, 0, 0),
b'\x19': (0, 0, 0, 1, 1, 0, 0, 1),
b'\x1a': (0, 0, 0, 1, 1, 0, 1, 0),
b'\x1b': (0, 0, 0, 1, 1, 0, 1, 1),
b'\x1c': (0, 0, 0, 1, 1, 1, 0, 0),
b'\x1d': (0, 0, 0, 1, 1, 1, 0, 1),
b'\x1e': (0, 0, 0, 1, 1, 1, 1, 0),
b'\x1f': (0, 0, 0, 1, 1, 1, 1, 1),
b' ': (0, 0, 1, 0, 0, 0, 0, 0),
b'!': (0, 0, 1, 0, 0, 0, 0, 1),
b'"': (0, 0, 1, 0, 0, 0, 1, 0),
b'#': (0, 0, 1, 0, 0, 0, 1, 1),
b'$': (0, 0, 1, 0, 0, 1, 0, 0),
b'%': (0, 0, 1, 0, 0, 1, 0, 1),
b'&': (0, 0, 1, 0, 0, 1, 1, 0),
b"'": (0, 0, 1, 0, 0, 1, 1, 1),
b'(': (0, 0, 1, 0, 1, 0, 0, 0),
b')': (0, 0, 1, 0, 1, 0, 0, 1),
b'*': (0, 0, 1, 0, 1, 0, 1, 0),
b'+': (0, 0, 1, 0, 1, 0, 1, 1),
b',': (0, 0, 1, 0, 1, 1, 0, 0),
b'-': (0, 0, 1, 0, 1, 1, 0, 1),
b'.': (0, 0, 1, 0, 1, 1, 1, 0),
b'/': (0, 0, 1, 0, 1, 1, 1, 1),
b'0': (0, 0, 1, 1, 0, 0, 0, 0),
b'1': (0, 0, 1, 1, 0, 0, 0, 1),
b'2': (0, 0, 1, 1, 0, 0, 1, 0),
b'3': (0, 0, 1, 1, 0, 0, 1, 1),
b'4': (0, 0, 1, 1, 0, 1, 0, 0),
b'5': (0, 0, 1, 1, 0, 1, 0, 1),
b'6': (0, 0, 1, 1, 0, 1, 1, 0),
b'7': (0, 0, 1, 1, 0, 1, 1, 1),
b'8': (0, 0, 1, 1, 1, 0, 0, 0),
b'9': (0, 0, 1, 1, 1, 0, 0, 1),
b':': (0, 0, 1, 1, 1, 0, 1, 0),
b';': (0, 0, 1, 1, 1, 0, 1, 1),
b'<': (0, 0, 1, 1, 1, 1, 0, 0),
b'=': (0, 0, 1, 1, 1, 1, 0, 1),
b'>': (0, 0, 1, 1, 1, 1, 1, 0),
b'?': (0, 0, 1, 1, 1, 1, 1, 1),
b'@': (0, 1, 0, 0, 0, 0, 0, 0),
b'A': (0, 1, 0, 0, 0, 0, 0, 1),
b'B': (0, 1, 0, 0, 0, 0, 1, 0),
b'C': (0, 1, 0, 0, 0, 0, 1, 1),
b'D': (0, 1, 0, 0, 0, 1, 0, 0),
b'E': (0, 1, 0, 0, 0, 1, 0, 1),
b'F': (0, 1, 0, 0, 0, 1, 1, 0),
b'G': (0, 1, 0, 0, 0, 1, 1, 1),
b'H': (0, 1, 0, 0, 1, 0, 0, 0),
b'I': (0, 1, 0, 0, 1, 0, 0, 1),
b'J': (0, 1, 0, 0, 1, 0, 1, 0),
b'K': (0, 1, 0, 0, 1, 0, 1, 1),
b'L': (0, 1, 0, 0, 1, 1, 0, 0),
b'M': (0, 1, 0, 0, 1, 1, 0, 1),
b'N': (0, 1, 0, 0, 1, 1, 1, 0),
b'O': (0, 1, 0, 0, 1, 1, 1, 1),
b'P': (0, 1, 0, 1, 0, 0, 0, 0),
b'Q': (0, 1, 0, 1, 0, 0, 0, 1),
b'R': (0, 1, 0, 1, 0, 0, 1, 0),
b'S': (0, 1, 0, 1, 0, 0, 1, 1),
b'T': (0, 1, 0, 1, 0, 1, 0, 0),
b'U': (0, 1, 0, 1, 0, 1, 0, 1),
b'V': (0, 1, 0, 1, 0, 1, 1, 0),
b'W': (0, 1, 0, 1, 0, 1, 1, 1),
b'X': (0, 1, 0, 1, 1, 0, 0, 0),
b'Y': (0, 1, 0, 1, 1, 0, 0, 1),
b'Z': (0, 1, 0, 1, 1, 0, 1, 0),
b'[': (0, 1, 0, 1, 1, 0, 1, 1),
b'\\': (0, 1, 0, 1, 1, 1, 0, 0),
b']': (0, 1, 0, 1, 1, 1, 0, 1),
b'^': (0, 1, 0, 1, 1, 1, 1, 0),
b'_': (0, 1, 0, 1, 1, 1, 1, 1),
b'`': (0, 1, 1, 0, 0, 0, 0, 0),
b'a': (0, 1, 1, 0, 0, 0, 0, 1),
b'b': (0, 1, 1, 0, 0, 0, 1, 0),
b'c': (0, 1, 1, 0, 0, 0, 1, 1),
b'd': (0, 1, 1, 0, 0, 1, 0, 0),
b'e': (0, 1, 1, 0, 0, 1, 0, 1),
b'f': (0, 1, 1, 0, 0, 1, 1, 0),
b'g': (0, 1, 1, 0, 0, 1, 1, 1),
b'h': (0, 1, 1, 0, 1, 0, 0, 0),
b'i': (0, 1, 1, 0, 1, 0, 0, 1),
b'j': (0, 1, 1, 0, 1, 0, 1, 0),
b'k': (0, 1, 1, 0, 1, 0, 1, 1),
b'l': (0, 1, 1, 0, 1, 1, 0, 0),
b'm': (0, 1, 1, 0, 1, 1, 0, 1),
b'n': (0, 1, 1, 0, 1, 1, 1, 0),
b'o': (0, 1, 1, 0, 1, 1, 1, 1),
b'p': (0, 1, 1, 1, 0, 0, 0, 0),
b'q': (0, 1, 1, 1, 0, 0, 0, 1),
b'r': (0, 1, 1, 1, 0, 0, 1, 0),
b's': (0, 1, 1, 1, 0, 0, 1, 1),
b't': (0, 1, 1, 1, 0, 1, 0, 0),
b'u': (0, 1, 1, 1, 0, 1, 0, 1),
b'v': (0, 1, 1, 1, 0, 1, 1, 0),
b'w': (0, 1, 1, 1, 0, 1, 1, 1),
b'x': (0, 1, 1, 1, 1, 0, 0, 0),
b'y': (0, 1, 1, 1, 1, 0, 0, 1),
b'z': (0, 1, 1, 1, 1, 0, 1, 0),
b'{': (0, 1, 1, 1, 1, 0, 1, 1),
b'|': (0, 1, 1, 1, 1, 1, 0, 0),
b'}': (0, 1, 1, 1, 1, 1, 0, 1),
b'~': (0, 1, 1, 1, 1, 1, 1, 0),
b'\x7f': (0, 1, 1, 1, 1, 1, 1, 1),
b'\x80': (1, 0, 0, 0, 0, 0, 0, 0),
b'\x81': (1, 0, 0, 0, 0, 0, 0, 1),
b'\x82': (1, 0, 0, 0, 0, 0, 1, 0),
b'\x83': (1, 0, 0, 0, 0, 0, 1, 1),
b'\x84': (1, 0, 0, 0, 0, 1, 0, 0),
b'\x85': (1, 0, 0, 0, 0, 1, 0, 1),
b'\x86': (1, 0, 0, 0, 0, 1, 1, 0),
b'\x87': (1, 0, 0, 0, 0, 1, 1, 1),
b'\x88': (1, 0, 0, 0, 1, 0, 0, 0),
b'\x89': (1, 0, 0, 0, 1, 0, 0, 1),
b'\x8a': (1, 0, 0, 0, 1, 0, 1, 0),
b'\x8b': (1, 0, 0, 0, 1, 0, 1, 1),
b'\x8c': (1, 0, 0, 0, 1, 1, 0, 0),
b'\x8d': (1, 0, 0, 0, 1, 1, 0, 1),
b'\x8e': (1, 0, 0, 0, 1, 1, 1, 0),
b'\x8f': (1, 0, 0, 0, 1, 1, 1, 1),
b'\x90': (1, 0, 0, 1, 0, 0, 0, 0),
b'\x91': (1, 0, 0, 1, 0, 0, 0, 1),
b'\x92': (1, 0, 0, 1, 0, 0, 1, 0),
b'\x93': (1, 0, 0, 1, 0, 0, 1, 1),
b'\x94': (1, 0, 0, 1, 0, 1, 0, 0),
b'\x95': (1, 0, 0, 1, 0, 1, 0, 1),
b'\x96': (1, 0, 0, 1, 0, 1, 1, 0),
b'\x97': (1, 0, 0, 1, 0, 1, 1, 1),
b'\x98': (1, 0, 0, 1, 1, 0, 0, 0),
b'\x99': (1, 0, 0, 1, 1, 0, 0, 1),
b'\x9a': (1, 0, 0, 1, 1, 0, 1, 0),
b'\x9b': (1, 0, 0, 1, 1, 0, 1, 1),
b'\x9c': (1, 0, 0, 1, 1, 1, 0, 0),
b'\x9d': (1, 0, 0, 1, 1, 1, 0, 1),
b'\x9e': (1, 0, 0, 1, 1, 1, 1, 0),
b'\x9f': (1, 0, 0, 1, 1, 1, 1, 1),
b'\xa0': (1, 0, 1, 0, 0, 0, 0, 0),
b'\xa1': (1, 0, 1, 0, 0, 0, 0, 1),
b'\xa2': (1, 0, 1, 0, 0, 0, 1, 0),
b'\xa3': (1, 0, 1, 0, 0, 0, 1, 1),
b'\xa4': (1, 0, 1, 0, 0, 1, 0, 0),
b'\xa5': (1, 0, 1, 0, 0, 1, 0, 1),
b'\xa6': (1, 0, 1, 0, 0, 1, 1, 0),
b'\xa7': (1, 0, 1, 0, 0, 1, 1, 1),
b'\xa8': (1, 0, 1, 0, 1, 0, 0, 0),
b'\xa9': (1, 0, 1, 0, 1, 0, 0, 1),
b'\xaa': (1, 0, 1, 0, 1, 0, 1, 0),
b'\xab': (1, 0, 1, 0, 1, 0, 1, 1),
b'\xac': (1, 0, 1, 0, 1, 1, 0, 0),
b'\xad': (1, 0, 1, 0, 1, 1, 0, 1),
b'\xae': (1, 0, 1, 0, 1, 1, 1, 0),
b'\xaf': (1, 0, 1, 0, 1, 1, 1, 1),
b'\xb0': (1, 0, 1, 1, 0, 0, 0, 0),
b'\xb1': (1, 0, 1, 1, 0, 0, 0, 1),
b'\xb2': (1, 0, 1, 1, 0, 0, 1, 0),
b'\xb3': (1, 0, 1, 1, 0, 0, 1, 1),
b'\xb4': (1, 0, 1, 1, 0, 1, 0, 0),
b'\xb5': (1, 0, 1, 1, 0, 1, 0, 1),
b'\xb6': (1, 0, 1, 1, 0, 1, 1, 0),
b'\xb7': (1, 0, 1, 1, 0, 1, 1, 1),
b'\xb8': (1, 0, 1, 1, 1, 0, 0, 0),
b'\xb9': (1, 0, 1, 1, 1, 0, 0, 1),
b'\xba': (1, 0, 1, 1, 1, 0, 1, 0),
b'\xbb': (1, 0, 1, 1, 1, 0, 1, 1),
b'\xbc': (1, 0, 1, 1, 1, 1, 0, 0),
b'\xbd': (1, 0, 1, 1, 1, 1, 0, 1),
b'\xbe': (1, 0, 1, 1, 1, 1, 1, 0),
b'\xbf': (1, 0, 1, 1, 1, 1, 1, 1),
b'\xc0': (1, 1, 0, 0, 0, 0, 0, 0),
b'\xc1': (1, 1, 0, 0, 0, 0, 0, 1),
b'\xc2': (1, 1, 0, 0, 0, 0, 1, 0),
b'\xc3': (1, 1, 0, 0, 0, 0, 1, 1),
b'\xc4': (1, 1, 0, 0, 0, 1, 0, 0),
b'\xc5': (1, 1, 0, 0, 0, 1, 0, 1),
b'\xc6': (1, 1, 0, 0, 0, 1, 1, 0),
b'\xc7': (1, 1, 0, 0, 0, 1, 1, 1),
b'\xc8': (1, 1, 0, 0, 1, 0, 0, 0),
b'\xc9': (1, 1, 0, 0, 1, 0, 0, 1),
b'\xca': (1, 1, 0, 0, 1, 0, 1, 0),
b'\xcb': (1, 1, 0, 0, 1, 0, 1, 1),
b'\xcc': (1, 1, 0, 0, 1, 1, 0, 0),
b'\xcd': (1, 1, 0, 0, 1, 1, 0, 1),
b'\xce': (1, 1, 0, 0, 1, 1, 1, 0),
b'\xcf': (1, 1, 0, 0, 1, 1, 1, 1),
b'\xd0': (1, 1, 0, 1, 0, 0, 0, 0),
b'\xd1': (1, 1, 0, 1, 0, 0, 0, 1),
b'\xd2': (1, 1, 0, 1, 0, 0, 1, 0),
b'\xd3': (1, 1, 0, 1, 0, 0, 1, 1),
b'\xd4': (1, 1, 0, 1, 0, 1, 0, 0),
b'\xd5': (1, 1, 0, 1, 0, 1, 0, 1),
b'\xd6': (1, 1, 0, 1, 0, 1, 1, 0),
b'\xd7': (1, 1, 0, 1, 0, 1, 1, 1),
b'\xd8': (1, 1, 0, 1, 1, 0, 0, 0),
b'\xd9': (1, 1, 0, 1, 1, 0, 0, 1),
b'\xda': (1, 1, 0, 1, 1, 0, 1, 0),
b'\xdb': (1, 1, 0, 1, 1, 0, 1, 1),
b'\xdc': (1, 1, 0, 1, 1, 1, 0, 0),
b'\xdd': (1, 1, 0, 1, 1, 1, 0, 1),
b'\xde': (1, 1, 0, 1, 1, 1, 1, 0),
b'\xdf': (1, 1, 0, 1, 1, 1, 1, 1),
b'\xe0': (1, 1, 1, 0, 0, 0, 0, 0),
b'\xe1': (1, 1, 1, 0, 0, 0, 0, 1),
b'\xe2': (1, 1, 1, 0, 0, 0, 1, 0),
b'\xe3': (1, 1, 1, 0, 0, 0, 1, 1),
b'\xe4': (1, 1, 1, 0, 0, 1, 0, 0),
b'\xe5': (1, 1, 1, 0, 0, 1, 0, 1),
b'\xe6': (1, 1, 1, 0, 0, 1, 1, 0),
b'\xe7': (1, 1, 1, 0, 0, 1, 1, 1),
b'\xe8': (1, 1, 1, 0, 1, 0, 0, 0),
b'\xe9': (1, 1, 1, 0, 1, 0, 0, 1),
b'\xea': (1, 1, 1, 0, 1, 0, 1, 0),
b'\xeb': (1, 1, 1, 0, 1, 0, 1, 1),
b'\xec': (1, 1, 1, 0, 1, 1, 0, 0),
b'\xed': (1, 1, 1, 0, 1, 1, 0, 1),
b'\xee': (1, 1, 1, 0, 1, 1, 1, 0),
b'\xef': (1, 1, 1, 0, 1, 1, 1, 1),
b'\xf0': (1, 1, 1, 1, 0, 0, 0, 0),
b'\xf1': (1, 1, 1, 1, 0, 0, 0, 1),
b'\xf2': (1, 1, 1, 1, 0, 0, 1, 0),
b'\xf3': (1, 1, 1, 1, 0, 0, 1, 1),
b'\xf4': (1, 1, 1, 1, 0, 1, 0, 0),
b'\xf5': (1, 1, 1, 1, 0, 1, 0, 1),
b'\xf6': (1, 1, 1, 1, 0, 1, 1, 0),
b'\xf7': (1, 1, 1, 1, 0, 1, 1, 1),
b'\xf8': (1, 1, 1, 1, 1, 0, 0, 0),
b'\xf9': (1, 1, 1, 1, 1, 0, 0, 1),
b'\xfa': (1, 1, 1, 1, 1, 0, 1, 0),
b'\xfb': (1, 1, 1, 1, 1, 0, 1, 1),
b'\xfc': (1, 1, 1, 1, 1, 1, 0, 0),
b'\xfd': (1, 1, 1, 1, 1, 1, 0, 1),
b'\xfe': (1, 1, 1, 1, 1, 1, 1, 0),
b'\xff': (1, 1, 1, 1, 1, 1, 1, 1)
}
BITTOARR_LUT = {
(0, 0, 0, 0, 0, 0, 0, 0) : 0,
(0, 0, 0, 0, 0, 0, 0, 1) : 1,
(0, 0, 0, 0, 0, 0, 1, 0) : 2,
(0, 0, 0, 0, 0, 0, 1, 1) : 3,
(0, 0, 0, 0, 0, 1, 0, 0) : 4,
(0, 0, 0, 0, 0, 1, 0, 1) : 5,
(0, 0, 0, 0, 0, 1, 1, 0) : 6,
(0, 0, 0, 0, 0, 1, 1, 1) : 7,
(0, 0, 0, 0, 1, 0, 0, 0) : 8,
(0, 0, 0, 0, 1, 0, 0, 1) : 9,
(0, 0, 0, 0, 1, 0, 1, 0) : 10,
(0, 0, 0, 0, 1, 0, 1, 1) : 11,
(0, 0, 0, 0, 1, 1, 0, 0) : 12,
(0, 0, 0, 0, 1, 1, 0, 1) : 13,
(0, 0, 0, 0, 1, 1, 1, 0) : 14,
(0, 0, 0, 0, 1, 1, 1, 1) : 15,
(0, 0, 0, 1, 0, 0, 0, 0) : 16,
(0, 0, 0, 1, 0, 0, 0, 1) : 17,
(0, 0, 0, 1, 0, 0, 1, 0) : 18,
(0, 0, 0, 1, 0, 0, 1, 1) : 19,
(0, 0, 0, 1, 0, 1, 0, 0) : 20,
(0, 0, 0, 1, 0, 1, 0, 1) : 21,
(0, 0, 0, 1, 0, 1, 1, 0) : 22,
(0, 0, 0, 1, 0, 1, 1, 1) : 23,
(0, 0, 0, 1, 1, 0, 0, 0) : 24,
(0, 0, 0, 1, 1, 0, 0, 1) : 25,
(0, 0, 0, 1, 1, 0, 1, 0) : 26,
(0, 0, 0, 1, 1, 0, 1, 1) : 27,
(0, 0, 0, 1, 1, 1, 0, 0) : 28,
(0, 0, 0, 1, 1, 1, 0, 1) : 29,
(0, 0, 0, 1, 1, 1, 1, 0) : 30,
(0, 0, 0, 1, 1, 1, 1, 1) : 31,
(0, 0, 1, 0, 0, 0, 0, 0) : 32,
(0, 0, 1, 0, 0, 0, 0, 1) : 33,
(0, 0, 1, 0, 0, 0, 1, 0) : 34,
(0, 0, 1, 0, 0, 0, 1, 1) : 35,
(0, 0, 1, 0, 0, 1, 0, 0) : 36,
(0, 0, 1, 0, 0, 1, 0, 1) : 37,
(0, 0, 1, 0, 0, 1, 1, 0) : 38,
(0, 0, 1, 0, 0, 1, 1, 1) : 39,
(0, 0, 1, 0, 1, 0, 0, 0) : 40,
(0, 0, 1, 0, 1, 0, 0, 1) : 41,
(0, 0, 1, 0, 1, 0, 1, 0) : 42,
(0, 0, 1, 0, 1, 0, 1, 1) : 43,
(0, 0, 1, 0, 1, 1, 0, 0) : 44,
(0, 0, 1, 0, 1, 1, 0, 1) : 45,
(0, 0, 1, 0, 1, 1, 1, 0) : 46,
(0, 0, 1, 0, 1, 1, 1, 1) : 47,
(0, 0, 1, 1, 0, 0, 0, 0) : 48,
(0, 0, 1, 1, 0, 0, 0, 1) : 49,
(0, 0, 1, 1, 0, 0, 1, 0) : 50,
(0, 0, 1, 1, 0, 0, 1, 1) : 51,
(0, 0, 1, 1, 0, 1, 0, 0) : 52,
(0, 0, 1, 1, 0, 1, 0, 1) : 53,
(0, 0, 1, 1, 0, 1, 1, 0) : 54,
(0, 0, 1, 1, 0, 1, 1, 1) : 55,
(0, 0, 1, 1, 1, 0, 0, 0) : 56,
(0, 0, 1, 1, 1, 0, 0, 1) : 57,
(0, 0, 1, 1, 1, 0, 1, 0) : 58,
(0, 0, 1, 1, 1, 0, 1, 1) : 59,
(0, 0, 1, 1, 1, 1, 0, 0) : 60,
(0, 0, 1, 1, 1, 1, 0, 1) : 61,
(0, 0, 1, 1, 1, 1, 1, 0) : 62,
(0, 0, 1, 1, 1, 1, 1, 1) : 63,
(0, 1, 0, 0, 0, 0, 0, 0) : 64,
(0, 1, 0, 0, 0, 0, 0, 1) : 65,
(0, 1, 0, 0, 0, 0, 1, 0) : 66,
(0, 1, 0, 0, 0, 0, 1, 1) : 67,
(0, 1, 0, 0, 0, 1, 0, 0) : 68,
(0, 1, 0, 0, 0, 1, 0, 1) : 69,
(0, 1, 0, 0, 0, 1, 1, 0) : 70,
(0, 1, 0, 0, 0, 1, 1, 1) : 71,
(0, 1, 0, 0, 1, 0, 0, 0) : 72,
(0, 1, 0, 0, 1, 0, 0, 1) : 73,
(0, 1, 0, 0, 1, 0, 1, 0) : 74,
(0, 1, 0, 0, 1, 0, 1, 1) : 75,
(0, 1, 0, 0, 1, 1, 0, 0) : 76,
(0, 1, 0, 0, 1, 1, 0, 1) : 77,
(0, 1, 0, 0, 1, 1, 1, 0) : 78,
(0, 1, 0, 0, 1, 1, 1, 1) : 79,
(0, 1, 0, 1, 0, 0, 0, 0) : 80,
(0, 1, 0, 1, 0, 0, 0, 1) : 81,
(0, 1, 0, 1, 0, 0, 1, 0) : 82,
(0, 1, 0, 1, 0, 0, 1, 1) : 83,
(0, 1, 0, 1, 0, 1, 0, 0) : 84,
(0, 1, 0, 1, 0, 1, 0, 1) : 85,
(0, 1, 0, 1, 0, 1, 1, 0) : 86,
(0, 1, 0, 1, 0, 1, 1, 1) : 87,
(0, 1, 0, 1, 1, 0, 0, 0) : 88,
(0, 1, 0, 1, 1, 0, 0, 1) : 89,
(0, 1, 0, 1, 1, 0, 1, 0) : 90,
(0, 1, 0, 1, 1, 0, 1, 1) : 91,
(0, 1, 0, 1, 1, 1, 0, 0) : 92,
(0, 1, 0, 1, 1, 1, 0, 1) : 93,
(0, 1, 0, 1, 1, 1, 1, 0) : 94,
(0, 1, 0, 1, 1, 1, 1, 1) : 95,
(0, 1, 1, 0, 0, 0, 0, 0) : 96,
(0, 1, 1, 0, 0, 0, 0, 1) : 97,
(0, 1, 1, 0, 0, 0, 1, 0) : 98,
(0, 1, 1, 0, 0, 0, 1, 1) : 99,
(0, 1, 1, 0, 0, 1, 0, 0) : 100,
(0, 1, 1, 0, 0, 1, 0, 1) : 101,
(0, 1, 1, 0, 0, 1, 1, 0) : 102,
(0, 1, 1, 0, 0, 1, 1, 1) : 103,
(0, 1, 1, 0, 1, 0, 0, 0) : 104,
(0, 1, 1, 0, 1, 0, 0, 1) : 105,
(0, 1, 1, 0, 1, 0, 1, 0) : 106,
(0, 1, 1, 0, 1, 0, 1, 1) : 107,
(0, 1, 1, 0, 1, 1, 0, 0) : 108,
(0, 1, 1, 0, 1, 1, 0, 1) : 109,
(0, 1, 1, 0, 1, 1, 1, 0) : 110,
(0, 1, 1, 0, 1, 1, 1, 1) : 111,
(0, 1, 1, 1, 0, 0, 0, 0) : 112,
(0, 1, 1, 1, 0, 0, 0, 1) : 113,
(0, 1, 1, 1, 0, 0, 1, 0) : 114,
(0, 1, 1, 1, 0, 0, 1, 1) : 115,
(0, 1, 1, 1, 0, 1, 0, 0) : 116,
(0, 1, 1, 1, 0, 1, 0, 1) : 117,
(0, 1, 1, 1, 0, 1, 1, 0) : 118,
(0, 1, 1, 1, 0, 1, 1, 1) : 119,
(0, 1, 1, 1, 1, 0, 0, 0) : 120,
(0, 1, 1, 1, 1, 0, 0, 1) : 121,
(0, 1, 1, 1, 1, 0, 1, 0) : 122,
(0, 1, 1, 1, 1, 0, 1, 1) : 123,
(0, 1, 1, 1, 1, 1, 0, 0) : 124,
(0, 1, 1, 1, 1, 1, 0, 1) : 125,
(0, 1, 1, 1, 1, 1, 1, 0) : 126,
(0, 1, 1, 1, 1, 1, 1, 1) : 127,
(1, 0, 0, 0, 0, 0, 0, 0) : 128,
(1, 0, 0, 0, 0, 0, 0, 1) : 129,
(1, 0, 0, 0, 0, 0, 1, 0) : 130,
(1, 0, 0, 0, 0, 0, 1, 1) : 131,
(1, 0, 0, 0, 0, 1, 0, 0) : 132,
(1, 0, 0, 0, 0, 1, 0, 1) : 133,
(1, 0, 0, 0, 0, 1, 1, 0) : 134,
(1, 0, 0, 0, 0, 1, 1, 1) : 135,
(1, 0, 0, 0, 1, 0, 0, 0) : 136,
(1, 0, 0, 0, 1, 0, 0, 1) : 137,
(1, 0, 0, 0, 1, 0, 1, 0) : 138,
(1, 0, 0, 0, 1, 0, 1, 1) : 139,
(1, 0, 0, 0, 1, 1, 0, 0) : 140,
(1, 0, 0, 0, 1, 1, 0, 1) : 141,
(1, 0, 0, 0, 1, 1, 1, 0) : 142,
(1, 0, 0, 0, 1, 1, 1, 1) : 143,
(1, 0, 0, 1, 0, 0, 0, 0) : 144,
(1, 0, 0, 1, 0, 0, 0, 1) : 145,
(1, 0, 0, 1, 0, 0, 1, 0) : 146,
(1, 0, 0, 1, 0, 0, 1, 1) : 147,
(1, 0, 0, 1, 0, 1, 0, 0) : 148,
(1, 0, 0, 1, 0, 1, 0, 1) : 149,
(1, 0, 0, 1, 0, 1, 1, 0) : 150,
(1, 0, 0, 1, 0, 1, 1, 1) : 151,
(1, 0, 0, 1, 1, 0, 0, 0) : 152,
(1, 0, 0, 1, 1, 0, 0, 1) : 153,
(1, 0, 0, 1, 1, 0, 1, 0) : 154,
(1, 0, 0, 1, 1, 0, 1, 1) : 155,
(1, 0, 0, 1, 1, 1, 0, 0) : 156,
(1, 0, 0, 1, 1, 1, 0, 1) : 157,
(1, 0, 0, 1, 1, 1, 1, 0) : 158,
(1, 0, 0, 1, 1, 1, 1, 1) : 159,
(1, 0, 1, 0, 0, 0, 0, 0) : 160,
(1, 0, 1, 0, 0, 0, 0, 1) : 161,
(1, 0, 1, 0, 0, 0, 1, 0) : 162,
(1, 0, 1, 0, 0, 0, 1, 1) : 163,
(1, 0, 1, 0, 0, 1, 0, 0) : 164,
(1, 0, 1, 0, 0, 1, 0, 1) : 165,
(1, 0, 1, 0, 0, 1, 1, 0) : 166,
(1, 0, 1, 0, 0, 1, 1, 1) : 167,
(1, 0, 1, 0, 1, 0, 0, 0) : 168,
(1, 0, 1, 0, 1, 0, 0, 1) : 169,
(1, 0, 1, 0, 1, 0, 1, 0) : 170,
(1, 0, 1, 0, 1, 0, 1, 1) : 171,
(1, 0, 1, 0, 1, 1, 0, 0) : 172,
(1, 0, 1, 0, 1, 1, 0, 1) : 173,
(1, 0, 1, 0, 1, 1, 1, 0) : 174,
(1, 0, 1, 0, 1, 1, 1, 1) : 175,
(1, 0, 1, 1, 0, 0, 0, 0) : 176,
(1, 0, 1, 1, 0, 0, 0, 1) : 177,
(1, 0, 1, 1, 0, 0, 1, 0) : 178,
(1, 0, 1, 1, 0, 0, 1, 1) : 179,
(1, 0, 1, 1, 0, 1, 0, 0) : 180,
(1, 0, 1, 1, 0, 1, 0, 1) : 181,
(1, 0, 1, 1, 0, 1, 1, 0) : 182,
(1, 0, 1, 1, 0, 1, 1, 1) : 183,
(1, 0, 1, 1, 1, 0, 0, 0) : 184,
(1, 0, 1, 1, 1, 0, 0, 1) : 185,
(1, 0, 1, 1, 1, 0, 1, 0) : 186,
(1, 0, 1, 1, 1, 0, 1, 1) : 187,
(1, 0, 1, 1, 1, 1, 0, 0) : 188,
(1, 0, 1, 1, 1, 1, 0, 1) : 189,
(1, 0, 1, 1, 1, 1, 1, 0) : 190,
(1, 0, 1, 1, 1, 1, 1, 1) : 191,
(1, 1, 0, 0, 0, 0, 0, 0) : 192,
(1, 1, 0, 0, 0, 0, 0, 1) : 193,
(1, 1, 0, 0, 0, 0, 1, 0) : 194,
(1, 1, 0, 0, 0, 0, 1, 1) : 195,
(1, 1, 0, 0, 0, 1, 0, 0) : 196,
(1, 1, 0, 0, 0, 1, 0, 1) : 197,
(1, 1, 0, 0, 0, 1, 1, 0) : 198,
(1, 1, 0, 0, 0, 1, 1, 1) : 199,
(1, 1, 0, 0, 1, 0, 0, 0) : 200,
(1, 1, 0, 0, 1, 0, 0, 1) : 201,
(1, 1, 0, 0, 1, 0, 1, 0) : 202,
(1, 1, 0, 0, 1, 0, 1, 1) : 203,
(1, 1, 0, 0, 1, 1, 0, 0) : 204,
(1, 1, 0, 0, 1, 1, 0, 1) : 205,
(1, 1, 0, 0, 1, 1, 1, 0) : 206,
(1, 1, 0, 0, 1, 1, 1, 1) : 207,
(1, 1, 0, 1, 0, 0, 0, 0) : 208,
(1, 1, 0, 1, 0, 0, 0, 1) : 209,
(1, 1, 0, 1, 0, 0, 1, 0) : 210,
(1, 1, 0, 1, 0, 0, 1, 1) : 211,
(1, 1, 0, 1, 0, 1, 0, 0) : 212,
(1, 1, 0, 1, 0, 1, 0, 1) : 213,
(1, 1, 0, 1, 0, 1, 1, 0) : 214,
(1, 1, 0, 1, 0, 1, 1, 1) : 215,
(1, 1, 0, 1, 1, 0, 0, 0) : 216,
(1, 1, 0, 1, 1, 0, 0, 1) : 217,
(1, 1, 0, 1, 1, 0, 1, 0) : 218,
(1, 1, 0, 1, 1, 0, 1, 1) : 219,
(1, 1, 0, 1, 1, 1, 0, 0) : 220,
(1, 1, 0, 1, 1, 1, 0, 1) : 221,
(1, 1, 0, 1, 1, 1, 1, 0) : 222,
(1, 1, 0, 1, 1, 1, 1, 1) : 223,
(1, 1, 1, 0, 0, 0, 0, 0) : 224,
(1, 1, 1, 0, 0, 0, 0, 1) : 225,
(1, 1, 1, 0, 0, 0, 1, 0) : 226,
(1, 1, 1, 0, 0, 0, 1, 1) : 227,
(1, 1, 1, 0, 0, 1, 0, 0) : 228,
(1, 1, 1, 0, 0, 1, 0, 1) : 229,
(1, 1, 1, 0, 0, 1, 1, 0) : 230,
(1, 1, 1, 0, 0, 1, 1, 1) : 231,
(1, 1, 1, 0, 1, 0, 0, 0) : 232,
(1, 1, 1, 0, 1, 0, 0, 1) : 233,
(1, 1, 1, 0, 1, 0, 1, 0) : 234,
(1, 1, 1, 0, 1, 0, 1, 1) : 235,
(1, 1, 1, 0, 1, 1, 0, 0) : 236,
(1, 1, 1, 0, 1, 1, 0, 1) : 237,
(1, 1, 1, 0, 1, 1, 1, 0) : 238,
(1, 1, 1, 0, 1, 1, 1, 1) : 239,
(1, 1, 1, 1, 0, 0, 0, 0) : 240,
(1, 1, 1, 1, 0, 0, 0, 1) : 241,
(1, 1, 1, 1, 0, 0, 1, 0) : 242,
(1, 1, 1, 1, 0, 0, 1, 1) : 243,
(1, 1, 1, 1, 0, 1, 0, 0) : 244,
(1, 1, 1, 1, 0, 1, 0, 1) : 245,
(1, 1, 1, 1, 0, 1, 1, 0) : 246,
(1, 1, 1, 1, 0, 1, 1, 1) : 247,
(1, 1, 1, 1, 1, 0, 0, 0) : 248,
(1, 1, 1, 1, 1, 0, 0, 1) : 249,
(1, 1, 1, 1, 1, 0, 1, 0) : 250,
(1, 1, 1, 1, 1, 0, 1, 1) : 251,
(1, 1, 1, 1, 1, 1, 0, 0) : 252,
(1, 1, 1, 1, 1, 1, 0, 1) : 253,
(1, 1, 1, 1, 1, 1, 1, 0) : 254,
(1, 1, 1, 1, 1, 1, 1, 1) : 255
}
BITTOBYTE_LUT = {
(0, 0, 0, 0, 0, 0, 0, 0): b'\x00',
(0, 0, 0, 0, 0, 0, 0, 1): b'\x01',
(0, 0, 0, 0, 0, 0, 1, 0): b'\x02',
(0, 0, 0, 0, 0, 0, 1, 1): b'\x03',
(0, 0, 0, 0, 0, 1, 0, 0): b'\x04',
(0, 0, 0, 0, 0, 1, 0, 1): b'\x05',
(0, 0, 0, 0, 0, 1, 1, 0): b'\x06',
(0, 0, 0, 0, 0, 1, 1, 1): b'\x07',
(0, 0, 0, 0, 1, 0, 0, 0): b'\x08',
(0, 0, 0, 0, 1, 0, 0, 1): b'\t',
(0, 0, 0, 0, 1, 0, 1, 0): b'\n',
(0, 0, 0, 0, 1, 0, 1, 1): b'\x0b',
(0, 0, 0, 0, 1, 1, 0, 0): b'\x0c',
(0, 0, 0, 0, 1, 1, 0, 1): b'\r',
(0, 0, 0, 0, 1, 1, 1, 0): b'\x0e',
(0, 0, 0, 0, 1, 1, 1, 1): b'\x0f',
(0, 0, 0, 1, 0, 0, 0, 0): b'\x10',
(0, 0, 0, 1, 0, 0, 0, 1): b'\x11',
(0, 0, 0, 1, 0, 0, 1, 0): b'\x12',
(0, 0, 0, 1, 0, 0, 1, 1): b'\x13',
(0, 0, 0, 1, 0, 1, 0, 0): b'\x14',
(0, 0, 0, 1, 0, 1, 0, 1): b'\x15',
(0, 0, 0, 1, 0, 1, 1, 0): b'\x16',
(0, 0, 0, 1, 0, 1, 1, 1): b'\x17',
(0, 0, 0, 1, 1, 0, 0, 0): b'\x18',
(0, 0, 0, 1, 1, 0, 0, 1): b'\x19',
(0, 0, 0, 1, 1, 0, 1, 0): b'\x1a',
(0, 0, 0, 1, 1, 0, 1, 1): b'\x1b',
(0, 0, 0, 1, 1, 1, 0, 0): b'\x1c',
(0, 0, 0, 1, 1, 1, 0, 1): b'\x1d',
(0, 0, 0, 1, 1, 1, 1, 0): b'\x1e',
(0, 0, 0, 1, 1, 1, 1, 1): b'\x1f',
(0, 0, 1, 0, 0, 0, 0, 0): b' ',
(0, 0, 1, 0, 0, 0, 0, 1): b'!',
(0, 0, 1, 0, 0, 0, 1, 0): b'"',
(0, 0, 1, 0, 0, 0, 1, 1): b'#',
(0, 0, 1, 0, 0, 1, 0, 0): b'$',
(0, 0, 1, 0, 0, 1, 0, 1): b'%',
(0, 0, 1, 0, 0, 1, 1, 0): b'&',
(0, 0, 1, 0, 0, 1, 1, 1): b"'",
(0, 0, 1, 0, 1, 0, 0, 0): b'(',
(0, 0, 1, 0, 1, 0, 0, 1): b')',
(0, 0, 1, 0, 1, 0, 1, 0): b'*',
(0, 0, 1, 0, 1, 0, 1, 1): b'+',
(0, 0, 1, 0, 1, 1, 0, 0): b',',
(0, 0, 1, 0, 1, 1, 0, 1): b'-',
(0, 0, 1, 0, 1, 1, 1, 0): b'.',
(0, 0, 1, 0, 1, 1, 1, 1): b'/',
(0, 0, 1, 1, 0, 0, 0, 0): b'0',
(0, 0, 1, 1, 0, 0, 0, 1): b'1',
(0, 0, 1, 1, 0, 0, 1, 0): b'2',
(0, 0, 1, 1, 0, 0, 1, 1): b'3',
(0, 0, 1, 1, 0, 1, 0, 0): b'4',
(0, 0, 1, 1, 0, 1, 0, 1): b'5',
(0, 0, 1, 1, 0, 1, 1, 0): b'6',
(0, 0, 1, 1, 0, 1, 1, 1): b'7',
(0, 0, 1, 1, 1, 0, 0, 0): b'8',
(0, 0, 1, 1, 1, 0, 0, 1): b'9',
(0, 0, 1, 1, 1, 0, 1, 0): b':',
(0, 0, 1, 1, 1, 0, 1, 1): b';',
(0, 0, 1, 1, 1, 1, 0, 0): b'<',
(0, 0, 1, 1, 1, 1, 0, 1): b'=',
(0, 0, 1, 1, 1, 1, 1, 0): b'>',
(0, 0, 1, 1, 1, 1, 1, 1): b'?',
(0, 1, 0, 0, 0, 0, 0, 0): b'@',
(0, 1, 0, 0, 0, 0, 0, 1): b'A',
(0, 1, 0, 0, 0, 0, 1, 0): b'B',
(0, 1, 0, 0, 0, 0, 1, 1): b'C',
(0, 1, 0, 0, 0, 1, 0, 0): b'D',
(0, 1, 0, 0, 0, 1, 0, 1): b'E',
(0, 1, 0, 0, 0, 1, 1, 0): b'F',
(0, 1, 0, 0, 0, 1, 1, 1): b'G',
(0, 1, 0, 0, 1, 0, 0, 0): b'H',
(0, 1, 0, 0, 1, 0, 0, 1): b'I',
(0, 1, 0, 0, 1, 0, 1, 0): b'J',
(0, 1, 0, 0, 1, 0, 1, 1): b'K',
(0, 1, 0, 0, 1, 1, 0, 0): b'L',
(0, 1, 0, 0, 1, 1, 0, 1): b'M',
(0, 1, 0, 0, 1, 1, 1, 0): b'N',
(0, 1, 0, 0, 1, 1, 1, 1): b'O',
(0, 1, 0, 1, 0, 0, 0, 0): b'P',
(0, 1, 0, 1, 0, 0, 0, 1): b'Q',
(0, 1, 0, 1, 0, 0, 1, 0): b'R',
(0, 1, 0, 1, 0, 0, 1, 1): b'S',
(0, 1, 0, 1, 0, 1, 0, 0): b'T',
(0, 1, 0, 1, 0, 1, 0, 1): b'U',
(0, 1, 0, 1, 0, 1, 1, 0): b'V',
(0, 1, 0, 1, 0, 1, 1, 1): b'W',
(0, 1, 0, 1, 1, 0, 0, 0): b'X',
(0, 1, 0, 1, 1, 0, 0, 1): b'Y',
(0, 1, 0, 1, 1, 0, 1, 0): b'Z',
(0, 1, 0, 1, 1, 0, 1, 1): b'[',
(0, 1, 0, 1, 1, 1, 0, 0): b'\\',
(0, 1, 0, 1, 1, 1, 0, 1): b']',
(0, 1, 0, 1, 1, 1, 1, 0): b'^',
(0, 1, 0, 1, 1, 1, 1, 1): b'_',
(0, 1, 1, 0, 0, 0, 0, 0): b'`',
(0, 1, 1, 0, 0, 0, 0, 1): b'a',
(0, 1, 1, 0, 0, 0, 1, 0): b'b',
(0, 1, 1, 0, 0, 0, 1, 1): b'c',
(0, 1, 1, 0, 0, 1, 0, 0): b'd',
(0, 1, 1, 0, 0, 1, 0, 1): b'e',
(0, 1, 1, 0, 0, 1, 1, 0): b'f',
(0, 1, 1, 0, 0, 1, 1, 1): b'g',
(0, 1, 1, 0, 1, 0, 0, 0): b'h',
(0, 1, 1, 0, 1, 0, 0, 1): b'i',
(0, 1, 1, 0, 1, 0, 1, 0): b'j',
(0, 1, 1, 0, 1, 0, 1, 1): b'k',
(0, 1, 1, 0, 1, 1, 0, 0): b'l',
(0, 1, 1, 0, 1, 1, 0, 1): b'm',
(0, 1, 1, 0, 1, 1, 1, 0): b'n',
(0, 1, 1, 0, 1, 1, 1, 1): b'o',
(0, 1, 1, 1, 0, 0, 0, 0): b'p',
(0, 1, 1, 1, 0, 0, 0, 1): b'q',
(0, 1, 1, 1, 0, 0, 1, 0): b'r',
(0, 1, 1, 1, 0, 0, 1, 1): b's',
(0, 1, 1, 1, 0, 1, 0, 0): b't',
(0, 1, 1, 1, 0, 1, 0, 1): b'u',
(0, 1, 1, 1, 0, 1, 1, 0): b'v',
(0, 1, 1, 1, 0, 1, 1, 1): b'w',
(0, 1, 1, 1, 1, 0, 0, 0): b'x',
(0, 1, 1, 1, 1, 0, 0, 1): b'y',
(0, 1, 1, 1, 1, 0, 1, 0): b'z',
(0, 1, 1, 1, 1, 0, 1, 1): b'{',
(0, 1, 1, 1, 1, 1, 0, 0): b'|',
(0, 1, 1, 1, 1, 1, 0, 1): b'}',
(0, 1, 1, 1, 1, 1, 1, 0): b'~',
(0, 1, 1, 1, 1, 1, 1, 1): b'\x7f',
(1, 0, 0, 0, 0, 0, 0, 0): b'\x80',
(1, 0, 0, 0, 0, 0, 0, 1): b'\x81',
(1, 0, 0, 0, 0, 0, 1, 0): b'\x82',
(1, 0, 0, 0, 0, 0, 1, 1): b'\x83',
(1, 0, 0, 0, 0, 1, 0, 0): b'\x84',
(1, 0, 0, 0, 0, 1, 0, 1): b'\x85',
(1, 0, 0, 0, 0, 1, 1, 0): b'\x86',
(1, 0, 0, 0, 0, 1, 1, 1): b'\x87',
(1, 0, 0, 0, 1, 0, 0, 0): b'\x88',
(1, 0, 0, 0, 1, 0, 0, 1): b'\x89',
(1, 0, 0, 0, 1, 0, 1, 0): b'\x8a',
(1, 0, 0, 0, 1, 0, 1, 1): b'\x8b',
(1, 0, 0, 0, 1, 1, 0, 0): b'\x8c',
(1, 0, 0, 0, 1, 1, 0, 1): b'\x8d',
(1, 0, 0, 0, 1, 1, 1, 0): b'\x8e',
(1, 0, 0, 0, 1, 1, 1, 1): b'\x8f',
(1, 0, 0, 1, 0, 0, 0, 0): b'\x90',
(1, 0, 0, 1, 0, 0, 0, 1): b'\x91',
(1, 0, 0, 1, 0, 0, 1, 0): b'\x92',
(1, 0, 0, 1, 0, 0, 1, 1): b'\x93',
(1, 0, 0, 1, 0, 1, 0, 0): b'\x94',
(1, 0, 0, 1, 0, 1, 0, 1): b'\x95',
(1, 0, 0, 1, 0, 1, 1, 0): b'\x96',
(1, 0, 0, 1, 0, 1, 1, 1): b'\x97',
(1, 0, 0, 1, 1, 0, 0, 0): b'\x98',
(1, 0, 0, 1, 1, 0, 0, 1): b'\x99',
(1, 0, 0, 1, 1, 0, 1, 0): b'\x9a',
(1, 0, 0, 1, 1, 0, 1, 1): b'\x9b',
(1, 0, 0, 1, 1, 1, 0, 0): b'\x9c',
(1, 0, 0, 1, 1, 1, 0, 1): b'\x9d',
(1, 0, 0, 1, 1, 1, 1, 0): b'\x9e',
(1, 0, 0, 1, 1, 1, 1, 1): b'\x9f',
(1, 0, 1, 0, 0, 0, 0, 0): b'\xa0',
(1, 0, 1, 0, 0, 0, 0, 1): b'\xa1',
(1, 0, 1, 0, 0, 0, 1, 0): b'\xa2',
(1, 0, 1, 0, 0, 0, 1, 1): b'\xa3',
(1, 0, 1, 0, 0, 1, 0, 0): b'\xa4',
(1, 0, 1, 0, 0, 1, 0, 1): b'\xa5',
(1, 0, 1, 0, 0, 1, 1, 0): b'\xa6',
(1, 0, 1, 0, 0, 1, 1, 1): b'\xa7',
(1, 0, 1, 0, 1, 0, 0, 0): b'\xa8',
(1, 0, 1, 0, 1, 0, 0, 1): b'\xa9',
(1, 0, 1, 0, 1, 0, 1, 0): b'\xaa',
(1, 0, 1, 0, 1, 0, 1, 1): b'\xab',
(1, 0, 1, 0, 1, 1, 0, 0): b'\xac',
(1, 0, 1, 0, 1, 1, 0, 1): b'\xad',
(1, 0, 1, 0, 1, 1, 1, 0): b'\xae',
(1, 0, 1, 0, 1, 1, 1, 1): b'\xaf',
(1, 0, 1, 1, 0, 0, 0, 0): b'\xb0',
(1, 0, 1, 1, 0, 0, 0, 1): b'\xb1',
(1, 0, 1, 1, 0, 0, 1, 0): b'\xb2',
(1, 0, 1, 1, 0, 0, 1, 1): b'\xb3',
(1, 0, 1, 1, 0, 1, 0, 0): b'\xb4',
(1, 0, 1, 1, 0, 1, 0, 1): b'\xb5',
(1, 0, 1, 1, 0, 1, 1, 0): b'\xb6',
(1, 0, 1, 1, 0, 1, 1, 1): b'\xb7',
(1, 0, 1, 1, 1, 0, 0, 0): b'\xb8',
(1, 0, 1, 1, 1, 0, 0, 1): b'\xb9',
(1, 0, 1, 1, 1, 0, 1, 0): b'\xba',
(1, 0, 1, 1, 1, 0, 1, 1): b'\xbb',
(1, 0, 1, 1, 1, 1, 0, 0): b'\xbc',
(1, 0, 1, 1, 1, 1, 0, 1): b'\xbd',
(1, 0, 1, 1, 1, 1, 1, 0): b'\xbe',
(1, 0, 1, 1, 1, 1, 1, 1): b'\xbf',
(1, 1, 0, 0, 0, 0, 0, 0): b'\xc0',
(1, 1, 0, 0, 0, 0, 0, 1): b'\xc1',
(1, 1, 0, 0, 0, 0, 1, 0): b'\xc2',
(1, 1, 0, 0, 0, 0, 1, 1): b'\xc3',
(1, 1, 0, 0, 0, 1, 0, 0): b'\xc4',
(1, 1, 0, 0, 0, 1, 0, 1): b'\xc5',
(1, 1, 0, 0, 0, 1, 1, 0): b'\xc6',
(1, 1, 0, 0, 0, 1, 1, 1): b'\xc7',
(1, 1, 0, 0, 1, 0, 0, 0): b'\xc8',
(1, 1, 0, 0, 1, 0, 0, 1): b'\xc9',
(1, 1, 0, 0, 1, 0, 1, 0): b'\xca',
(1, 1, 0, 0, 1, 0, 1, 1): b'\xcb',
(1, 1, 0, 0, 1, 1, 0, 0): b'\xcc',
(1, 1, 0, 0, 1, 1, 0, 1): b'\xcd',
(1, 1, 0, 0, 1, 1, 1, 0): b'\xce',
(1, 1, 0, 0, 1, 1, 1, 1): b'\xcf',
(1, 1, 0, 1, 0, 0, 0, 0): b'\xd0',
(1, 1, 0, 1, 0, 0, 0, 1): b'\xd1',
(1, 1, 0, 1, 0, 0, 1, 0): b'\xd2',
(1, 1, 0, 1, 0, 0, 1, 1): b'\xd3',
(1, 1, 0, 1, 0, 1, 0, 0): b'\xd4',
(1, 1, 0, 1, 0, 1, 0, 1): b'\xd5',
(1, 1, 0, 1, 0, 1, 1, 0): b'\xd6',
(1, 1, 0, 1, 0, 1, 1, 1): b'\xd7',
(1, 1, 0, 1, 1, 0, 0, 0): b'\xd8',
(1, 1, 0, 1, 1, 0, 0, 1): b'\xd9',
(1, 1, 0, 1, 1, 0, 1, 0): b'\xda',
(1, 1, 0, 1, 1, 0, 1, 1): b'\xdb',
(1, 1, 0, 1, 1, 1, 0, 0): b'\xdc',
(1, 1, 0, 1, 1, 1, 0, 1): b'\xdd',
(1, 1, 0, 1, 1, 1, 1, 0): b'\xde',
(1, 1, 0, 1, 1, 1, 1, 1): b'\xdf',
(1, 1, 1, 0, 0, 0, 0, 0): b'\xe0',
(1, 1, 1, 0, 0, 0, 0, 1): b'\xe1',
(1, 1, 1, 0, 0, 0, 1, 0): b'\xe2',
(1, 1, 1, 0, 0, 0, 1, 1): b'\xe3',
(1, 1, 1, 0, 0, 1, 0, 0): b'\xe4',
(1, 1, 1, 0, 0, 1, 0, 1): b'\xe5',
(1, 1, 1, 0, 0, 1, 1, 0): b'\xe6',
(1, 1, 1, 0, 0, 1, 1, 1): b'\xe7',
(1, 1, 1, 0, 1, 0, 0, 0): b'\xe8',
(1, 1, 1, 0, 1, 0, 0, 1): b'\xe9',
(1, 1, 1, 0, 1, 0, 1, 0): b'\xea',
(1, 1, 1, 0, 1, 0, 1, 1): b'\xeb',
(1, 1, 1, 0, 1, 1, 0, 0): b'\xec',
(1, 1, 1, 0, 1, 1, 0, 1): b'\xed',
(1, 1, 1, 0, 1, 1, 1, 0): b'\xee',
(1, 1, 1, 0, 1, 1, 1, 1): b'\xef',
(1, 1, 1, 1, 0, 0, 0, 0): b'\xf0',
(1, 1, 1, 1, 0, 0, 0, 1): b'\xf1',
(1, 1, 1, 1, 0, 0, 1, 0): b'\xf2',
(1, 1, 1, 1, 0, 0, 1, 1): b'\xf3',
(1, 1, 1, 1, 0, 1, 0, 0): b'\xf4',
(1, 1, 1, 1, 0, 1, 0, 1): b'\xf5',
(1, 1, 1, 1, 0, 1, 1, 0): b'\xf6',
(1, 1, 1, 1, 0, 1, 1, 1): b'\xf7',
(1, 1, 1, 1, 1, 0, 0, 0): b'\xf8',
(1, 1, 1, 1, 1, 0, 0, 1): b'\xf9',
(1, 1, 1, 1, 1, 0, 1, 0): b'\xfa',
(1, 1, 1, 1, 1, 0, 1, 1): b'\xfb',
(1, 1, 1, 1, 1, 1, 0, 0): b'\xfc',
(1, 1, 1, 1, 1, 1, 0, 1): b'\xfd',
(1, 1, 1, 1, 1, 1, 1, 0): b'\xfe',
(1, 1, 1, 1, 1, 1, 1, 1): b'\xff'
}
def bytes_to_bitlist(buf):
"""Convert a bytes string to a list of bits -0 or 1-
Args:
buf (bytes) : bytes string
Returns:
bitlist (list of integer) : list of 0 and 1
Raises:
KeyError : if `s' is not bytes
"""
bitlist = []
[bitlist.extend(ARRTOBIT_LUT[val]) for val in buf]
return bitlist
def bitlist_to_bytes(bitlist):
"""Convert an iterable of bits -0 or 1- to a bytes string
Args:
bitlist (iterable of integer) : iterable of 0 and 1
Returns:
buf (bytes) : bytes string
Raises:
KeyError : if bitlist contains invalid values
"""
buf = []
# cast the iterable to a tuple for dict LU
bitlist = tuple(bitlist)
trail = len(bitlist) % 8
if trail:
[buf.append(BITTOARR_LUT[bitlist[i:i+8]]) \
for i in range(0, len(bitlist)-trail, 8)]
buf.append(BITTOARR_LUT[bitlist[-trail:] + (8-trail) * (0, )] )
return bytes(buf)
else:
[buf.append(BITTOARR_LUT[bitlist[i:i+8]]) \
for i in range(0, len(bitlist), 8)]
return bytes(buf)
#------------------------------------------------------------------------------#
# bytes buffer functions
#------------------------------------------------------------------------------#
def bytes_lshift(buf=b'', bitlen=0):
"""Shift left a bytes buffer of `bitlen' bits
Args:
buf (bytes) : bytes string
bitlen (int) : length in bits
Returns:
buf_sh (bytes) : shifted bytes string
"""
if bitlen > 8*len(buf):
bitlen = 8*len(buf)
byte_len, bit_len = bitlen>>3, bitlen%8
# full byte shifting
buf_sh = buf[byte_len:]
bl = 8 * len(buf_sh)
# bit shifting
if bitlen:
return uint_to_bytes((bytes_to_uint(buf_sh, bl) << bit_len) & \
((1<<bl)-1), bl)
else:
return buf_sh
def bytes_zero_last_bits(buf, bitlen=1):
"""Zero the `bitlen' last bits of the bytes buffer `buf'
Args:
buf (bytes) : bytes string
bitlen (integer) : length in bits
Returns:
buf_z (bytes) : bytes buffer with last bits set to zero
Raises:
PycrateErr : if `bitlen' is not between 1 and 7 inclusive
"""
if not 0 < bitlen < 8:
raise(PycrateErr('bitlen must be between 0 and 8, not inclusive'))
return buf[:-1] + bytes( (buf[-1] & (0x100-(1<<bitlen)), ) )
def bytes_to_bytelist(buf):
"""Convert a bytes buffer to a list of bytes -uint8-
Args:
buf (bytes) : bytes string
Returns:
bytelist (list of integers) : list of uint8 values (0<=X<=255)
"""
return list(buf)
def bytelist_to_bytes(bytelist):
"""Convert a list of bytes -uint8- to a bytes buffer
Args:
bytelist (list of integer) : list of uint8 values (0<=X<=255)
Returns:
buf (bytes) : bytes string
"""
return bytes(bytelist)
#------------------------------------------------------------------------------#
# bytelist functions
#------------------------------------------------------------------------------#
def bytelist_lshift(bytelist, bitlen=0):
"""Shift left a byte list of `bitlen' bits
Args:
bytelist (iterable of integer) : iterable of uint8
bitlen (integer) : length in bits
Returns:
bytelist_sh (list of integer) : list of uint8
"""
return list(bytes_lshift(bytes(bytelist), bitlen))
def uint_to_bytelist(val, bitlen=1):
"""Convert an unsigned integer to a bytelist of `bitlen' length in bits,
uint with most significant bit leftmost
Args:
val (integer) : unsigned integer
bitlen (integer) : length in bits
Returns:
bytelist (list of integer) : list of uint8 values (0<=X<=255)
Raises:
PycrateErr : if `bitlen' is not strictly positive
"""
return list(uint_to_bytes(val, bitlen))
def bytelist_to_uint(bytelist, bitlen=1):
"""Convert bytelist to an unsigned integer of `bitlen' length in bits,
uint with most significant bit leftmost
Args:
val (integer) : unsigned integer
bitlen (integer) : length in bits
Returns:
bytelist (list of integer) : list of uint8 values (0<=X<=255)
Raises:
PycrateErr : if `bitlen' is not strictly positive
"""
return bytes_to_uint(bytes(bytelist), bitlen)
#------------------------------------------------------------------------------#
# integer functions
#------------------------------------------------------------------------------#
def bytes_to_uint(buf, bitlen=1):
"""Convert the leftmost bits of a bytes buffer to an unsigned integer,
uint with most significant bit leftmost
Args:
buf (bytes) : bytes string
bitlen (integer) : length in bits
Returns:
uint (integer) : unsigned integer value
Raises:
PycrateErr : if `bitlen' is not strictly positive or if `buf' is not
long enough
"""
# leverage Python3 built-in conversion: int.from_bytes()
if bitlen <= 0:
raise(PycrateErr('bitlen must be strictly positive'))
len_byte, len_bit = bitlen>>3, bitlen%8
if len_bit:
if len(buf) < len_byte + 1:
raise(PycrateErr('bytes buffer not long enough'))
else:
return int.from_bytes(buf[:len_byte+1], 'big') >> (8-len_bit)
else:
if len(buf) < len_byte:
raise(PycrateErr('bytes buffer not long enough'))
elif len_byte == 1:
return buf[0]
else:
return int.from_bytes(buf[:len_byte], 'big')
def uint_to_bytes(val, bitlen=1):
"""Convert an unsigned integer to a bytes buffer of given length in bits,
uint with most significant bit leftmost
Args:
val (integer) : unsigned integer
bitlen (integer) : length in bits
Returns:
buf (bytes) : bytes string
Raises:
PycrateErr : if `bitlen' is not strictly positive
"""
# Python3 built-in conversion: int.to_bytes()
if bitlen <= 0:
raise(PycrateErr('bitlen must be strictly positive'))
len_byte, len_bit = bitlen>>3, bitlen % 8
# if len_bit, need padding bits appended rightmost
if val >= (1<<bitlen):
if len_bit:
return len_byte * b'\xff' + bchr(0x100-(1<<(8-len_bit)))
else:
return len_byte * b'\xff'
elif len_bit == 0:
if len_byte == 1:
return bchr(val)
else:
if _WITH_MPZ and isinstance(val, _MPZ_T):
return int(val).to_bytes(len_byte, 'big')
else:
return val.to_bytes(len_byte, 'big')
else:
if _WITH_MPZ and isinstance(val, _MPZ_T):
return int(val<<(8-len_bit)).to_bytes(len_byte+1, 'big')
else:
return (val<<(8-len_bit)).to_bytes(len_byte+1, 'big')
def bytes_to_uint_le(buf, bitlen=8):
"""Convert the leftmost bits of a bytes buffer to an unsigned integer in
little endian format (least significant byte leftmost)
Args:
buf (bytes) : bytes string
bitlen (integer) : length in bits, must be a multiple of 8
Returns:
uint (integer) : unsigned integer value
Raises:
PycrateErr : if `bitlen' is not strictly positive or not byte-aligned
or if `buf' is not long enough
"""
# leverage Python3 built-in conversion: int.from_bytes()
if bitlen <= 0 or bitlen%8:
raise(PycrateErr('invalid bitlen for little endian uint: {0}'\
.format(bitlen)))
len_byte = bitlen>>3
#
if len(buf) < len_byte:
raise(PycrateErr('bytes buffer not long enough'))
elif len_byte == 1:
return buf[0]
else:
return int.from_bytes(buf[:len_byte], 'little')
def uint_le_to_bytes(val, bitlen=8):
"""Convert an unsigned integer to a bytes buffer of given length in bits,
uint in little endian format (least significant byte leftmost)
Args:
val (integer) : unsigned integer
bitlen (integer) : length in bits, must be a multiple of 8
Returns:
buf (bytes) : bytes string
Raises:
PycrateErr : if `bitlen' is not strictly positive or not byte-aligned
"""
# Python3 built-in conversion: int.to_bytes()
if bitlen <= 0 or bitlen%8:
raise(PycrateErr('invalid bitlen for little endian uint: {0}'\
.format(bitlen)))
len_byte = bitlen>>3
#
if val >= (1<<bitlen):
return len_byte * b'\xff'
elif len_byte == 1:
return bchr(val)
else:
if _WITH_MPZ and isinstance(val, _MPZ_T):
return int(val).to_bytes(len_byte, 'little')
else:
return val.to_bytes(len_byte, 'little')
def decompose_uint(mul=0x100, val=0):
"""Decompose a value in a list of factors of `mul'
decompose_uint(1<<X, Y) -> [a, b, c, d ...]
where Y = a + (b << X) + (c << 2X) + (d << 3X) ...
or
decompose_uint(X', Y) -> [a, b, c, d ...]
where Y = a + b * X' + c * X'^2 + d*X'^3 ...
Args:
mul (integer) : unsigned integer used as factor
val (integer) : unsigned integer to be factored
Returns:
dec (list of integers) : list of factors
"""
# benefit from Python built-in int() which is pretty fast
if mul == 2:
dec = list(map(int, bin(val)[2:]))
dec.reverse()
return dec
elif mul == 16 and val >= 10000000:
h = hex(val)[2:]
dec = list(map(int, h, len(h)*[16]))
dec.reverse()
return dec
# decompose simply by iterative division
else:
dec = [ int(val % mul) ]
while val >= mul:
val //= mul
dec.append( int(val % mul) )
return dec
def swap_uint(uint, bitlen):
"""Swap the endianness of the unsigned integer uint of length bitlen
Args:
uint (unsigned integer)
bitlen (unsigned integer)
Returns:
uint (unsigned integer)
"""
if bitlen < 0 or bitlen % 8:
raise(PycrateErr('invalid bitlen of little endian uint: {0}'\
.format(bitlen)))
len_byte = bitlen>>3
return int.from_bytes(uint.to_bytes(len_byte, byteorder='little'), byteorder='big')
#------------------------------------------------------------------------------#
# concatenation
#------------------------------------------------------------------------------#
def bytes_lshift_bnd(buf, buflen=8, shlen=1):
"""Shift left of `shlen' bits the bytes buffer `buf' of length in bits
`buflen' with 0 < shlen < 8
provide the heading value of `shlen' bits that leaves the buffer
the shifted buffer, fully byte-aligned (can be of size 0)
the trailing value of remaining bits (can be None)
Args:
buf (bytes) : bytes string
buflen (integer) : length in bits of the bytes buffer
shlen (integer) : value of the shift, between 1 and 7
Returns:
tuple of (integer, bytes, integer or None)
"""
if buflen <= shlen:
# only heading bits
head = (buf[0] & (0x100 - (1<<(8-buflen)))) >> (8-shlen)
return head, b'', None
elif buflen < 8 + shlen:
# only heading and trailing bits
head = buf[0] >> (8-shlen)
buf = bytes_lshift(buf, shlen)
trail = buf[0] & (0x100 - (1<<(8-buflen+shlen)))
return head, b'', trail
#
head = buf[0]>>(8-shlen)
buf = bytes_lshift(buf, shlen)
restlen = buflen % 8
if restlen == 0:
trail = buf[-1]
buf = buf[:-1]
elif restlen < shlen:
trail = buf[-2] & (0x100 - (1<<(shlen-restlen)))
buf = buf[:-2]
elif restlen == shlen:
trail = None
buf = buf[:-1]
else:
trail = buf[-1] & (0x100 - (1<<(8+shlen-restlen)))
buf = buf[:-1]
return head, buf, trail
TYPE_BYTES = 1
TYPE_UINT = 2
TYPE_INT = 3
TYPE_UINT_LE = 12
TYPE_INT_LE = 13
#
FMT_INT = {
8 : 'b',
16: 'h',
32: 'i',
64: 'q'
}
FMT_UINT = {
8 : 'B',
16: 'H',
32: 'I',
64: 'Q'
}
FMT_LUT = {
2: FMT_UINT,
3: FMT_INT,
12: FMT_UINT,
13: FMT_INT
}
#
PACK_FMT_BE = 0
PACK_FMT_LE = 1
def pack_val(*val):
"""Packs heterogenous bytes buffer and (un)signed integers, all with a given
length in bits, to a resulting bytes buffer
Args:
val (tuple) : tuple of (type, value, bitlen)
type must be TYPE_BYTES, TYPE_UINT, TYPE_UINT_LE, TYPE_INT or TYPE_INT_LE
value must be a bytes string or an integer, according to type
bitlen must be an integer over 0
warning: for TYPE_UINT_LE and TYPE_INT_LE, bitlen must be a multiple
of 8 (hence the value will be byte-aligned)
Returns:
buf (tuple of (bytes, integer)) : a tuple containing the actual
resulting bytes string and the length in bits
Example:
pack_val( (TYPE_BYTES, b'AAAA\xC0', 34),
(TYPE_UINT, 2500, 32),
(TYPE_UINT, 10000000000, 64),
(TYPE_INT, -1, 8),
(TYPE_BYTES, b'bbbbbb', 48),
(TYPE_INT, -2000, 54),
(TYPE_UINT, 1, 2),
(TYPE_BYTES, b'\0', 7) )
-> (b'AAAA\xc0\x00\x02q\x00\x00\x00\x00\x95\x02\xf9\x00?'\
'\xd8\x98\x98\x98\x98\x98?\xff\xff\xff\xff\xf80@\x00',
249)
"""
# global resulting byte buffer
concat, len_bit = [], 0
# junction byte when unaligned values are concatenated
junc = None
# cumulative processing for int / uint
pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
for v in val:
#print('val : {0}, {1}, {2}'.format(*v))
#print('pack : fmt {0}, val {1}'.format(pack_fmt, pack_val))
#print('junc : {0}'.format(junc))
#print('len_bit : {0}'.format(len_bit))
#print('concat : {0}'.format(concat))
#print('')
#
rest_bit = len_bit%8
#
# 0) bypass null field
if v[2] == 0:
pass
#
# 1) cumulative processing for 8/16/32/64 bits big endian (u)int
elif v[0] in (TYPE_INT, TYPE_UINT) and v[2] in (8, 16, 32, 64):
if pack_end == PACK_FMT_LE and pack_fmt is not None:
# a) append previous integers that were little endian
pack_buf = pack(''.join(pack_fmt), *pack_val)
if rest_bit == 0:
# a.a) aligned access
assert( junc is None )
concat.append(pack_buf)
len_bit += pack_len
else:
# a.b) unaligned access
assert( 0 <= junc < 256 )
head, buf, trail = bytes_lshift_bnd(pack_buf, pack_len, 8-rest_bit)
# complete the junction byte and append it
# with the shifted buffer
len_bit += pack_len
if buf:
# heading bits, buffer and potential trailing bits
concat.extend( (bchr(junc + head), buf) )
junc = trail
elif trail is not None:
# heading bits and potential trailing bits
concat.append( bchr(junc + head) )
junc = trail
elif not len_bit % 8:
# heading bits only
concat.append( bchr(junc + head) )
junc = None
else:
# no buf and no trailing bits
junc += head
pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
#
# b) accumulate value into pack_val
if pack_fmt is None:
pack_end = PACK_FMT_BE
pack_fmt = ['>', FMT_LUT[v[0]][v[2]]]
pack_val = [v[1]]
else:
pack_fmt.append( FMT_LUT[v[0]][v[2]] )
pack_val.append( v[1] )
pack_len += v[2]
#
# 2) cumulative processing for 8/16/32/64 bits little endian (u)int
elif v[0] in (TYPE_INT_LE, TYPE_UINT_LE) and v[2] in (8, 16, 32, 64):
# a) append previous integers if were big endian
if pack_end == PACK_FMT_BE and pack_fmt is not None:
pack_buf = pack(''.join(pack_fmt), *pack_val)
if rest_bit == 0:
# a.a) aligned access
assert( junc is None )
concat.append(pack_buf)
len_bit += pack_len
else:
# a.b) unaligned access
assert( 0 <= junc < 256 )
head, buf, trail = bytes_lshift_bnd(pack_buf, pack_len, 8-rest_bit)
# complete the junction byte and append it
# with the shifted buffer
len_bit += pack_len
if buf:
# heading bits, buffer and potential trailing bits
concat.extend( (bchr(junc + head), buf) )
junc = trail
elif trail is not None:
# heading bits and potential trailing bits
concat.append( bchr(junc + head) )
junc = trail
elif not len_bit % 8:
# heading bits only
concat.append( bchr(junc + head) )
junc = None
else:
# no buf and no trailing bits
junc += head
pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
#
# b) accumulate value into pack_val
if pack_fmt is None:
pack_end = PACK_FMT_LE
pack_fmt = ['<', FMT_LUT[v[0]][v[2]]]
pack_val = [v[1]]
else:
pack_fmt.append( FMT_LUT[v[0]][v[2]] )
pack_val.append( v[1] )
pack_len += v[2]
#
# 3) standard processing for bytes buffer
elif v[0] == TYPE_BYTES:
# a) append pack_val first, if exist
if pack_fmt is not None:
pack_buf = pack(''.join(pack_fmt), *pack_val)
if rest_bit == 0:
# a.a) aligned access
assert( junc is None )
concat.append(pack_buf)
len_bit += pack_len
#
concat.append(v[1][:v[2]>>3])
if v[2]%8:
# remaining bits goes to junction byte
junc = (v[1][v[2]>>3]) & (0x100 - (1<<(8-v[2]%8)))
len_bit += v[2]
#
else:
# a.b) unaligned access
assert( 0 <= junc < 256 )
if v[2] % 8:
buf = pack_buf + v[1][:1+(v[2]>>3)]
else:
buf = pack_buf + v[1][:v[2]>>3]
buflen = pack_len + v[2]
head, buf, trail = bytes_lshift_bnd(buf, buflen, 8-rest_bit)
# complete the junction byte and append it
# with the shifted buffer
len_bit += buflen
if buf:
# heading bits, buffer and potential trailing bits
concat.extend( (bchr(junc + head), buf) )
junc = trail
elif trail is not None:
# heading bits and potential trailing bits
concat.append( bchr(junc + head) )
junc = trail
elif not len_bit % 8:
# heading bits only
concat.append( bchr(junc + head) )
junc = None
else:
# no buf and no trailing bits
junc += head
#
pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
#
# b) nothing to pack
elif rest_bit == 0:
# b.a) aligned access
assert( junc is None )
if v[2] < 8:
junc = v[1][0] & (0x100 - (1<<(8-v[2])))
else:
concat.append( v[1][:v[2]>>3] )
if v[2] % 8:
# remaining bits goes to junction byte
junc = (v[1][v[2]>>3]) & (0x100 - (1<<(8-v[2]%8)))
len_bit += v[2]
#
else:
# b.b) unaligned access
assert( 0 <= junc < 256 )
if v[2] % 8:
head, buf, trail = bytes_lshift_bnd(v[1][:1+(v[2]>>3)],
v[2], 8-rest_bit)
else:
head, buf, trail = bytes_lshift_bnd(v[1][:v[2]>>3],
v[2], 8-rest_bit)
# complete the junction byte and append it
# with the shifted buffer
len_bit += v[2]
if buf:
# heading bits, buffer and potential trailing bits
concat.extend( (bchr(junc + head), buf) )
junc = trail
elif trail is not None:
# heading bits and potential trailing bits
concat.append( bchr(junc + head) )
junc = trail
elif not len_bit % 8:
# heading bits only
concat.append( bchr(junc + head) )
junc = None
else:
# no buf and no trailing bits, only some more junction bits
junc += head
#
# 3) standard processing for uint
elif v[0] == TYPE_UINT:
# a) append pack_val first, if exist
if pack_fmt is not None:
pack_buf = pack(''.join(pack_fmt), *pack_val)
if rest_bit == 0:
# a.a) aligned access
assert( junc is None )
concat.append(pack_buf)
len_bit += pack_len
#
buf = uint_to_bytes(v[1], v[2])
concat.append(buf[:v[2]>>3])
if v[2]%8:
# remaining bits goes to junction byte
junc = buf[v[2]>>3]
len_bit += v[2]
#
else:
# a.b) unaligned access
assert( 0 <= junc < 256 )
# first shift the existing packed buffer
# TODO: this may be faster to shift integer values before
# packing them; however, this will break their format and
# cause me more headache
head, buf, trail = bytes_lshift_bnd(pack_buf,
pack_len, 8-rest_bit)
if buf:
concat.extend( (bchr(junc + head), buf) )
else:
concat.append( bchr(junc + head) )
# pack_buf is always byte-aligned,
# so there are always trailing bits
junc = trail
u = v[1] & ((1<<v[2])-1)
# heading bits from the uint value to pack
if v[2] < 8-rest_bit:
junc += u << (8-rest_bit-v[2])
elif v[2] == 8-rest_bit:
concat.append( bchr(junc + u) )
junc = None
else:
lb = v[2]-8+rest_bit
concat.append( bchr(junc + (u>>lb)) )
if lb >= 8:
# body of the uint value
lt = lb%8
if lt == 0:
# no trailing bits
concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
junc = None
else:
# with trailing bits
concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
lb-lt) )
junc = (u&((1<<lt)-1))<<(8-lt)
else:
# no body, only trailing bits
junc = (u&((1<<lb)-1))<<(8-lb)
len_bit += pack_len + v[2]
#
pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
#
# b) nothing to pack
elif len_bit % 8 == 0:
# b.a) aligned access
assert( junc is None )
if v[2] < 8:
if v[1] >= (1<<v[2]):
junc = 0x100 - (1<<(8-v[2]))
else:
junc = v[1] << (8-v[2])
else:
buf = uint_to_bytes(v[1], v[2])
concat.append(buf[:v[2]>>3])
if v[2]%8:
# remaining bits goes to junction byte
junc = buf[v[2]>>3]
len_bit += v[2]
#
else:
# b.b) unaligned access
assert( 0 <= junc < 256 )
u = v[1] & ((1<<v[2])-1)
# heading bits from the uint value to pack
if v[2] < 8-rest_bit:
junc += u << (8-rest_bit-v[2])
elif v[2] == 8-rest_bit:
concat.append( bchr(junc + u) )
junc = None
else:
lb = v[2]-8+rest_bit
concat.append( bchr(junc + (u>>lb)) )
if lb >= 8:
# body of the uint value
lt = lb%8
if lt == 0:
# no trailing bits
concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
junc = None
else:
# with trailing bits
concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
lb-lt) )
junc = (u&((1<<lt)-1))<<(8-lt)
else:
# no body, only trailing bits
junc = (u&((1<<lb)-1))<<(8-lb)
len_bit += v[2]
#
# 4) standard processing for int
elif v[0] == TYPE_INT:
#
if v[1] >= 0:
u = v[1]&((1<<v[2]-1)-1)
else:
# take 2's complement, so we only manipulate uint
u = v[1]+(1<<v[2])
if u < (1<<(v[2]-1)):
u = 1<<(v[2]-1)
#
# a) append pack_val first, if exist
if pack_fmt is not None:
pack_buf = pack(''.join(pack_fmt), *pack_val)
if rest_bit == 0:
# a.a) aligned access
assert( junc is None )
concat.append(pack_buf)
len_bit += pack_len
#
buf = uint_to_bytes(u, v[2])
concat.append(buf[:v[2]>>3])
if v[2]%8:
# remaining bits goes to junction byte
junc = buf[v[2]>>3]
len_bit += v[2]
#
else:
# a.b) unaligned access
assert( 0 <= junc < 256 )
# first shift the existing packed buffer
# TODO: this may be faster to shift integer values before
# packing them; however, this will break their format and
# cause me more headache
head, buf, trail = bytes_lshift_bnd(pack_buf,
pack_len, 8-rest_bit)
if buf:
concat.extend( (bchr(junc + head), buf) )
else:
concat.append( bchr(junc + head) )
# pack_buf is always byte-aligned,
# so there are always trailing bits
junc = trail
#
# heading bits from the uint value to pack
if v[2] < 8-rest_bit:
junc += u << (8-rest_bit-v[2])
elif v[2] == 8-rest_bit:
concat.append( bchr(junc + u) )
junc = None
else:
lb = v[2]-8+rest_bit
concat.append( bchr(junc + (u>>lb)) )
if lb >= 8:
# body of the uint value
lt = lb%8
if lt == 0:
# no trailing bits
concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
junc = None
else:
# with trailing bits
concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
lb-lt) )
junc = (u&((1<<lt)-1))<<(8-lt)
else:
# no body, only trailing bits
junc = (u&((1<<lb)-1))<<(8-lb)
len_bit += pack_len + v[2]
#
pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
#
# b) nothing to pack
elif len_bit % 8 == 0:
# b.a) aligned access
assert( junc is None )
if v[2] < 8:
junc = u << (8-v[2])
else:
buf = uint_to_bytes(u, v[2])
concat.append(buf[:v[2]>>3])
if v[2]%8:
# remaining bits goes to junction byte
junc = buf[v[2]>>3]
len_bit += v[2]
#
else:
# b.b) unaligned access
assert( 0 <= junc < 256 )
# heading bits from the uint value to pack
if v[2] < 8-rest_bit:
junc += u << (8-rest_bit-v[2])
elif v[2] == 8-rest_bit:
concat.append( bchr(junc + u) )
junc = None
else:
lb = v[2]-8+rest_bit
concat.append( bchr(junc + (u>>lb)) )
if lb >= 8:
# body of the uint value
lt = lb%8
if lt == 0:
# no trailing bits
concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
junc = None
else:
# with trailing bits
concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
lb-lt) )
junc = (u&((1<<lt)-1))<<(8-lt)
else:
# no body, only trailing bits
junc = (u&((1<<lb)-1))<<(8-lb)
len_bit += v[2]
#
# 5) standard processing for little-endian integers
elif v[0] in (TYPE_UINT_LE, TYPE_INT_LE):
if v[0] == TYPE_UINT_LE:
v_bytes = uint_le_to_bytes(v[1], v[2])
else:
if v[1] >= 0:
u = v[1]&((1<<v[2]-1)-1)
else:
# take 2's complement, so we only manipulate uint
u = v[1]+(1<<v[2])
if u < (1<<(v[2]-1)):
u = 1<<(v[2]-1)
v_bytes = uint_le_to_bytes(u, v[2])
# a) append pack_val first, if exist
if pack_fmt is not None:
pack_buf = pack(''.join(pack_fmt), *pack_val)
if rest_bit == 0:
# a.a) aligned access
assert( junc is None )
concat.append(pack_buf)
len_bit += pack_len
#
concat.append(v_bytes)
len_bit += v[2]
#
else:
# a.b) unaligned access
assert( 0 <= junc < 256 )
buf = pack_buf + v_bytes
buflen = pack_len + v[2]
head, buf, trail = bytes_lshift_bnd(buf, buflen, 8-rest_bit)
# complete the junction byte and append it
# with the shifted buffer
len_bit += buflen
if buf:
# heading bits, buffer and potential trailing bits
concat.extend( (bchr(junc + head), buf) )
junc = trail
elif trail is not None:
# heading bits and potential trailing bits
concat.append( bchr(junc + head) )
junc = trail
elif not len_bit % 8:
# heading bits only
concat.append( bchr(junc + head) )
junc = None
else:
# no buf and no trailing bits
junc += head
#
pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
#
# b) nothing to pack
elif rest_bit == 0:
# b.a) aligned access
assert( junc is None )
concat.append(v_bytes)
len_bit += v[2]
#
else:
# b.b) unaligned access
assert( 0 <= junc < 256 )
head, buf, trail = bytes_lshift_bnd(v_bytes, v[2], 8-rest_bit)
# complete the junction byte and append it
# with the shifted buffer
len_bit += v[2]
if buf:
# heading bits, buffer and potential trailing bits
concat.extend( (bchr(junc + head), buf) )
junc = trail
elif trail is not None:
# heading bits and potential trailing bits
concat.append( bchr(junc + head) )
junc = trail
elif not len_bit % 8:
# heading bits only
concat.append( bchr(junc + head) )
junc = None
else:
# no buf and no trailing bits
junc += head
#
else:
raise(PycrateErr('invalid type for packing: {0}'.format(v[0])))
#
#print('pack : fmt {0}, val {1}'.format(pack_fmt, pack_val))
#print('junc : {0}'.format(junc))
#print('len_bit : {0}'.format(len_bit))
#print('concat : {0}'.format(concat))
#print('')
#
# 5) in case some integers to pack remains
if pack_val is not None:
rest_bit = len_bit%8
pack_buf = pack(''.join(pack_fmt), *pack_val)
if rest_bit == 0:
# a) aligned access
assert( junc is None )
concat.append(pack_buf)
len_bit += pack_len
else:
# b) unaligned access
assert( 0 <= junc < 256 )
# TODO: again, this may be faster to shift integer values before
# packing them...
head, buf, trail = bytes_lshift_bnd(pack_buf, pack_len, 8-rest_bit)
# complete the junction byte and append it
# with the shifted buffer
if buf:
concat.extend( (bchr(junc + head), buf) )
junc = trail
else:
concat.append( bchr(junc + head) )
junc = trail
len_bit += pack_len
#
#pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
#
#print('junc : {0}'.format(junc))
#print('len_bit : {0}'.format(len_bit))
#print('concat : {0}'.format(concat))
#print('')
#
# 6) pack the remaining junction byte
if junc is not None:
concat.append( bchr(junc) )
#
# 7) return the length in bits and bytes buffer
return b''.join(concat), len_bit