Last active
December 24, 2020 06:10
-
-
Save iwill/ee86aefe2214ee762e1a937592496d2a 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
Base64 = Base64 || { | |
// @param n Number, 6 bits, e.g. 0b111111 | |
// @return String, a char, e.g. "/" | |
encode6Bits: function(n) { | |
n = Math.min(Math.max(0, n), 63); | |
if (n >= 0 && n <= 25) return String.fromCharCode("A".charCodeAt(0) + n); // ["A", "Z"] | |
else if (n >= 26 && n <= 51) return String.fromCharCode("a".charCodeAt(0) + n - 26); // ["a", "z"] | |
else if (n >= 52 && n <= 61) return String.fromCharCode("0".charCodeAt(0) + n - 52); // ["0", "9"] | |
else if (n == 62) return "+"; | |
else /* if (n == 63) */ return "/"; | |
}, | |
// @param c Number, char code, e.g. 47 | |
// @return Number, 6 bits, e.g. 0b111111 | |
decode6Bits: function(c) { // c: charCode | |
if (c >= "A".charCodeAt(0) && c <= "Z".charCodeAt(0)) return c - "A".charCodeAt(0); // [ 0, 25] | |
else if (c >= "a".charCodeAt(0) && c <= "z".charCodeAt(0)) return c - "a".charCodeAt(0) + 26; // [26, 51] | |
else if (c >= "0".charCodeAt(0) && c <= "9".charCodeAt(0)) return c - "0".charCodeAt(0) + 52; // [52, 61] | |
else if (c == "+".charCodeAt(0)) return 62; | |
else /* if (c == "/".charCodeAt(0)) */ return 63; | |
}, | |
// @param bits2x32 Bits2x32, e.g. { high32: 0xFFFFFFFF, low32: 0xFFFFFFFF } | |
// @return String, 1 ~ 11 chars, e.g. "//////////P" | |
encode2x32Bits: function(bits2x32) { | |
let high32 = bits2x32.high32, low32 = bits2x32.low32; | |
let base64 = ""; | |
while (high32 > 0 || low32 > 0) { | |
base64 += this.encode6Bits(low32 & 0b111111); // 0b111111: 6 bits | |
low32 = (high32 << (32 - 6) >>> 0) | (low32 >>> 6); | |
high32 >>>= 6; | |
} | |
return base64 || "A"; | |
}, | |
// @param base64 String, 1 ~ 11 chars, e.g. "//////////P" | |
// @return Bits2x32, e.g. { high32: 0xFFFFFFFF, low32: 0xFFFFFFFF } | |
decode2x32Bits: function(base64) { | |
let length = Math.min(base64.length, 11); // 11: 64 bits ~= 11 chars * 6 bits | |
let high32 = 0, low32 = 0; | |
for (let i = 0; i < length; ++i) { | |
let bits06 = this.decode6Bits(base64.charCodeAt(i)); | |
if (i < 5) { | |
low32 |= bits06 << (6 * i) >>> 0; | |
} | |
else if (i == 5) { | |
low32 |= (bits06 & 0b11) << (6 * i) >>> 0; | |
high32 |= bits06 >>> 2; | |
} | |
else { | |
high32 |= bits06 << (6 * i % 32) >>> 0; | |
} | |
low32 >>>= 0; | |
high32 >>>= 0; | |
} | |
return new Bits2x32(high32, low32); | |
} | |
}; | |
function Bits2x32(high32, low32) { | |
this.low32 = low32; | |
this.high32 = high32; | |
} | |
Bits2x32.prototype = { | |
getBit: function(index) { | |
let key = index < 32 ? "low32" : "high32"; | |
return (this[key] >>> (index % 32)) & 1; | |
}, | |
setBit: function(index, bool) { | |
let key = index < 32 ? "low32" : "high32"; | |
let mask = 1 << (index % 32); // >>> 0 | |
this[key] = bool ? ((this[key] | mask) >>> 0) : (this[key] & (0xFFFFFFFF & ~mask)); | |
}, | |
encode64Bits: function() { | |
return Base64.encode64Bits(this); | |
} | |
}; | |
Author
iwill
commented
Dec 23, 2020
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment