annotate base64.js @ 39:a9dbf9f45896 jsonrpc

Update adapter code
author Chris Cannam
date Wed, 05 Oct 2016 18:00:58 +0100
parents 3faa4e3eedac
children
rev   line source
Chris@35 1 'use strict'
Chris@35 2
Chris@35 3 if (typeof document === "undefined") {
Chris@35 4 exports.byteLength = byteLength
Chris@35 5 exports.toByteArray = toByteArray
Chris@35 6 exports.fromByteArray = fromByteArray
Chris@35 7 }
Chris@35 8
Chris@35 9 var lookup = []
Chris@35 10 var revLookup = []
Chris@35 11 var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
Chris@35 12
Chris@35 13 var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
Chris@35 14 for (var i = 0, len = code.length; i < len; ++i) {
Chris@35 15 lookup[i] = code[i]
Chris@35 16 revLookup[code.charCodeAt(i)] = i
Chris@35 17 }
Chris@35 18
Chris@35 19 revLookup['-'.charCodeAt(0)] = 62
Chris@35 20 revLookup['_'.charCodeAt(0)] = 63
Chris@35 21
Chris@35 22 function placeHoldersCount (b64) {
Chris@35 23 var len = b64.length
Chris@35 24 if (len % 4 > 0) {
Chris@35 25 throw new Error('Invalid string. Length must be a multiple of 4')
Chris@35 26 }
Chris@35 27
Chris@35 28 // the number of equal signs (place holders)
Chris@35 29 // if there are two placeholders, than the two characters before it
Chris@35 30 // represent one byte
Chris@35 31 // if there is only one, then the three characters before it represent 2 bytes
Chris@35 32 // this is just a cheap hack to not do indexOf twice
Chris@35 33 return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
Chris@35 34 }
Chris@35 35
Chris@35 36 function byteLength (b64) {
Chris@35 37 // base64 is 4/3 + up to two characters of the original data
Chris@35 38 return b64.length * 3 / 4 - placeHoldersCount(b64)
Chris@35 39 }
Chris@35 40
Chris@35 41 function toByteArray (b64) {
Chris@35 42 var i, j, l, tmp, placeHolders, arr
Chris@35 43 var len = b64.length
Chris@35 44 placeHolders = placeHoldersCount(b64)
Chris@35 45
Chris@35 46 arr = new Arr(len * 3 / 4 - placeHolders)
Chris@35 47
Chris@35 48 // if there are placeholders, only get up to the last complete 4 chars
Chris@35 49 l = placeHolders > 0 ? len - 4 : len
Chris@35 50
Chris@35 51 var L = 0
Chris@35 52
Chris@35 53 for (i = 0, j = 0; i < l; i += 4, j += 3) {
Chris@35 54 tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
Chris@35 55 arr[L++] = (tmp >> 16) & 0xFF
Chris@35 56 arr[L++] = (tmp >> 8) & 0xFF
Chris@35 57 arr[L++] = tmp & 0xFF
Chris@35 58 }
Chris@35 59
Chris@35 60 if (placeHolders === 2) {
Chris@35 61 tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
Chris@35 62 arr[L++] = tmp & 0xFF
Chris@35 63 } else if (placeHolders === 1) {
Chris@35 64 tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
Chris@35 65 arr[L++] = (tmp >> 8) & 0xFF
Chris@35 66 arr[L++] = tmp & 0xFF
Chris@35 67 }
Chris@35 68
Chris@35 69 return arr
Chris@35 70 }
Chris@35 71
Chris@35 72 function tripletToBase64 (num) {
Chris@35 73 return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
Chris@35 74 }
Chris@35 75
Chris@35 76 function encodeChunk (uint8, start, end) {
Chris@35 77 var tmp
Chris@35 78 var output = []
Chris@35 79 for (var i = start; i < end; i += 3) {
Chris@35 80 tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
Chris@35 81 output.push(tripletToBase64(tmp))
Chris@35 82 }
Chris@35 83 return output.join('')
Chris@35 84 }
Chris@35 85
Chris@35 86 function fromByteArray (uint8) {
Chris@35 87 var tmp
Chris@35 88 var len = uint8.length
Chris@35 89 var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
Chris@35 90 var output = ''
Chris@35 91 var parts = []
Chris@35 92 var maxChunkLength = 16383 // must be multiple of 3
Chris@35 93
Chris@35 94 // go through the array every three bytes, we'll deal with trailing stuff later
Chris@35 95 for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
Chris@35 96 parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
Chris@35 97 }
Chris@35 98
Chris@35 99 // pad the end with zeros, but make sure to not forget the extra bytes
Chris@35 100 if (extraBytes === 1) {
Chris@35 101 tmp = uint8[len - 1]
Chris@35 102 output += lookup[tmp >> 2]
Chris@35 103 output += lookup[(tmp << 4) & 0x3F]
Chris@35 104 output += '=='
Chris@35 105 } else if (extraBytes === 2) {
Chris@35 106 tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
Chris@35 107 output += lookup[tmp >> 10]
Chris@35 108 output += lookup[(tmp >> 4) & 0x3F]
Chris@35 109 output += lookup[(tmp << 2) & 0x3F]
Chris@35 110 output += '='
Chris@35 111 }
Chris@35 112
Chris@35 113 parts.push(output)
Chris@35 114
Chris@35 115 return parts.join('')
Chris@35 116 }