github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/common/math/integer.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package math 18 19 import ( 20 "fmt" 21 "strconv" 22 ) 23 24 // Integer limit values. 25 const ( 26 MaxInt8 = 1<<7 - 1 27 MinInt8 = -1 << 7 28 MaxInt16 = 1<<15 - 1 29 MinInt16 = -1 << 15 30 MaxInt32 = 1<<31 - 1 31 MinInt32 = -1 << 31 32 MaxInt64 = 1<<63 - 1 33 MinInt64 = -1 << 63 34 MaxUint8 = 1<<8 - 1 35 MaxUint16 = 1<<16 - 1 36 MaxUint32 = 1<<32 - 1 37 MaxUint64 = 1<<64 - 1 38 ) 39 40 // HexOrDecimal64 marshals uint64 as hex or decimal. 41 type HexOrDecimal64 uint64 42 43 // UnmarshalText implements encoding.TextUnmarshaler. 44 func (i *HexOrDecimal64) UnmarshalText(input []byte) error { 45 int, ok := ParseUint64(string(input)) 46 if !ok { 47 return fmt.Errorf("invalid hex or decimal integer %q", input) 48 } 49 *i = HexOrDecimal64(int) 50 return nil 51 } 52 53 // MarshalText implements encoding.TextMarshaler. 54 func (i HexOrDecimal64) MarshalText() ([]byte, error) { 55 return []byte(fmt.Sprintf("%#x", uint64(i))), nil 56 } 57 58 // ParseUint64 parses s as an integer in decimal or hexadecimal syntax. 59 // Leading zeros are accepted. The empty string parses as zero. 60 func ParseUint64(s string) (uint64, bool) { 61 if s == "" { 62 return 0, true 63 } 64 if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { 65 v, err := strconv.ParseUint(s[2:], 16, 64) 66 return v, err == nil 67 } 68 v, err := strconv.ParseUint(s, 10, 64) 69 return v, err == nil 70 } 71 72 // MustParseUint64 parses s as an integer and panics if the string is invalid. 73 func MustParseUint64(s string) uint64 { 74 v, ok := ParseUint64(s) 75 if !ok { 76 panic("invalid unsigned 64 bit integer: " + s) 77 } 78 return v 79 } 80 81 // NOTE: The following methods need to be optimised using either bit checking or asm 82 83 // SafeSub returns subtraction result and whether overflow occurred. 84 func SafeSub(x, y uint64) (uint64, bool) { 85 return x - y, x < y 86 } 87 88 // SafeAdd returns the result and whether overflow occurred. 89 func SafeAdd(x, y uint64) (uint64, bool) { 90 return x + y, y > MaxUint64-x 91 } 92 93 // SafeMul returns multiplication result and whether overflow occurred. 94 func SafeMul(x, y uint64) (uint64, bool) { 95 if x == 0 || y == 0 { 96 return 0, false 97 } 98 return x * y, y > MaxUint64/x 99 }