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