Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / json-iterator / go / stream_str.go
1 package jsoniter
2
3 import (
4         "unicode/utf8"
5 )
6
7 // htmlSafeSet holds the value true if the ASCII character with the given
8 // array position can be safely represented inside a JSON string, embedded
9 // inside of HTML <script> tags, without any additional escaping.
10 //
11 // All values are true except for the ASCII control characters (0-31), the
12 // double quote ("), the backslash character ("\"), HTML opening and closing
13 // tags ("<" and ">"), and the ampersand ("&").
14 var htmlSafeSet = [utf8.RuneSelf]bool{
15         ' ':      true,
16         '!':      true,
17         '"':      false,
18         '#':      true,
19         '$':      true,
20         '%':      true,
21         '&':      false,
22         '\'':     true,
23         '(':      true,
24         ')':      true,
25         '*':      true,
26         '+':      true,
27         ',':      true,
28         '-':      true,
29         '.':      true,
30         '/':      true,
31         '0':      true,
32         '1':      true,
33         '2':      true,
34         '3':      true,
35         '4':      true,
36         '5':      true,
37         '6':      true,
38         '7':      true,
39         '8':      true,
40         '9':      true,
41         ':':      true,
42         ';':      true,
43         '<':      false,
44         '=':      true,
45         '>':      false,
46         '?':      true,
47         '@':      true,
48         'A':      true,
49         'B':      true,
50         'C':      true,
51         'D':      true,
52         'E':      true,
53         'F':      true,
54         'G':      true,
55         'H':      true,
56         'I':      true,
57         'J':      true,
58         'K':      true,
59         'L':      true,
60         'M':      true,
61         'N':      true,
62         'O':      true,
63         'P':      true,
64         'Q':      true,
65         'R':      true,
66         'S':      true,
67         'T':      true,
68         'U':      true,
69         'V':      true,
70         'W':      true,
71         'X':      true,
72         'Y':      true,
73         'Z':      true,
74         '[':      true,
75         '\\':     false,
76         ']':      true,
77         '^':      true,
78         '_':      true,
79         '`':      true,
80         'a':      true,
81         'b':      true,
82         'c':      true,
83         'd':      true,
84         'e':      true,
85         'f':      true,
86         'g':      true,
87         'h':      true,
88         'i':      true,
89         'j':      true,
90         'k':      true,
91         'l':      true,
92         'm':      true,
93         'n':      true,
94         'o':      true,
95         'p':      true,
96         'q':      true,
97         'r':      true,
98         's':      true,
99         't':      true,
100         'u':      true,
101         'v':      true,
102         'w':      true,
103         'x':      true,
104         'y':      true,
105         'z':      true,
106         '{':      true,
107         '|':      true,
108         '}':      true,
109         '~':      true,
110         '\u007f': true,
111 }
112
113 // safeSet holds the value true if the ASCII character with the given array
114 // position can be represented inside a JSON string without any further
115 // escaping.
116 //
117 // All values are true except for the ASCII control characters (0-31), the
118 // double quote ("), and the backslash character ("\").
119 var safeSet = [utf8.RuneSelf]bool{
120         ' ':      true,
121         '!':      true,
122         '"':      false,
123         '#':      true,
124         '$':      true,
125         '%':      true,
126         '&':      true,
127         '\'':     true,
128         '(':      true,
129         ')':      true,
130         '*':      true,
131         '+':      true,
132         ',':      true,
133         '-':      true,
134         '.':      true,
135         '/':      true,
136         '0':      true,
137         '1':      true,
138         '2':      true,
139         '3':      true,
140         '4':      true,
141         '5':      true,
142         '6':      true,
143         '7':      true,
144         '8':      true,
145         '9':      true,
146         ':':      true,
147         ';':      true,
148         '<':      true,
149         '=':      true,
150         '>':      true,
151         '?':      true,
152         '@':      true,
153         'A':      true,
154         'B':      true,
155         'C':      true,
156         'D':      true,
157         'E':      true,
158         'F':      true,
159         'G':      true,
160         'H':      true,
161         'I':      true,
162         'J':      true,
163         'K':      true,
164         'L':      true,
165         'M':      true,
166         'N':      true,
167         'O':      true,
168         'P':      true,
169         'Q':      true,
170         'R':      true,
171         'S':      true,
172         'T':      true,
173         'U':      true,
174         'V':      true,
175         'W':      true,
176         'X':      true,
177         'Y':      true,
178         'Z':      true,
179         '[':      true,
180         '\\':     false,
181         ']':      true,
182         '^':      true,
183         '_':      true,
184         '`':      true,
185         'a':      true,
186         'b':      true,
187         'c':      true,
188         'd':      true,
189         'e':      true,
190         'f':      true,
191         'g':      true,
192         'h':      true,
193         'i':      true,
194         'j':      true,
195         'k':      true,
196         'l':      true,
197         'm':      true,
198         'n':      true,
199         'o':      true,
200         'p':      true,
201         'q':      true,
202         'r':      true,
203         's':      true,
204         't':      true,
205         'u':      true,
206         'v':      true,
207         'w':      true,
208         'x':      true,
209         'y':      true,
210         'z':      true,
211         '{':      true,
212         '|':      true,
213         '}':      true,
214         '~':      true,
215         '\u007f': true,
216 }
217
218 var hex = "0123456789abcdef"
219
220 // WriteStringWithHTMLEscaped write string to stream with html special characters escaped
221 func (stream *Stream) WriteStringWithHTMLEscaped(s string) {
222         valLen := len(s)
223         stream.buf = append(stream.buf, '"')
224         // write string, the fast path, without utf8 and escape support
225         i := 0
226         for ; i < valLen; i++ {
227                 c := s[i]
228                 if c < utf8.RuneSelf && htmlSafeSet[c] {
229                         stream.buf = append(stream.buf, c)
230                 } else {
231                         break
232                 }
233         }
234         if i == valLen {
235                 stream.buf = append(stream.buf, '"')
236                 return
237         }
238         writeStringSlowPathWithHTMLEscaped(stream, i, s, valLen)
239 }
240
241 func writeStringSlowPathWithHTMLEscaped(stream *Stream, i int, s string, valLen int) {
242         start := i
243         // for the remaining parts, we process them char by char
244         for i < valLen {
245                 if b := s[i]; b < utf8.RuneSelf {
246                         if htmlSafeSet[b] {
247                                 i++
248                                 continue
249                         }
250                         if start < i {
251                                 stream.WriteRaw(s[start:i])
252                         }
253                         switch b {
254                         case '\\', '"':
255                                 stream.writeTwoBytes('\\', b)
256                         case '\n':
257                                 stream.writeTwoBytes('\\', 'n')
258                         case '\r':
259                                 stream.writeTwoBytes('\\', 'r')
260                         case '\t':
261                                 stream.writeTwoBytes('\\', 't')
262                         default:
263                                 // This encodes bytes < 0x20 except for \t, \n and \r.
264                                 // If escapeHTML is set, it also escapes <, >, and &
265                                 // because they can lead to security holes when
266                                 // user-controlled strings are rendered into JSON
267                                 // and served to some browsers.
268                                 stream.WriteRaw(`\u00`)
269                                 stream.writeTwoBytes(hex[b>>4], hex[b&0xF])
270                         }
271                         i++
272                         start = i
273                         continue
274                 }
275                 c, size := utf8.DecodeRuneInString(s[i:])
276                 if c == utf8.RuneError && size == 1 {
277                         if start < i {
278                                 stream.WriteRaw(s[start:i])
279                         }
280                         stream.WriteRaw(`\ufffd`)
281                         i++
282                         start = i
283                         continue
284                 }
285                 // U+2028 is LINE SEPARATOR.
286                 // U+2029 is PARAGRAPH SEPARATOR.
287                 // They are both technically valid characters in JSON strings,
288                 // but don't work in JSONP, which has to be evaluated as JavaScript,
289                 // and can lead to security holes there. It is valid JSON to
290                 // escape them, so we do so unconditionally.
291                 // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
292                 if c == '\u2028' || c == '\u2029' {
293                         if start < i {
294                                 stream.WriteRaw(s[start:i])
295                         }
296                         stream.WriteRaw(`\u202`)
297                         stream.writeByte(hex[c&0xF])
298                         i += size
299                         start = i
300                         continue
301                 }
302                 i += size
303         }
304         if start < len(s) {
305                 stream.WriteRaw(s[start:])
306         }
307         stream.writeByte('"')
308 }
309
310 // WriteString write string to stream without html escape
311 func (stream *Stream) WriteString(s string) {
312         valLen := len(s)
313         stream.buf = append(stream.buf, '"')
314         // write string, the fast path, without utf8 and escape support
315         i := 0
316         for ; i < valLen; i++ {
317                 c := s[i]
318                 if c > 31 && c != '"' && c != '\\' {
319                         stream.buf = append(stream.buf, c)
320                 } else {
321                         break
322                 }
323         }
324         if i == valLen {
325                 stream.buf = append(stream.buf, '"')
326                 return
327         }
328         writeStringSlowPath(stream, i, s, valLen)
329 }
330
331 func writeStringSlowPath(stream *Stream, i int, s string, valLen int) {
332         start := i
333         // for the remaining parts, we process them char by char
334         for i < valLen {
335                 if b := s[i]; b < utf8.RuneSelf {
336                         if safeSet[b] {
337                                 i++
338                                 continue
339                         }
340                         if start < i {
341                                 stream.WriteRaw(s[start:i])
342                         }
343                         switch b {
344                         case '\\', '"':
345                                 stream.writeTwoBytes('\\', b)
346                         case '\n':
347                                 stream.writeTwoBytes('\\', 'n')
348                         case '\r':
349                                 stream.writeTwoBytes('\\', 'r')
350                         case '\t':
351                                 stream.writeTwoBytes('\\', 't')
352                         default:
353                                 // This encodes bytes < 0x20 except for \t, \n and \r.
354                                 // If escapeHTML is set, it also escapes <, >, and &
355                                 // because they can lead to security holes when
356                                 // user-controlled strings are rendered into JSON
357                                 // and served to some browsers.
358                                 stream.WriteRaw(`\u00`)
359                                 stream.writeTwoBytes(hex[b>>4], hex[b&0xF])
360                         }
361                         i++
362                         start = i
363                         continue
364                 }
365                 i++
366                 continue
367         }
368         if start < len(s) {
369                 stream.WriteRaw(s[start:])
370         }
371         stream.writeByte('"')
372 }