gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }