diff --git a/README.md b/README.md index 0135744..1eb9fd8 100644 --- a/README.md +++ b/README.md @@ -121,9 +121,9 @@ Though goldmark builds clean extensible AST structure and get full compliance wi Commonmark, it is resonably fast and less memory consumption. ``` -BenchmarkGoldMark-4 200 7981524 ns/op 2485650 B/op 15716 allocs/op -BenchmarkGolangCommonMark-4 200 8609737 ns/op 3053758 B/op 18681 allocs/op -BenchmarkBlackFriday-4 200 6311112 ns/op 3356762 B/op 17481 allocs/op +BenchmarkGoldMark-4 200 7176000 ns/op 2482660 B/op 15597 allocs/op +BenchmarkGolangCommonMark-4 200 7874817 ns/op 3053775 B/op 18682 allocs/op +BenchmarkBlackFriday-4 300 5871891 ns/op 3356419 B/op 17481 allocs/op ``` Donation diff --git a/util/util.go b/util/util.go index c5998c2..ec04ae5 100644 --- a/util/util.go +++ b/util/util.go @@ -377,16 +377,21 @@ func EscapeHTMLByte(b byte) []byte { // EscapeHTML escapes characters that should be escaped in HTML text. func EscapeHTML(v []byte) []byte { - result := make([]byte, 0, len(v)+10) - for _, c := range v { + cob := NewCopyOnWriteBuffer(v) + n := 0 + for i := 0; i < len(v); i++ { + c := v[i] escaped := htmlEscapeTable[c] if escaped != nil { - result = append(result, escaped...) - } else { - result = append(result, c) + cob.Write(v[n:i]) + cob.Write(escaped) + n = i + 1 } } - return result + if cob.IsCopied() { + cob.Write(v[n:len(v)]) + } + return cob.Bytes() } // UnescapePunctuations unescapes blackslash escaped punctuations. @@ -508,17 +513,9 @@ func URLEscape(v []byte, resolveReference bool) []byte { v = ResolveNumericReferences(v) v = ResolveEntityNames(v) } - ret := v - changed := false + cob := NewCopyOnWriteBuffer(v) limit := len(v) n := 0 - add := func(b []byte) { - if !changed { - ret = make([]byte, 0, len(v)+20) - changed = true - } - ret = append(ret, b...) - } for i := 0; i < limit; { c := v[i] @@ -536,21 +533,21 @@ func URLEscape(v []byte, resolveReference bool) []byte { continue } if c == ' ' { - add(v[n:i]) - add(htmlSpace) + cob.Write(v[n:i]) + cob.Write(htmlSpace) i++ n = i continue } - add(v[n:i]) - add([]byte(url.QueryEscape(string(v[i : i+int(u8len)])))) + cob.Write(v[n:i]) + cob.Write(StringToReadOnlyBytes(url.QueryEscape(string(v[i : i+int(u8len)])))) i += int(u8len) n = i } - if changed { - add(v[n:len(v)]) + if cob.IsCopied() { + cob.Write(v[n:len(v)]) } - return ret + return cob.Bytes() } // FindAttributeIndex searchs