diff --git a/.gitignore b/.gitignore index 80a01ec..5428831 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ node_modules npm-debug.log build -.lock-wscript \ No newline at end of file +.lock-wscript + +.idea \ No newline at end of file diff --git a/Readme.md b/Readme.md index e71ac65..4d712a2 100644 --- a/Readme.md +++ b/Readme.md @@ -15,12 +15,27 @@ npm install base62 ## Usage +### Default Character Set Example + ```javascript Base62 = require('base62') Base62.encode(999) // 'g7' Base62.decode('g7') // 999 ``` +### Custom Character Set Example + +The default character set is `0-9a-zA-Z`. This can be updated to a custom character set. Naturally, it must be 62 characters long. + +Instead of the character set `0-9a-zA-Z` you want to use `0-9A-Za-z`, call the `setCharacterSet()` method on the Base62 object passing in the string `"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"`. Note that all characters must be unique. + +```javascript +Base62 = require('base62') +Base62.setCharacterSet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); +Base62.encode(999) // 'G7' +Base62.decode('G7') // 999 +``` + ## Development Source hosted at [GitHub](http://github.com/andrew/base62.js). diff --git a/base62.js b/base62.js index 221a1d9..8b0ec2b 100644 --- a/base62.js +++ b/base62.js @@ -1,25 +1,38 @@ -module.exports = (function (my) { - my.chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); - - my.encode = function(i){ - if (i === 0) {return '0';} - var s = ''; - while (i > 0) { - s = this.chars[i % 62] + s; - i = Math.floor(i/62); - } - return s; - }; - my.decode = function(a,b,c,d){ - for ( - b = c = ( - a === (/\W|_|^$/.test(a += "") || a) - ) - 1; - d = a.charCodeAt(c++); - ) - b = b * 62 + d - [, 48, 29, 87][d >> 5]; - return b; - }; - - return my; +module.exports = (function (Base62) { + var DEFAULT_CHARACTER_SET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + Base62.encode = function(integer){ + if (integer === 0) {return '0';} + var s = ''; + while (integer > 0) { + s = Base62.characterSet[integer % 62] + s; + integer = Math.floor(integer/62); + } + return s; + }; + + Base62.decode = function(base62String){ + var val = 0, base62Chars = base62String.split("").reverse(); + base62Chars.forEach(function(character, index){ + val += Base62.characterSet.indexOf(character) * Math.pow(62, index); + }); + return val; + }; + + Base62.setCharacterSet = function(chars) { + var arrayOfChars = chars.split(""), uniqueCharacters = []; + + if(arrayOfChars.length != 62) throw Error("You must supply 62 characters"); + + arrayOfChars.forEach(function(char){ + if(!~uniqueCharacters.indexOf(char)) uniqueCharacters.push(char); + }); + + if(uniqueCharacters.length != 62) throw Error("You must use unique characters."); + + Base62.characterSet = arrayOfChars; + }; + + Base62.setCharacterSet(DEFAULT_CHARACTER_SET); + return Base62; }({})); diff --git a/test/test.js b/test/test.js index 36509dd..be4e184 100644 --- a/test/test.js +++ b/test/test.js @@ -2,13 +2,73 @@ var assert = require('assert'); var Base62 = require('../base62'); describe("encode", function() { - it("should encode a number to a Base62 string", function() { - assert.equal(Base62.encode(999), 'g7'); - }); + it("should encode a number to a Base62 string", function() { + assert.equal(Base62.encode(999), 'g7'); + assert.equal(Base62.encode(65), '13'); + //test big numbers + assert.equal(Base62.encode(10000000000001), "2Q3rKTOF"); + assert.equal(Base62.encode(10000000000002), "2Q3rKTOG"); + + }); }); describe("decode", function() { - it("should decode a number from a Base62 string", function() { - assert.equal(Base62.decode('g7'), 999); - }); + it("should decode a number from a Base62 string", function() { + assert.equal(Base62.decode('g7'), 999); + assert.equal(Base62.decode('13'), 65); + //test big numbers + assert.equal(Base62.decode("2Q3rKTOF"), 10000000000001); + assert.equal(Base62.decode("2Q3rKTOH"), 10000000000003); + }); }); + +describe("setCharacterSequence", function(){ + it("should update the character sequence", function(){ + Base62.setCharacterSet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + + //Test default character set is not intact + assert.notEqual(Base62.encode(999), 'g7'); + + //Test new character set test cases + var testCases = { + "G7": 999, + "Lxf7": 5234233, + "qx": 3283, + "29": 133, + "1S": 90, + "3k": 232, + "4I": 266, + "2X": 157, + "1E": 76, + "1L": 83 + }; + + Object.keys(testCases).forEach(function(base62String){ + assert.equal(Base62.encode(testCases[base62String]), base62String); + assert.equal(Base62.decode(base62String), testCases[base62String]); + }); + + }); + + it("should throw exceptions on invalid strings", function(){ + var errorCheck = function(err) { + if ( (err instanceof Error) && /value/.test(err) ) { + return true; + } + }; + + assert.throws(function(){ + Base62.setCharacterSet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"); + }, /You must supply 62 characters/); + + assert.throws(function(){ + Base62.setCharacterSet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;"); + }, /You must supply 62 characters/); + + + assert.throws(function(){ + Base62.setCharacterSet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxzz"); + }, /You must use unique characters/); + + }); +}); \ No newline at end of file