github.com/chain5j/chain5j-pkg@v1.0.7/util/hexutil/hexutil.go (about)

     1  // Copyright 2016 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  /*
    18  Package hexutil implements hex encoding with 0x prefix.
    19  This encoding is used by the Ethereum RPC API to transport binary data in JSON payloads.
    20  
    21  Encoding Rules
    22  
    23  All hex data must have prefix "0x".
    24  
    25  For byte slices, the hex data must be of even length. An empty byte slice
    26  encodes as "0x".
    27  
    28  Integers are encoded using the least amount of digits (no leading zero digits). Their
    29  encoding may be of uneven length. The number zero encodes as "0x0".
    30  */
    31  package hexutil
    32  
    33  import (
    34  	"encoding/hex"
    35  	"fmt"
    36  	"math"
    37  	"math/big"
    38  	"strconv"
    39  	"strings"
    40  )
    41  
    42  const uintBits = 32 << (uint64(^uint(0)) >> 63)
    43  
    44  // Errors
    45  var (
    46  	ErrEmptyString   = &decError{"empty hex string"}
    47  	ErrSyntax        = &decError{"invalid hex string"}
    48  	ErrMissingPrefix = &decError{"hex string without 0x prefix"}
    49  	ErrOddLength     = &decError{"hex string of odd length"}
    50  	ErrEmptyNumber   = &decError{"hex string \"0x\""}
    51  	ErrLeadingZero   = &decError{"hex number with leading zero digits"}
    52  	ErrUint64Range   = &decError{"hex number > 64 bits"}
    53  	ErrUintRange     = &decError{fmt.Sprintf("hex number > %d bits", uintBits)}
    54  	ErrBig256Range   = &decError{"hex number > 256 bits"}
    55  )
    56  
    57  type decError struct{ msg string }
    58  
    59  func (err decError) Error() string { return err.msg }
    60  
    61  // Decode decodes a hex string with 0x prefix.
    62  func Decode(input string) ([]byte, error) {
    63  	if len(input) == 0 {
    64  		return nil, ErrEmptyString
    65  	}
    66  	var tHex string
    67  	if !HasHexPrefix(input) {
    68  		tHex = input
    69  	} else {
    70  		tHex = input[2:]
    71  	}
    72  	if len(tHex)%2 == 1 {
    73  		tHex = "0" + tHex
    74  	}
    75  	b, err := hex.DecodeString(tHex)
    76  	if err != nil {
    77  		err = mapError(err)
    78  	}
    79  	return b, err
    80  }
    81  
    82  // MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
    83  func MustDecode(input string) []byte {
    84  	dec, err := Decode(input)
    85  	if err != nil {
    86  		panic(err)
    87  	}
    88  	return dec
    89  }
    90  
    91  // Encode encodes b as a hex string with 0x prefix.
    92  func Encode(b []byte) string {
    93  	if len(b) == 0 {
    94  		return ""
    95  	}
    96  	enc := make([]byte, len(b)*2+2)
    97  	copy(enc, "0x")
    98  	hex.Encode(enc[2:], b)
    99  	return string(enc)
   100  }
   101  
   102  func EncodeNoPrefix(b []byte) string {
   103  	if len(b) == 0 {
   104  		return ""
   105  	}
   106  	return hex.EncodeToString(b)
   107  }
   108  
   109  // DecodeUint64 decodes a hex string with 0x prefix as a quantity.
   110  func DecodeUint64(input string) (uint64, error) {
   111  	raw, err := checkNumber(input)
   112  	if err != nil {
   113  		return 0, err
   114  	}
   115  	dec, err := strconv.ParseUint(raw, 16, 64)
   116  	if err != nil {
   117  		err = mapError(err)
   118  	}
   119  	return dec, err
   120  }
   121  
   122  // MustDecodeUint64 decodes a hex string with 0x prefix as a quantity.
   123  // It panics for invalid input.
   124  func MustDecodeUint64(input string) uint64 {
   125  	dec, err := DecodeUint64(input)
   126  	if err != nil {
   127  		panic(err)
   128  	}
   129  	return dec
   130  }
   131  
   132  // EncodeUint64 encodes i as a hex string with 0x prefix.
   133  func EncodeUint64(i uint64) string {
   134  	enc := make([]byte, 2, 10)
   135  	copy(enc, "0x")
   136  	return string(strconv.AppendUint(enc, i, 16))
   137  }
   138  
   139  var bigWordNibbles int
   140  
   141  func init() {
   142  	// This is a weird way to compute the number of nibbles required for big.Word.
   143  	// The usual way would be to use constant arithmetic but go vet can't handle that.
   144  	b, _ := new(big.Int).SetString("FFFFFFFFFF", 16)
   145  	switch len(b.Bits()) {
   146  	case 1:
   147  		bigWordNibbles = 16
   148  	case 2:
   149  		bigWordNibbles = 8
   150  	default:
   151  		panic("weird big.Word size")
   152  	}
   153  }
   154  
   155  // DecodeBig decodes a hex string with 0x prefix as a quantity.
   156  // Numbers larger than 256 bits are not accepted.
   157  func DecodeBig(input string) (*big.Int, error) {
   158  	raw, err := checkNumber(input)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  	if len(raw) > 64 {
   163  		return nil, ErrBig256Range
   164  	}
   165  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   166  	end := len(raw)
   167  	for i := range words {
   168  		start := end - bigWordNibbles
   169  		if start < 0 {
   170  			start = 0
   171  		}
   172  		for ri := start; ri < end; ri++ {
   173  			nib := decodeNibble(raw[ri])
   174  			if nib == badNibble {
   175  				return nil, ErrSyntax
   176  			}
   177  			words[i] *= 16
   178  			words[i] += big.Word(nib)
   179  		}
   180  		end = start
   181  	}
   182  	dec := new(big.Int).SetBits(words)
   183  	return dec, nil
   184  }
   185  
   186  // MustDecodeBig decodes a hex string with 0x prefix as a quantity.
   187  // It panics for invalid input.
   188  func MustDecodeBig(input string) *big.Int {
   189  	dec, err := DecodeBig(input)
   190  	if err != nil {
   191  		panic(err)
   192  	}
   193  	return dec
   194  }
   195  
   196  // EncodeBig encodes bigint as a hex string with 0x prefix.
   197  // The sign of the integer is ignored.
   198  func EncodeBig(bigint *big.Int) string {
   199  	nbits := bigint.BitLen()
   200  	if nbits == 0 {
   201  		return "0x0"
   202  	}
   203  	return fmt.Sprintf("%#x", bigint)
   204  }
   205  
   206  // HasHexPrefix validates str begins with '0x' or '0X'.
   207  func HasHexPrefix(input string) bool {
   208  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   209  }
   210  
   211  // IsHexCharacter returns bool of c being a valid hexadecimal.
   212  func IsHexCharacter(c byte) bool {
   213  	return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
   214  }
   215  
   216  // IsHex validates whether each byte is valid hexadecimal string.
   217  func IsHex(str string) bool {
   218  	if len(str)%2 != 0 {
   219  		return false
   220  	}
   221  	str = RemoveHexPrefix(str)
   222  	for _, c := range []byte(str) {
   223  		if !IsHexCharacter(c) {
   224  			return false
   225  		}
   226  	}
   227  	return true
   228  }
   229  
   230  func checkNumber(input string) (raw string, err error) {
   231  	if len(input) == 0 {
   232  		return "", ErrEmptyString
   233  	}
   234  	if HasHexPrefix(input) {
   235  		input = input[2:]
   236  	}
   237  	if len(input) == 0 {
   238  		return "", ErrEmptyNumber
   239  	}
   240  	if len(input) > 1 && input[0] == '0' {
   241  		return "", ErrLeadingZero
   242  	}
   243  	return input, nil
   244  }
   245  
   246  const badNibble = ^uint64(0)
   247  
   248  func decodeNibble(in byte) uint64 {
   249  	switch {
   250  	case in >= '0' && in <= '9':
   251  		return uint64(in - '0')
   252  	case in >= 'A' && in <= 'F':
   253  		return uint64(in - 'A' + 10)
   254  	case in >= 'a' && in <= 'f':
   255  		return uint64(in - 'a' + 10)
   256  	default:
   257  		return badNibble
   258  	}
   259  }
   260  
   261  func mapError(err error) error {
   262  	if err, ok := err.(*strconv.NumError); ok {
   263  		switch err.Err {
   264  		case strconv.ErrRange:
   265  			return ErrUint64Range
   266  		case strconv.ErrSyntax:
   267  			return ErrSyntax
   268  		}
   269  	}
   270  	if _, ok := err.(hex.InvalidByteError); ok {
   271  		return ErrSyntax
   272  	}
   273  	if err == hex.ErrLength {
   274  		return ErrOddLength
   275  	}
   276  	return err
   277  }
   278  
   279  var tenToAny map[int]string = map[int]string{0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7", 8: "8", 9: "9", 10: "a", 11: "b", 12: "c", 13: "d", 14: "e", 15: "f", 16: "g", 17: "h", 18: "i", 19: "j", 20: "k", 21: "l", 22: "m", 23: "n", 24: "o", 25: "p", 26: "q", 27: "r", 28: "s", 29: "t", 30: "u", 31: "v", 32: "w", 33: "x", 34: "y", 35: "z", 36: ":", 37: ";", 38: "<", 39: "=", 40: ">", 41: "?", 42: "@", 43: "[", 44: "]", 45: "^", 46: "_", 47: "{", 48: "|", 49: "}", 50: "A", 51: "B", 52: "C", 53: "D", 54: "E", 55: "F", 56: "G", 57: "H", 58: "I", 59: "J", 60: "K", 61: "L", 62: "M", 63: "N", 64: "O", 65: "P", 66: "Q", 67: "R", 68: "S", 69: "T", 70: "U", 71: "V", 72: "W", 73: "X", 74: "Y", 75: "Z"}
   280  
   281  // DecimalToAny 10进制转任意进制
   282  func DecimalToAny(num, n int) string {
   283  	new_num_str := ""
   284  	var remainder int
   285  	var remainder_string string
   286  	for num != 0 {
   287  		remainder = num % n
   288  		if 76 > remainder && remainder > 9 {
   289  			remainder_string = tenToAny[remainder]
   290  		} else {
   291  			remainder_string = strconv.Itoa(remainder)
   292  		}
   293  		new_num_str = remainder_string + new_num_str
   294  		num = num / n
   295  	}
   296  	return new_num_str
   297  }
   298  
   299  // map根据value找key
   300  func findkey(in string) int {
   301  	result := -1
   302  	for k, v := range tenToAny {
   303  		if in == v {
   304  			result = k
   305  		}
   306  	}
   307  	return result
   308  }
   309  
   310  // AnyToDecimal 任意进制转10进制
   311  func AnyToDecimal(num string, n int) int {
   312  	var newNum float64
   313  	newNum = 0.0
   314  	nNum := len(strings.Split(num, "")) - 1
   315  	for _, value := range strings.Split(num, "") {
   316  		tmp := float64(findkey(value))
   317  		if tmp != -1 {
   318  			newNum = newNum + tmp*math.Pow(float64(n), float64(nNum))
   319  			nNum = nNum - 1
   320  		} else {
   321  			break
   322  		}
   323  	}
   324  	return int(newNum)
   325  }
   326  
   327  func RemoveHexPrefix(str string) string {
   328  	if HasHexPrefix(str) {
   329  		return str[2:]
   330  	}
   331  	return str
   332  }