github.com/spi-ca/misc@v1.0.1/dbg/dumper.go (about) 1 package dbg 2 3 import "bytes" 4 5 import ( 6 "fmt" 7 "golang.org/x/text/width" 8 "unicode/utf8" 9 ) 10 11 // HexDump returns hexadecimal data dump data. 12 func HexDump(by []byte) string { 13 n := len(by) 14 rowcount := 0 15 stop := (n / 16) * 16 16 k := 0 17 buf := &bytes.Buffer{} 18 19 for i := 0; i <= stop; i += 16 { 20 k++ 21 if i+16 < n { 22 rowcount = 16 23 } else { 24 rowcount = min(k*16, n) % 16 25 } 26 27 fmt.Fprintf(buf, "%08x ", i) 28 for j := 0; j < rowcount; j++ { 29 if j%8 == 0 { 30 fmt.Fprintf(buf, " %02x ", by[i+j]) 31 } else { 32 fmt.Fprintf(buf, "%02x ", by[i+j]) 33 } 34 35 } 36 37 for j := rowcount; j < 16; j++ { 38 if j%8 == 0 { 39 fmt.Fprintf(buf, " ") 40 } else { 41 fmt.Fprintf(buf, " ") 42 } 43 } 44 buf.WriteRune('|') 45 viewString(by[i:(i+rowcount)], buf) 46 buf.WriteRune('|') 47 buf.WriteRune('\n') 48 buf.WriteRune('\r') 49 } 50 return buf.String() 51 } 52 53 func max(a, b int) int { 54 if a > b { 55 return a 56 } 57 return b 58 } 59 func min(a, b int) int { 60 if a < b { 61 return a 62 } 63 return b 64 } 65 66 // GuessUnicodeWidth returns the size of bytes for a single rune. 67 func GuessUnicodeWidth(char rune) (realSize int) { 68 prop := width.LookupRune(char) 69 switch prop.Kind() { 70 case width.EastAsianFullwidth: 71 fallthrough 72 case width.EastAsianWide: 73 realSize = 2 74 case width.EastAsianHalfwidth: 75 fallthrough 76 case width.EastAsianNarrow: 77 realSize = 2 78 case width.EastAsianAmbiguous: 79 fallthrough 80 case width.Neutral: 81 fallthrough 82 default: 83 realSize = 1 84 } 85 return 86 } 87 88 func viewString(b []byte, buf *bytes.Buffer) { 89 for { 90 if r, size := utf8.DecodeRune(b); size == 0 { 91 return 92 } else if r == utf8.RuneError { 93 for i := 0; i < size; i++ { 94 buf.WriteRune('_') 95 } 96 b = b[size:] 97 } else if r < 32 { 98 for i := 0; i < size; i++ { 99 buf.WriteRune('.') 100 } 101 b = b[size:] 102 } else { 103 buf.WriteRune(r) 104 pad := max(0, size-GuessUnicodeWidth(r)) 105 for i := 0; i < pad; i++ { 106 buf.WriteRune('.') 107 } 108 b = b[size:] 109 } 110 } 111 }