github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/iterator_int64.go (about)

     1  package jzon
     2  
     3  import (
     4  	"io"
     5  	"math"
     6  	"strconv"
     7  )
     8  
     9  const (
    10  	maxUint64Div10NumDigits = 19
    11  	maxUint64Div10          = uint64(math.MaxUint64) / 10
    12  	maxUint64Mod10          = int8(math.MaxUint64 - maxUint64Div10*10)
    13  )
    14  
    15  // ReadUint64 reads an uint64 value
    16  func (it *Iterator) ReadUint64() (uint64, error) {
    17  	c, err := it.nextToken()
    18  	if err != nil {
    19  		return 0, err
    20  	}
    21  	it.head++
    22  	return it.readUint64(c)
    23  }
    24  
    25  func (it *Iterator) readUint64(c byte) (ret uint64, err error) {
    26  	u := intDigits[c]
    27  	if u == 0 {
    28  		return 0, nil
    29  	}
    30  	if u == invalidDigit {
    31  		return 0, InvalidDigitError{c: c}
    32  	}
    33  	ret = uint64(u)
    34  	numDigit := 1
    35  	// TODO: inline expansion
    36  	for {
    37  		i := it.head
    38  		for ; i < it.tail; i++ {
    39  			digit := intDigits[it.buffer[i]]
    40  			if digit == invalidDigit {
    41  				it.head = i
    42  				return ret, nil
    43  			}
    44  			if numDigit >= maxUint64Div10NumDigits {
    45  				if ret > maxUint64Div10 ||
    46  					(ret == maxUint64Div10 && digit > maxUint64Mod10) {
    47  					it.head = i
    48  					err = IntOverflowError{}
    49  					return
    50  				}
    51  			}
    52  			ret = (ret << 3) + (ret << 1) + uint64(digit)
    53  			numDigit++
    54  		}
    55  		it.head = i
    56  		if err = it.readMore(); err != nil {
    57  			if err == io.EOF {
    58  				err = nil
    59  			}
    60  			return
    61  		}
    62  	}
    63  }
    64  
    65  func (it *Iterator) readInt64(c byte) (int64, error) {
    66  	if c == '-' {
    67  		c, err := it.nextByte()
    68  		if err != nil {
    69  			return 0, err
    70  		}
    71  		it.head++
    72  		v, err := it.readUint64(c)
    73  		if err != nil {
    74  			return 0, err
    75  		}
    76  		if v > math.MaxInt64+1 {
    77  			return 0, IntOverflowError{
    78  				typ:   "int64",
    79  				value: "-" + strconv.FormatUint(uint64(v), 10),
    80  			}
    81  		}
    82  		return -int64(v), nil
    83  	}
    84  	v, err := it.readUint64(c)
    85  	if err != nil {
    86  		return 0, err
    87  	}
    88  	if v > math.MaxInt64 {
    89  		return 0, IntOverflowError{
    90  			typ:   "int64",
    91  			value: strconv.FormatUint(uint64(v), 10),
    92  		}
    93  	}
    94  	return int64(v), nil
    95  }
    96  
    97  // ReadInt64 reads an int64 value
    98  func (it *Iterator) ReadInt64() (int64, error) {
    99  	c, err := it.nextToken()
   100  	if err != nil {
   101  		return 0, err
   102  	}
   103  	it.head++
   104  	return it.readInt64(c)
   105  }