summaryrefslogtreecommitdiff
path: root/src/dump.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/dump.zig')
-rw-r--r--src/dump.zig109
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 });
+}