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