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