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 }