Skip to content

Commit

Permalink
show: improve binary show
Browse files Browse the repository at this point in the history
  • Loading branch information
fcharlie committed Dec 21, 2024
1 parent 857f37d commit ab91a45
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 62 deletions.
1 change: 0 additions & 1 deletion pkg/command/command_show.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
// Show various types of objects
type Show struct {
Textconv bool `name:"textconv" help:"Converting text to Unicode"`
Output string `name:"output" help:"Output to a specific file instead of stdout" placeholder:"<file>"`
Histogram bool `name:"histogram" help:"Generate a diff using the \"Histogram diff\" algorithm"`
ONP bool `name:"onp" help:"Generate a diff using the \"O(NP) diff\" algorithm"`
Myers bool `name:"myers" help:"Generate a diff using the \"Myers diff\" algorithm"`
Expand Down
177 changes: 117 additions & 60 deletions pkg/zeta/hastyhex.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
package zeta

import (
"bytes"
"fmt"
"io"
"math"
"strings"
)

const (
CN byte = 0x37 /* null */
CS byte = 0x92 /* space */
CP byte = 0x96 /* print */
CC byte = 0x95 /* control */
CH byte = 0x93 /* high */
colorTemplate = "00000000 " +
"\x1b[XXm## \x1b[XXm## \x1b[XXm## \x1b[XXm## " +
"\x1b[XXm## \x1b[XXm## \x1b[XXm## \x1b[XXm## " +
"\x1b[XXm## \x1b[XXm## \x1b[XXm## \x1b[XXm## " +
"\x1b[XXm## \x1b[XXm## \x1b[XXm## \x1b[XXm## " +
"\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm." +
"\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm.\x1b[XXm." +
"\x1b[0m\n"
CN byte = 90 /* null */
CS byte = 92 /* space */
CP byte = 96 /* print */
CC byte = 95 /* control */
CH byte = 93 /* high */
)

var (
hex = []byte("0123456789abcdef")
table = []byte{
colorTable = []byte{
CN, CC, CC, CC, CC, CC, CC, CC, CC, CC, CS, CS, CS, CS, CC, CC, CC, CC, CC, CC, CC, CC, CC, CC, CC, CC,
CC, CC, CC, CC, CC, CC, CS, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP,
CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP,
Expand Down Expand Up @@ -51,67 +45,130 @@ var (
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
}
slots = []int{ /* ANSI-color, hex, ANSI-color, ASCII */
12, 15, 142, 145, 20, 23, 148, 151, 28, 31, 154, 157, 36, 39, 160, 163,
44, 47, 166, 169, 52, 55, 172, 175, 60, 63, 178, 181, 68, 71, 184, 187,
77, 80, 190, 193, 85, 88, 196, 199, 93, 96, 202, 205, 101, 104, 208, 211,
109, 112, 214, 217, 117, 120, 220, 223, 125, 128, 226, 229, 133, 136, 232, 235}
)

type binaryPrinter struct {
*bytes.Buffer
w io.Writer
}

func newBinaryPrinter(w io.Writer) *binaryPrinter {
byteBuffer := &bytes.Buffer{}
byteBuffer.Grow(400)
return &binaryPrinter{Buffer: byteBuffer, w: w}
}

// left_corner: '┌',
// horizontal_line: '─',
// column_separator: '┬',
// right_corner: '┐',
// left_corner: '└',
// horizontal_line: '─',
// column_separator: '┴',
// right_corner: '┘',
// │ ┊
const (
// Hexadecimal => 2
// [ 4d 5a 90 00 03 00 00 00 ]
panelSize = 2*8 + 9
)

func (b *binaryPrinter) doPrintln(a ...string) {
for _, s := range a {
_, _ = b.WriteString(s)
}
_ = b.WriteByte('\n')
}
func (b *binaryPrinter) writeBorder() error {
pannelStr := strings.Repeat("─", panelSize)
h8 := strings.Repeat("─", 8)
b.doPrintln("┌", h8, "┬", pannelStr, "┬", pannelStr, "┬", h8, "┬", h8, "┐")
return b.flush()
}

func (b *binaryPrinter) writeFooter() error {
pannelStr := strings.Repeat("─", panelSize)
h8 := strings.Repeat("─", 8)
b.doPrintln("└", h8, "┴", pannelStr, "┴", pannelStr, "┴", h8, "┴", h8, "┘")
return b.flush()
}

func (b *binaryPrinter) formatByte(v byte) {
c := colorTable[v]
fmt.Fprintf(b.Buffer, "\x1b[%dm%02x\x1b[0m ", c, v)
}

func (b *binaryPrinter) displayByte(v byte) {
c := colorTable[v]
fmt.Fprintf(b.Buffer, "\x1b[%dm%c\x1b[0m", c, displayTable[v])
}

func (b *binaryPrinter) writeLine(offset int64, input []byte) error {
fmt.Fprintf(b.Buffer, "│\x1b[90m%08x\x1b[0m│ ", offset)
var i int
for ; i < min(8, len(input)); i++ {
b.formatByte(input[i])
}
for ; i < 8; i++ {
_, _ = b.WriteString(" ")
}
_, _ = b.WriteString("┊ ")
for ; i < min(16, len(input)); i++ {
b.formatByte(input[i])
}
for ; i < 16; i++ {
_, _ = b.WriteString(" ")
}
_, _ = b.WriteString("│")
var j int
for ; j < min(8, len(input)); j++ {
b.displayByte(input[j])
}
for ; j < 8; j++ {
_, _ = b.WriteString(" ")
}
_, _ = b.WriteString("┊")
for ; j < min(16, len(input)); j++ {
b.displayByte(input[j])
}
for ; j < 16; j++ {
_, _ = b.WriteString(" ")
}
_, _ = b.WriteString("│\n")
return b.flush()
}

func (b *binaryPrinter) flush() error {
_, err := b.w.Write(b.Bytes())
b.Reset()
return err
}

func processColor(r io.Reader, w io.Writer, size int64) error {
var input [16]byte
colortemplate := []byte(colorTemplate)
if size < 0 {
size = math.MaxInt64
}
var input [16]byte
b := newBinaryPrinter(w)
if err := b.writeBorder(); err != nil {
return err
}
var offset int64
for {
rn := min(size, 16)
n, err := io.ReadFull(r, input[:rn])
readBytes := min(size, 16)
n, err := io.ReadFull(r, input[:readBytes])
if err != nil {
break
}
/* Write the offset */
for i := 0; i < 8; i++ {
colortemplate[i] = hex[(offset>>(28-i*4))&15]
}
size -= int64(n)
/* Fill out the colortemplate */
for i := 0; i < 16; i++ {
/* Use a fixed loop count instead of "n" to encourage loop
* unrolling by the compiler. Empty bytes will be erased
* later.
*/
v := input[i]
c := table[v]
colortemplate[slots[i*4+0]+0] = hex[c>>4]
colortemplate[slots[i*4+0]+1] = hex[c&15]
colortemplate[slots[i*4+1]+0] = hex[v>>4]
colortemplate[slots[i*4+1]+1] = hex[v&15]
colortemplate[slots[i*4+2]+0] = hex[c>>4]
colortemplate[slots[i*4+2]+1] = hex[c&15]
colortemplate[slots[i*4+3]+0] = displayTable[v]
}
/* Erase any trailing bytes */
for i := n; i < 16; i++ {
/* This loop is only used once: the last line of output. The
* branch predictor will quickly learn that it's never taken.
*/
colortemplate[slots[i*4+0]+0] = '0'
colortemplate[slots[i*4+0]+1] = '0'
colortemplate[slots[i*4+1]+0] = ' '
colortemplate[slots[i*4+1]+1] = ' '
colortemplate[slots[i*4+2]+0] = '0'
colortemplate[slots[i*4+2]+1] = '0'
colortemplate[slots[i*4+3]+0] = ' '
}
if _, err := w.Write(colortemplate); err != nil {
if err := b.writeLine(offset, input[:n]); err != nil {
return err
}
offset += 16
size -= int64(n)
if n != 16 || size <= 0 {
break
}
}
return nil

return b.writeFooter()
}
14 changes: 13 additions & 1 deletion pkg/zeta/hastyhex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,22 @@ import (

func TestProcessColor(t *testing.T) {
b := make([]byte, 1000)
_, err := rand.Read(b)
_, err := rand.Read(b[10:])
if err != nil {
return
}
processColor(bytes.NewReader(b), os.Stdout, int64(len(b)))
}

func TestBorder(t *testing.T) {
input := make([]byte, 15)
_, err := rand.Read(input)
if err != nil {
return
}
b := newBinaryPrinter(os.Stderr)
_ = b.writeBorder()
_ = b.writeLine(0, input)
_ = b.writeLine(16, []byte("world"))
_ = b.writeFooter()
}

0 comments on commit ab91a45

Please sign in to comment.