diff options
| author | Shulhan <ms@kilabit.info> | 2024-12-28 16:22:29 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2024-12-28 16:46:59 +0700 |
| commit | c1aab5c376dfa1845b839f1c4b9876a1412a8d24 (patch) | |
| tree | a4d191420f52a3f1aad25c4609ced5e03036e5ab | |
| parent | 4003b6359747f6e43357e4bf190d4e71a66ec796 (diff) | |
| download | pakakeh.go-c1aab5c376dfa1845b839f1c4b9876a1412a8d24.tar.xz | |
lib/bytes: split the hexdump related functions to separate package
Package hexdump implements reading and writing bytes from and into
hexadecimal number.
It support parsing output from hexdump(1) tool.
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | lib/binary/apo_file_test.go | 7 | ||||
| -rw-r--r-- | lib/bytes/bytes.go | 205 | ||||
| -rw-r--r-- | lib/bytes/bytes_example_test.go | 47 | ||||
| -rw-r--r-- | lib/bytes/bytes_test.go | 70 | ||||
| -rw-r--r-- | lib/dns/message_test.go | 16 | ||||
| -rw-r--r-- | lib/dns/zone_test.go | 12 | ||||
| -rw-r--r-- | lib/hexdump/hexdump.go | 217 | ||||
| -rw-r--r-- | lib/hexdump/hexdump_example_test.go | 61 | ||||
| -rw-r--r-- | lib/hexdump/hexdump_test.go | 76 | ||||
| -rw-r--r-- | lib/hexdump/testdata/Parse_exp_dir_tar_test.txt (renamed from lib/bytes/testdata/ParseHexDump_exp_dir_tar_test.txt) | 4 | ||||
| -rw-r--r-- | lib/hexdump/testdata/Parse_test.txt (renamed from lib/bytes/testdata/ParseHexDump_test.txt) | 4 | ||||
| -rw-r--r-- | lib/hexdump/testdata/exp_dir.tar (renamed from lib/bytes/testdata/exp_dir.tar) | bin | 10240 -> 10240 bytes | |||
| -rw-r--r-- | lib/hexdump/testdata/exp_dir.tar.license | 3 | ||||
| -rw-r--r-- | lib/memfs/internal/test/embed/embed_test.go | 38 |
15 files changed, 410 insertions, 355 deletions
@@ -102,6 +102,11 @@ A library for working with slice of float64. [**git**](https://pkg.go.dev/git.sr.ht/~shulhan/pakakeh.go/lib/git):: A wrapper for git command line interface. +[**hexdump**](https://pkg.go.dev/git.sr.ht/~shulhan/pakakeh.go/lib/hexdump):: +Package hexdump implements reading and writing bytes from and into +hexadecimal number. +It support parsing output from hexdump(1) tool. + [**http**](https://pkg.go.dev/git.sr.ht/~shulhan/pakakeh.go/lib/http):: Package http extends the standard http package with simplified routing handler and builtin memory file system. diff --git a/lib/binary/apo_file_test.go b/lib/binary/apo_file_test.go index 52d54500..ac5912dc 100644 --- a/lib/binary/apo_file_test.go +++ b/lib/binary/apo_file_test.go @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> +// // SPDX-License-Identifier: BSD-3-Clause package binary @@ -9,7 +10,7 @@ import ( "path/filepath" "testing" - libbytes "git.sr.ht/~shulhan/pakakeh.go/lib/bytes" + "git.sr.ht/~shulhan/pakakeh.go/lib/hexdump" "git.sr.ht/~shulhan/pakakeh.go/lib/test" ) @@ -47,7 +48,7 @@ func TestOpenApo(t *testing.T) { } var gotDump bytes.Buffer - libbytes.DumpPrettyTable(&gotDump, `empty`, gotb) + hexdump.PrettyPrint(&gotDump, `empty`, gotb) var exp = string(tdata.Output[`empty`]) test.Assert(t, `empty`, exp, gotDump.String()) @@ -141,7 +142,7 @@ func testWrite(t *testing.T, tcase testCaseWrite, apow *ApoFile) { } var gotDump bytes.Buffer - libbytes.DumpPrettyTable(&gotDump, tcase.tag, gotb) + hexdump.PrettyPrint(&gotDump, tcase.tag, gotb) test.Assert(t, tcase.tag, tcase.expHexdump, gotDump.String()) } diff --git a/lib/bytes/bytes.go b/lib/bytes/bytes.go index b47b0a85..3bbf529b 100644 --- a/lib/bytes/bytes.go +++ b/lib/bytes/bytes.go @@ -7,9 +7,6 @@ package bytes import ( "bytes" - "fmt" - "io" - "strconv" "unicode" inbytes "git.sr.ht/~shulhan/pakakeh.go/internal/bytes" @@ -323,156 +320,6 @@ func MergeSpaces(in []byte) (out []byte) { return out } -// ParseHexDump parse the default output of [hexdump](1) utility from -// parameter in back into stream of byte. -// -// An example of default output of hexdump is -// -// 0000000 7865 5f70 6964 2f72 0000 0000 0000 0000 -// 0000010 0000 0000 0000 0000 0000 0000 0000 0000 -// * -// 0000060 0000 0000 3030 3030 3537 0035 3030 3130 -// -// The first column is the address and the rest of the column is the data. -// -// Each data column is 16-bit words in big-endian order, so in the above -// example, the first byte would be 65, second byte is 78 and so on. -// If parameter networkByteOrder is true, the first byte would be 78, second -// by is 65, and so on. -// -// The asterisk "*" means that the address from 0000020 to 0000050 is equal -// to the previous line, 0000010. -// -// [hexdump]: https://man.archlinux.org/man/hexdump.1 -func ParseHexDump(in []byte, networkByteOrder bool) (out []byte, err error) { - var ( - logp = `ParseHexDump` - parser = NewParser(in, []byte(" \n")) - d byte = 255 // Just to make the first for-loop pass. - - token []byte - vint64 int64 - x int - isAsterisk bool - ) - for d != 0 { - // Read the address. - token, d = parser.Read() - if len(token) == 0 { - break - } - if len(token) == 1 { - if token[0] != '*' { - break - } - isAsterisk = true - continue - } - - vint64, err = strconv.ParseInt(string(token), 16, 64) - if err != nil { - return nil, fmt.Errorf(`%s: %w`, logp, err) - } - - if isAsterisk { - if len(out) > 0 { - var start = len(out) - if start < 16 { - start = 0 - } else { - start -= 16 - } - var ( - prevRow = out[start:] - identicalRow = int((vint64 - int64(len(out))) / 16) - ) - for x = 0; x < identicalRow; x++ { - out = append(out, prevRow...) - } - } - } - - // Read the two-hex, 16-bit words. - for x = 0; x < 8; x++ { - token, d = parser.Read() - if len(token) == 0 { - break - } - - vint64, err = strconv.ParseInt(string(token), 16, 64) - if err != nil { - return nil, fmt.Errorf(`%s: %w`, logp, err) - } - - switch len(token) { - case 2: - out = append(out, byte(vint64)) - case 4: - if networkByteOrder { - out = append(out, byte(vint64>>8)) - out = append(out, byte(vint64)) - } else { - out = append(out, byte(vint64)) - out = append(out, byte(vint64>>8)) - } - } - - if d == '\n' { - break - } - } - // Ignore trailing characters. - if d != '\n' { - parser.SkipLine() - } - } - return out, nil -} - -// PrintHex will print each byte in slice as hexadecimal value into N column -// length. -func PrintHex(title string, data []byte, col int) { - var ( - start, x int - c byte - ) - fmt.Print(title) - for x, c = range data { - if x%col == 0 { - if x > 0 { - fmt.Print(" ||") - } - for y := start; y < x; y++ { - if data[y] >= 33 && data[y] <= 126 { - fmt.Printf(" %c", data[y]) - } else { - fmt.Print(" .") - } - } - fmt.Printf("\n%4d -", x) - start = x - } - - fmt.Printf(" %02X", c) - } - rest := col - (x % col) - if rest > 0 { - for y := 1; y < rest; y++ { - fmt.Print(" ") - } - fmt.Print(" ||") - } - for y := start; y <= x; y++ { - if data[y] >= 33 && data[y] <= 126 { - fmt.Printf(" %c", data[y]) - } else { - fmt.Print(" .") - } - } - - fmt.Println() -} - // ReadHexByte read two hexadecimal characters from "data" start from index // "x" and convert them to byte. // It will return the byte and true if its read exactly two hexadecimal @@ -722,58 +569,6 @@ func WordIndexes(s []byte, word []byte) (idxs []int) { return idxs } -// DumpPrettyTable write each byte in slice data as hexadecimal, ASCII -// character, and integer with 8 columns width. -func DumpPrettyTable(w io.Writer, title string, data []byte) { - const ncol = 8 - - fmt.Fprintf(w, "%s\n", title) - fmt.Fprint(w, " | 0 1 2 3 4 5 6 7 | 01234567 | 0 1 2 3 4 5 6 7 |\n") - fmt.Fprint(w, " | 8 9 A B C D E F | 89ABCDEF | 8 9 A B C D E F |\n") - - var ( - chunks = SplitEach(data, ncol) - chunk []byte - x int - y int - c byte - ) - for x, chunk = range chunks { - fmt.Fprintf(w, `%#08x|`, x*ncol) - - // Print as hex. - for y, c = range chunk { - fmt.Fprintf(w, ` %02x`, c) - } - for y++; y < ncol; y++ { - fmt.Fprint(w, ` `) - } - - // Print as char. - fmt.Fprint(w, ` | `) - for y, c = range chunk { - if c >= 33 && c <= 126 { - fmt.Fprintf(w, `%c`, c) - } else { - fmt.Fprint(w, `.`) - } - } - for y++; y < ncol; y++ { - fmt.Fprint(w, ` `) - } - - // Print as integer. - fmt.Fprint(w, ` |`) - for y, c = range chunk { - fmt.Fprintf(w, ` %3d`, c) - } - for y++; y < ncol; y++ { - fmt.Fprint(w, ` `) - } - fmt.Fprintf(w, " |%d\n", x*ncol) - } -} - // WriteUint16 write uint16 value "v" into "data" start at position "x". // If x is out range, the data will not change. func WriteUint16(data []byte, x uint, v uint16) { diff --git a/lib/bytes/bytes_example_test.go b/lib/bytes/bytes_example_test.go index 0c2fbf49..6615f36d 100644 --- a/lib/bytes/bytes_example_test.go +++ b/lib/bytes/bytes_example_test.go @@ -5,9 +5,7 @@ package bytes_test import ( - "bytes" "fmt" - "log" "math" "git.sr.ht/~shulhan/pakakeh.go/lib/ascii" @@ -305,35 +303,6 @@ func ExampleMergeSpaces() { // a } -func ExampleParseHexDump() { - var ( - in = []byte("0000000 6548 6c6c 2c6f 7720 726f 646c 0021") - - out []byte - err error - ) - - out, err = libbytes.ParseHexDump(in, false) - if err != nil { - log.Fatal(err) - } - - fmt.Printf(`%s`, libbytes.TrimNull(out)) - // Output: - // Hello, world! -} - -func ExamplePrintHex() { - title := "PrintHex" - data := []byte("Hello, world !") - libbytes.PrintHex(title, data, 5) - // Output: - // PrintHex - // 0 - 48 65 6C 6C 6F || H e l l o - // 5 - 2C 20 77 6F 72 || , . w o r - // 10 - 6C 64 20 21 || l d . ! -} - func ExampleReadHexByte() { fmt.Println(libbytes.ReadHexByte([]byte{}, 0)) fmt.Println(libbytes.ReadHexByte([]byte("x0"), 0)) @@ -492,22 +461,6 @@ func ExampleWordIndexes() { // [] } -func ExampleDumpPrettyTable() { - var ( - data = []byte{1, 2, 3, 'H', 'e', 'l', 'l', 'o', 254, 255} - bb bytes.Buffer - ) - - libbytes.DumpPrettyTable(&bb, `DumpPrettyTable`, data) - fmt.Println(bb.String()) - // Output: - // DumpPrettyTable - // | 0 1 2 3 4 5 6 7 | 01234567 | 0 1 2 3 4 5 6 7 | - // | 8 9 A B C D E F | 89ABCDEF | 8 9 A B C D E F | - // 0x00000000| 01 02 03 48 65 6c 6c 6f | ...Hello | 1 2 3 72 101 108 108 111 |0 - // 0x00000008| fe ff | .. | 254 255 |8 -} - func ExampleWriteUint16() { data := []byte("Hello, world!") diff --git a/lib/bytes/bytes_test.go b/lib/bytes/bytes_test.go index 94d474f0..d41e399d 100644 --- a/lib/bytes/bytes_test.go +++ b/lib/bytes/bytes_test.go @@ -1,80 +1,16 @@ -// Copyright 2023, Shulhan <ms@kilabit.info>. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// SPDX-FileCopyrightText: 2023 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause package bytes import ( "fmt" - "os" - "path" "testing" "git.sr.ht/~shulhan/pakakeh.go/lib/test" ) -func TestParseHexDump(t *testing.T) { - var ( - tdata *test.Data - err error - ) - - tdata, err = test.LoadData(`testdata/ParseHexDump_test.txt`) - if err != nil { - t.Fatal(err) - } - - var ( - tag string - in []byte - exp []byte - got []byte - ) - for tag, in = range tdata.Input { - exp = tdata.Output[tag] - - got, err = ParseHexDump(in, false) - if err != nil { - test.Assert(t, tag, string(exp), err.Error()) - continue - } - - test.Assert(t, tag, string(exp), string(got)) - } -} - -func TestParseHexDumpExpDirTar(t *testing.T) { - var ( - tdata *test.Data - err error - ) - - tdata, err = test.LoadData(`testdata/ParseHexDump_exp_dir_tar_test.txt`) - if err != nil { - t.Fatal(err) - } - - var ( - tag = `exp_dir.tar` - expFile = path.Join(`testdata`, tag) - - exp []byte - got []byte - ) - - got, err = ParseHexDump(tdata.Input[tag], false) - if err != nil { - t.Fatal(err) - } - - exp, err = os.ReadFile(expFile) - if err != nil { - t.Fatal(err) - } - - test.Assert(t, tag, exp, got) -} - func TestTrimNull(t *testing.T) { type testCase struct { in []byte diff --git a/lib/dns/message_test.go b/lib/dns/message_test.go index 9d833389..824ace68 100644 --- a/lib/dns/message_test.go +++ b/lib/dns/message_test.go @@ -1,6 +1,6 @@ -// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// SPDX-FileCopyrightText: 2018 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause package dns @@ -9,7 +9,7 @@ import ( "encoding/json" "testing" - libbytes "git.sr.ht/~shulhan/pakakeh.go/lib/bytes" + "git.sr.ht/~shulhan/pakakeh.go/lib/hexdump" "git.sr.ht/~shulhan/pakakeh.go/lib/test" ) @@ -974,7 +974,7 @@ func TestMessageAddAuthority(t *testing.T) { // Compare the message packet. bb.Reset() - libbytes.DumpPrettyTable(&bb, msg.Question.String(), msg.packet) + hexdump.PrettyPrint(&bb, msg.Question.String(), msg.packet) exp = tdata.Output[`packet`] test.Assert(t, `AddAuthority`, string(exp), bb.String()) @@ -2101,7 +2101,7 @@ func TestUnpackMessage_OPT(t *testing.T) { bbuf bytes.Buffer ) for _, tcase = range listCase { - stream, err = libbytes.ParseHexDump(tdata.Input[tcase], true) + stream, err = hexdump.Parse(tdata.Input[tcase], true) if err != nil { t.Fatal(err) } @@ -2125,7 +2125,7 @@ func TestUnpackMessage_OPT(t *testing.T) { t.Fatal(err) } bbuf.Reset() - libbytes.DumpPrettyTable(&bbuf, msg.Question.String(), stream) + hexdump.PrettyPrint(&bbuf, msg.Question.String(), stream) tcase += `.hexdump` test.Assert(t, tcase, string(tdata.Output[tcase]), bbuf.String()) } @@ -2161,7 +2161,7 @@ func TestUnpackMessage_SVCB(t *testing.T) { msg *Message ) for _, name = range listCase { - stream, err = libbytes.ParseHexDump(tdata.Input[name], true) + stream, err = hexdump.Parse(tdata.Input[name], true) if err != nil { t.Fatal(logp, err) } diff --git a/lib/dns/zone_test.go b/lib/dns/zone_test.go index d8b80814..b4f3feb1 100644 --- a/lib/dns/zone_test.go +++ b/lib/dns/zone_test.go @@ -1,6 +1,6 @@ -// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// SPDX-FileCopyrightText: 2018 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause package dns @@ -10,7 +10,7 @@ import ( "strconv" "testing" - libbytes "git.sr.ht/~shulhan/pakakeh.go/lib/bytes" + "git.sr.ht/~shulhan/pakakeh.go/lib/hexdump" "git.sr.ht/~shulhan/pakakeh.go/lib/test" ) @@ -75,7 +75,7 @@ func TestParseZone(t *testing.T) { ) for x, msg = range zone.messages { bb.Reset() - libbytes.DumpPrettyTable(&bb, msg.Question.String(), msg.packet) + hexdump.PrettyPrint(&bb, msg.Question.String(), msg.packet) vstr = fmt.Sprintf(`message_%d.hex`, x) vbytes = tdata.Output[vstr] @@ -155,7 +155,7 @@ func TestParseZone_SVCB(t *testing.T) { for x, msg = range zone.messages { out.Reset() - libbytes.DumpPrettyTable(&out, msg.Question.String(), msg.packet) + hexdump.PrettyPrint(&out, msg.Question.String(), msg.packet) tag = fmt.Sprintf(`%s:message_%d.hex`, name, x) stream = tdata.Output[tag] diff --git a/lib/hexdump/hexdump.go b/lib/hexdump/hexdump.go new file mode 100644 index 00000000..50c0a3ce --- /dev/null +++ b/lib/hexdump/hexdump.go @@ -0,0 +1,217 @@ +// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause + +// Package hexdump implements reading and writing bytes from and into +// hexadecimal number. +// It support parsing output from hexdump(1) tool. +package hexdump + +import ( + "fmt" + "io" + "strconv" + + "git.sr.ht/~shulhan/pakakeh.go/lib/bytes" +) + +// Parse parse the default output of [hexdump(1)] utility from parameter in +// back into stream of byte. +// +// An example of default output of hexdump is +// +// 0000000 7865 5f70 6964 2f72 0000 0000 0000 0000 +// 0000010 0000 0000 0000 0000 0000 0000 0000 0000 +// * +// 0000060 0000 0000 3030 3030 3537 0035 3030 3130 +// +// The first column is the address and the rest of the column is the data. +// +// Each data column is 16-bit words in little-endian order, so in the above +// example, the first byte would be 65, second byte is 78 and so on. +// If parameter networkByteOrder (big-endian) is true, the first byte would be +// 78, second by is 65, and so on. +// +// The asterisk "*" means that the values from address 0000020 to 0000050 is +// equal to the previous line, 0000010. +// +// [hexdump(1)]: https://man.archlinux.org/man/hexdump.1 +func Parse(in []byte, networkByteOrder bool) (out []byte, err error) { + var ( + logp = `ParseHexDump` + parser = bytes.NewParser(in, []byte(" \n")) + d byte = 255 // Just to make the first for-loop pass. + + token []byte + vint64 int64 + x int + isAsterisk bool + ) + for d != 0 { + // Read the address. + token, d = parser.Read() + if len(token) == 0 { + break + } + if len(token) == 1 { + if token[0] != '*' { + break + } + isAsterisk = true + continue + } + + vint64, err = strconv.ParseInt(string(token), 16, 64) + if err != nil { + return nil, fmt.Errorf(`%s: %w`, logp, err) + } + + if isAsterisk { + if len(out) > 0 { + var start = len(out) + if start < 16 { + start = 0 + } else { + start -= 16 + } + var ( + prevRow = out[start:] + identicalRow = int((vint64 - int64(len(out))) / 16) + ) + for x = 0; x < identicalRow; x++ { + out = append(out, prevRow...) + } + } + } + + // Read the two-hex, 16-bit words. + for x = 0; x < 8; x++ { + token, d = parser.Read() + if len(token) == 0 { + break + } + + vint64, err = strconv.ParseInt(string(token), 16, 64) + if err != nil { + return nil, fmt.Errorf(`%s: %w`, logp, err) + } + + switch len(token) { + case 2: + out = append(out, byte(vint64)) + case 4: + if networkByteOrder { + out = append(out, byte(vint64>>8)) + out = append(out, byte(vint64)) + } else { + out = append(out, byte(vint64)) + out = append(out, byte(vint64>>8)) + } + } + + if d == '\n' { + break + } + } + // Ignore trailing characters. + if d != '\n' { + parser.SkipLine() + } + } + return out, nil +} + +// Print print each byte in slice as hexadecimal value into N column length. +func Print(title string, data []byte, col int) { + var ( + start, x int + c byte + ) + fmt.Print(title) + for x, c = range data { + if x%col == 0 { + if x > 0 { + fmt.Print(` ||`) + } + for y := start; y < x; y++ { + if data[y] >= 33 && data[y] <= 126 { + fmt.Printf(` %c`, data[y]) + } else { + fmt.Print(` .`) + } + } + fmt.Printf("\n%4d -", x) + start = x + } + + fmt.Printf(` %02X`, c) + } + rest := col - (x % col) + if rest > 0 { + for y := 1; y < rest; y++ { + fmt.Print(` `) + } + fmt.Print(` ||`) + } + for y := start; y <= x; y++ { + if data[y] >= 33 && data[y] <= 126 { + fmt.Printf(` %c`, data[y]) + } else { + fmt.Print(` .`) + } + } + + fmt.Println() +} + +// PrettyPrint write each byte in slice data as hexadecimal, ASCII +// character, and integer with 8 columns width. +func PrettyPrint(w io.Writer, title string, data []byte) { + const ncol = 8 + + fmt.Fprintf(w, "%s\n", title) + fmt.Fprint(w, " | 0 1 2 3 4 5 6 7 | 01234567 | 0 1 2 3 4 5 6 7 |\n") + fmt.Fprint(w, " | 8 9 A B C D E F | 89ABCDEF | 8 9 A B C D E F |\n") + + var ( + chunks = bytes.SplitEach(data, ncol) + chunk []byte + x int + y int + c byte + ) + for x, chunk = range chunks { + fmt.Fprintf(w, `%#08x|`, x*ncol) + + // Print as hex. + for y, c = range chunk { + fmt.Fprintf(w, ` %02x`, c) + } + for y++; y < ncol; y++ { + fmt.Fprint(w, ` `) + } + + // Print as char. + fmt.Fprint(w, ` | `) + for y, c = range chunk { + if c >= 33 && c <= 126 { + fmt.Fprintf(w, `%c`, c) + } else { + fmt.Fprint(w, `.`) + } + } + for y++; y < ncol; y++ { + fmt.Fprint(w, ` `) + } + + // Print as integer. + fmt.Fprint(w, ` |`) + for y, c = range chunk { + fmt.Fprintf(w, ` %3d`, c) + } + for y++; y < ncol; y++ { + fmt.Fprint(w, ` `) + } + fmt.Fprintf(w, " |%d\n", x*ncol) + } +} diff --git a/lib/hexdump/hexdump_example_test.go b/lib/hexdump/hexdump_example_test.go new file mode 100644 index 00000000..24058ca2 --- /dev/null +++ b/lib/hexdump/hexdump_example_test.go @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause + +package hexdump_test + +import ( + "bytes" + "fmt" + "log" + + libbytes "git.sr.ht/~shulhan/pakakeh.go/lib/bytes" + "git.sr.ht/~shulhan/pakakeh.go/lib/hexdump" +) + +func ExampleParse() { + var ( + in = []byte(`0000000 6548 6c6c 2c6f 7720 726f 646c 0021`) + + out []byte + err error + ) + + out, err = hexdump.Parse(in, false) + if err != nil { + log.Fatal(err) + } + + fmt.Printf(`%s`, libbytes.TrimNull(out)) + + // Output: + // Hello, world! +} + +func ExamplePrettyPrint() { + var ( + data = []byte{1, 2, 3, 'H', 'e', 'l', 'l', 'o', 254, 255} + bb bytes.Buffer + ) + + hexdump.PrettyPrint(&bb, `PrettyPrint`, data) + fmt.Println(bb.String()) + // Output: + // PrettyPrint + // | 0 1 2 3 4 5 6 7 | 01234567 | 0 1 2 3 4 5 6 7 | + // | 8 9 A B C D E F | 89ABCDEF | 8 9 A B C D E F | + // 0x00000000| 01 02 03 48 65 6c 6c 6f | ...Hello | 1 2 3 72 101 108 108 111 |0 + // 0x00000008| fe ff | .. | 254 255 |8 +} + +func ExamplePrint() { + title := `Print` + data := []byte(`Hello, world !`) + hexdump.Print(title, data, 5) + + // Output: + // Print + // 0 - 48 65 6C 6C 6F || H e l l o + // 5 - 2C 20 77 6F 72 || , . w o r + // 10 - 6C 64 20 21 || l d . ! +} diff --git a/lib/hexdump/hexdump_test.go b/lib/hexdump/hexdump_test.go new file mode 100644 index 00000000..e1c21b8f --- /dev/null +++ b/lib/hexdump/hexdump_test.go @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause + +package hexdump_test + +import ( + "os" + "path" + "testing" + + "git.sr.ht/~shulhan/pakakeh.go/lib/hexdump" + "git.sr.ht/~shulhan/pakakeh.go/lib/test" +) + +func TestParse(t *testing.T) { + var ( + tdata *test.Data + err error + ) + + tdata, err = test.LoadData(`testdata/Parse_test.txt`) + if err != nil { + t.Fatal(err) + } + + var ( + tag string + in []byte + exp []byte + got []byte + ) + for tag, in = range tdata.Input { + exp = tdata.Output[tag] + + got, err = hexdump.Parse(in, false) + if err != nil { + test.Assert(t, tag, string(exp), err.Error()) + continue + } + + test.Assert(t, tag, string(exp), string(got)) + } +} + +func TestParseExpDirTar(t *testing.T) { + var ( + tdata *test.Data + err error + ) + + tdata, err = test.LoadData(`testdata/Parse_exp_dir_tar_test.txt`) + if err != nil { + t.Fatal(err) + } + + var ( + tag = `exp_dir.tar` + expFile = path.Join(`testdata`, tag) + + exp []byte + got []byte + ) + + got, err = hexdump.Parse(tdata.Input[tag], false) + if err != nil { + t.Fatal(err) + } + + exp, err = os.ReadFile(expFile) + if err != nil { + t.Fatal(err) + } + + test.Assert(t, tag, exp, got) +} diff --git a/lib/bytes/testdata/ParseHexDump_exp_dir_tar_test.txt b/lib/hexdump/testdata/Parse_exp_dir_tar_test.txt index dceff86f..0c50929e 100644 --- a/lib/bytes/testdata/ParseHexDump_exp_dir_tar_test.txt +++ b/lib/hexdump/testdata/Parse_exp_dir_tar_test.txt @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause + >>> exp_dir.tar 0000000 7865 5f70 6964 2f72 0000 0000 0000 0000 0000010 0000 0000 0000 0000 0000 0000 0000 0000 diff --git a/lib/bytes/testdata/ParseHexDump_test.txt b/lib/hexdump/testdata/Parse_test.txt index e326072d..72cbe110 100644 --- a/lib/bytes/testdata/ParseHexDump_test.txt +++ b/lib/hexdump/testdata/Parse_test.txt @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> +// +// SPDX-License-Identifier: BSD-3-Clause + >>> trailing new line 0000000 6548 6c6c 2c6f 7720 726f 646c 0a21 diff --git a/lib/bytes/testdata/exp_dir.tar b/lib/hexdump/testdata/exp_dir.tar Binary files differindex 465deda2..465deda2 100644 --- a/lib/bytes/testdata/exp_dir.tar +++ b/lib/hexdump/testdata/exp_dir.tar diff --git a/lib/hexdump/testdata/exp_dir.tar.license b/lib/hexdump/testdata/exp_dir.tar.license new file mode 100644 index 00000000..5dd7fe5c --- /dev/null +++ b/lib/hexdump/testdata/exp_dir.tar.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> + +SPDX-License-Identifier: BSD-3-Clause diff --git a/lib/memfs/internal/test/embed/embed_test.go b/lib/memfs/internal/test/embed/embed_test.go index 1dcfc954..06b16d3a 100644 --- a/lib/memfs/internal/test/embed/embed_test.go +++ b/lib/memfs/internal/test/embed/embed_test.go @@ -16,7 +16,7 @@ func generate_testdata() *memfs.Node { GenFuncName: "generate_testdata", } node.SetMode(0o20000000755) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1699901114, 455911441) node.SetName("/") node.SetSize(0) node.AddChild(_memFS_getNode(memFS, "/direct", generate_testdata_direct)) @@ -37,7 +37,7 @@ func generate_testdata_direct() *memfs.Node { GenFuncName: "generate_testdata_direct", } node.SetMode(0o20000000755) - node.SetModTimeUnix(1709751019, 626038828) + node.SetModTimeUnix(1569586540, 0) node.SetName("direct") node.SetSize(0) node.AddChild(_memFS_getNode(memFS, "/direct/add", generate_testdata_direct_add)) @@ -52,7 +52,7 @@ func generate_testdata_direct_add() *memfs.Node { GenFuncName: "generate_testdata_direct_add", } node.SetMode(0o20000000755) - node.SetModTimeUnix(1709751019, 626038828) + node.SetModTimeUnix(1569586540, 0) node.SetName("add") node.SetSize(0) node.AddChild(_memFS_getNode(memFS, "/direct/add/file", generate_testdata_direct_add_file)) @@ -69,7 +69,7 @@ func generate_testdata_direct_add_file() *memfs.Node { Content: []byte("\x54\x65\x73\x74\x20\x64\x69\x72\x65\x63\x74\x20\x61\x64\x64\x20\x66\x69\x6C\x65\x2E\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 626038828) + node.SetModTimeUnix(1569586540, 0) node.SetName("file") node.SetSize(22) return node @@ -84,7 +84,7 @@ func generate_testdata_direct_add_file2() *memfs.Node { Content: []byte("\x54\x65\x73\x74\x20\x64\x69\x72\x65\x63\x74\x20\x61\x64\x64\x20\x66\x69\x6C\x65\x20\x32\x2E\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 626038828) + node.SetModTimeUnix(1569586540, 0) node.SetName("file2") node.SetSize(24) return node @@ -98,7 +98,7 @@ func generate_testdata_exclude() *memfs.Node { GenFuncName: "generate_testdata_exclude", } node.SetMode(0o20000000755) - node.SetModTimeUnix(1710216708, 236975330) + node.SetModTimeUnix(1633792794, 467899662) node.SetName("exclude") node.SetSize(0) node.AddChild(_memFS_getNode(memFS, "/exclude/dir", generate_testdata_exclude_dir)) @@ -116,7 +116,7 @@ func generate_testdata_exclude_dir() *memfs.Node { GenFuncName: "generate_testdata_exclude_dir", } node.SetMode(0o20000000700) - node.SetModTimeUnix(1710216708, 236975330) + node.SetModTimeUnix(1629620045, 798024232) node.SetName("dir") node.SetSize(0) return node @@ -131,7 +131,7 @@ func generate_testdata_exclude_index_link_css() *memfs.Node { Content: []byte("\x62\x6F\x64\x79\x20\x7B\x0A\x7D\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 626038828) + node.SetModTimeUnix(1562038157, 0) node.SetName("index-link.css") node.SetSize(9) return node @@ -146,7 +146,7 @@ func generate_testdata_exclude_index_link_html() *memfs.Node { Content: []byte("\x3C\x68\x74\x6D\x6C\x3E\x3C\x2F\x68\x74\x6D\x6C\x3E\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1588592347, 0) node.SetName("index-link.html") node.SetSize(14) return node @@ -161,7 +161,7 @@ func generate_testdata_exclude_index_link_js() *memfs.Node { Content: []byte("\x66\x75\x6E\x63\x74\x69\x6F\x6E\x20\x58\x28\x29\x20\x7B\x7D\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1562038157, 0) node.SetName("index-link.js") node.SetSize(16) return node @@ -175,7 +175,7 @@ func generate_testdata_include() *memfs.Node { GenFuncName: "generate_testdata_include", } node.SetMode(0o20000000755) - node.SetModTimeUnix(1710216708, 236975330) + node.SetModTimeUnix(1629623653, 749800911) node.SetName("include") node.SetSize(0) node.AddChild(_memFS_getNode(memFS, "/include/dir", generate_testdata_include_dir)) @@ -193,7 +193,7 @@ func generate_testdata_include_dir() *memfs.Node { GenFuncName: "generate_testdata_include_dir", } node.SetMode(0o20000000700) - node.SetModTimeUnix(1710216708, 236975330) + node.SetModTimeUnix(1564836597, 0) node.SetName("dir") node.SetSize(0) return node @@ -208,7 +208,7 @@ func generate_testdata_include_index_css() *memfs.Node { Content: []byte("\x62\x6F\x64\x79\x20\x7B\x0A\x7D\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 626038828) + node.SetModTimeUnix(1562038157, 0) node.SetName("index.css") node.SetSize(9) return node @@ -223,7 +223,7 @@ func generate_testdata_include_index_html() *memfs.Node { Content: []byte("\x3C\x68\x74\x6D\x6C\x3E\x3C\x2F\x68\x74\x6D\x6C\x3E\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1588592347, 0) node.SetName("index.html") node.SetSize(14) return node @@ -238,7 +238,7 @@ func generate_testdata_include_index_js() *memfs.Node { Content: []byte("\x66\x75\x6E\x63\x74\x69\x6F\x6E\x20\x58\x28\x29\x20\x7B\x7D\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1562038157, 0) node.SetName("index.js") node.SetSize(16) return node @@ -253,7 +253,7 @@ func generate_testdata_index_css() *memfs.Node { Content: []byte("\x62\x6F\x64\x79\x20\x7B\x0A\x7D\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 626038828) + node.SetModTimeUnix(1562038157, 0) node.SetName("index.css") node.SetSize(9) return node @@ -268,7 +268,7 @@ func generate_testdata_index_html() *memfs.Node { Content: []byte("\x3C\x68\x74\x6D\x6C\x3E\x3C\x2F\x68\x74\x6D\x6C\x3E\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1588592347, 0) node.SetName("index.html") node.SetSize(14) return node @@ -283,7 +283,7 @@ func generate_testdata_index_js() *memfs.Node { Content: []byte("\x66\x75\x6E\x63\x74\x69\x6F\x6E\x20\x58\x28\x29\x20\x7B\x7D\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1562038157, 0) node.SetName("index.js") node.SetSize(16) return node @@ -298,7 +298,7 @@ func generate_testdata_plain() *memfs.Node { Content: []byte("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x70\x6C\x61\x69\x6E\x20\x74\x65\x78\x74\x2E\x0A"), } node.SetMode(0o644) - node.SetModTimeUnix(1709751019, 629372161) + node.SetModTimeUnix(1562038157, 0) node.SetName("plain") node.SetSize(22) return node |
