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  }