Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / json-iterator / go / iter_float.go
1 package jsoniter
2
3 import (
4         "encoding/json"
5         "io"
6         "math/big"
7         "strconv"
8         "strings"
9         "unsafe"
10 )
11
12 var floatDigits []int8
13
14 const invalidCharForNumber = int8(-1)
15 const endOfNumber = int8(-2)
16 const dotInNumber = int8(-3)
17
18 func 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
36 func (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
54 func (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
70 func (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
79 func (iter *Iterator) readPositiveFloat32() (ret float32) {
80         i := iter.head
81         // first char
82         if i == iter.tail {
83                 return iter.readFloat32SlowPath()
84         }
85         c := iter.buf[i]
86         i++
87         ind := floatDigits[c]
88         switch ind {
89         case invalidCharForNumber:
90                 return iter.readFloat32SlowPath()
91         case endOfNumber:
92                 iter.ReportError("readFloat32", "empty number")
93                 return
94         case dotInNumber:
95                 iter.ReportError("readFloat32", "leading dot is invalid")
96                 return
97         case 0:
98                 if i == iter.tail {
99                         return iter.readFloat32SlowPath()
100                 }
101                 c = iter.buf[i]
102                 switch c {
103                 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
104                         iter.ReportError("readFloat32", "leading zero is invalid")
105                         return
106                 }
107         }
108         value := uint64(ind)
109         // chars before dot
110 non_decimal_loop:
111         for ; i < iter.tail; i++ {
112                 c = iter.buf[i]
113                 ind := floatDigits[c]
114                 switch ind {
115                 case invalidCharForNumber:
116                         return iter.readFloat32SlowPath()
117                 case endOfNumber:
118                         iter.head = i
119                         return float32(value)
120                 case dotInNumber:
121                         break non_decimal_loop
122                 }
123                 if value > uint64SafeToMultiple10 {
124                         return iter.readFloat32SlowPath()
125                 }
126                 value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
127         }
128         // chars after dot
129         if c == '.' {
130                 i++
131                 decimalPlaces := 0
132                 if i == iter.tail {
133                         return iter.readFloat32SlowPath()
134                 }
135                 for ; i < iter.tail; i++ {
136                         c = iter.buf[i]
137                         ind := floatDigits[c]
138                         switch ind {
139                         case endOfNumber:
140                                 if decimalPlaces > 0 && decimalPlaces < len(pow10) {
141                                         iter.head = i
142                                         return float32(float64(value) / float64(pow10[decimalPlaces]))
143                                 }
144                                 // too many decimal places
145                                 return iter.readFloat32SlowPath()
146                         case invalidCharForNumber, dotInNumber:
147                                 return iter.readFloat32SlowPath()
148                         }
149                         decimalPlaces++
150                         if value > uint64SafeToMultiple10 {
151                                 return iter.readFloat32SlowPath()
152                         }
153                         value = (value << 3) + (value << 1) + uint64(ind)
154                 }
155         }
156         return iter.readFloat32SlowPath()
157 }
158
159 func (iter *Iterator) readNumberAsString() (ret string) {
160         strBuf := [16]byte{}
161         str := strBuf[0:0]
162 load_loop:
163         for {
164                 for i := iter.head; i < iter.tail; i++ {
165                         c := iter.buf[i]
166                         switch c {
167                         case '+', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
168                                 str = append(str, c)
169                                 continue
170                         default:
171                                 iter.head = i
172                                 break load_loop
173                         }
174                 }
175                 if !iter.loadMore() {
176                         break
177                 }
178         }
179         if iter.Error != nil && iter.Error != io.EOF {
180                 return
181         }
182         if len(str) == 0 {
183                 iter.ReportError("readNumberAsString", "invalid number")
184         }
185         return *(*string)(unsafe.Pointer(&str))
186 }
187
188 func (iter *Iterator) readFloat32SlowPath() (ret float32) {
189         str := iter.readNumberAsString()
190         if iter.Error != nil && iter.Error != io.EOF {
191                 return
192         }
193         errMsg := validateFloat(str)
194         if errMsg != "" {
195                 iter.ReportError("readFloat32SlowPath", errMsg)
196                 return
197         }
198         val, err := strconv.ParseFloat(str, 32)
199         if err != nil {
200                 iter.Error = err
201                 return
202         }
203         return float32(val)
204 }
205
206 // ReadFloat64 read float64
207 func (iter *Iterator) ReadFloat64() (ret float64) {
208         c := iter.nextToken()
209         if c == '-' {
210                 return -iter.readPositiveFloat64()
211         }
212         iter.unreadByte()
213         return iter.readPositiveFloat64()
214 }
215
216 func (iter *Iterator) readPositiveFloat64() (ret float64) {
217         i := iter.head
218         // first char
219         if i == iter.tail {
220                 return iter.readFloat64SlowPath()
221         }
222         c := iter.buf[i]
223         i++
224         ind := floatDigits[c]
225         switch ind {
226         case invalidCharForNumber:
227                 return iter.readFloat64SlowPath()
228         case endOfNumber:
229                 iter.ReportError("readFloat64", "empty number")
230                 return
231         case dotInNumber:
232                 iter.ReportError("readFloat64", "leading dot is invalid")
233                 return
234         case 0:
235                 if i == iter.tail {
236                         return iter.readFloat64SlowPath()
237                 }
238                 c = iter.buf[i]
239                 switch c {
240                 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
241                         iter.ReportError("readFloat64", "leading zero is invalid")
242                         return
243                 }
244         }
245         value := uint64(ind)
246         // chars before dot
247 non_decimal_loop:
248         for ; i < iter.tail; i++ {
249                 c = iter.buf[i]
250                 ind := floatDigits[c]
251                 switch ind {
252                 case invalidCharForNumber:
253                         return iter.readFloat64SlowPath()
254                 case endOfNumber:
255                         iter.head = i
256                         return float64(value)
257                 case dotInNumber:
258                         break non_decimal_loop
259                 }
260                 if value > uint64SafeToMultiple10 {
261                         return iter.readFloat64SlowPath()
262                 }
263                 value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
264         }
265         // chars after dot
266         if c == '.' {
267                 i++
268                 decimalPlaces := 0
269                 if i == iter.tail {
270                         return iter.readFloat64SlowPath()
271                 }
272                 for ; i < iter.tail; i++ {
273                         c = iter.buf[i]
274                         ind := floatDigits[c]
275                         switch ind {
276                         case endOfNumber:
277                                 if decimalPlaces > 0 && decimalPlaces < len(pow10) {
278                                         iter.head = i
279                                         return float64(value) / float64(pow10[decimalPlaces])
280                                 }
281                                 // too many decimal places
282                                 return iter.readFloat64SlowPath()
283                         case invalidCharForNumber, dotInNumber:
284                                 return iter.readFloat64SlowPath()
285                         }
286                         decimalPlaces++
287                         if value > uint64SafeToMultiple10 {
288                                 return iter.readFloat64SlowPath()
289                         }
290                         value = (value << 3) + (value << 1) + uint64(ind)
291                 }
292         }
293         return iter.readFloat64SlowPath()
294 }
295
296 func (iter *Iterator) readFloat64SlowPath() (ret float64) {
297         str := iter.readNumberAsString()
298         if iter.Error != nil && iter.Error != io.EOF {
299                 return
300         }
301         errMsg := validateFloat(str)
302         if errMsg != "" {
303                 iter.ReportError("readFloat64SlowPath", errMsg)
304                 return
305         }
306         val, err := strconv.ParseFloat(str, 64)
307         if err != nil {
308                 iter.Error = err
309                 return
310         }
311         return val
312 }
313
314 func validateFloat(str string) string {
315         // strconv.ParseFloat is not validating `1.` or `1.e1`
316         if len(str) == 0 {
317                 return "empty number"
318         }
319         if str[0] == '-' {
320                 return "-- is not valid"
321         }
322         dotPos := strings.IndexByte(str, '.')
323         if dotPos != -1 {
324                 if dotPos == len(str)-1 {
325                         return "dot can not be last character"
326                 }
327                 switch str[dotPos+1] {
328                 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
329                 default:
330                         return "missing digit after dot"
331                 }
332         }
333         return ""
334 }
335
336 // ReadNumber read json.Number
337 func (iter *Iterator) ReadNumber() (ret json.Number) {
338         return json.Number(iter.readNumberAsString())
339 }