From 8198882b13054f0c2aa1766909c6ba4742242e2e Mon Sep 17 00:00:00 2001 From: raspi Date: Fri, 19 Jun 2020 11:20:39 +0300 Subject: [PATCH] Add width parameter --- main.go | 28 +++++++++++++++++++++++----- pkg/reader/reader.go | 18 +++++++++++++----- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index 67c840c..470c01a 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,7 @@ const ( ) // Parse command line arguments -func getParams() (source iface.ReadSeekerCloser, displays []reader.ByteFormatter, offsetViewer []reader.OffsetFormatter, limit uint64, palette [256]color.AnsiColor, filesize int64) { +func getParams() (source iface.ReadSeekerCloser, displays []reader.ByteFormatter, offsetViewer []reader.OffsetFormatter, limit uint64, palette [256]color.AnsiColor, filesize int64, width uint16) { opt := getoptions.New() opt.HelpSynopsisArgs(` or STDIN`) @@ -67,6 +67,12 @@ func getParams() (source iface.ReadSeekerCloser, displays []reader.ByteFormatter opt.Description(`Start reading from certain offset. See NOTES.`), ) + argWidth := opt.StringOptional(`width`, `16`, + opt.Alias("w"), + opt.ArgName(`[prefix]width`), + opt.Description(`Width. See NOTES.`), + ) + remainingArgs, err := opt.Parse(os.Args[1:]) if opt.Called("help") { @@ -74,7 +80,7 @@ func getParams() (source iface.ReadSeekerCloser, displays []reader.ByteFormatter _, _ = fmt.Fprintf(os.Stdout, `(c) %v 2019- [ %v ]`+"\n", AUTHOR, HOMEPAGE) _, _ = fmt.Fprintln(os.Stdout, opt.Help()) _, _ = fmt.Fprintln(os.Stdout, `NOTES:`) - _, _ = fmt.Fprintln(os.Stdout, ` - You can use prefixes for seek and limit. 0x = hex, 0b = binary, 0o = octal`) + _, _ = fmt.Fprintln(os.Stdout, ` - You can use prefixes for seek, limit and width. 0x = hex, 0b = binary, 0o = octal`) _, _ = fmt.Fprintln(os.Stdout, ` - Use 'no' or '' for offset formatter for disabling offset output`) _, _ = fmt.Fprintln(os.Stdout, ` - Use '--seek \-1234' for seeking from end of file`) _, _ = fmt.Fprintln(os.Stdout, ` - Limit and seek parameters supports units (KB, KiB, MB, MiB, GB, GiB, TB, TiB)`) @@ -87,6 +93,7 @@ func getParams() (source iface.ReadSeekerCloser, displays []reader.ByteFormatter _, _ = fmt.Fprintln(os.Stdout, ` heksa -l 0x1024 foo.dat`) _, _ = fmt.Fprintln(os.Stdout, ` heksa -s 0b1010 foo.dat`) _, _ = fmt.Fprintln(os.Stdout, ` heksa -s 4321KiB foo.dat`) + _, _ = fmt.Fprintln(os.Stdout, ` heksa -w 8 foo.dat`) os.Exit(0) } else if opt.Called("version") { _, _ = fmt.Fprintf(os.Stdout, `%v build %v on %v`+"\n", VERSION, BUILD, BUILDDATE) @@ -112,6 +119,17 @@ func getParams() (source iface.ReadSeekerCloser, displays []reader.ByteFormatter os.Exit(1) } + widthTmp, err := units.Parse(*argWidth) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, `error parsing width: %v`, err) + os.Exit(1) + } + width = uint16(widthTmp) + if width == 0 { + _, _ = fmt.Fprint(os.Stderr, `width must be > 0`) + os.Exit(1) + } + offsetViewer, err = reader.GetOffsetFormatters(strings.Split(*argOffset, `,`)) if err != nil { _, _ = fmt.Fprintf(os.Stderr, `error getting offset formatter: %v`, err) @@ -173,16 +191,16 @@ func getParams() (source iface.ReadSeekerCloser, displays []reader.ByteFormatter source = fhandle } - return source, displays, offsetViewer, limit, palette, filesize + return source, displays, offsetViewer, limit, palette, filesize, width } func main() { - source, displays, offViewer, limit, palette, filesize := getParams() + source, displays, offViewer, limit, palette, filesize, width := getParams() stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt) - r := reader.New(source, offViewer, displays, palette, filesize) + r := reader.New(source, offViewer, displays, palette, width, filesize) isEven := false // Dump hex diff --git a/pkg/reader/reader.go b/pkg/reader/reader.go index 79be597..13a9ecb 100644 --- a/pkg/reader/reader.go +++ b/pkg/reader/reader.go @@ -32,13 +32,19 @@ type Reader struct { offsetFormatterWidth map[OffsetFormatter]int // How much padding width needed, calculated from fileSize variable Colors Colors // Colors growHint int // Grow hint for sb strings.Builder variable for speed + width int // Width + visualSplitterSize int // Size of visual splitter (2 = XX XX XX, 3 = XXX XXX XXX, etc) } -func New(r iface.ReadSeekerCloser, offsetFormatter []OffsetFormatter, formatters []ByteFormatter, palette [256]color.AnsiColor, filesize int64) *Reader { +func New(r iface.ReadSeekerCloser, offsetFormatter []OffsetFormatter, formatters []ByteFormatter, palette [256]color.AnsiColor, width uint16, filesize int64) *Reader { if formatters == nil { panic(`nil formatter`) } + if width == 0 { + panic(`zero width`) + } + var calcpalette [256]string for idx := range palette { @@ -47,6 +53,8 @@ func New(r iface.ReadSeekerCloser, offsetFormatter []OffsetFormatter, formatters reader := &Reader{ r: r, + visualSplitterSize: 8, // Insert extra space after every N bytes + width: int(width), fileSize: filesize, charFormatters: formatters, offsetFormatter: offsetFormatter, @@ -152,7 +160,7 @@ func (r *Reader) getoffsetRight(offset uint64) string { return r.sb.String() } -// Read reads 16 bytes and provides string to display +// Read reads N (r.width) bytes and provides string to display func (r *Reader) Read() (string, error) { var offset uint64 @@ -176,7 +184,7 @@ func (r *Reader) Read() (string, error) { r.sb.WriteString(offsetLeft) - tmp := make([]byte, 16) + tmp := make([]byte, r.width) rb, err := r.r.Read(tmp) if err != nil { return ``, err @@ -187,8 +195,8 @@ func (r *Reader) Read() (string, error) { // iterate through every formatter which outputs it's own format for didx, byteFormatterType := range r.charFormatters { - for i := 0; i < 16; i++ { - if i == 8 { + for i := 0; i < r.width; i++ { + if i > 0 && i%r.visualSplitterSize == 0 { // Add pad for better visualization r.sb.WriteString(` `) }