github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/parse/read/int.go (about) 1 package read 2 3 import ( 4 "strconv" 5 "errors" 6 "math" 7 "github.com/v2pro/plz/parse" 8 ) 9 10 var intDigits []int8 11 12 const invalidCharForNumber = int8(-1) 13 const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1 14 15 func init() { 16 intDigits = make([]int8, 256) 17 for i := 0; i < len(intDigits); i++ { 18 intDigits[i] = invalidCharForNumber 19 } 20 for i := int8('0'); i <= int8('9'); i++ { 21 intDigits[i] = i - int8('0') 22 } 23 } 24 25 func Int(src *parse.Source) int { 26 if strconv.IntSize == 32 { 27 return int(Int32(src)) 28 } 29 return int(Int64(src)) 30 } 31 32 func Int32(src *parse.Source) int32 { 33 c := src.Peek()[0] 34 if c == '-' { 35 src.ConsumeN(1) 36 val := Uint64(src) 37 if val > math.MaxInt32+1 { 38 src.ReportError(errors.New("int32: overflow")) 39 return 0 40 } 41 return -int32(val) 42 } 43 val := Uint64(src) 44 if val > math.MaxInt32 { 45 src.ReportError(errors.New("int32: overflow")) 46 return 0 47 } 48 return int32(val) 49 } 50 51 func Int64(src *parse.Source) int64 { 52 c := src.Peek()[0] 53 if c == '-' { 54 src.ConsumeN(1) 55 val := Uint64(src) 56 if val > math.MaxInt64+1 { 57 src.ReportError(errors.New("int64: overflow")) 58 return 0 59 } 60 return -int64(val) 61 } 62 val := Uint64(src) 63 if val > math.MaxInt64 { 64 src.ReportError(errors.New("int64: overflow")) 65 return 0 66 } 67 return int64(val) 68 } 69 70 func Uint64(src *parse.Source) uint64 { 71 value := uint64(0) 72 for src.Error() == nil { 73 buf := src.Peek() 74 for i, c := range buf { 75 ind := intDigits[c] 76 if ind == invalidCharForNumber { 77 src.ConsumeN(i) 78 return value 79 } 80 if value > uint64SafeToMultiple10 { 81 value2 := (value << 3) + (value << 1) + uint64(ind) 82 if value2 < value { 83 src.ReportError(errors.New("uint64: overflow")) 84 return 0 85 } 86 value = value2 87 continue 88 } 89 value = (value << 3) + (value << 1) + uint64(ind) 90 } 91 src.Consume() 92 } 93 return value 94 }