Skip to content

Commit

Permalink
Combine Stream.WriteString's slow path into one with escapeHTML bool …
Browse files Browse the repository at this point in the history
  • Loading branch information
Kz Ho committed Mar 9, 2023
1 parent de82dbd commit 88045f2
Showing 1 changed file with 24 additions and 67 deletions.
91 changes: 24 additions & 67 deletions stream_str.go
Expand Up @@ -235,15 +235,36 @@ func (stream *Stream) WriteStringWithHTMLEscaped(s string) {
stream.buf = append(stream.buf, '"')
return
}
writeStringSlowPathWithHTMLEscaped(stream, i, s, valLen)
writeStringSlowPath(stream, i, s, valLen, true)
}

func writeStringSlowPathWithHTMLEscaped(stream *Stream, i int, s string, valLen int) {
// WriteString write string to stream without html escape
func (stream *Stream) WriteString(s string) {
valLen := len(s)
stream.buf = append(stream.buf, '"')
// write string, the fast path, without utf8 and escape support
i := 0
for ; i < valLen; i++ {
c := s[i]
if c < utf8.RuneSelf && safeSet[c] {
stream.buf = append(stream.buf, c)
} else {
break
}
}
if i == valLen {
stream.buf = append(stream.buf, '"')
return
}
writeStringSlowPath(stream, i, s, valLen, false)
}

func writeStringSlowPath(stream *Stream, i int, s string, valLen int, escapeHTML bool) {
start := i
// for the remaining parts, we process them char by char
for i < valLen {
if b := s[i]; b < utf8.RuneSelf {
if htmlSafeSet[b] {
if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
i++
continue
}
Expand Down Expand Up @@ -306,67 +327,3 @@ func writeStringSlowPathWithHTMLEscaped(stream *Stream, i int, s string, valLen
}
stream.writeByte('"')
}

// WriteString write string to stream without html escape
func (stream *Stream) WriteString(s string) {
valLen := len(s)
stream.buf = append(stream.buf, '"')
// write string, the fast path, without utf8 and escape support
i := 0
for ; i < valLen; i++ {
c := s[i]
if c < utf8.RuneSelf && safeSet[c] {
stream.buf = append(stream.buf, c)
} else {
break
}
}
if i == valLen {
stream.buf = append(stream.buf, '"')
return
}
writeStringSlowPath(stream, i, s, valLen)
}

func writeStringSlowPath(stream *Stream, i int, s string, valLen int) {
start := i
// for the remaining parts, we process them char by char
for i < valLen {
if b := s[i]; b < utf8.RuneSelf {
if safeSet[b] {
i++
continue
}
if start < i {
stream.WriteRaw(s[start:i])
}
switch b {
case '\\', '"':
stream.writeTwoBytes('\\', b)
case '\n':
stream.writeTwoBytes('\\', 'n')
case '\r':
stream.writeTwoBytes('\\', 'r')
case '\t':
stream.writeTwoBytes('\\', 't')
default:
// This encodes bytes < 0x20 except for \t, \n and \r.
// If escapeHTML is set, it also escapes <, >, and &
// because they can lead to security holes when
// user-controlled strings are rendered into JSON
// and served to some browsers.
stream.WriteRaw(`\u00`)
stream.writeTwoBytes(hex[b>>4], hex[b&0xF])
}
i++
start = i
continue
}
i++
continue
}
if start < len(s) {
stream.WriteRaw(s[start:])
}
stream.writeByte('"')
}

0 comments on commit 88045f2

Please sign in to comment.