1 | 'use strict'
|
---|
2 |
|
---|
3 | const RE_PLUS = /\+/g
|
---|
4 |
|
---|
5 | const HEX = [
|
---|
6 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
7 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
8 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
9 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
---|
10 | 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
11 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
12 | 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
13 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
---|
14 | ]
|
---|
15 |
|
---|
16 | function Decoder () {
|
---|
17 | this.buffer = undefined
|
---|
18 | }
|
---|
19 | Decoder.prototype.write = function (str) {
|
---|
20 | // Replace '+' with ' ' before decoding
|
---|
21 | str = str.replace(RE_PLUS, ' ')
|
---|
22 | let res = ''
|
---|
23 | let i = 0; let p = 0; const len = str.length
|
---|
24 | for (; i < len; ++i) {
|
---|
25 | if (this.buffer !== undefined) {
|
---|
26 | if (!HEX[str.charCodeAt(i)]) {
|
---|
27 | res += '%' + this.buffer
|
---|
28 | this.buffer = undefined
|
---|
29 | --i // retry character
|
---|
30 | } else {
|
---|
31 | this.buffer += str[i]
|
---|
32 | ++p
|
---|
33 | if (this.buffer.length === 2) {
|
---|
34 | res += String.fromCharCode(parseInt(this.buffer, 16))
|
---|
35 | this.buffer = undefined
|
---|
36 | }
|
---|
37 | }
|
---|
38 | } else if (str[i] === '%') {
|
---|
39 | if (i > p) {
|
---|
40 | res += str.substring(p, i)
|
---|
41 | p = i
|
---|
42 | }
|
---|
43 | this.buffer = ''
|
---|
44 | ++p
|
---|
45 | }
|
---|
46 | }
|
---|
47 | if (p < len && this.buffer === undefined) { res += str.substring(p) }
|
---|
48 | return res
|
---|
49 | }
|
---|
50 | Decoder.prototype.reset = function () {
|
---|
51 | this.buffer = undefined
|
---|
52 | }
|
---|
53 |
|
---|
54 | module.exports = Decoder
|
---|