Last active
August 29, 2015 14:09
-
-
Save h2non/37a6d588271fc9c1e828 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
(function (global) { | |
'use strict'; | |
/*\ | |
|*| | |
|*| Base64 / binary data / UTF-8 strings utilities | |
|*| | |
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding | |
|*| | |
\*/ | |
/* Array of bytes to base64 string decoding */ | |
function b64ToUint6(nChr) { | |
return nChr > 64 && nChr < 91 ? | |
nChr - 65 : nChr > 96 && nChr < 123 ? | |
nChr - 71 : nChr > 47 && nChr < 58 ? | |
nChr + 4 : nChr === 43 ? | |
62 : nChr === 47 ? | |
63 : | |
0; | |
} | |
function base64DecToArr(sBase64, nBlocksSize) { | |
var | |
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), | |
nInLen = sB64Enc.length, | |
nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, | |
taBytes = new Uint8Array(nOutLen); | |
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) { | |
nMod4 = nInIdx & 3; | |
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4; | |
if (nMod4 === 3 || nInLen - nInIdx === 1) { | |
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { | |
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255; | |
} | |
nUint24 = 0; | |
} | |
} | |
return taBytes; | |
} | |
/* Base64 string to array encoding */ | |
function uint6ToB64(nUint6) { | |
return nUint6 < 26 ? | |
nUint6 + 65 : nUint6 < 52 ? | |
nUint6 + 71 : nUint6 < 62 ? | |
nUint6 - 4 : nUint6 === 62 ? | |
43 : nUint6 === 63 ? | |
47 : | |
65; | |
} | |
function base64EncArr(aBytes) { | |
var nMod3 = 2, | |
sB64Enc = ""; | |
for (var nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { | |
nMod3 = nIdx % 3; | |
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { | |
sB64Enc += "\r\n"; | |
} | |
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24); | |
if (nMod3 === 2 || aBytes.length - nIdx === 1) { | |
sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63)); | |
nUint24 = 0; | |
} | |
} | |
return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '=='); | |
} | |
/* UTF-8 array to DOMString and vice versa */ | |
function UTF8ArrToStr(aBytes) { | |
var sView = ""; | |
for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) { | |
nPart = aBytes[nIdx]; | |
sView += String.fromCharCode( | |
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */ | |
/* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */ | |
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */ | |
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */ | |
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */ | |
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */ | |
(nPart - 192 << 6) + aBytes[++nIdx] - 128 : /* nPart < 127 ? */ /* one byte */ | |
nPart | |
); | |
} | |
return sView; | |
} | |
function strToUTF8Arr(sDOMStr) { | |
var aBytes, nChr, nStrLen = sDOMStr.length, | |
nArrLen = 0; | |
/* mapping... */ | |
for (var nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) { | |
nChr = sDOMStr.charCodeAt(nMapIdx); | |
nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6; | |
} | |
aBytes = new Uint8Array(nArrLen); | |
/* transcription... */ | |
for (var nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) { | |
nChr = sDOMStr.charCodeAt(nChrIdx); | |
if (nChr < 128) { | |
/* one byte */ | |
aBytes[nIdx++] = nChr; | |
} else if (nChr < 0x800) { | |
/* two bytes */ | |
aBytes[nIdx++] = 192 + (nChr >>> 6); | |
aBytes[nIdx++] = 128 + (nChr & 63); | |
} else if (nChr < 0x10000) { | |
/* three bytes */ | |
aBytes[nIdx++] = 224 + (nChr >>> 12); | |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); | |
aBytes[nIdx++] = 128 + (nChr & 63); | |
} else if (nChr < 0x200000) { | |
/* four bytes */ | |
aBytes[nIdx++] = 240 + (nChr >>> 18); | |
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); | |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); | |
aBytes[nIdx++] = 128 + (nChr & 63); | |
} else if (nChr < 0x4000000) { | |
/* five bytes */ | |
aBytes[nIdx++] = 248 + (nChr >>> 24); | |
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); | |
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); | |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); | |
aBytes[nIdx++] = 128 + (nChr & 63); | |
} else /* if (nChr <= 0x7fffffff) */ { | |
/* six bytes */ | |
aBytes[nIdx++] = 252 + (nChr >>> 30); | |
aBytes[nIdx++] = 128 + (nChr >>> 24 & 63); | |
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); | |
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); | |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); | |
aBytes[nIdx++] = 128 + (nChr & 63); | |
} | |
} | |
return aBytes | |
} | |
global.base64 = { | |
encode: function (str) { | |
return base64EncArr(strToUTF8Arr(str)) | |
}, | |
decode: function(str) { | |
return UTF8ArrToStr(base64DecToArr(str)) | |
} | |
} | |
}(window)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment