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 }