Created
June 20, 2021 11:41
-
-
Save paulc/784b965284d0740d3adebdc5305cf4d1 to your computer and use it in GitHub Desktop.
Base64 module for QuickJS
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
import * as os from "os"; | |
import * as std from "std"; | |
export const Base64 = { | |
_key : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", | |
decode: function(input) { | |
input = input.replace(/[^A-Za-z0-9\+\/\=]/g,""); | |
const padding = input.includes("=") ? input.length - input.indexOf("=") : 0 | |
const buflen = (input.length / 4) * 3 - padding; | |
const buf = new ArrayBuffer(buflen) | |
const uarray = new Uint8Array(buf); | |
let i = 0, j = 0, enc1, enc2, enc3, enc4; | |
while (i < input.length) { | |
enc1 = this._key.indexOf(input.charAt(i++)); | |
enc2 = this._key.indexOf(input.charAt(i++)); | |
enc3 = this._key.indexOf(input.charAt(i++)); | |
enc4 = this._key.indexOf(input.charAt(i++)); | |
uarray[j++] = (enc1 << 2) | (enc2 >> 4); | |
if (enc3 != 64) uarray[j++] = ((enc2 & 15) << 4) | (enc3 >> 2); | |
if (enc4 != 64) uarray[j++] = ((enc3 & 3) << 6) | enc4; | |
} | |
return buf; | |
}, | |
decodeStr: function(input) { | |
return String.fromCharCode.apply(null, new Uint16Array(this.decode(input))); | |
}, | |
encode: function(arrayBuffer) { | |
let base64 = ''; | |
const bytes = new Uint8Array(arrayBuffer); | |
const byteLength = bytes.byteLength; | |
const byteRemainder = byteLength % 3; | |
const mainLength = byteLength - byteRemainder; | |
let a,b,c,d,chunk; | |
// Main loop deals with bytes in chunks of 3 | |
for (let i = 0; i < mainLength; i += 3) { | |
// Combine the three bytes into a single integer | |
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; | |
// Use bitmasks to extract 6-bit segments from the triplet | |
a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 | |
b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 | |
c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 | |
d = chunk & 63; // 63 = 2^6 - 1 | |
// Convert the raw binary segments to the appropriate ASCII encoding | |
base64 += this._key[a] + this._key[b] + this._key[c] + this._key[d]; | |
} | |
// Deal with the remaining bytes and padding | |
if (byteRemainder === 1) { | |
chunk = bytes[mainLength]; | |
a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 | |
// Set the 4 least significant bits to zero | |
b = (chunk & 3) << 4; // 3 = 2^2 - 1 | |
base64 += `${this._key[a]}${this._key[b]}==`; | |
} else if (byteRemainder === 2) { | |
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; | |
a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 | |
b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 | |
// Set the 2 least significant bits to zero | |
c = (chunk & 15) << 2; // 15 = 2^4 - 1 | |
base64 += `${this._key[a]}${this._key[b]}${this._key[c]}=`; | |
} | |
return base64; | |
}, | |
readFileToBuffer: function(f) { | |
const bufLength = 1024; | |
let buf = new ArrayBuffer(bufLength); | |
let outbuf; | |
let out = [] | |
while (true) { | |
let n = std.in.read(buf,0,buf.byteLength); | |
if (n == bufLength) { | |
out.push(buf); | |
buf = new ArrayBuffer(bufLength); | |
} else { | |
outbuf = new ArrayBuffer((out.length*bufLength) + n) | |
const outbuf_v = new Uint8Array(outbuf); | |
let i = 0; | |
for (i=0;i<out.length;i++) { | |
outbuf_v.set(new Uint8Array(out[i]),i*bufLength,bufLength); | |
} | |
outbuf_v.set(new Uint8Array(buf,0,n),i*bufLength,n); | |
break; | |
} | |
} | |
return outbuf; | |
}, | |
stringFromArray: function(a) { | |
return String.fromCharCode.apply(null,a); | |
}, | |
} | |
if (scriptArgs[1] == "-d") { | |
const dec = Base64.decode(std.in.readAsString()); | |
std.out.write(dec,0,dec.byteLength); | |
} else if (scriptArgs[1] == "-ds") { | |
const dec = Base64.decode(scriptArgs[2]); | |
std.out.write(dec,0,dec.byteLength); | |
} else { | |
print(Base64.encode(Base64.readFileToBuffer(std.in))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment