1 package json
2
3 import (
4 "fmt"
5 "unicode/utf8"
6 )
7
8 const hex = "0123456789abcdef"
9
10 var noEscapeTable = [256]bool{}
11
12 func init() {
13 for i := 0; i <= 0x7e; i++ {
14 noEscapeTable[i] = i >= 0x20 && i != '\\' && i != '"'
15 }
16 }
17
18
19
20 func (e Encoder) AppendStrings(dst []byte, vals []string) []byte {
21 if len(vals) == 0 {
22 return append(dst, '[', ']')
23 }
24 dst = append(dst, '[')
25 dst = e.AppendString(dst, vals[0])
26 if len(vals) > 1 {
27 for _, val := range vals[1:] {
28 dst = e.AppendString(append(dst, ','), val)
29 }
30 }
31 dst = append(dst, ']')
32 return dst
33 }
34
35
36
37
38
39
40
41
42
43
44 func (Encoder) AppendString(dst []byte, s string) []byte {
45
46 dst = append(dst, '"')
47
48 for i := 0; i < len(s); i++ {
49
50
51
52 if !noEscapeTable[s[i]] {
53
54
55 dst = appendStringComplex(dst, s, i)
56 return append(dst, '"')
57 }
58 }
59
60
61 dst = append(dst, s...)
62
63 return append(dst, '"')
64 }
65
66
67
68 func (e Encoder) AppendStringers(dst []byte, vals []fmt.Stringer) []byte {
69 if len(vals) == 0 {
70 return append(dst, '[', ']')
71 }
72 dst = append(dst, '[')
73 dst = e.AppendStringer(dst, vals[0])
74 if len(vals) > 1 {
75 for _, val := range vals[1:] {
76 dst = e.AppendStringer(append(dst, ','), val)
77 }
78 }
79 return append(dst, ']')
80 }
81
82
83
84 func (e Encoder) AppendStringer(dst []byte, val fmt.Stringer) []byte {
85 if val == nil {
86 return e.AppendInterface(dst, nil)
87 }
88 return e.AppendString(dst, val.String())
89 }
90
91
92
93
94 func appendStringComplex(dst []byte, s string, i int) []byte {
95 start := 0
96 for i < len(s) {
97 b := s[i]
98 if b >= utf8.RuneSelf {
99 r, size := utf8.DecodeRuneInString(s[i:])
100 if r == utf8.RuneError && size == 1 {
101
102
103
104 if start < i {
105 dst = append(dst, s[start:i]...)
106 }
107 dst = append(dst, `\ufffd`...)
108 i += size
109 start = i
110 continue
111 }
112 i += size
113 continue
114 }
115 if noEscapeTable[b] {
116 i++
117 continue
118 }
119
120
121
122
123 if start < i {
124 dst = append(dst, s[start:i]...)
125 }
126 switch b {
127 case '"', '\\':
128 dst = append(dst, '\\', b)
129 case '\b':
130 dst = append(dst, '\\', 'b')
131 case '\f':
132 dst = append(dst, '\\', 'f')
133 case '\n':
134 dst = append(dst, '\\', 'n')
135 case '\r':
136 dst = append(dst, '\\', 'r')
137 case '\t':
138 dst = append(dst, '\\', 't')
139 default:
140 dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
141 }
142 i++
143 start = i
144 }
145 if start < len(s) {
146 dst = append(dst, s[start:]...)
147 }
148 return dst
149 }
150
View as plain text