hex.go (3505B)
1 // Copyright 2016 Tom Thorogood. All rights reserved. 2 // Use of this source code is governed by a 3 // Modified BSD License license that can be found in 4 // the LICENSE file. 5 // 6 // Copyright 2009 The Go Authors. All rights reserved. 7 // Use of this source code is governed by a BSD-style 8 // license that can be found in the LICENSE file. 9 10 // Package hex is an efficient hexadecimal implementation for Golang. 11 package hex 12 13 import ( 14 "errors" 15 "fmt" 16 ) 17 18 var errLength = errors.New("go-hex: odd length hex string") 19 20 var ( 21 lower = []byte("0123456789abcdef") 22 upper = []byte("0123456789ABCDEF") 23 ) 24 25 // InvalidByteError values describe errors resulting from an invalid byte in a hex string. 26 type InvalidByteError byte 27 28 func (e InvalidByteError) Error() string { 29 return fmt.Sprintf("go-hex: invalid byte: %#U", rune(e)) 30 } 31 32 // EncodedLen returns the length of an encoding of n source bytes. 33 func EncodedLen(n int) int { 34 return n * 2 35 } 36 37 // DecodedLen returns the length of a decoding of n source bytes. 38 func DecodedLen(n int) int { 39 return n / 2 40 } 41 42 // Encode encodes src into EncodedLen(len(src)) 43 // bytes of dst. As a convenience, it returns the number 44 // of bytes written to dst, but this value is always EncodedLen(len(src)). 45 // Encode implements lowercase hexadecimal encoding. 46 func Encode(dst, src []byte) int { 47 return RawEncode(dst, src, lower) 48 } 49 50 // EncodeUpper encodes src into EncodedLen(len(src)) 51 // bytes of dst. As a convenience, it returns the number 52 // of bytes written to dst, but this value is always EncodedLen(len(src)). 53 // EncodeUpper implements uppercase hexadecimal encoding. 54 func EncodeUpper(dst, src []byte) int { 55 return RawEncode(dst, src, upper) 56 } 57 58 // EncodeToString returns the lowercase hexadecimal encoding of src. 59 func EncodeToString(src []byte) string { 60 return RawEncodeToString(src, lower) 61 } 62 63 // EncodeUpperToString returns the uppercase hexadecimal encoding of src. 64 func EncodeUpperToString(src []byte) string { 65 return RawEncodeToString(src, upper) 66 } 67 68 // RawEncodeToString returns the hexadecimal encoding of src for a given 69 // alphabet. 70 func RawEncodeToString(src, alpha []byte) string { 71 dst := make([]byte, EncodedLen(len(src))) 72 RawEncode(dst, src, alpha) 73 return string(dst) 74 } 75 76 // DecodeString returns the bytes represented by the hexadecimal string s. 77 func DecodeString(s string) ([]byte, error) { 78 src := []byte(s) 79 dst := make([]byte, DecodedLen(len(src))) 80 81 if _, err := Decode(dst, src); err != nil { 82 return nil, err 83 } 84 85 return dst, nil 86 } 87 88 // MustDecodeString is like DecodeString but panics if the string cannot be 89 // parsed. It simplifies safe initialization of global variables holding 90 // binary data. 91 func MustDecodeString(str string) []byte { 92 dst, err := DecodeString(str) 93 if err != nil { 94 panic(err) 95 } 96 97 return dst 98 } 99 100 func encodeGeneric(dst, src, alpha []byte) { 101 for i, v := range src { 102 dst[i*2] = alpha[v>>4] 103 dst[i*2+1] = alpha[v&0x0f] 104 } 105 } 106 107 func decodeGeneric(dst, src []byte) (uint64, bool) { 108 for i := 0; i < len(src)/2; i++ { 109 a, ok := fromHexChar(src[i*2]) 110 if !ok { 111 return uint64(i * 2), false 112 } 113 114 b, ok := fromHexChar(src[i*2+1]) 115 if !ok { 116 return uint64(i*2 + 1), false 117 } 118 119 dst[i] = (a << 4) | b 120 } 121 122 return 0, true 123 } 124 125 // fromHexChar converts a hex character into its value and a success flag. 126 func fromHexChar(c byte) (byte, bool) { 127 switch { 128 case '0' <= c && c <= '9': 129 return c - '0', true 130 case 'a' <= c && c <= 'f': 131 return c - 'a' + 10, true 132 case 'A' <= c && c <= 'F': 133 return c - 'A' + 10, true 134 } 135 136 return 0, false 137 }