...

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  	"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