148 lines
5.2 KiB
JavaScript
148 lines
5.2 KiB
JavaScript
// bases.js
|
|
// Utility for converting numbers to/from different bases/alphabets.
|
|
// See README.md for details.
|
|
|
|
var bases = (typeof exports !== 'undefined' ? exports : (window.Bases = {}));
|
|
|
|
// Returns a string representation of the given number for the given alphabet:
|
|
bases.toAlphabet = function (num, alphabet) {
|
|
var base = alphabet.length;
|
|
var digits = []; // these will be in reverse order since arrays are stacks
|
|
|
|
// execute at least once, even if num is 0, since we should return the '0':
|
|
do {
|
|
digits.push(num % base); // TODO handle negatives properly?
|
|
num = Math.floor(num / base);
|
|
} while (num > 0);
|
|
|
|
var chars = [];
|
|
while (digits.length) {
|
|
chars.push(alphabet[digits.pop()]);
|
|
}
|
|
return chars.join('');
|
|
};
|
|
|
|
// Returns an integer representation of the given string for the given alphabet:
|
|
bases.fromAlphabet = function (str, alphabet) {
|
|
var base = alphabet.length;
|
|
var pos = 0;
|
|
var num = 0;
|
|
var c;
|
|
|
|
while (str.length) {
|
|
c = str[str.length - 1];
|
|
str = str.substr(0, str.length - 1);
|
|
num += Math.pow(base, pos) * alphabet.indexOf(c);
|
|
pos++;
|
|
}
|
|
|
|
return num;
|
|
};
|
|
|
|
// Known alphabets:
|
|
bases.NUMERALS = '0123456789';
|
|
bases.LETTERS_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';
|
|
bases.LETTERS_UPPERCASE = bases.LETTERS_LOWERCASE.toUpperCase();
|
|
bases.KNOWN_ALPHABETS = {};
|
|
|
|
// Each of the number ones, starting from base-2 (base-1 doesn't make sense?):
|
|
for (var i = 2; i <= 10; i++) {
|
|
bases.KNOWN_ALPHABETS[i] = bases.NUMERALS.substr(0, i);
|
|
}
|
|
|
|
// Node's native hex is 0-9 followed by *lowercase* a-f, so we'll take that
|
|
// approach for everything from base-11 to base-16:
|
|
for (var i = 11; i <= 16; i++) {
|
|
bases.KNOWN_ALPHABETS[i] = bases.NUMERALS + bases.LETTERS_LOWERCASE.substr(0, i - 10);
|
|
}
|
|
|
|
// We also model base-36 off of that, just using the full letter alphabet:
|
|
bases.KNOWN_ALPHABETS[36] = bases.NUMERALS + bases.LETTERS_LOWERCASE;
|
|
|
|
// And base-62 will be the uppercase letters added:
|
|
bases.KNOWN_ALPHABETS[62] = bases.NUMERALS + bases.LETTERS_LOWERCASE + bases.LETTERS_UPPERCASE;
|
|
|
|
// For base-26, we'll assume the user wants just the letter alphabet:
|
|
bases.KNOWN_ALPHABETS[26] = bases.LETTERS_LOWERCASE;
|
|
|
|
// We'll also add a similar base-52, just letters, lowercase then uppercase:
|
|
bases.KNOWN_ALPHABETS[52] = bases.LETTERS_LOWERCASE + bases.LETTERS_UPPERCASE;
|
|
|
|
// Base-64 is a formally-specified alphabet that has a particular order:
|
|
// http://en.wikipedia.org/wiki/Base64 (and Node.js follows this too)
|
|
// TODO FIXME But our code above doesn't add padding! Don't use this yet...
|
|
bases.KNOWN_ALPHABETS[64] = bases.LETTERS_UPPERCASE + bases.LETTERS_LOWERCASE + bases.NUMERALS + '+/';
|
|
|
|
// Flickr and others also have a base-58 that removes confusing characters, but
|
|
// there isn't consensus on the order of lowercase vs. uppercase... =/
|
|
// http://www.flickr.com/groups/api/discuss/72157616713786392/
|
|
// https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart
|
|
// https://github.com/dougal/base58/blob/master/lib/base58.rb
|
|
// http://icoloma.blogspot.com/2010/03/create-your-own-bitly-using-base58.html
|
|
// We'll arbitrarily stay consistent with the above and using lowercase first:
|
|
bases.KNOWN_ALPHABETS[58] = bases.KNOWN_ALPHABETS[62].replace(/[0OlI]/g, '');
|
|
|
|
// And Douglas Crockford shared a similar base-32 from base-36:
|
|
// http://www.crockford.com/wrmg/base32.html
|
|
// Unlike our base-36, he explicitly specifies uppercase letters
|
|
bases.KNOWN_ALPHABETS[32] = bases.NUMERALS + bases.LETTERS_UPPERCASE.replace(/[ILOU]/g, '');
|
|
|
|
// Closure helper for convenience aliases like bases.toBase36():
|
|
function makeAlias(base, alphabet) {
|
|
bases['toBase' + base] = function (num) {
|
|
return bases.toAlphabet(num, alphabet);
|
|
};
|
|
bases['fromBase' + base] = function (str) {
|
|
return bases.fromAlphabet(str, alphabet);
|
|
};
|
|
}
|
|
|
|
// Do this for all known alphabets:
|
|
for (var base in bases.KNOWN_ALPHABETS) {
|
|
if (bases.KNOWN_ALPHABETS.hasOwnProperty(base)) {
|
|
makeAlias(base, bases.KNOWN_ALPHABETS[base]);
|
|
}
|
|
}
|
|
|
|
// And a generic alias too:
|
|
bases.toBase = function (num, base) {
|
|
return bases.toAlphabet(num, bases.KNOWN_ALPHABETS[base]);
|
|
};
|
|
|
|
bases.fromBase = function (str, base) {
|
|
return bases.fromAlphabet(str, bases.KNOWN_ALPHABETS[base]);
|
|
};
|
|
|
|
|
|
(function ($) {
|
|
var hex_more = $('#hex_more');
|
|
$('.js-hex').on('click', function (e) {
|
|
hex_more.val($(this).val());
|
|
});
|
|
$('#main_form').on('submit', function (e) {
|
|
e.preventDefault();
|
|
var num = $('#num').val();
|
|
var hex = hex_more.val();
|
|
var num = bases.fromBase(num, hex);
|
|
$('#base_2').val(bases.toBase(num, 2));
|
|
$('#base_8').val(bases.toBase(num, 8));
|
|
$('#base_10').val(bases.toBase(num, 10));
|
|
$('#base_16').val(bases.toBase(num, 16));
|
|
$('#base_32').val(bases.toBase(num, 32));
|
|
$('#base_58').val(bases.toBase(num, 58));
|
|
$('#base_62').val(bases.toBase(num, 62));
|
|
$('#base_64').val(bases.toBase(num, 64));
|
|
});
|
|
})(jQuery);
|
|
|
|
function empty(){
|
|
$('#num').val("");
|
|
$('#base_2').val("");
|
|
$('#base_8').val("");
|
|
$('#base_10').val("");
|
|
$('#base_16').val("");
|
|
$('#base_32').val("");
|
|
$('#base_58').val("");
|
|
$('#base_62').val("");
|
|
$('#base_64').val("");
|
|
} |