-
Notifications
You must be signed in to change notification settings - Fork 1
/
hexdump.go
109 lines (99 loc) · 3.56 KB
/
hexdump.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package xd
import (
"fmt"
"io"
"strings"
)
var charmap = []string{
"▪", "☺", "☻", "♥", "♦", "♣", "♠", "•",
"◘", "○", "◙", "♂", "♀", "♪", "♫", "☼",
"►", "◄", "↕", "‼", "¶", "§", "▬", "↨",
"↑", "↓", "→", "←", "∟", "↔", "▲", "▼",
" ", "!", `"`, "#", "$", "%", "&", "'",
"(", ")", "*", "+", ",", "-", ".", "/",
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", ":", ";", "<", "=", ">", "?",
"@", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "[", `\`, "]", "^", "_",
"`", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "{", "|", "}", "~", "⌂",
"█", "⡀", "⢀", "⣀", "⠠", "⡠", "⢠", "⣠",
"⠄", "⡄", "⢄", "⣄", "⠤", "⡤", "⢤", "⣤",
"⠁", "⡁", "⢁", "⣁", "⠡", "⡡", "⢡", "⣡",
"⠅", "⡅", "⢅", "⣅", "⠥", "⡥", "⢥", "⣥",
"⠃", "⡃", "⢃", "⣃", "⠣", "⡣", "⢣", "⣣",
"⠇", "⡇", "⢇", "⣇", "⠧", "⡧", "⢧", "⣧",
"⠉", "⡉", "⢉", "⣉", "⠩", "⡩", "⢩", "⣩",
"⠍", "⡍", "⢍", "⣍", "⠭", "⡭", "⢭", "⣭",
"⠊", "⡊", "⢊", "⣊", "⠪", "⡪", "⢪", "⣪",
"⠎", "⡎", "⢎", "⣎", "⠮", "⡮", "⢮", "⣮",
"⠑", "⡑", "⢑", "⣑", "⠱", "⡱", "⢱", "⣱",
"⠕", "⡕", "⢕", "⣕", "⠵", "⡵", "⢵", "⣵",
"⠚", "⡚", "⢚", "⣚", "⠺", "⡺", "⢺", "⣺",
"⠞", "⡞", "⢞", "⣞", "⠾", "⡾", "⢾", "⣾",
"⠛", "⡛", "⢛", "⣛", "⠻", "⡻", "⢻", "⣻",
"⠟", "⡟", "⢟", "⣟", "⠿", "⡿", "⢿", "⣿",
}
func line(w *strings.Builder, data []byte, dataOffset int, lineStart int) {
fmt.Fprintf(w, "%08x ", lineStart)
for i := 0; i < 16; i++ {
if i == 8 {
w.WriteString(" ")
}
if lineStart+i < dataOffset || lineStart+i >= len(data)+dataOffset {
w.WriteString(" ")
} else {
fmt.Fprintf(w, " %02x", data[lineStart+i-dataOffset])
}
}
w.WriteString(" ")
for i := 0; i < 16 && lineStart+i < len(data)+dataOffset; i++ {
if lineStart+i < dataOffset {
w.WriteString(" ")
} else {
if lineStart+i == dataOffset || i == 0 {
w.WriteString("|")
}
w.WriteString(charmap[data[lineStart+i-dataOffset]])
}
}
w.WriteString("|\n")
}
// Sprint takes the binary data and formats it. Offset is the
// offset in the binary stream, used to print address, and to
// align printed data to 16 bytes boundary.
func Sprint(data []byte, offset int) string {
builder := strings.Builder{}
// Every byte of data produces between 5 and 7 bytes of output
// (fewer bytes for printable ASCII, more bytes for non-ASCII)
builder.Grow(6 * len(data))
for lineStart := offset / 16 * 16; lineStart < offset+len(data); lineStart += 16 {
line(&builder, data, offset, lineStart)
}
return builder.String()
}
// Print is a convenience function to format data like Sprint
// and print it to stdout
func Print(data []byte, offset int) (int, error) {
return fmt.Print(Sprint(data, offset))
}
// Fprint is a convenience function to format data like Sprint
// and print it to the passed writer.
func Fprint(w io.Writer, data []byte, offset int) (int, error) {
builder := strings.Builder{}
written := 0
for lineStart := offset / 16 * 16; lineStart < offset+len(data); lineStart += 16 {
builder.Grow(7 * 16) // Reserve space for the whole line once
line(&builder, data, offset, lineStart)
n, err := fmt.Fprint(w, builder.String())
if err != nil {
return written + n, err
}
written += n
}
return written, nil
}