1 | 'use strict'
|
2 |
|
3 | exports.toByteArray = toByteArray
|
4 | exports.fromByteArray = fromByteArray
|
5 |
|
6 | var lookup = []
|
7 | var revLookup = []
|
8 | var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
|
9 |
|
10 | function init () {
|
11 | var i
|
12 | var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
13 | var len = code.length
|
14 |
|
15 | for (i = 0; i < len; i++) {
|
16 | lookup[i] = code[i]
|
17 | }
|
18 |
|
19 | for (i = 0; i < len; ++i) {
|
20 | revLookup[code.charCodeAt(i)] = i
|
21 | }
|
22 | revLookup['-'.charCodeAt(0)] = 62
|
23 | revLookup['_'.charCodeAt(0)] = 63
|
24 | }
|
25 |
|
26 | init()
|
27 |
|
28 | function toByteArray (b64) {
|
29 | var i, j, l, tmp, placeHolders, arr
|
30 | var len = b64.length
|
31 |
|
32 | if (len % 4 > 0) {
|
33 | throw new Error('Invalid string. Length must be a multiple of 4')
|
34 | }
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
|
42 |
|
43 |
|
44 | arr = new Arr(len * 3 / 4 - placeHolders)
|
45 |
|
46 |
|
47 | l = placeHolders > 0 ? len - 4 : len
|
48 |
|
49 | var L = 0
|
50 |
|
51 | for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
52 | tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
|
53 | arr[L++] = (tmp & 0xFF0000) >> 16
|
54 | arr[L++] = (tmp & 0xFF00) >> 8
|
55 | arr[L++] = tmp & 0xFF
|
56 | }
|
57 |
|
58 | if (placeHolders === 2) {
|
59 | tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
|
60 | arr[L++] = tmp & 0xFF
|
61 | } else if (placeHolders === 1) {
|
62 | tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
|
63 | arr[L++] = (tmp >> 8) & 0xFF
|
64 | arr[L++] = tmp & 0xFF
|
65 | }
|
66 |
|
67 | return arr
|
68 | }
|
69 |
|
70 | function tripletToBase64 (num) {
|
71 | return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
|
72 | }
|
73 |
|
74 | function encodeChunk (uint8, start, end) {
|
75 | var tmp
|
76 | var output = []
|
77 | for (var i = start; i < end; i += 3) {
|
78 | tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
79 | output.push(tripletToBase64(tmp))
|
80 | }
|
81 | return output.join('')
|
82 | }
|
83 |
|
84 | function fromByteArray (uint8) {
|
85 | var tmp
|
86 | var len = uint8.length
|
87 | var extraBytes = len % 3
|
88 | var output = ''
|
89 | var parts = []
|
90 | var maxChunkLength = 16383
|
91 |
|
92 |
|
93 | for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
94 | parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
|
95 | }
|
96 |
|
97 |
|
98 | if (extraBytes === 1) {
|
99 | tmp = uint8[len - 1]
|
100 | output += lookup[tmp >> 2]
|
101 | output += lookup[(tmp << 4) & 0x3F]
|
102 | output += '=='
|
103 | } else if (extraBytes === 2) {
|
104 | tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
|
105 | output += lookup[tmp >> 10]
|
106 | output += lookup[(tmp >> 4) & 0x3F]
|
107 | output += lookup[(tmp << 2) & 0x3F]
|
108 | output += '='
|
109 | }
|
110 |
|
111 | parts.push(output)
|
112 |
|
113 | return parts.join('')
|
114 | }
|