-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
No line breaks when generating base64 strings (#2008)
* fix bug for long strings * Update base64.js using new TextEncoder
- Loading branch information
Showing
1 changed file
with
5 additions
and
121 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,125 +1,9 @@ | ||
function strToBase64(str) { | ||
return base64EncArr(strToUTF8Arr(str)); | ||
return bytesToBase64(new TextEncoder().encode(str)); | ||
} | ||
|
||
// https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8 | ||
function uint6ToB64(nUint6) { | ||
return nUint6 < 26 | ||
? nUint6 + 65 | ||
: nUint6 < 52 | ||
? nUint6 + 71 | ||
: nUint6 < 62 | ||
? nUint6 - 4 | ||
: nUint6 === 62 | ||
? 43 | ||
: nUint6 === 63 | ||
? 47 | ||
: 65; | ||
// https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem | ||
function bytesToBase64(bytes) { | ||
const binString = String.fromCodePoint(...bytes); | ||
return btoa(binString); | ||
} | ||
|
||
function base64EncArr(aBytes) { | ||
let nMod3 = 2; | ||
let sB64Enc = ""; | ||
|
||
const nLen = aBytes.length; | ||
let nUint24 = 0; | ||
for (let 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.fromCodePoint( | ||
uint6ToB64((nUint24 >>> 18) & 63), | ||
uint6ToB64((nUint24 >>> 12) & 63), | ||
uint6ToB64((nUint24 >>> 6) & 63), | ||
uint6ToB64(nUint24 & 63) | ||
); | ||
nUint24 = 0; | ||
} | ||
} | ||
return ( | ||
sB64Enc.substring(0, sB64Enc.length - 2 + nMod3) + | ||
(nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==") | ||
); | ||
} | ||
|
||
function strToUTF8Arr(sDOMStr) { | ||
let aBytes; | ||
let nChr; | ||
const nStrLen = sDOMStr.length; | ||
let nArrLen = 0; | ||
|
||
/* mapping… */ | ||
for (let nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) { | ||
nChr = sDOMStr.codePointAt(nMapIdx); | ||
|
||
if (nChr > 65536) { | ||
nMapIdx++; | ||
} | ||
|
||
nArrLen += | ||
nChr < 0x80 | ||
? 1 | ||
: nChr < 0x800 | ||
? 2 | ||
: nChr < 0x10000 | ||
? 3 | ||
: nChr < 0x200000 | ||
? 4 | ||
: nChr < 0x4000000 | ||
? 5 | ||
: 6; | ||
} | ||
|
||
aBytes = new Uint8Array(nArrLen); | ||
|
||
/* transcription… */ | ||
let nIdx = 0; | ||
let nChrIdx = 0; | ||
while (nIdx < nArrLen) { | ||
nChr = sDOMStr.codePointAt(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); | ||
nChrIdx++; | ||
} 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); | ||
nChrIdx++; | ||
} /* if (nChr <= 0x7fffffff) */ else { | ||
/* 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); | ||
nChrIdx++; | ||
} | ||
nChrIdx++; | ||
} | ||
|
||
return aBytes; | ||
} |