Commit f8e9b9f1 authored by Solly Ross's avatar Solly Ross

Cleanup and Test: base64.js

This is the first commit in a series of commits
which improve the readability of some of the code
and add tests.

File: base64.js
Tests Added: True
Changes:
- Improved indentation
- Fixed JSHint errors
- Moved loop variables to be declared in the loop for better readability
  (N.B. Javascript does not have block scoping, so the variables are
  still technically available outside the loop -- it just makes the code
  clearer to place them inside the loop, since they are only used there)
parent 95eb681b
...@@ -4,38 +4,36 @@ ...@@ -4,38 +4,36 @@
// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js // From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js
/*jslint white: false, bitwise: false, plusplus: false */ /*jslint white: false */
/*global console */ /*global console */
var Base64 = { var Base64 = {
/* Convert data (an array of integers) to a Base64 string. */
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
base64Pad : '=',
/* Convert data (an array of integers) to a Base64 string. */ encode: function (data) {
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
base64Pad : '=',
encode: function (data) {
"use strict"; "use strict";
var result = ''; var result = '';
var toBase64Table = Base64.toBase64Table; var toBase64Table = Base64.toBase64Table;
var length = data.length var length = data.length;
var lengthpad = (length%3); var lengthpad = (length % 3);
var i = 0, j = 0;
// Convert every three bytes to 4 ascii characters. // Convert every three bytes to 4 ascii characters.
/* BEGIN LOOP */
for (i = 0; i < (length - 2); i += 3) { for (var i = 0; i < (length - 2); i += 3) {
result += toBase64Table[data[i] >> 2]; result += toBase64Table[data[i] >> 2];
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)]; result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)]; result += toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
result += toBase64Table[data[i+2] & 0x3f]; result += toBase64Table[data[i + 2] & 0x3f];
} }
/* END LOOP */
// Convert the remaining 1 or 2 bytes, pad out to 4 characters. // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
var j = 0;
if (lengthpad === 2) { if (lengthpad === 2) {
j = length - lengthpad; j = length - lengthpad;
result += toBase64Table[data[j] >> 2]; result += toBase64Table[data[j] >> 2];
result += toBase64Table[((data[j] & 0x03) << 4) + (data[j+1] >> 4)]; result += toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)];
result += toBase64Table[(data[j+1] & 0x0f) << 2]; result += toBase64Table[(data[j + 1] & 0x0f) << 2];
result += toBase64Table[64]; result += toBase64Table[64];
} else if (lengthpad === 1) { } else if (lengthpad === 1) {
j = length - lengthpad; j = length - lengthpad;
...@@ -46,10 +44,11 @@ encode: function (data) { ...@@ -46,10 +44,11 @@ encode: function (data) {
} }
return result; return result;
}, },
/* Convert Base64 data to a string */ /* Convert Base64 data to a string */
toBinaryTable : [ /* jshint -W013 */
toBinaryTable : [
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
...@@ -58,14 +57,15 @@ toBinaryTable : [ ...@@ -58,14 +57,15 @@ toBinaryTable : [
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
], ],
/* jshint +W013 */
decode: function (data, offset) { decode: function (data, offset) {
"use strict"; "use strict";
offset = typeof(offset) !== 'undefined' ? offset : 0; offset = typeof(offset) !== 'undefined' ? offset : 0;
var toBinaryTable = Base64.toBinaryTable; var toBinaryTable = Base64.toBinaryTable;
var base64Pad = Base64.base64Pad; var base64Pad = Base64.base64Pad;
var result, result_length, idx, i, c, padding; var result, result_length;
var leftbits = 0; // number of bits decoded, but yet to be appended var leftbits = 0; // number of bits decoded, but yet to be appended
var leftdata = 0; // bits decoded, but yet to be appended var leftdata = 0; // bits decoded, but yet to be appended
var data_length = data.indexOf('=') - offset; var data_length = data.indexOf('=') - offset;
...@@ -73,14 +73,13 @@ decode: function (data, offset) { ...@@ -73,14 +73,13 @@ decode: function (data, offset) {
if (data_length < 0) { data_length = data.length - offset; } if (data_length < 0) { data_length = data.length - offset; }
/* Every four characters is 3 resulting numbers */ /* Every four characters is 3 resulting numbers */
result_length = (data_length >> 2) * 3 + Math.floor((data_length%4)/1.5); result_length = (data_length >> 2) * 3 + Math.floor((data_length % 4) / 1.5);
result = new Array(result_length); result = new Array(result_length);
// Convert one by one. // Convert one by one.
/* BEGIN LOOP */ for (var idx = 0, i = offset; i < data.length; i++) {
for (idx = 0, i = offset; i < data.length; i++) { var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
c = toBinaryTable[data.charCodeAt(i) & 0x7f]; var padding = (data.charAt(i) === base64Pad);
padding = (data.charAt(i) === base64Pad);
// Skip illegal characters and whitespace // Skip illegal characters and whitespace
if (c === -1) { if (c === -1) {
console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i); console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
...@@ -101,15 +100,14 @@ decode: function (data, offset) { ...@@ -101,15 +100,14 @@ decode: function (data, offset) {
leftdata &= (1 << leftbits) - 1; leftdata &= (1 << leftbits) - 1;
} }
} }
/* END LOOP */
// If there are any bits left, the base64 string was corrupted // If there are any bits left, the base64 string was corrupted
if (leftbits) { if (leftbits) {
throw {name: 'Base64-Error', err = new Error('Corrupted base64 string');
message: 'Corrupted base64 string'}; err.name = 'Base64-Error';
throw err;
} }
return result; return result;
} }
}; /* End of Base64 namespace */ }; /* End of Base64 namespace */
// requires local modules: base64
var assert = chai.assert;
var expect = chai.expect;
describe('Base64 Tools', function() {
"use strict";
var BIN_ARR = new Array(256);
for (var i = 0; i < 256; i++) {
BIN_ARR[i] = i;
}
var B64_STR = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
describe('encode', function() {
it('should encode a binary string into Base64', function() {
var encoded = Base64.encode(BIN_ARR);
expect(encoded).to.equal(B64_STR);
});
});
describe('decode', function() {
it('should decode a Base64 string into a normal string', function() {
var decoded = Base64.decode(B64_STR);
expect(decoded).to.deep.equal(BIN_ARR);
});
it('should throw an error if we have extra characters at the end of the string', function() {
expect(function () { Base64.decode(B64_STR+'abcdef'); }).to.throw(Error);
});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment