-
Notifications
You must be signed in to change notification settings - Fork 0
/
Base128.js
118 lines (115 loc) · 2.53 KB
/
Base128.js
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
const escapechr = [
0, // null -> 1
9, // tab -> 2
10, // enter -> 3
13, // enter -> 4
34, // double quote - 5
0, // skip
38, // ampersand - 7
92, // back slash - 8
// shortend for 10
];
const encode = (bin) => {
const len = bin.length;
const res = new Uint8Array(((len / 7 * 8) >> 0) * 2 + 1);
let idx = 0;
let bits = 0;
let nbits = 6;
let state = 0;
for (let i = 0; i < len; i++) {
const b = bin[i];
for (let j = 7; j >= 0; j--) {
bits |= ((b >> j) & 1) << nbits;
if (nbits == 0) {
if (state == 0) {
const n = escapechr.indexOf(bits);
if (n >= 0) {
res[idx++] = 0xc0 | ((n + 1) << 1);
state = 1;
} else {
res[idx++] = bits;
}
} else {
res[idx - 1] |= bits >> 6;
res[idx++] = 0x80 | (bits & 0x3f);
state = 0;
}
bits = 0;
nbits = 6;
} else {
nbits--;
}
}
}
if (nbits != 6) {
if (state == 0) {
const n = escapechr.indexOf(bits);
if (n >= 0) {
res[idx++] = 0xc0 | (10 << 1) | (bits >> 6);
res[idx++] = 0x80 | (bits & 0x3f);
} else {
res[idx++] = bits;
}
} else {
res[idx - 1] |= bits >> 6;
res[idx++] |= 0x80 | (bits & 0x3f);
}
} else {
if (state == 1) {
res[idx - 1] |= bits >> 6;
res[idx++] |= 0x80 | (bits & 0x3f);
}
}
return new TextDecoder().decode(res.subarray(0, idx));
};
const decode = (s) => {
const len = s.length;
let elen = len;
for (let i = 0; i < len - 1; i++) {
if (s.charCodeAt(i) >= 0x80) {
elen++;
}
}
const len2 = ((elen * 7 / 8) >> 0) + (elen % 8 == 0 ? 0 : 1);
const res = new Uint8Array(len2);
let idx = 0;
let bits = 0;
let nbits = 7;
let state = 0;
for (let i = 0; i < len; i++) {
let b = s.charCodeAt(i);
if (state == 0) {
if (b >= 0x80) {
const type = b >> 7;
if (type == 10) { // shortend
b &= 0x7f;
} else {
b = escapechr[type - 1];
i--;
state = 1;
}
}
} else {
b &= 0x7f;
state = 0;
}
for (let j = 6; j >= 0; j--) {
bits |= ((b >> j) & 1) << nbits;
if (nbits == 0) {
res[idx++] = bits;
bits = 0;
nbits = 7;
} else {
nbits--;
}
}
if (idx == res.length) {
break;
}
}
if (res.length != idx) {
return new Uint8Array(res.buffer, 0, idx);
}
return res;
};
export const Base128 = { encode, decode };