Skip to content

Instantly share code, notes, and snippets.

@iwill
Last active December 24, 2020 06:10
Show Gist options
  • Save iwill/ee86aefe2214ee762e1a937592496d2a to your computer and use it in GitHub Desktop.
Save iwill/ee86aefe2214ee762e1a937592496d2a to your computer and use it in GitHub Desktop.
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);
}
};
@iwill
Copy link
Author

iwill commented Dec 23, 2020

let bits2x32 = new Bits2x32(0b11111111111111111111111111111111, 0b11111111111111111111111111111111);
let base64 = bits2x32.encode2x32Bits();
console.log(bits2x32);
console.log(base64);
console.log(Base64.decode2x32Bits(base64));

bits2x32 = new Bits2x32(0b11111111111111111111111111111111, 0b11111111111111111111111111111111);
console.log(bits2x32);
bits2x32.setBit(31, 0);
console.log(bits2x32);
bits2x32.setBit(63, 0);
console.log(bits2x32);
bits2x32.setBit(31, 1);
console.log(bits2x32);
bits2x32.setBit(63, 1);
console.log(bits2x32);

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