-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathoriginal_base122.py
104 lines (92 loc) · 3.24 KB
/
original_base122.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
###################################################
# THIS SHOULD NOT BE USED ANYMORE BECAUSE THE OTHER ONE IS ALMOST 2X FASTER
###################################################
import base64 # for converting b64 strings to b122
import sys
PY2 = sys.version_info[0] == 2
# null, newline, carriage return, double quote, ampersand, backslash
kIllegals = [chr(0), chr(10), chr(13), chr(34), chr(38), chr(92)]
kShortened = 0b111 # last two-byte char encodes <= 7 bits
def encode(rawData, warnings=True):
if PY2 and warnings:
raise NotImplementedError(
"This hasn't been tested on Python2 yet! Turn this warning off by passing warnings=False."
)
if isinstance(rawData, str):
rawData = bytearray(rawData, "UTF-8")
else:
raise TypeError("rawData must be a string!")
curIndex = curBit = 0
curMask = 0b10000000
outData = bytearray()
def get7():
nonlocal curIndex, curMask, rawData, curBit
if curIndex >= len(rawData):
return False
firstByte = rawData[curIndex]
firstPart = (((0b11111110 % 0x100000000) >> curBit) & firstByte) << curBit
firstPart >>= 1
curBit += 7
if curBit < 8:
return firstPart
curBit -= 8
curIndex += 1
if curIndex >= len(rawData):
return firstPart
secondByte = rawData[curIndex]
secondPart = (((0xFF00 % 0x100000000) >> curBit) & secondByte) & 0xFF
secondPart >>= 8 - curBit
return firstPart | secondPart
while True:
bits = get7()
if not bits:
break
try:
illegalIndex = kIllegals.index(bits)
except ValueError:
outData.append(bits)
continue
nextBits = get7()
b1 = 0b11000010
b2 = 0b10000000
if not nextBits:
b1 |= (0b111 & kShortened) << 2
nextBits = bits
else:
b1 |= (0b111 & illegalIndex) << 2
firstBit = 1 if (nextBits & 0b01000000) > 0 else 0
b1 |= firstBit
b2 |= nextBits & 0b00111111
outData.extend([b1, b2])
return outData
def decode(strData, warnings=True):
if PY2 and warnings:
raise NotImplementedError(
"This hasn't been tested on Python2 yet! Turn this warning off by passing warnings=False."
)
decoded = []
decodedIndex = curByte = bitOfByte = 0
def push7(byte):
nonlocal curByte, bitOfByte, decoded
byte <<= 1
curByte |= (byte % 0x100000000) >> bitOfByte
bitOfByte += 7
if bitOfByte >= 8:
decoded.append(curByte)
bitOfByte -= 8
curByte = (byte << (7 - bitOfByte)) & 255
for i in range(len(strData)):
c = strData[i]
if not isinstance(c, int):
raise TypeError("You can only decode an encoded string!")
if c > 127:
illegalIndex = rshift(c, 8) & 7
if illegalIndex != kShortened:
push7(kIllegals[illegalIndex])
push7(c & 127)
else:
push7(c)
return "".join([chr(letter) for letter in decoded])
# helper function for people already storing data in base64
def encodeFromBase64(base64str):
return encode(base64.b64decode(base64str))