Created
June 2, 2014 17:12
-
-
Save josephg/d8e9c258eeac4cb4bb22 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
assert = require 'assert' | |
_a = 'a'.charCodeAt(0) | |
_f = 'f'.charCodeAt(0) | |
_A = 'A'.charCodeAt(0) | |
_F = 'F'.charCodeAt(0) | |
hexForChar = (c, pos = 0) -> | |
ascii = c.charCodeAt pos | |
switch | |
when _a <= ascii <= _f then 10 + ascii - _a | |
when _A <= ascii <= _F then 10 + ascii - _A | |
else +c[pos] | |
exports.fromHex = fromHex = (str) -> | |
# Array buffers would be faster, but they aren't dynamically sized. | |
# Eh. | |
bytes = [] | |
for i in [0...str.length] by 2 | |
high = hexForChar str, i | |
low = hexForChar str, i + 1 | |
bytes.push (high << 4) + low | |
break unless low? # ignore trailing single characters | |
bytes | |
exports.toHex = toHex = (bytes) -> | |
str = '' # Actually not so bad these days on v8. | |
for b in bytes | |
vals = b.toString(16) | |
str += if vals.length is 1 then "0#{vals}" else vals | |
str | |
base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + | |
'abcdefghijklmnopqrstuvwxyz' + '0123456789+/' | |
base64Map = {} | |
base64Map[c] = i for c, i in base64Chars | |
base64Map['='] = '=' # special | |
# There's an implementation of base64 encoding & decoding built | |
# into the standard library, but it felt like the point of this | |
# question was to write my own. Eh. Did it. Felt good. | |
exports.fromBase64 = fromBase64 = (str) -> | |
bytes = [] | |
overflow = 0 | |
# Remove all newlines before processing. | |
pos = 0 | |
getNextChar = -> | |
pos++ while pos < str.length and base64Map[str[pos]] is undefined | |
str[pos++] | |
while pos < str.length | |
group = (base64Map[getNextChar()] for [0...4]) | |
bytes.push group[0]<<2 | group[1]>>4 | |
# Just care about one byte. | |
break if group[2] is '=' | |
bytes.push (group[1] & 0xf)<<4 | group[2]>>2 | |
break if group[3] is '=' | |
bytes.push (group[2] & 0x3)<<6 | group[3] | |
bytes | |
exports.toBase64 = toBase64 = (bytes) -> | |
str = '' | |
for i in [0...bytes.length] by 3 | |
str += base64Chars[bytes[i] >> 2] | |
# This still works correctly if we overflow the array. | |
# Good ol' javascript. | |
str += base64Chars[(bytes[i] & 3)<<4 | (bytes[i+1]>>4)] | |
if i + 1 >= bytes.length | |
str += '==' | |
break | |
str += base64Chars[(bytes[i+1] & 0xf)<<2 | bytes[i+2]>>6] | |
if i + 2 >= bytes.length | |
str += '=' | |
break | |
str += base64Chars[bytes[i+2] & 0x3f] | |
str |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment