Last active
July 17, 2019 13:55
-
-
Save fliptopbox/dfbb7ce14730ba1533d48329e4d7740a to your computer and use it in GitHub Desktop.
Base64 library - lets you encode UTF-16 or UTF-8 (with UMD decorator)
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
(function(root, factory, NS = "Base64") { if (typeof define === "function" && define.amd) { define([], factory); } else if (typeof exports === "object") { module.exports = factory(); } else { root[NS] = factory(); } })(this, function() | |
{ | |
/* | |
Base64 library | |
Lets you encode with UTF-16 or UTF-8 | |
https://gist.github.com/fliptopbox/dfbb7ce14730ba1533d48329e4d7740a | |
To see console output remove the # --> *#/ | |
const teststring = `Ħ€ǁǿ ɰṏ®ʆď - http://say:[email protected]/?kilroy=was+here&now=gone#!extinct\n\rfin!`; | |
const utf16 = new Base64(16); | |
const utf8 = new Base64(8); | |
const A = utf16.encode(teststring); | |
const B = utf8.encode(teststring); | |
const Adec = utf16.decode(A); | |
const Bdec = utf8.decode(B); | |
const Alen = A.length; | |
const Blen = B.length; | |
const ratio = Alen / Blen; | |
const AlessThanB = Alen < Blen; | |
const percent = (AlessThanB ? ratio : (1 / ratio)) * 100 >> 0 / 100; | |
console.clear(); | |
console.log("%cResults: Winner is %s (by %s%)", "font-size:2em;", AlessThanB ? "UTF-16" : "UTF-8", percent); | |
console.log("Decoded UTF-16 and UTF-8 strings are equal (%s)", Adec === Bdec); | |
console.log(`Length: UTF-16(%s) UTF-8(%s) A<B(%s) Ratio(%s%)`, Alen, Blen, AlessThanB, percent); | |
/**/ | |
return Base64; | |
function Base64(bit = 8) { | |
// | |
// Base64 / binary data / UTF-8 strings utilities (#3) | |
// https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding | |
// Which method are we using 16bit or 8bit (default) ? | |
const utf8 = !(bit === 16); | |
function btoaUTF16(sString) { | |
const aUTF16CodeUnits = new Uint16Array(sString.length); | |
aUTF16CodeUnits.forEach((el, idx, arr) => { | |
arr[idx] = sString.charCodeAt(idx); | |
}); | |
return btoa(String.fromCharCode(...new Uint8Array(aUTF16CodeUnits.buffer))); | |
} | |
function atobUTF16(sBase64) { | |
const sBinaryString = atob(sBase64); | |
const aBinaryView = new Uint8Array(sBinaryString.length); | |
aBinaryView.forEach((_, idx, arr) => { | |
arr[idx] = sBinaryString.charCodeAt(idx); | |
}); | |
return String.fromCharCode(...new Uint16Array(aBinaryView.buffer)); | |
} | |
// | |
// Traditional approach using URLencode and character escaping | |
const escaping = new RegExp("%([0-9A-F]{2})", "g"); // eg: "&" > %26 > 0x26 | |
const toSolidBytes = (_, p1) => String.fromCharCode(`0x${p1}`); | |
function btoaUTF8(sString) { | |
return btoa(encodeURIComponent(sString).replace(escaping, toSolidBytes)); | |
} | |
function atobUTF8(sBase64) { | |
return decodeURIComponent( | |
atob(sBase64) | |
.split("") | |
.map(c => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)) | |
.join("") | |
); | |
} | |
this.encode = utf8 ? btoaUTF8 : btoaUTF16; | |
this.decode = utf8 ? atobUTF8 : atobUTF16; | |
this.escaping = escaping; | |
this.toSolidBytes = toSolidBytes; | |
this.bit = utf8 ? 8 : 16; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment