135
|
1 # base85.py: pure python base85 codec
|
|
2 #
|
|
3 # Copyright (C) 2009 Brendan Cully <brendan@kublai.com>
|
|
4 #
|
|
5 # This software may be used and distributed according to the terms of the
|
|
6 # GNU General Public License version 2, incorporated herein by reference.
|
|
7
|
|
8 import struct
|
|
9
|
|
10 _b85chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
|
11 "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
|
|
12 _b85chars2 = [(a + b) for a in _b85chars for b in _b85chars]
|
|
13 _b85dec = {}
|
|
14
|
|
15 def _mkb85dec():
|
|
16 for i, c in enumerate(_b85chars):
|
|
17 _b85dec[c] = i
|
|
18
|
|
19 def b85encode(text, pad=False):
|
|
20 """encode text in base85 format"""
|
|
21 l = len(text)
|
|
22 r = l % 4
|
|
23 if r:
|
|
24 text += '\0' * (4 - r)
|
|
25 longs = len(text) >> 2
|
|
26 words = struct.unpack('>%dL' % (longs), text)
|
|
27
|
|
28 out = ''.join(_b85chars[(word / 52200625) % 85] +
|
|
29 _b85chars2[(word / 7225) % 7225] +
|
|
30 _b85chars2[word % 7225]
|
|
31 for word in words)
|
|
32
|
|
33 if pad:
|
|
34 return out
|
|
35
|
|
36 # Trim padding
|
|
37 olen = l % 4
|
|
38 if olen:
|
|
39 olen += 1
|
|
40 olen += l / 4 * 5
|
|
41 return out[:olen]
|
|
42
|
|
43 def b85decode(text):
|
|
44 """decode base85-encoded text"""
|
|
45 if not _b85dec:
|
|
46 _mkb85dec()
|
|
47
|
|
48 l = len(text)
|
|
49 out = []
|
|
50 for i in range(0, len(text), 5):
|
|
51 chunk = text[i:i+5]
|
|
52 acc = 0
|
|
53 for j, c in enumerate(chunk):
|
|
54 try:
|
|
55 acc = acc * 85 + _b85dec[c]
|
|
56 except KeyError:
|
|
57 raise TypeError('Bad base85 character at byte %d' % (i + j))
|
|
58 if acc > 4294967295:
|
|
59 raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
|
|
60 out.append(acc)
|
|
61
|
|
62 # Pad final chunk if necessary
|
|
63 cl = l % 5
|
|
64 if cl:
|
|
65 acc *= 85 ** (5 - cl)
|
|
66 if cl > 1:
|
|
67 acc += 0xffffff >> (cl - 2) * 8
|
|
68 out[-1] = acc
|
|
69
|
|
70 out = struct.pack('>%dL' % (len(out)), *out)
|
|
71 if cl:
|
|
72 out = out[:-(5 - cl)]
|
|
73
|
|
74 return out
|