From b2bf66c4365dcb2793cf66dfe3a80e263874a102 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Thu, 19 Jan 2023 02:58:31 +0100 Subject: [PATCH] Hexdump: complete rewrite, fixes all known problems. --- zig-impl/src/hexdump.zig | 124 +++++++++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 30 deletions(-) diff --git a/zig-impl/src/hexdump.zig b/zig-impl/src/hexdump.zig index c86483c..0f31810 100644 --- a/zig-impl/src/hexdump.zig +++ b/zig-impl/src/hexdump.zig @@ -2,8 +2,7 @@ const std = @import("std"); const print = std.debug.print; pub fn hexdump(stream: anytype, header: [] const u8, buffer: [] const u8) std.os.WriteError!void { - try stream.writeAll("\n"); - + // Print a header. if (header.len > 0) { var hdr: [64] u8 = undefined; var offset: usize = (hdr.len / 2) - ((header.len / 2) - 1); @@ -17,52 +16,117 @@ pub fn hexdump(stream: anytype, header: [] const u8, buffer: [] const u8) std.os var hexb: u32 = 0; var ascii: [16] u8 = undefined; + // First line, first left side (simple number). try stream.print("\n {d:0>4}: ", .{ hexb }); + // Loop on all values in the buffer (i from 0 to buffer.len). var i: u32 = 0; while (i < buffer.len) : (i += 1) { + // Print actual hexadecimal value. try stream.print("{X:0>2} ", .{ buffer[i] }); + // What to print (simple ascii text, right side). if (buffer[i] >= ' ' and buffer[i] <= '~') { ascii[(i % 16)] = buffer[i]; } else { ascii[(i % 16)] = '.'; } - if ((i + 1) % 8 == 0 or (i + 1) == buffer.len) { + // Next input is a multiple of 8 = extra space. + if ((i + 1) % 8 == 0) { try stream.writeAll(" "); + } - if ((i + 1) % 16 == 0) { - hexb += 16; - - if ((i + 1) != buffer.len) { - try stream.print("{s}\n {d:0>4}: ", .{ ascii[0..ascii.len], hexb }); - } else { - try stream.print("{s}\n", .{ ascii[0..ascii.len] }); - } - } else if ((i + 1) == buffer.len) { - var x: u32 = (i + 1) % 16; - - while (x < 16) : (x += 1) { - try stream.writeAll(" "); - } - - try stream.print(" {s}\n", .{ ascii[0..((i+1) % 16)] }); + // No next input: print the right amount of spaces. + if ((i + 1) == buffer.len) { + // Each line is 16 bytes to print, each byte takes 3 characters. + var missing_spaces = 3 * (15 - (i%16)); + // Missing an extra space if the current index % 16 is less than 7. + if ((i%16) < 7) { missing_spaces += 1; } + while (missing_spaces > 0) : (missing_spaces -= 1) { + try stream.writeAll(" "); } } + + // Every 16 bytes: print ascii text and line return. + + // Case 1: it's been 16 bytes AND it's the last byte to print. + if ((i + 1) % 16 == 0 and (i + 1) == buffer.len) { + try stream.print("{s}\n", .{ ascii[0..ascii.len] }); + } + // Case 2: it's been 16 bytes but it's not the end of the buffer. + else if ((i + 1) % 16 == 0 and (i + 1) != buffer.len) { + try stream.print("{s}\n", .{ ascii[0..ascii.len] }); + hexb += 16; + try stream.print(" {d:0>4}: ", .{ hexb }); + } + // Case 3: not the end of the 16 bytes row but it's the end of the buffer. + else if ((i + 1) % 16 != 0 and (i + 1) == buffer.len) { + try stream.print(" {s}\n", .{ ascii[0..((i+1) % 16)] }); + } + // Case 4: not the end of the 16 bytes row and not the end of the buffer. + // Do nothing. } try stream.writeAll("\n"); } -// test "simple hexdump test" { -// print("\n\nPrint hexdump, NO AUTOMATIC VERIFICATION, READ SOURCE CODE\n\n", .{}); -// -// var buffer = "hello this is a simple text to print"; -// var hexbuf: [2000]u8 = undefined; -// var hexfbs = std.io.fixedBufferStream(&hexbuf); -// var hexwriter = hexfbs.writer(); -// try hexdump(hexwriter, "Hello World", buffer); -// print("{s}\n", .{hexfbs.getWritten()}); -// -// } +test "36-byte hexdump test" { + print("\nPrint hexdump, NO AUTOMATIC VERIFICATION, READ SOURCE CODE\n", .{}); + + var buffer = "hello this is a simple text to print"; + var hexbuf: [2000]u8 = undefined; + var hexfbs = std.io.fixedBufferStream(&hexbuf); + var hexwriter = hexfbs.writer(); + try hexdump(hexwriter, "Hello World", buffer); + print("{s}\n", .{hexfbs.getWritten()}); + +} + +test "32-byte hexdump test" { + print("\nPrint hexdump, NO AUTOMATIC VERIFICATION, READ SOURCE CODE\n", .{}); + + var buffer = "THIS IS THE END, MY ONLY... END"; + var hexbuf: [2000]u8 = undefined; + var hexfbs = std.io.fixedBufferStream(&hexbuf); + var hexwriter = hexfbs.writer(); + try hexdump(hexwriter, "Hello World", buffer); + print("{s}\n", .{hexfbs.getWritten()}); + +} + +test "26-byte hexdump test" { + print("\nPrint hexdump, NO AUTOMATIC VERIFICATION, READ SOURCE CODE\n", .{}); + + var buffer = "hello this is another text"; + var hexbuf: [2000]u8 = undefined; + var hexfbs = std.io.fixedBufferStream(&hexbuf); + var hexwriter = hexfbs.writer(); + try hexdump(hexwriter, "Hello World", buffer); + print("{s}\n", .{hexfbs.getWritten()}); + +} + +test "1-byte hexdump test" { + print("\nPrint hexdump, NO AUTOMATIC VERIFICATION, READ SOURCE CODE\n", .{}); + + var buffer = "h"; + var hexbuf: [2000]u8 = undefined; + var hexfbs = std.io.fixedBufferStream(&hexbuf); + var hexwriter = hexfbs.writer(); + try hexdump(hexwriter, "Hello World", buffer); + print("{s}\n", .{hexfbs.getWritten()}); + +} + +test "0-byte hexdump test" { + print("\nPrint hexdump, NO AUTOMATIC VERIFICATION, READ SOURCE CODE\n", .{}); + + var buffer = ""; + var hexbuf: [2000]u8 = undefined; + var hexfbs = std.io.fixedBufferStream(&hexbuf); + var hexwriter = hexfbs.writer(); + try hexdump(hexwriter, "Hello World", buffer); + print("{s}\n", .{hexfbs.getWritten()}); + +}