1
1
package quicktemplate
2
2
3
3
import (
4
+ "bytes"
4
5
"fmt"
5
6
"strings"
6
7
)
@@ -17,7 +18,10 @@ func hasSpecialChars(s string) bool {
17
18
return false
18
19
}
19
20
20
- func appendJSONString (dst []byte , s string , addQuotes bool ) []byte {
21
+ // AppendJSONString appends json-encoded string s to dst and returns the result.
22
+ //
23
+ // If addQuotes is true, then the appended json string is wrapped into double quotes.
24
+ func AppendJSONString (dst []byte , s string , addQuotes bool ) []byte {
21
25
if ! hasSpecialChars (s ) {
22
26
// Fast path - nothing to escape.
23
27
if ! addQuotes {
@@ -33,33 +37,64 @@ func appendJSONString(dst []byte, s string, addQuotes bool) []byte {
33
37
if addQuotes {
34
38
dst = append (dst , '"' )
35
39
}
36
- bb := AcquireByteBuffer ()
37
- var tmp []byte
38
- tmp , bb .B = bb .B , dst
39
- _ , err := jsonReplacer .WriteString (bb , s )
40
- if err != nil {
41
- panic (fmt .Errorf ("BUG: unexpected error returned from jsonReplacer.WriteString: %s" , err ))
42
- }
43
- dst , bb .B = bb .B , tmp
44
- ReleaseByteBuffer (bb )
40
+ dst = jsonReplacer .AppendReplace (dst , s )
45
41
if addQuotes {
46
42
dst = append (dst , '"' )
47
43
}
48
44
return dst
49
45
}
50
46
51
- var jsonReplacer = strings .NewReplacer (func () []string {
52
- a := []string {
53
- "\n " , `\n` ,
54
- "\r " , `\r` ,
55
- "\t " , `\t` ,
56
- "\" " , `\"` ,
57
- "\\ " , `\\` ,
58
- "<" , `\u003c` ,
59
- "'" , `\u0027` ,
60
- }
47
+ var jsonReplacer = newByteReplacer (func () ([]byte , []string ) {
48
+ oldChars := []byte ("\n \r \t \b \f \" \\ <'" )
49
+ newStrings := []string {`\n` , `\r` , `\t` , `\b` , `\f` , `\"` , `\\` , `\u003c` , `\u0027` }
61
50
for i := 0 ; i < 0x20 ; i ++ {
62
- a = append (a , string ([]byte {byte (i )}), fmt .Sprintf (`\u%04x` , i ))
51
+ c := byte (i )
52
+ if n := bytes .IndexByte (oldChars , c ); n >= 0 {
53
+ continue
54
+ }
55
+ oldChars = append (oldChars , byte (i ))
56
+ newStrings = append (newStrings , fmt .Sprintf (`\u%04x` , i ))
57
+ }
58
+ return oldChars , newStrings
59
+ }())
60
+
61
+ type byteReplacer struct {
62
+ m [256 ]byte
63
+ newStrings []string
64
+ }
65
+
66
+ func newByteReplacer (oldChars []byte , newStrings []string ) * byteReplacer {
67
+ if len (oldChars ) != len (newStrings ) {
68
+ panic (fmt .Errorf ("len(oldChars)=%d must be equal to len(newStrings)=%d" , len (oldChars ), len (newStrings )))
69
+ }
70
+ if len (oldChars ) >= 255 {
71
+ panic (fmt .Errorf ("len(oldChars)=%d must be smaller than 255" , len (oldChars )))
72
+ }
73
+
74
+ var m [256 ]byte
75
+ for i := range m [:] {
76
+ m [i ] = 255
63
77
}
64
- return a
65
- }()... )
78
+ for i , c := range oldChars {
79
+ m [c ] = byte (i )
80
+ }
81
+ return & byteReplacer {
82
+ m : m ,
83
+ newStrings : newStrings ,
84
+ }
85
+ }
86
+
87
+ func (br * byteReplacer ) AppendReplace (dst []byte , s string ) []byte {
88
+ m := br .m
89
+ newStrings := br .newStrings
90
+ for i := 0 ; i < len (s ); i ++ {
91
+ c := s [i ]
92
+ n := m [c ]
93
+ if n == 255 {
94
+ dst = append (dst , c )
95
+ } else {
96
+ dst = append (dst , newStrings [n ]... )
97
+ }
98
+ }
99
+ return dst
100
+ }
0 commit comments