diff options
Diffstat (limited to 'src/dump.zig')
-rw-r--r-- | src/dump.zig | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/dump.zig b/src/dump.zig new file mode 100644 index 0000000..a41b2be --- /dev/null +++ b/src/dump.zig @@ -0,0 +1,109 @@ +const std = @import("std"); +const adler32 = std.hash.Adler32; +const openFlags = std.fs.File.OpenFlags{ + .read = true, + .write = false, + .lock = std.fs.File.Lock.None, +}; +const output_flags = std.fs.File.CreateFlags{ + .read = false, + .truncate = true, + .exclusive = false, + .lock = std.fs.File.Lock.None, +}; + +fn help(args: [][]u8) u8 { + std.debug.warn( + \\Usage: {} {} [-h] [-o OUTPUT] input ... + \\ + \\Optional arguments: + \\ -h, --help show this help message and exit + \\ -o, --output OUTPUT output header file (by default, stdout) + \\ + \\Positional arguments: + \\ input one or more input files + \\ + , .{ args[0], args[1] }); + return if (args.len < 3) 255 else 0; +} + +pub fn cmd(args: [][]u8) u8 { + if (args.len < 3) { + return help(args); + } + + const State = enum { + Start, + OptionOutput, + }; + + var output_file: ?std.fs.File = null; + defer if (output_file != null) output_file.?.close(); + + var input_index: ?usize = null; + var state: State = State.Start; + + parse_args: for (args[2..args.len]) |c, i| { + switch (state) { + State.Start => { + switch (adler32.hash(c)) { + adler32.hash("-h"), adler32.hash("--help") => return help(args), + adler32.hash("-o"), adler32.hash("--output") => state = State.OptionOutput, + else => { + if (input_index == null) { + input_index = i; + break :parse_args; + } + }, + } + }, + State.OptionOutput => { + output_file = switch (std.fs.path.isAbsolute(c)) { + true => std.fs.createFileAbsolute(c, output_flags) catch return 128, + false => std.fs.cwd().createFile(c, output_flags) catch return 128, + }; + state = State.Start; + }, + } + } + + var output = (output_file orelse std.io.getStdOut()).outStream(); + + if (input_index == null) + return help(args); + + for (args[2 + input_index.? .. args.len]) |path| { + output.print("// {}\n", .{path}) catch return 1; + hexdump(output, path, path) catch std.debug.warn("// Could not read file '{}'\n", .{path}); + } + + return 0; +} + +fn hexdump(out: std.fs.File.OutStream, path: []const u8, name: []const u8) !void { + var file = switch (std.fs.path.isAbsolute(path)) { + true => try std.fs.openFileAbsolute(path, openFlags), + false => try std.fs.cwd().openFile(path, openFlags), + }; + defer file.close(); + + var buffer: [16]u8 = undefined; + var r: u64 = undefined; + var l: u64 = 0; + + try out.print("constexpr uint8_t {}_data[] = {{\n", .{name}); + while (true) { + r = file.read(&buffer) catch break; + if (r <= 0) + break; + + l += r; + try out.print(" ", .{}); + for (buffer[0..r]) |c| { + try out.print("0x{x:2}, ", .{c}); + } + try out.print("\n", .{}); + } + try out.print("}};\n", .{}); + try out.print("constexpr size_t {}_len = {};\n\n", .{ name, l }); +} |