Browse Source

Merge pull request #19 from greggman/optimize-for-out-of-memory

Optimize for out of memory
master
Feross Aboukhadijeh 9 years ago
parent
commit
41577aa9d3
  1. 65
      lib/b64.js
  2. 24
      test/big-data.js

65
lib/b64.js

@ -1,28 +1,23 @@
;(function (exports) {
'use strict'
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
var lookup = Array.prototype.map.call(code, function (c) { return c })
var revLookup = []
for (var i = 0; i < code.length; ++i) {
revLookup[code.charCodeAt(i)] = i
}
revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
var PLUS_URL_SAFE = '-'.charCodeAt(0)
var SLASH_URL_SAFE = '_'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS || code === PLUS_URL_SAFE) return 62 // '+'
if (code === SLASH || code === SLASH_URL_SAFE) return 63 // '/'
if (code < NUMBER) return -1 // no match
if (code < NUMBER + 10) return code - NUMBER + 26 + 26
if (code < UPPER + 26) return code - UPPER
if (code < LOWER + 26) return code - LOWER + 26
var v = revLookup[elt.charCodeAt(0)]
return v !== undefined ? v : -1
}
function b64ToByteArray (b64) {
@ -71,24 +66,36 @@
return arr
}
function encode (num) {
return lookup[num]
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
function encodeChunk (uint8, start, end) {
var temp
var output = []
for (var i = start; i < end; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output.push(tripletToBase64(temp))
}
return output.join('')
}
function uint8ToBase64 (uint8) {
var i
var extraBytes = uint8.length % 3 // if we have 1 byte left, pad 2 bytes
var output = ''
var parts = []
var temp, length
function encode (num) {
return lookup.charAt(num)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
var maxChunkLength = 16383 // must be multiple of 3
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output += tripletToBase64(temp)
for (i = 0, length = uint8.length - extraBytes; i < length; i += maxChunkLength) {
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > length ? length : (i + maxChunkLength)))
}
// pad the end with zeros, but make sure to not forget the extra bytes
@ -110,7 +117,9 @@
break
}
return output
parts.push(output)
return parts.join('')
}
exports.toByteArray = b64ToByteArray

24
test/big-data.js

@ -0,0 +1,24 @@
var test = require('tape')
var b64 = require('../lib/b64')
test('convert big data to base64', function (t) {
var b64str, arr, i, length
var big = new Uint8Array(64 * 1024 * 1024)
for (i = 0, length = big.length; i < length; ++i) {
big[i] = i % 256
}
b64str = b64.fromByteArray(big)
arr = b64.toByteArray(b64str)
t.ok(equal(arr, big))
t.end()
})
function equal (a, b) {
var i
var length = a.length
if (length !== b.length) return false
for (i = 0; i < length; ++i) {
if (a[i] !== b[i]) return false
}
return true
}
Loading…
Cancel
Save