| // Copyright 2014 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "encoding/hex" |
| "fmt" |
| "io/ioutil" |
| "regexp" |
| "strconv" |
| "strings" |
| "testing" |
| ) |
| |
| // mustParseHexdumpFile returns a block of data generated by |
| // parsing the hex dump in the named file. |
| // If the file cannot be read or does not contain a valid hex dump, |
| // mustParseHexdumpFile calls t.Fatal. |
| func mustParseHexdumpFile(t *testing.T, file string) []byte { |
| hex, err := ioutil.ReadFile(file) |
| if err != nil { |
| t.Fatal(err) |
| } |
| data, err := parseHexdump(string(hex)) |
| if err != nil { |
| t.Fatal(err) |
| } |
| return data |
| } |
| |
| // parseHexdump parses the hex dump in text, which should be the |
| // output of "hexdump -C" or Plan 9's "xd -b", |
| // and returns the original data used to produce the dump. |
| // It is meant to enable storing golden binary files as text, so that |
| // changes to the golden files can be seen during code reviews. |
| func parseHexdump(text string) ([]byte, error) { |
| var out []byte |
| for _, line := range strings.Split(text, "\n") { |
| if i := strings.Index(line, "|"); i >= 0 { // remove text dump |
| line = line[:i] |
| } |
| f := strings.Fields(line) |
| if len(f) > 1+16 { |
| return nil, fmt.Errorf("parsing hex dump: too many fields on line %q", line) |
| } |
| if len(f) == 0 || len(f) == 1 && f[0] == "*" { // all zeros block omitted |
| continue |
| } |
| addr64, err := strconv.ParseUint(f[0], 16, 0) |
| if err != nil { |
| return nil, fmt.Errorf("parsing hex dump: invalid address %q", f[0]) |
| } |
| addr := int(addr64) |
| if len(out) < addr { |
| out = append(out, make([]byte, addr-len(out))...) |
| } |
| for _, x := range f[1:] { |
| val, err := strconv.ParseUint(x, 16, 8) |
| if err != nil { |
| return nil, fmt.Errorf("parsing hexdump: invalid hex byte %q", x) |
| } |
| out = append(out, byte(val)) |
| } |
| } |
| return out, nil |
| } |
| |
| func hexdump(data []byte) string { |
| text := hex.Dump(data) + fmt.Sprintf("%08x\n", len(data)) |
| text = regexp.MustCompile(`\n([0-9a-f]+(\s+00){16}.*\n)+`).ReplaceAllString(text, "\n*\n") |
| return text |
| } |