commit 5ac9f99e972b79bf6c38c1afe0b4e0cd6bcb82a2 Author: Jameson Little Date: Fri Nov 25 16:08:34 2011 -0800 Test succeeds diff --git a/README.md b/README.md new file mode 100644 index 0000000..4a98a59 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +Intro +===== + +`base64-js` does basic base64 encoding/decoding in pure JS. Many browsers already have this functionality, but it is for text data, not all-purpose binary data. + +Sometimes encoding/decoding binary data in the browser is useful, and that is what this module does. + +API +=== + +`base64-js` has two exposed functions, `toByteArray` and `fromByteArray`, which both take a single argument. + +* toByteArray- Takes a base64 string and returns a byte array +* fromByteArray- Takes a byte array and returns a base64 string diff --git a/lib/b64.js b/lib/b64.js new file mode 100644 index 0000000..5b6ab20 --- /dev/null +++ b/lib/b64.js @@ -0,0 +1,78 @@ +(function (exports) { + 'use strict'; + + var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + + function b64ToByteArray(b64) { + var i, l, tmp, hasPadding, arr = []; + + if (i % 4 > 0) { + throw 'Invalid string. Length must be a multiple of 4'; + } + + hasPadding = /=$/.test(b64); + + l = hasPadding ? b64.length - 4: b64.length; + + for (i = 0; i < l; i += 4) { + tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]); + arr.push((tmp & 0xFF0000) >> 16); + arr.push((tmp & 0xFF00) >> 8); + arr.push(tmp & 0xFF); + } + + if (hasPadding) { + b64 = b64.substring(i, b64.indexOf('=')); + + if (b64.length === 2) { + tmp = (lookup.indexOf(b64[0]) << 2) | (lookup.indexOf(b64[1]) >> 4); + arr.push(tmp & 0xFF); + } else { + tmp = (lookup.indexOf(b64[0]) << 10) | (lookup.indexOf(b64[1]) << 4) | (lookup.indexOf(b64[2]) >> 2); + arr.push((tmp >> 8) & 0xFF); + arr.push(tmp & 0xFF); + } + } + + return arr; + } + + function uint8ToBase64(uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length; + + function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; + }; + + // 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); + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1]; + output += lookup[temp >> 2]; + output += lookup[(temp << 4) & 0x3F]; + output += '=='; + break; + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]); + output += lookup[temp >> 10]; + output += lookup[(temp >> 4) & 0x3F]; + output += lookup[(temp << 2) & 0x3F]; + output += '='; + break; + } + + return output; + } + + module.exports.toByteArray = b64ToByteArray; + module.exports.fromByteArray = uint8ToBase64; +}()); diff --git a/package.json b/package.json new file mode 100644 index 0000000..751920d --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "author": "T. Jameson Little ", + "name": "base64-js", + "description": "Base64 encoding/decoding in pure JS", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "git://github.com/beatgammit/deflate-js.git" + }, + "main": "lib/b64.js", + "scripts": { + "test": "cd test; node runner.js; cd -" + }, + "engines": { + "node": ">= 0.4" + }, + "dependencies": {}, + "devDependencies": {} +} diff --git a/test/runner.js b/test/runner.js new file mode 100644 index 0000000..8f65b53 --- /dev/null +++ b/test/runner.js @@ -0,0 +1,39 @@ +(function () { + 'use strict'; + + var b64 = require('../lib/b64'), + checks = [ + 'a', + 'aa', + 'aaa', + 'hi', + 'hi!', + 'hi!!', + 'sup', + 'sup?', + 'sup?!' + ], + res; + + res = checks.some(function (check) { + var b64Str, + arr, + str; + + b64Str = b64.fromByteArray(Array.prototype.map.call(check, function (char) { return char.charCodeAt(0); })); + + arr = b64.toByteArray(b64Str); + str = arr.map(function (byte) { return String.fromCharCode(byte); }).join(''); + if (check !== str) { + console.log('Fail:', check); + console.log('Base64:', b64Str); + return true; + } + }); + + if (res) { + console.log('Test failed'); + } else { + console.log('All tests passed!'); + } +}());