iter_float.go (7641B)
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 if value > maxFloat64 { 292 return iter.readFloat64SlowPath() 293 } 294 } 295 } 296 return iter.readFloat64SlowPath() 297 } 298 299 func (iter *Iterator) readFloat64SlowPath() (ret float64) { 300 str := iter.readNumberAsString() 301 if iter.Error != nil && iter.Error != io.EOF { 302 return 303 } 304 errMsg := validateFloat(str) 305 if errMsg != "" { 306 iter.ReportError("readFloat64SlowPath", errMsg) 307 return 308 } 309 val, err := strconv.ParseFloat(str, 64) 310 if err != nil { 311 iter.Error = err 312 return 313 } 314 return val 315 } 316 317 func validateFloat(str string) string { 318 // strconv.ParseFloat is not validating `1.` or `1.e1` 319 if len(str) == 0 { 320 return "empty number" 321 } 322 if str[0] == '-' { 323 return "-- is not valid" 324 } 325 dotPos := strings.IndexByte(str, '.') 326 if dotPos != -1 { 327 if dotPos == len(str)-1 { 328 return "dot can not be last character" 329 } 330 switch str[dotPos+1] { 331 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 332 default: 333 return "missing digit after dot" 334 } 335 } 336 return "" 337 } 338 339 // ReadNumber read json.Number 340 func (iter *Iterator) ReadNumber() (ret json.Number) { 341 return json.Number(iter.readNumberAsString()) 342 }