caellion-python-commons: caellion/pycommons/encoding/base36.py Source File

caellion-python-commons

base36.py
Go to the documentation of this file.
1 """!
2 This module provides utlilities related to converting to/from base36 encoding.
3 """
4
5
6 class InvalidCustomCharsetLengthException(Exception):
7 """!
8 This exception is raised when custom character set length .
9 """
10
11 pass
12
13
14 class InvalidCustomCharsetException(Exception):
15 """!
16 This exception is raised when more than exactly one instance of a given field is contained within field list.
17 """
18
19 pass
20
21
22 class InvalidInputStringException(Exception):
23 """!
24 This exception is raised when encountering a character not defined in custom charset in input string.
25 """
26
27 pass
28
29
30 class NumberNotPositiveOrZeroException(Exception):
31 """!
32 This exception is raised when non-positive integer is passed to encode function.
33 """
34
35 pass
36
37
38 class ValueTooLargeException(Exception):
39 """!
40 This exception is raised when encountering an integer over maximum size of 16 bytes.
41 """
42
43 pass
44
45
46 class Base36Coder:
47 """!
48 This class provides methods allowing conversion between integer, hexadecimal integer and base36 strings.
49 """
50
51 # Custom charset to use with this instance of Base36Coder
52 custom_charset = None
53
54 def __init__(self, custom_charset="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
55 """!
56 Initialize coder.
57
58 @param custom_charset custom character set to use with the coder
59
60 @throws InvalidCustomCharsetLengthException
61 @throws InvalidCustomCharsetException
62 """
63 if len(custom_charset) != 36:
64 raise InvalidCustomCharsetLengthException(
65 "Custom charset is not exactly 36 characters long")
66
67 xchk = []
68 idx = 0
69 for x in custom_charset:
70 if x not in xchk:
71 xchk.append(x)
72 idx += 1
73 else:
74 idxf = custom_charset.find(x)
75 raise InvalidCustomCharsetException(
76 "Character '%s' at position %s, first appeared at position %s is repeated in custom charset" % (x, idx, idxf))
77
78 self.custom_charsetcustom_charset = custom_charset
79
80 def to_standard_charset(self, unformatted):
81 """!
82 Converts custom charset to standard charset
83
84 @param unformatted Base36 string in custom charset encoding
85
86 @returns Base36 string in standardized format
87
88 @throws InvalidInputStringException
89 """
90 std_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
91 formatted = ""
92
93 for symbol in unformatted:
94 idx = self.custom_charsetcustom_charset.find(symbol)
95
96 if idx == -1:
97 raise InvalidInputStringException(
98 "Unexpected '%s' in input string." % symbol)
99 else:
100 formatted += std_charset[idx]
101
102 return formatted
103
104 def to_custom_charset(self, unformatted):
105 """!
106 Converts standard charset to custom charset
107
108 @param unformatted Base36 string in standard charset encoding
109
110 @returns Base36 string in custom format
111
112 @throws InvalidInputStringException
113 """
114 std_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
115 formatted = ""
116
117 for symbol in unformatted:
118 idx = std_charset.find(symbol)
119
120 if idx == -1:
121 raise InvalidInputStringException(
122 "Unexpected '%s' in input string." % symbol)
123 else:
124 formatted += self.custom_charsetcustom_charset[idx]
125
126 return formatted
127
128 def bytes_to_b36(self, bytes_in):
129 """!
130 Converts bytes to base36 string in custom charset encoding
131
132 @param bytes_in a bytes object to encode
133
134 @returns Base36 string in custom format
135 """
136 integer = int.from_bytes(bytes_in, 'big')
137 # convert to base 36
138 if integer < len(self.custom_charsetcustom_charset):
139 return self.custom_charsetcustom_charset[integer]
140 b36string = ""
141 while integer != 0:
142 integer, i = divmod(integer, len(self.custom_charsetcustom_charset))
143 # no need to re-encode this to custom charset as it is already encoded in custom charset
144 b36string = self.custom_charsetcustom_charset[i] + b36string
145 return b36string
146
147 def int_to_b36(self, integer):
148 """!
149 Converts int to base36 string in custom charset encoding
150
151 @param integer an int to encode
152
153 @returns Base36 string in custom format
154
155 @throws NumberNotPositiveOrZeroException
156 """
157 if integer < 0:
158 raise NumberNotPositiveOrZeroException(
159 "'%s' is not a positive or integer or zero." % integer)
160 else:
161 # convert to base 36
162 if integer < len(self.custom_charsetcustom_charset):
163 return self.custom_charsetcustom_charset[integer]
164 b36string = ""
165 while integer != 0:
166 integer, i = divmod(integer, len(self.custom_charsetcustom_charset))
167 # no need to re-encode this to custom charset as it is already encoded in custom charset
168 b36string = self.custom_charsetcustom_charset[i] + b36string
169 return b36string
170
171 def b36_to_bytes(self, b36):
172 """!
173 Converts base36 string in custom encoding charset to bytes.
174
175 @param b36 string in custom encoding charset
176
177 @returns decoded bytes
178
179 @throws InvalidInputStringException
180 @throws ValueTooLargeException
181 """
182 integer = self.b36_to_intb36_to_int(b36)
183 length = 1
184 bytesdata = b""
185 while length < 16 and bytesdata == b"":
186 try:
187 bytesdata = integer.to_bytes(length, byteorder='big')
188 break
189 except OverflowError:
190 length += 1
191 if length > 1 and bytesdata == b"":
192 raise ValueTooLargeException(
193 "Value '%s' (%s) is too large to convert to bytes (maximum 16 bytes long integer)" % (b36, integer))
194 return bytesdata
195
196 def b36_to_int(self, b36):
197 """!
198 Converts base36 string in custom encoding charset to integer.
199
200 @param b36 base36 string in custom encoding charset
201
202 @returns decoded integer
203
204 @throws InvalidInputStringException
205 """
206 # decode from custom charset
207 b36std = self.to_standard_charsetto_standard_charset(b36)
208 # then use normal to_base
209 integer = int(b36std, 36)
210 return integer
caellion.pycommons.encoding.base36.Base36Coder
This class provides methods allowing conversion between integer, hexadecimal integer and base36 strin...
Definition: base36.py:46
caellion.pycommons.encoding.base36.Base36Coder.b36_to_bytes
def b36_to_bytes(self, b36)
Converts base36 string in custom encoding charset to bytes.
Definition: base36.py:171
caellion.pycommons.encoding.base36.Base36Coder.bytes_to_b36
def bytes_to_b36(self, bytes_in)
Converts bytes to base36 string in custom charset encoding.
Definition: base36.py:128
caellion.pycommons.encoding.base36.Base36Coder.to_standard_charset
def to_standard_charset(self, unformatted)
Converts custom charset to standard charset.
Definition: base36.py:80
caellion.pycommons.encoding.base36.Base36Coder.__init__
def __init__(self, custom_charset="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
Initialize coder.
Definition: base36.py:54
caellion.pycommons.encoding.base36.Base36Coder.int_to_b36
def int_to_b36(self, integer)
Converts int to base36 string in custom charset encoding.
Definition: base36.py:147
caellion.pycommons.encoding.base36.Base36Coder.b36_to_int
def b36_to_int(self, b36)
Converts base36 string in custom encoding charset to integer.
Definition: base36.py:196
caellion.pycommons.encoding.base36.Base36Coder.custom_charset
custom_charset
Definition: base36.py:52
caellion.pycommons.encoding.base36.Base36Coder.to_custom_charset
def to_custom_charset(self, unformatted)
Converts standard charset to custom charset.
Definition: base36.py:104
caellion.pycommons.encoding.base36.InvalidCustomCharsetException
This exception is raised when more than exactly one instance of a given field is contained within fie...
Definition: base36.py:14
caellion.pycommons.encoding.base36.InvalidCustomCharsetLengthException
This exception is raised when custom character set length .
Definition: base36.py:6
caellion.pycommons.encoding.base36.InvalidInputStringException
This exception is raised when encountering a character not defined in custom charset in input string.
Definition: base36.py:22
caellion.pycommons.encoding.base36.NumberNotPositiveOrZeroException
This exception is raised when non-positive integer is passed to encode function.
Definition: base36.py:30
caellion.pycommons.encoding.base36.ValueTooLargeException
This exception is raised when encountering an integer over maximum size of 16 bytes.
Definition: base36.py:38