blob: 4f883c0959f75ac4f0ebcd467d55c2c3f4f7aaf1 [file] [log] [blame]
sslobodrd046be82019-01-16 10:02:22 -05001package jsoniter
2
3import (
4 "encoding/json"
5 "io"
6 "math/big"
7 "strconv"
8 "strings"
9 "unsafe"
10)
11
12var floatDigits []int8
13
14const invalidCharForNumber = int8(-1)
15const endOfNumber = int8(-2)
16const dotInNumber = int8(-3)
17
18func init() {
19 floatDigits = make([]int8, 256)
20 for i := 0; i < len(floatDigits); i++ {
21 floatDigits[i] = invalidCharForNumber
22 }
23 for i := int8('0'); i <= int8('9'); i++ {
24 floatDigits[i] = i - int8('0')
25 }
26 floatDigits[','] = endOfNumber
27 floatDigits[']'] = endOfNumber
28 floatDigits['}'] = endOfNumber
29 floatDigits[' '] = endOfNumber
30 floatDigits['\t'] = endOfNumber
31 floatDigits['\n'] = endOfNumber
32 floatDigits['.'] = dotInNumber
33}
34
35// ReadBigFloat read big.Float
36func (iter *Iterator) ReadBigFloat() (ret *big.Float) {
37 str := iter.readNumberAsString()
38 if iter.Error != nil && iter.Error != io.EOF {
39 return nil
40 }
41 prec := 64
42 if len(str) > prec {
43 prec = len(str)
44 }
45 val, _, err := big.ParseFloat(str, 10, uint(prec), big.ToZero)
46 if err != nil {
47 iter.Error = err
48 return nil
49 }
50 return val
51}
52
53// ReadBigInt read big.Int
54func (iter *Iterator) ReadBigInt() (ret *big.Int) {
55 str := iter.readNumberAsString()
56 if iter.Error != nil && iter.Error != io.EOF {
57 return nil
58 }
59 ret = big.NewInt(0)
60 var success bool
61 ret, success = ret.SetString(str, 10)
62 if !success {
63 iter.ReportError("ReadBigInt", "invalid big int")
64 return nil
65 }
66 return ret
67}
68
69//ReadFloat32 read float32
70func (iter *Iterator) ReadFloat32() (ret float32) {
71 c := iter.nextToken()
72 if c == '-' {
73 return -iter.readPositiveFloat32()
74 }
75 iter.unreadByte()
76 return iter.readPositiveFloat32()
77}
78
79func (iter *Iterator) readPositiveFloat32() (ret float32) {
80 value := uint64(0)
81 c := byte(' ')
82 i := iter.head
83 // first char
84 if i == iter.tail {
85 return iter.readFloat32SlowPath()
86 }
87 c = iter.buf[i]
88 i++
89 ind := floatDigits[c]
90 switch ind {
91 case invalidCharForNumber:
92 return iter.readFloat32SlowPath()
93 case endOfNumber:
94 iter.ReportError("readFloat32", "empty number")
95 return
96 case dotInNumber:
97 iter.ReportError("readFloat32", "leading dot is invalid")
98 return
99 case 0:
100 if i == iter.tail {
101 return iter.readFloat32SlowPath()
102 }
103 c = iter.buf[i]
104 switch c {
105 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
106 iter.ReportError("readFloat32", "leading zero is invalid")
107 return
108 }
109 }
110 value = uint64(ind)
111 // chars before dot
112non_decimal_loop:
113 for ; i < iter.tail; i++ {
114 c = iter.buf[i]
115 ind := floatDigits[c]
116 switch ind {
117 case invalidCharForNumber:
118 return iter.readFloat32SlowPath()
119 case endOfNumber:
120 iter.head = i
121 return float32(value)
122 case dotInNumber:
123 break non_decimal_loop
124 }
125 if value > uint64SafeToMultiple10 {
126 return iter.readFloat32SlowPath()
127 }
128 value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
129 }
130 // chars after dot
131 if c == '.' {
132 i++
133 decimalPlaces := 0
134 if i == iter.tail {
135 return iter.readFloat32SlowPath()
136 }
137 for ; i < iter.tail; i++ {
138 c = iter.buf[i]
139 ind := floatDigits[c]
140 switch ind {
141 case endOfNumber:
142 if decimalPlaces > 0 && decimalPlaces < len(pow10) {
143 iter.head = i
144 return float32(float64(value) / float64(pow10[decimalPlaces]))
145 }
146 // too many decimal places
147 return iter.readFloat32SlowPath()
148 case invalidCharForNumber:
149 fallthrough
150 case dotInNumber:
151 return iter.readFloat32SlowPath()
152 }
153 decimalPlaces++
154 if value > uint64SafeToMultiple10 {
155 return iter.readFloat32SlowPath()
156 }
157 value = (value << 3) + (value << 1) + uint64(ind)
158 }
159 }
160 return iter.readFloat32SlowPath()
161}
162
163func (iter *Iterator) readNumberAsString() (ret string) {
164 strBuf := [16]byte{}
165 str := strBuf[0:0]
166load_loop:
167 for {
168 for i := iter.head; i < iter.tail; i++ {
169 c := iter.buf[i]
170 switch c {
171 case '+', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
172 str = append(str, c)
173 continue
174 default:
175 iter.head = i
176 break load_loop
177 }
178 }
179 if !iter.loadMore() {
180 break
181 }
182 }
183 if iter.Error != nil && iter.Error != io.EOF {
184 return
185 }
186 if len(str) == 0 {
187 iter.ReportError("readNumberAsString", "invalid number")
188 }
189 return *(*string)(unsafe.Pointer(&str))
190}
191
192func (iter *Iterator) readFloat32SlowPath() (ret float32) {
193 str := iter.readNumberAsString()
194 if iter.Error != nil && iter.Error != io.EOF {
195 return
196 }
197 errMsg := validateFloat(str)
198 if errMsg != "" {
199 iter.ReportError("readFloat32SlowPath", errMsg)
200 return
201 }
202 val, err := strconv.ParseFloat(str, 32)
203 if err != nil {
204 iter.Error = err
205 return
206 }
207 return float32(val)
208}
209
210// ReadFloat64 read float64
211func (iter *Iterator) ReadFloat64() (ret float64) {
212 c := iter.nextToken()
213 if c == '-' {
214 return -iter.readPositiveFloat64()
215 }
216 iter.unreadByte()
217 return iter.readPositiveFloat64()
218}
219
220func (iter *Iterator) readPositiveFloat64() (ret float64) {
221 value := uint64(0)
222 c := byte(' ')
223 i := iter.head
224 // first char
225 if i == iter.tail {
226 return iter.readFloat64SlowPath()
227 }
228 c = iter.buf[i]
229 i++
230 ind := floatDigits[c]
231 switch ind {
232 case invalidCharForNumber:
233 return iter.readFloat64SlowPath()
234 case endOfNumber:
235 iter.ReportError("readFloat64", "empty number")
236 return
237 case dotInNumber:
238 iter.ReportError("readFloat64", "leading dot is invalid")
239 return
240 case 0:
241 if i == iter.tail {
242 return iter.readFloat64SlowPath()
243 }
244 c = iter.buf[i]
245 switch c {
246 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
247 iter.ReportError("readFloat64", "leading zero is invalid")
248 return
249 }
250 }
251 value = uint64(ind)
252 // chars before dot
253non_decimal_loop:
254 for ; i < iter.tail; i++ {
255 c = iter.buf[i]
256 ind := floatDigits[c]
257 switch ind {
258 case invalidCharForNumber:
259 return iter.readFloat64SlowPath()
260 case endOfNumber:
261 iter.head = i
262 return float64(value)
263 case dotInNumber:
264 break non_decimal_loop
265 }
266 if value > uint64SafeToMultiple10 {
267 return iter.readFloat64SlowPath()
268 }
269 value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
270 }
271 // chars after dot
272 if c == '.' {
273 i++
274 decimalPlaces := 0
275 if i == iter.tail {
276 return iter.readFloat64SlowPath()
277 }
278 for ; i < iter.tail; i++ {
279 c = iter.buf[i]
280 ind := floatDigits[c]
281 switch ind {
282 case endOfNumber:
283 if decimalPlaces > 0 && decimalPlaces < len(pow10) {
284 iter.head = i
285 return float64(value) / float64(pow10[decimalPlaces])
286 }
287 // too many decimal places
288 return iter.readFloat64SlowPath()
289 case invalidCharForNumber:
290 fallthrough
291 case dotInNumber:
292 return iter.readFloat64SlowPath()
293 }
294 decimalPlaces++
295 if value > uint64SafeToMultiple10 {
296 return iter.readFloat64SlowPath()
297 }
298 value = (value << 3) + (value << 1) + uint64(ind)
299 }
300 }
301 return iter.readFloat64SlowPath()
302}
303
304func (iter *Iterator) readFloat64SlowPath() (ret float64) {
305 str := iter.readNumberAsString()
306 if iter.Error != nil && iter.Error != io.EOF {
307 return
308 }
309 errMsg := validateFloat(str)
310 if errMsg != "" {
311 iter.ReportError("readFloat64SlowPath", errMsg)
312 return
313 }
314 val, err := strconv.ParseFloat(str, 64)
315 if err != nil {
316 iter.Error = err
317 return
318 }
319 return val
320}
321
322func validateFloat(str string) string {
323 // strconv.ParseFloat is not validating `1.` or `1.e1`
324 if len(str) == 0 {
325 return "empty number"
326 }
327 if str[0] == '-' {
328 return "-- is not valid"
329 }
330 dotPos := strings.IndexByte(str, '.')
331 if dotPos != -1 {
332 if dotPos == len(str)-1 {
333 return "dot can not be last character"
334 }
335 switch str[dotPos+1] {
336 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
337 default:
338 return "missing digit after dot"
339 }
340 }
341 return ""
342}
343
344// ReadNumber read json.Number
345func (iter *Iterator) ReadNumber() (ret json.Number) {
346 return json.Number(iter.readNumberAsString())
347}