13 // Taken from Go's encoding/json and modified for use here.
15 // Copyright 2010 The Go Authors. All rights reserved.
16 // Use of this source code is governed by a BSD-style
17 // license that can be found in the LICENSE file.
19 var hex = "0123456789abcdef"
21 var bufferPool = sync.Pool{
22 New: func() interface{} {
23 return &bytes.Buffer{}
27 func getBuffer() *bytes.Buffer {
28 return bufferPool.Get().(*bytes.Buffer)
31 func poolBuffer(buf *bytes.Buffer) {
36 // NOTE: keep in sync with writeQuotedBytes below.
37 func writeQuotedString(w io.Writer, s string) (int, error) {
41 for i := 0; i < len(s); {
42 if b := s[i]; b < utf8.RuneSelf {
43 if 0x20 <= b && b != '\\' && b != '"' {
48 buf.WriteString(s[start:i])
64 // This encodes bytes < 0x20 except for \n, \r, and \t.
65 buf.WriteString(`\u00`)
66 buf.WriteByte(hex[b>>4])
67 buf.WriteByte(hex[b&0xF])
73 c, size := utf8.DecodeRuneInString(s[i:])
74 if c == utf8.RuneError {
76 buf.WriteString(s[start:i])
78 buf.WriteString(`\ufffd`)
86 buf.WriteString(s[start:])
89 n, err := w.Write(buf.Bytes())
94 // NOTE: keep in sync with writeQuoteString above.
95 func writeQuotedBytes(w io.Writer, s []byte) (int, error) {
99 for i := 0; i < len(s); {
100 if b := s[i]; b < utf8.RuneSelf {
101 if 0x20 <= b && b != '\\' && b != '"' {
106 buf.Write(s[start:i])
122 // This encodes bytes < 0x20 except for \n, \r, and \t.
123 buf.WriteString(`\u00`)
124 buf.WriteByte(hex[b>>4])
125 buf.WriteByte(hex[b&0xF])
131 c, size := utf8.DecodeRune(s[i:])
132 if c == utf8.RuneError {
134 buf.Write(s[start:i])
136 buf.WriteString(`\ufffd`)
147 n, err := w.Write(buf.Bytes())
152 // getu4 decodes \uXXXX from the beginning of s, returning the hex value,
154 func getu4(s []byte) rune {
155 if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
158 r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
165 func unquoteBytes(s []byte) (t []byte, ok bool) {
166 if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
171 // Check for unusual characters. If there are none,
172 // then no unquoting is needed, so return a slice of the
177 if c == '\\' || c == '"' || c < ' ' {
180 if c < utf8.RuneSelf {
184 rr, size := utf8.DecodeRune(s[r:])
185 if rr == utf8.RuneError {
194 b := make([]byte, len(s)+2*utf8.UTFMax)
197 // Out of room? Can only happen if s is full of
198 // malformed UTF-8 and we're replacing each
199 // byte with RuneError.
200 if w >= len(b)-2*utf8.UTFMax {
201 nb := make([]byte, (len(b)+utf8.UTFMax)*2)
214 case '"', '\\', '/', '\'':
245 if utf16.IsSurrogate(rr) {
247 if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
248 // A valid pair; consume.
250 w += utf8.EncodeRune(b[w:], dec)
253 // Invalid surrogate; fall back to replacement rune.
254 rr = unicode.ReplacementChar
256 w += utf8.EncodeRune(b[w:], rr)
259 // Quote, control characters are invalid.
260 case c == '"', c < ' ':
264 case c < utf8.RuneSelf:
269 // Coerce to well-formed UTF-8.
271 rr, size := utf8.DecodeRune(s[r:])
273 w += utf8.EncodeRune(b[w:], rr)