-
Notifications
You must be signed in to change notification settings - Fork 1
/
decode.go
148 lines (128 loc) · 2.4 KB
/
decode.go
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package base91
import (
"io"
)
func decode(src []byte) []byte {
// b and n must be at least uint32
var b, n uint32 = 0, 0
v := -1
decoded := []byte{}
for i := 0; i < len(src); i++ {
p := dectab[src[i]]
if p > 90 {
// skip invalid character silently
continue
}
if v < 0 {
v = int(p)
continue
}
v += int(p) * 91
b |= uint32(v) << n
if v&0x1fff > 88 {
n += 13
} else {
n += 14
}
for {
decoded = append(decoded, uint8(b))
b >>= 8
n -= 8
if n <= 7 {
break
}
}
v = -1
}
if v > -1 {
decoded = append(decoded, uint8(b|uint32(v)<<n))
}
return decoded
}
// Decode decodes src into dst. It returns the number of bytes written to dst.
// Whereas base91 uses up to nearly all printable characters, Decode skips
// invalid characters silently.
func Decode(dst, src []byte) int {
return copy(dst, decode(src))
}
// DecodeString returns the bytes represented by the base91 string s, probably
// what you want.
func DecodeString(s string) []byte {
return decode([]byte(s))
}
type decoder struct {
// input
reader io.Reader
err error
outBuf []byte
inBuf *[1024]byte
nInBuf int
b, n uint32
v int
}
// NewDecoder constructs a new base91 stream decoder. Data read from the
// returned reader is base91 decoded from r.
func NewDecoder(r io.Reader) io.Reader {
return &decoder{
reader: r,
err: nil,
outBuf: []byte{},
inBuf: new([1024]byte),
nInBuf: 0,
b: 0,
n: 0,
v: -1,
}
}
func (d *decoder) Read(c []byte) (int, error) {
if len(c) == 0 {
return 0, nil
}
if d.err != nil {
return 0, d.err
}
n := 0
for n < len(c) && d.err == nil {
var upn int
upn, d.err = d.reader.Read(d.inBuf[d.nInBuf:])
next := d.nInBuf + upn
for ; d.nInBuf < next; d.nInBuf++ {
p := dectab[d.inBuf[d.nInBuf]]
if p > 90 {
continue
}
if d.v < 0 {
d.v = int(p)
continue
}
d.v += int(p) * 91
d.b |= uint32(d.v) << d.n
if d.v&0x1fff > 88 {
d.n += 13
} else {
d.n += 14
}
for {
d.outBuf = append(d.outBuf, uint8(d.b))
d.b >>= 8
d.n -= 8
if d.n <= 7 {
break
}
}
d.v = -1
}
if d.nInBuf >= 1024 {
d.nInBuf = 0
}
if d.err != nil && d.v > -1 {
// EOF is met, flush
d.outBuf = append(d.outBuf, uint8(d.b|uint32(d.v)<<d.n))
}
m := copy(c[n:], d.outBuf)
d.outBuf = d.outBuf[m:]
n += m
// if m < len(c), then outBuf did not suffuse c
}
return n, d.err
}