Skip to content

Instantly share code, notes, and snippets.

@sebastien-p
Forked from 140bytes/LICENSE.txt
Created August 25, 2011 13:00
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save sebastien-p/1170594 to your computer and use it in GitHub Desktop.
Save sebastien-p/1170594 to your computer and use it in GitHub Desktop.
base62 decode
function (
a, // base62 encoded string
b, // placeholder for result
c, // placeholder for iterator
d // placeholder for char code
) {
for (
b = c = ( // 'false - 1' will return '-1' and 'true - 1' will return '0'
a === (/\W|_|^$/.test(a += "") || a) // tests if 'a' is a properly base62-encoded string and coerces it to one
) - 1; // so, 'b' and 'c' are initialized with either '-1' or '0'
d = a.charCodeAt(c++); // if 'c' equals '-1', 'd' is 'NaN' which breaks the loop execution
)
b = b * 62 + d - [, 48, 29, 87][d >> 5]; // See comments : https://gist.github.com/1170594#gistcomment-48129
return b // positive base10 integer or '-1' if 'a' is not a base62 encoded string
}
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}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Sebastien P. https://twitter.com/#!/_sebastienp
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "base62 decode",
"description": "A JavaScript implementation of base62 decode.",
"keywords": [
"base62",
"decode",
"string",
"number",
"integer"
]
}
<!DOCTYPE html>
<title>Foo</title>
<div>Expected value: <b>3748986303764</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var base62decode = 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};
document.getElementById("ret").innerHTML = base62decode("140bytes")
</script>
@atk
Copy link

atk commented Aug 25, 2011

A less safe, but very small base62 decoder:

function(a,b,c,d){for(b=c=0;d=a.charCodeAt(c++);b=b*62+d-[,48,29,87][d>>5]);return b}

@sebastien-p
Copy link
Author

@atk : thanks, the b=b*62+d-[,48,29,87][d>>5] part is awesome, exactly what I needed !

@atk
Copy link

atk commented Aug 26, 2011

You're welcome, @sebastien-p :-)

I would really like to see more comments in the annotated part. I have only just worked out what the first part of the for loop does (leading to the false-y charCodeAt(-1) in the second for-loop-part if a is not string or not base62).

@sebastien-p
Copy link
Author

@atk : is it better now ? :) Can you explain the line I kept from your code as I don't always understand well those bitwise tricks ? Thanks.

@atk
Copy link

atk commented Aug 30, 2011

Thanks, much better now. Of course I can explain this line (except of the b*62 part, which seems pretty self-explaining to me):

// We are expecting either numbers (ascii 48-58), uppercase letter (ascii 65-90) and lowercase letters (ascii 97-122)
// and want to map the numbers to 0-9, the uppercase letters to 36-61 and the lowercase letters to 10-35; therefore,
// we integer divide the character code by 32 using shift right 5, so numbers will yield 1, uppercase letters 2 and lowercase 3
// and let this result select the corresponding substractor from a sparse array (because the extra comma is smaller than -1):
[,48,29,87][d>>5]

@sebastien-p
Copy link
Author

@atk : thank you, I understand it a little more now :) but still don't manage to apply this kind of hack to the encoding function :(

@atk
Copy link

atk commented Aug 30, 2011

it does not apply there, because we'd need another formula than d>>5 to filter 0-9, 10-35 and 36-61 to 0, 1 and 2. If I find one, I'll tell you.

@sebastien-p
Copy link
Author

@atk : I would be very interested to know, thank you.

@atk
Copy link

atk commented Aug 30, 2011

no formula I could think of would be shorter than x>35?87:x>10?29:48.

@sebastien-p
Copy link
Author

@atk : ok, thanks. If you want to help, I released the new version of the encoding function, still 4 bytes to go :) https://gist.github.com/1168420

@sebastien-p
Copy link
Author

a === (/\W|_/.test(a += "") || a) could be great instead of a === (a += "") && /^[a-z\d]+$/i.test(a) but sadly doesn't prevent passing an empty string as argument.

@atk
Copy link

atk commented Sep 18, 2011

how about saving at least 1 byte with a===(/^[a-z\d]+$/i.exec(a)||0)[0] which should take care of empty strings? Or even shorter: a===(/\W|_|^$/.test(a)||a) in which we use the property of /^$/ to match empty strings?

@sebastien-p
Copy link
Author

@atk : thanks, base62 decode is now 4 bytes shorter :)

@atk
Copy link

atk commented Sep 20, 2011

@sebastien-p: test coerces its argument to string, so a+='' has no function there. You may want to use a===(/\W|_|^$/.test(a)||a+'')

@sebastien-p
Copy link
Author

@atk : yep, I know, but a needs to be a string for a.charCodeAt(c++) to work, so I force coercion here on purpose.

@atk
Copy link

atk commented Sep 20, 2011

For a not to be a string and to be coerced to a string that coerced into a valid base62 string, it would have to be an object with a toString method, so handling non-strings is rather pointless, isn't it?

@sebastien-p
Copy link
Author

@atk : you're right, input value validation is optional and the whole entry would be shorter without it. I added it because it fits and mostly because I needed the function to be designed this way.

@yckart
Copy link

yckart commented Jan 14, 2013

true // -1
false // -1

@Quacky2200
Copy link

I found this useful and converted it into C# if anyone ever needs it. Not intended to be 140 bytes small.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment