github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/encoding/hex/hex.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package hex implements hexadecimal encoding and decoding. 6 package hex 7 8 import ( 9 "bytes" 10 "errors" 11 "fmt" 12 "io" 13 ) 14 15 const hextable = "0123456789abcdef" 16 17 // EncodedLen returns the length of an encoding of n source bytes. 18 // Specifically, it returns n * 2. 19 func EncodedLen(n int) int { return n * 2 } 20 21 // Encode encodes src into EncodedLen(len(src)) 22 // bytes of dst. As a convenience, it returns the number 23 // of bytes written to dst, but this value is always EncodedLen(len(src)). 24 // Encode implements hexadecimal encoding. 25 func Encode(dst, src []byte) int { 26 for i, v := range src { 27 dst[i*2] = hextable[v>>4] 28 dst[i*2+1] = hextable[v&0x0f] 29 } 30 31 return len(src) * 2 32 } 33 34 // ErrLength results from decoding an odd length slice. 35 var ErrLength = errors.New("encoding/hex: odd length hex string") 36 37 // InvalidByteError values describe errors resulting from an invalid byte in a hex string. 38 type InvalidByteError byte 39 40 func (e InvalidByteError) Error() string { 41 return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e)) 42 } 43 44 // DecodedLen returns the length of a decoding of x source bytes. 45 // Specifically, it returns x / 2. 46 func DecodedLen(x int) int { return x / 2 } 47 48 // Decode decodes src into DecodedLen(len(src)) bytes, 49 // returning the actual number of bytes written to dst. 50 // 51 // Decode expects that src contain only hexadecimal 52 // characters and that src should have an even length. 53 func Decode(dst, src []byte) (int, error) { 54 if len(src)%2 == 1 { 55 return 0, ErrLength 56 } 57 58 for i := 0; i < len(src)/2; i++ { 59 a, ok := fromHexChar(src[i*2]) 60 if !ok { 61 return i, InvalidByteError(src[i*2]) 62 } 63 b, ok := fromHexChar(src[i*2+1]) 64 if !ok { 65 return i, InvalidByteError(src[i*2+1]) 66 } 67 dst[i] = (a << 4) | b 68 } 69 70 return len(src) / 2, nil 71 } 72 73 // fromHexChar converts a hex character into its value and a success flag. 74 func fromHexChar(c byte) (byte, bool) { 75 switch { 76 case '0' <= c && c <= '9': 77 return c - '0', true 78 case 'a' <= c && c <= 'f': 79 return c - 'a' + 10, true 80 case 'A' <= c && c <= 'F': 81 return c - 'A' + 10, true 82 } 83 84 return 0, false 85 } 86 87 // EncodeToString returns the hexadecimal encoding of src. 88 func EncodeToString(src []byte) string { 89 dst := make([]byte, EncodedLen(len(src))) 90 Encode(dst, src) 91 return string(dst) 92 } 93 94 // DecodeString returns the bytes represented by the hexadecimal string s. 95 func DecodeString(s string) ([]byte, error) { 96 src := []byte(s) 97 // We can use the source slice itself as the destination 98 // because the decode loop increments by one and then the 'seen' byte is not used anymore. 99 len, err := Decode(src, src) 100 if err != nil { 101 return nil, err 102 } 103 return src[:len], nil 104 } 105 106 // Dump returns a string that contains a hex dump of the given data. The format 107 // of the hex dump matches the output of `hexdump -C` on the command line. 108 func Dump(data []byte) string { 109 var buf bytes.Buffer 110 dumper := Dumper(&buf) 111 dumper.Write(data) 112 dumper.Close() 113 return buf.String() 114 } 115 116 // bufferSize is the number of hexadecimal characters to buffer in encoder and decoder. 117 const bufferSize = 1024 118 119 type encoder struct { 120 w io.Writer 121 err error 122 out [bufferSize]byte // output buffer 123 } 124 125 // NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w. 126 func NewEncoder(w io.Writer) io.Writer { 127 return &encoder{w: w} 128 } 129 130 func (e *encoder) Write(p []byte) (n int, err error) { 131 for len(p) > 0 && e.err == nil { 132 chunkSize := bufferSize / 2 133 if len(p) < chunkSize { 134 chunkSize = len(p) 135 } 136 137 var written int 138 encoded := Encode(e.out[:], p[:chunkSize]) 139 written, e.err = e.w.Write(e.out[:encoded]) 140 n += written / 2 141 p = p[chunkSize:] 142 } 143 return n, e.err 144 } 145 146 type decoder struct { 147 r io.Reader 148 err error 149 in []byte // input buffer (encoded form) 150 arr [bufferSize]byte // backing array for in 151 } 152 153 // NewDecoder returns an io.Reader that decodes hexadecimal characters from r. 154 // NewDecoder expects that r contain only an even number of hexadecimal characters. 155 func NewDecoder(r io.Reader) io.Reader { 156 return &decoder{r: r} 157 } 158 159 func (d *decoder) Read(p []byte) (n int, err error) { 160 // Fill internal buffer with sufficient bytes to decode 161 if len(d.in) < 2 && d.err == nil { 162 var numCopy, numRead int 163 numCopy = copy(d.arr[:], d.in) // Copies either 0 or 1 bytes 164 numRead, d.err = d.r.Read(d.arr[numCopy:]) 165 d.in = d.arr[:numCopy+numRead] 166 if d.err == io.EOF && len(d.in)%2 != 0 { 167 d.err = io.ErrUnexpectedEOF 168 } 169 } 170 171 // Decode internal buffer into output buffer 172 if numAvail := len(d.in) / 2; len(p) > numAvail { 173 p = p[:numAvail] 174 } 175 numDec, err := Decode(p, d.in[:len(p)*2]) 176 d.in = d.in[2*numDec:] 177 if err != nil { 178 d.in, d.err = nil, err // Decode error; discard input remainder 179 } 180 181 if len(d.in) < 2 { 182 return numDec, d.err // Only expose errors when buffer fully consumed 183 } 184 return numDec, nil 185 } 186 187 // Dumper returns a WriteCloser that writes a hex dump of all written data to 188 // w. The format of the dump matches the output of `hexdump -C` on the command 189 // line. 190 func Dumper(w io.Writer) io.WriteCloser { 191 return &dumper{w: w} 192 } 193 194 type dumper struct { 195 w io.Writer 196 rightChars [18]byte 197 buf [14]byte 198 used int // number of bytes in the current line 199 n uint // number of bytes, total 200 } 201 202 func toChar(b byte) byte { 203 if b < 32 || b > 126 { 204 return '.' 205 } 206 return b 207 } 208 209 func (h *dumper) Write(data []byte) (n int, err error) { 210 // Output lines look like: 211 // 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=| 212 // ^ offset ^ extra space ^ ASCII of line. 213 for i := range data { 214 if h.used == 0 { 215 // At the beginning of a line we print the current 216 // offset in hex. 217 h.buf[0] = byte(h.n >> 24) 218 h.buf[1] = byte(h.n >> 16) 219 h.buf[2] = byte(h.n >> 8) 220 h.buf[3] = byte(h.n) 221 Encode(h.buf[4:], h.buf[:4]) 222 h.buf[12] = ' ' 223 h.buf[13] = ' ' 224 _, err = h.w.Write(h.buf[4:]) 225 if err != nil { 226 return 227 } 228 } 229 Encode(h.buf[:], data[i:i+1]) 230 h.buf[2] = ' ' 231 l := 3 232 if h.used == 7 { 233 // There's an additional space after the 8th byte. 234 h.buf[3] = ' ' 235 l = 4 236 } else if h.used == 15 { 237 // At the end of the line there's an extra space and 238 // the bar for the right column. 239 h.buf[3] = ' ' 240 h.buf[4] = '|' 241 l = 5 242 } 243 _, err = h.w.Write(h.buf[:l]) 244 if err != nil { 245 return 246 } 247 n++ 248 h.rightChars[h.used] = toChar(data[i]) 249 h.used++ 250 h.n++ 251 if h.used == 16 { 252 h.rightChars[16] = '|' 253 h.rightChars[17] = '\n' 254 _, err = h.w.Write(h.rightChars[:]) 255 if err != nil { 256 return 257 } 258 h.used = 0 259 } 260 } 261 return 262 } 263 264 func (h *dumper) Close() (err error) { 265 // See the comments in Write() for the details of this format. 266 if h.used == 0 { 267 return 268 } 269 h.buf[0] = ' ' 270 h.buf[1] = ' ' 271 h.buf[2] = ' ' 272 h.buf[3] = ' ' 273 h.buf[4] = '|' 274 nBytes := h.used 275 for h.used < 16 { 276 l := 3 277 if h.used == 7 { 278 l = 4 279 } else if h.used == 15 { 280 l = 5 281 } 282 _, err = h.w.Write(h.buf[:l]) 283 if err != nil { 284 return 285 } 286 h.used++ 287 } 288 h.rightChars[nBytes] = '|' 289 h.rightChars[nBytes+1] = '\n' 290 _, err = h.w.Write(h.rightChars[:nBytes+2]) 291 return 292 }