Skip to content

Commit 42bc6ba

Browse files
committed
Further optimize base64Write
1 parent 0a0b942 commit 42bc6ba

File tree

1 file changed

+49
-20
lines changed

1 file changed

+49
-20
lines changed

index.js

+49-20
Original file line numberDiff line numberDiff line change
@@ -1019,36 +1019,59 @@ function asciiWrite (buf, string, offset, length) {
10191019
}
10201020

10211021
function base64Write (buf, string, offset, length) {
1022-
const src = string.replace(/[^+/0-9A-Za-z-_=]/g, '')
1023-
const eq = src.indexOf('=')
1022+
const src = string
10241023
const dst = buf
10251024

1026-
let srcLen = eq >= 0 ? eq : src.length
1025+
let srcLen = src.length
10271026
let srcPos = 0
10281027
let dstLen = length
10291028
let dstPos = offset
1029+
let invalid = false
1030+
1031+
if (srcLen > 0 && src[srcLen - 1] === '=') srcLen -= 1
1032+
if (srcLen > 0 && src[srcLen - 1] === '=') srcLen -= 1
1033+
1034+
retry: for (;;) { // eslint-disable-line
1035+
while (srcLen >= 4 && dstLen >= 3) {
1036+
const c1 = src.charCodeAt(srcPos++)
1037+
const c2 = src.charCodeAt(srcPos++)
1038+
const c3 = src.charCodeAt(srcPos++)
1039+
const c4 = src.charCodeAt(srcPos++)
1040+
const t1 = base64Table[c1 & 0x7f]
1041+
const t2 = base64Table[c2 & 0x7f]
1042+
const t3 = base64Table[c3 & 0x7f]
1043+
const t4 = base64Table[c4 & 0x7f]
1044+
1045+
if ((c1 | c2 | c3 | c4 | t1 | t2 | t3 | t4) & ~0x7f) {
1046+
srcPos -= 4
1047+
invalid = true // Slow parsing until we recover.
1048+
break
1049+
}
10301050

1031-
while (srcLen >= 4 && dstLen >= 3) {
1032-
const t1 = base64Table[src.charCodeAt(srcPos++)]
1033-
const t2 = base64Table[src.charCodeAt(srcPos++)]
1034-
const t3 = base64Table[src.charCodeAt(srcPos++)]
1035-
const t4 = base64Table[src.charCodeAt(srcPos++)]
1036-
1037-
dst[dstPos++] = (t1 << 2) | (t2 >> 4)
1038-
dst[dstPos++] = (t2 << 4) | (t3 >> 2)
1039-
dst[dstPos++] = (t3 << 6) | (t4 >> 0)
1051+
dst[dstPos++] = (t1 << 2) | (t2 >> 4)
1052+
dst[dstPos++] = (t2 << 4) | (t3 >> 2)
1053+
dst[dstPos++] = (t3 << 6) | (t4 >> 0)
10401054

1041-
srcLen -= 4
1042-
dstLen -= 3
1043-
}
1055+
srcLen -= 4
1056+
dstLen -= 3
1057+
}
10441058

1045-
{
10461059
let w1, w2, w3, w4
1060+
let state = 0
10471061

10481062
while (srcLen && dstLen) {
1049-
const w = base64Table[src.charCodeAt(srcPos)]
1063+
const c = src.charCodeAt(srcPos)
1064+
const w = base64Table[c & 0x7f]
1065+
1066+
srcPos++
1067+
srcLen--
10501068

1051-
switch (srcPos & 3) {
1069+
if ((c | w) & ~0x7f) {
1070+
if (c === 0x3d) break // Stop on `=`
1071+
continue // Skip invalid
1072+
}
1073+
1074+
switch (state & 3) {
10521075
case 0:
10531076
w1 = w
10541077
break
@@ -1066,12 +1089,18 @@ function base64Write (buf, string, offset, length) {
10661089
w4 = w
10671090
dst[dstPos++] = (w3 << 6) | (w4 >> 0)
10681091
dstLen--
1092+
if (invalid) {
1093+
// Retry fast parsing.
1094+
invalid = false
1095+
continue retry // eslint-disable-line
1096+
}
10691097
break
10701098
}
10711099

1072-
srcPos++
1073-
srcLen--
1100+
state++
10741101
}
1102+
1103+
break
10751104
}
10761105

10771106
return dstPos - offset

0 commit comments

Comments
 (0)