| // 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 | |
| } |