...

Source file src/pkg/encoding/hex/hex.go

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

View as plain text