...

Source file src/github.com/json-iterator/go/iter_float.go

Documentation: github.com/json-iterator/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  			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  }
   343  

View as plain text