...
Run Format

Source file src/encoding/hex/hex.go

Documentation: encoding/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  

View as plain text