1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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 });
}
|