77- decodes file content to str (read)
88- encodes file content from str to bytes (write)
99"""
10- from string import ascii_lowercase as lower , ascii_uppercase as upper , digits
11-
12- from ..__common__ import *
1310from ._base import digits , lower , upper
11+ from ..__common__ import *
1412
1513# no __examples__ ; handled manually in tests/test_base.py
16- __guess__ = ["base91" , "base91-inv" ]
14+ __guess__ = ["base91" , "base91-inv" , "base91-alt" , "base91-alt-inv" ]
1715
1816
1917B91 = {
20- '' : upper + lower + digits + "!#$%&()*+,./:;<=>?@[]^_`{|}~\" " ,
21- 'inv' : lower + upper + digits + "!#$%&()*+,./:;<=>?@[]^_`{|}~\" " ,
18+ '' : upper + lower + digits + "!#$%&()*+,./:;<=>?@[]^_`{|}~\" " ,
19+ 'inv' : lower + upper + digits + "!#$%&()*+,./:;<=>?@[]^_`{|}~\" " ,
20+ 'alt' : "!#$%&'()*+,-./" + digits + ":;<=>?@" + upper + "[\\ ]^_" + lower + "{|}" ,
21+ 'alt-inv' : "!#$%&'()*+,-./" + digits + ":;<=>?@" + lower + "[\\ ]^_" + upper + "{|}" ,
2222}
2323
2424
@@ -31,57 +31,89 @@ class Base91DecodeError(ValueError):
3131
3232
3333def base91_encode (mode ):
34- b91 = B91 [["inv" , "" ][mode == "" ]]
34+ mode = mode .replace ("alternate" , "alt" ).replace ("inverted" , "inv" ).replace ("_" , "-" ).lstrip ("-" )
35+ b91 = B91 [mode if mode in B91 .keys () else "" ]
3536 def encode (text , errors = "strict" ):
36- t = b (text )
37- s = ""
38- bits = ""
39- for c in t :
40- bits = bin (__ord (c ))[2 :].zfill (8 ) + bits
41- if len (bits ) > 13 :
42- n = int (bits [- 13 :], 2 )
43- if n > 88 :
44- bits = bits [:- 13 ]
37+ t , s , bits = b (text ), "" , ""
38+ if mode .startswith ("alt" ):
39+ while len (bits ) < 13 and t :
40+ bits += "{:08b}" .format (__ord (t [0 ]))
41+ t = t [1 :]
42+ while len (bits ) > 13 or t :
43+ n = int (bits [:13 ], 2 )
44+ s += b91 [n // 91 ] + b91 [n % 91 ]
45+ bits = bits [13 :]
46+ while len (bits ) < 13 and t :
47+ bits += "{:08b}" .format (__ord (t [0 ]))
48+ t = t [1 :]
49+ if len (bits ) > 0 :
50+ if len (bits ) < 7 :
51+ bits += "0" * (6 - len (bits ))
52+ s += b91 [int (bits , 2 )]
4553 else :
46- n = int (bits [- 14 :], 2 )
47- bits = bits [:- 14 ]
48- s += b91 [n % 91 ] + b91 [n // 91 ]
49- if len (bits ) > 0 :
50- n = int (bits , 2 )
51- s += b91 [n % 91 ]
52- if len (bits ) > 7 or n > 90 :
53- s += b91 [n // 91 ]
54+ bits += "0" * (13 - len (bits ))
55+ n = int (bits , 2 )
56+ print (bits , n )
57+ s += b91 [n // 91 ] + b91 [n % 91 ]
58+ else :
59+ for c in t :
60+ bits = bin (__ord (c ))[2 :].zfill (8 ) + bits
61+ if len (bits ) > 13 :
62+ n = int (bits [- 13 :], 2 )
63+ if n > 88 :
64+ bits = bits [:- 13 ]
65+ else :
66+ n = int (bits [- 14 :], 2 )
67+ bits = bits [:- 14 ]
68+ s += b91 [n % 91 ] + b91 [n // 91 ]
69+ if len (bits ) > 0 :
70+ n = int (bits , 2 )
71+ s += b91 [n % 91 ]
72+ if len (bits ) > 7 or n > 90 :
73+ s += b91 [n // 91 ]
5474 return s , len (t )
5575 return encode
5676
5777
5878def base91_decode (mode ):
59- b91 = {c : i for i , c in enumerate (B91 [["inv" , "" ][mode == "" ]])}
79+ mode = mode .replace ("alternate" , "alt" ).replace ("inverted" , "inv" ).replace ("_" , "-" ).lstrip ("-" )
80+ b91 = {c : i for i , c in enumerate (B91 [mode if mode in B91 .keys () else "" ])}
6081 def decode (text , errors = "strict" ):
61- t = b (text )
62- s = ""
63- bits = ""
82+ t , s , bits , alt = b (text ), "" , "" , mode .startswith ("alt" )
83+ err = "'base91' codec can't decode character '%s' in position %d"
6484 for i in range (0 , len (t ), 2 ):
6585 try :
66- n = b91 [__chr (t [i ])]
86+ n = b91 [__chr (t [i ])] * [ 1 , 91 ][ alt ]
6787 except KeyError :
68- raise Base91DecodeError ("'base91' codec can't decode character '%s' in position %d" % (__chr (t [i ]), i ))
88+ raise Base91DecodeError (err % (__chr (t [i ]), i ))
6989 try :
7090 j = i + 1
71- n += b91 [__chr (t [j ])] * 91
91+ n += b91 [__chr (t [j ])] * [ 91 , 1 ][ alt ]
7292 except IndexError :
7393 pass
7494 except KeyError :
75- raise Base91DecodeError ("'base91' codec can't decode character '%s' in position %d" % (__chr (t [j ]), j ))
76- bits = bin (n )[2 :].zfill ([14 , 13 ][n & 8191 > 88 ]) + bits
77- while len (bits ) > 8 :
78- s += chr (int (bits [- 8 :], 2 ))
79- bits = bits [:- 8 ]
80- if len (bits ) > 0 and not set (bits ) == {"0" }:
95+ raise Base91DecodeError (err % (__chr (t [j ]), j ))
96+ if alt :
97+ bits += "{:013b}" .format (n )
98+ while 8 <= len (bits ):
99+ s += chr (int (bits [0 :8 ], 2 ))
100+ bits = bits [8 :]
101+ else :
102+ bits = bin (n )[2 :].zfill ([14 , 13 ][n & 8191 > 88 ]) + bits
103+ while len (bits ) > 8 :
104+ s += chr (int (bits [- 8 :], 2 ))
105+ bits = bits [:- 8 ]
106+ if alt and len (t ) % 2 == 1 :
107+ bits += "{:06b}" .format (b91 [__chr (t [- 1 ])])
108+ while 8 <= len (bits ):
109+ s += chr (int (bits [:8 ], 2 ))
110+ bits = bits [8 :]
111+ elif not alt and len (bits ) > 0 and not set (bits ) == {"0" }:
81112 s += chr (int (bits , 2 ))
82113 return s , len (t )
83114 return decode
84115
85116
86- add ("base91" , base91_encode , base91_decode , r"^base[-_]?91(|[-_]inv(?:erted)?)$" , entropy = 6.5 )
117+ add ("base91" , base91_encode , base91_decode , r"^base[-_]?91((?:|[-_]alt(?:ernate)?)(?:|[-_]inv(?:erted)?)?)$" ,
118+ entropy = 6.5 )
87119
0 commit comments