mirror of
https://github.com/NotAShelf/hexxy.git
synced 2024-11-22 13:20:49 +00:00
[hexxy] init
This commit is contained in:
commit
f5307e6a75
1 changed files with 173 additions and 0 deletions
173
hexxy.go
Normal file
173
hexxy.go
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jessevdk/go-flags"
|
||||||
|
)
|
||||||
|
|
||||||
|
var opts struct {
|
||||||
|
NoColor bool `short:"N" long:"no-color" description:"do not print output with color"`
|
||||||
|
Verbose bool `short:"v" long:"verbose" description:"print debugging information and verbose output"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var Debug = func(string, ...interface{}) {}
|
||||||
|
|
||||||
|
type Color struct {
|
||||||
|
disable bool
|
||||||
|
values [256]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Color) Compute() {
|
||||||
|
const WHITEB = "\x1b[1;37m"
|
||||||
|
for i := 0; i < 256; i++ {
|
||||||
|
var fg, bg string
|
||||||
|
|
||||||
|
lowVis := i == 0 || (i >= 16 && i <= 20) || (i >= 232 && i <= 242)
|
||||||
|
|
||||||
|
if lowVis {
|
||||||
|
fg = WHITEB + "\x1b[38;5;" + "255" + "m"
|
||||||
|
bg = "\x1b[48;5;" + strconv.Itoa(int(i)) + "m"
|
||||||
|
} else {
|
||||||
|
fg = "\x1b[38;5;" + strconv.Itoa(int(i)) + "m"
|
||||||
|
bg = ""
|
||||||
|
}
|
||||||
|
c.values[i] = bg + fg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Color) Colorize(s string, clr byte) string {
|
||||||
|
const NOCOLOR = "\x1b[0m"
|
||||||
|
return c.values[clr] + s + NOCOLOR
|
||||||
|
}
|
||||||
|
|
||||||
|
func stdinOpen() bool {
|
||||||
|
stat, _ := os.Stdin.Stat()
|
||||||
|
if stat.Mode()&os.ModeCharDevice == os.ModeCharDevice {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func asciiRow(ascii []byte, clr *Color, stdout io.Writer) {
|
||||||
|
var s string
|
||||||
|
for _, b := range ascii {
|
||||||
|
if b >= 33 && b <= 126 {
|
||||||
|
s = clr.Colorize(string(b), b)
|
||||||
|
} else {
|
||||||
|
s = clr.Colorize(".", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(stdout, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hexdump(file *os.File, color *Color) error {
|
||||||
|
stdout := bufio.NewWriter(os.Stdout)
|
||||||
|
stderr := os.Stderr
|
||||||
|
ascii := [16]byte{}
|
||||||
|
|
||||||
|
var i uint64 = 0
|
||||||
|
reader := bufio.NewReaderSize(file, 10*1024*1024)
|
||||||
|
|
||||||
|
for {
|
||||||
|
b, err := reader.ReadByte()
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(stderr, "Failed to read %v: %v\n", file.Name(), err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ascii[i%16] = b
|
||||||
|
|
||||||
|
// offset
|
||||||
|
if i%16 == 0 {
|
||||||
|
fmt.Fprintf(stdout, "%08x ", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// byte
|
||||||
|
fmt.Fprintf(stdout, color.Colorize("%02x", b)+" ", b)
|
||||||
|
|
||||||
|
// extra space every 4 bytes
|
||||||
|
if (i+1)%4 == 0 {
|
||||||
|
fmt.Fprint(stdout, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// print ascii row and newline │ | ┆
|
||||||
|
if (i+1)%16 == 0 {
|
||||||
|
fmt.Fprint(stdout, "│")
|
||||||
|
asciiRow(ascii[:i%16], color, stdout)
|
||||||
|
fmt.Fprintln(stdout, "│")
|
||||||
|
ascii = [16]byte{} // reset
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if i%16 != 0 {
|
||||||
|
left := int(16 - i%16)
|
||||||
|
spaces := 3*left + (left-1)/4 + 1
|
||||||
|
fmt.Fprint(stdout, strings.Repeat(" ", spaces))
|
||||||
|
fmt.Fprint(stdout, "│")
|
||||||
|
asciiRow(ascii[:i%16], color, stdout)
|
||||||
|
fmt.Fprintln(stdout, "│")
|
||||||
|
fmt.Fprintf(stdout, "%08x\n", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hexxy(args []string) error {
|
||||||
|
color := &Color{}
|
||||||
|
|
||||||
|
if opts.NoColor {
|
||||||
|
color.disable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !color.disable {
|
||||||
|
color.Compute()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) < 1 && stdinOpen() {
|
||||||
|
return Hexdump(os.Stdin, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range args {
|
||||||
|
file, err := os.Open(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
Hexdump(file, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
args, err := flags.Parse(&opts)
|
||||||
|
if flags.WroteHelp(err) {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Verbose {
|
||||||
|
Debug = log.Printf
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := Hexxy(args); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue