...
1
2
3
4 package jwriter
5
6 import (
7 "encoding/json"
8 "io"
9 "strconv"
10 "unicode/utf8"
11 )
12
13
14
15
16
17
18
19 var (
20 tokenNull = []byte("null")
21 tokenTrue = []byte("true")
22 tokenFalse = []byte("false")
23 )
24
25 type tokenWriter struct {
26 buf streamableBuffer
27 tempBytes [50]byte
28 }
29
30 func newTokenWriter() tokenWriter {
31 return tokenWriter{}
32 }
33
34 func newStreamingTokenWriter(dest io.Writer, bufferSize int) tokenWriter {
35 tw := tokenWriter{}
36 tw.buf.Grow(bufferSize)
37 tw.buf.SetStreamingWriter(dest, bufferSize)
38 return tw
39 }
40
41
42
43
44
45 func (tw *tokenWriter) Bytes() []byte {
46 return tw.buf.Bytes()
47 }
48
49
50
51 func (tw *tokenWriter) Grow(n int) {
52 tw.buf.Grow(n)
53 }
54
55
56
57 func (tw *tokenWriter) Flush() error {
58 return tw.buf.Flush()
59 }
60
61
62 func (tw *tokenWriter) Null() error {
63 tw.buf.Write(tokenNull)
64 return tw.buf.GetWriterError()
65 }
66
67
68 func (tw *tokenWriter) Bool(value bool) error {
69 var out []byte
70 if value {
71 out = tokenTrue
72 } else {
73 out = tokenFalse
74 }
75 tw.buf.Write(out)
76 return tw.buf.GetWriterError()
77 }
78
79
80 func (tw *tokenWriter) Int(value int) error {
81 if value == 0 {
82 tw.buf.WriteByte('0')
83 } else {
84 out := tw.tempBytes[0:0]
85 out = strconv.AppendInt(out, int64(value), 10)
86 tw.buf.Write(out)
87 }
88 return tw.buf.GetWriterError()
89 }
90
91
92 func (tw *tokenWriter) Float64(value float64) error {
93 if value == 0 {
94 tw.buf.WriteByte('0')
95 } else {
96 i := int(value)
97 if float64(i) == value {
98 return tw.Int(i)
99 }
100 out := tw.tempBytes[0:0]
101 out = strconv.AppendFloat(out, value, 'g', -1, 64)
102 tw.buf.Write(out)
103 }
104 return tw.buf.GetWriterError()
105 }
106
107
108 func (tw *tokenWriter) String(value string) error {
109 return tw.writeQuotedString(value)
110 }
111
112
113 func (tw *tokenWriter) Raw(value json.RawMessage) error {
114 tw.buf.Write(value)
115 return tw.buf.GetWriterError()
116 }
117
118
119 func (tw *tokenWriter) PropertyName(name string) error {
120 if err := tw.String(name); err != nil {
121 return err
122 }
123 tw.buf.WriteByte(':')
124 return tw.buf.GetWriterError()
125 }
126
127
128 func (tw *tokenWriter) Delimiter(delimiter byte) error {
129 tw.buf.WriteByte(delimiter)
130 return tw.buf.GetWriterError()
131 }
132
133 func (tw *tokenWriter) writeQuotedString(s string) error {
134
135 tw.buf.WriteByte('"')
136 start := 0
137 for i := 0; i < len(s); {
138 aByte := s[i]
139 if aByte < ' ' || aByte == '"' || aByte == '\\' {
140 if i > start {
141 tw.buf.WriteString(s[start:i])
142 }
143 tw.writeEscapedChar(aByte)
144 i++
145 start = i
146 } else {
147 if aByte < utf8.RuneSelf {
148 i++
149 } else {
150 _, size := utf8.DecodeRuneInString(s[i:])
151 i += size
152 }
153 }
154 }
155 if start < len(s) {
156 tw.buf.WriteString(s[start:])
157 }
158 tw.buf.WriteByte('"')
159 return tw.buf.GetWriterError()
160 }
161
162 func (tw *tokenWriter) writeEscapedChar(ch byte) {
163 out := tw.tempBytes[0:2]
164 out[0] = '\\'
165 switch ch {
166 case '\b':
167 out[1] = 'b'
168 case '\t':
169 out[1] = 't'
170 case '\n':
171 out[1] = 'n'
172 case '\f':
173 out[1] = 'f'
174 case '\r':
175 out[1] = 'r'
176 case '"':
177 out[1] = '"'
178 case '\\':
179 out[1] = '\\'
180 default:
181 out[1] = 'u'
182 out = append(out, '0')
183 out = append(out, '0')
184 hexChars := make([]byte, 0, 4)
185 hexChars = strconv.AppendInt(hexChars, int64(ch), 16)
186 if len(hexChars) < 2 {
187 out = append(out, '0')
188 }
189 out = append(out, hexChars...)
190 }
191 tw.buf.Write(out)
192 }
193
View as plain text