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  }