summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jimmi Holst Christensen2018-03-14 21:36:50 +0100
committerGravatar Jimmi Holst Christensen2018-03-14 21:36:50 +0100
commit79f0c9cee9e5cd4413a65ae96a32872330e308ad (patch)
tree5b9e8f835ce7b4d9e3189db63777aa8e2ffe2c83
parentFixed code crashing Zig (diff)
downloadzig-clap-79f0c9cee9e5cd4413a65ae96a32872330e308ad.tar.gz
zig-clap-79f0c9cee9e5cd4413a65ae96a32872330e308ad.tar.xz
zig-clap-79f0c9cee9e5cd4413a65ae96a32872330e308ad.zip
Refactored clap to use inline loops where possible.
Time to study the differences in the assemply
-rw-r--r--.gitattributes1
-rw-r--r--clap.zig110
2 files changed, 64 insertions, 47 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..ef01f61
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
*.zig text eol=lf
diff --git a/clap.zig b/clap.zig
index f390229..6e3e7a8 100644
--- a/clap.zig
+++ b/clap.zig
@@ -22,16 +22,16 @@ pub fn Option(comptime Result: type, comptime ParseError: type) type {
22 IgnoresRequired 22 IgnoresRequired
23 }; 23 };
24 24
25 parser: fn(&Result, []const u8) ParseError!void, 25 parse: fn(&Result, []const u8) ParseError!void,
26 help: []const u8, 26 help: []const u8,
27 kind: Kind, 27 kind: Kind,
28 takes_value: bool, 28 takes_value: bool,
29 short: ?u8, 29 short: ?u8,
30 long: ?[]const u8, 30 long: ?[]const u8,
31 31
32 pub fn init(parser: fn(&Result, []const u8) ParseError!void) Self { 32 pub fn init(parse_fn: fn(&Result, []const u8) ParseError!void) Self {
33 return Self { 33 return Self {
34 .parser = parser, 34 .parse = parse_fn,
35 .help = "", 35 .help = "",
36 .kind = Kind.Optional, 36 .kind = Kind.Optional,
37 .takes_value = false, 37 .takes_value = false,
@@ -82,10 +82,12 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default
82 // This limits the user to 128 required arguments, which is more than 82 // This limits the user to 128 required arguments, which is more than
83 // enough. 83 // enough.
84 const required_mask = comptime blk: { 84 const required_mask = comptime blk: {
85 var required_index : u128 = 0;
85 var required_res : u128 = 0; 86 var required_res : u128 = 0;
86 for (options) |option, i| { 87 for (options) |option, i| {
87 if (option.kind == OptionT.Kind.Required) { 88 if (option.kind == OptionT.Kind.Required) {
88 required_res = (required_res << 1) | 0x1; 89 required_res |= 0x1 << required_index;
90 required_index += 1;
89 } 91 }
90 } 92 }
91 93
@@ -93,7 +95,17 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default
93 }; 95 };
94 96
95 return struct { 97 return struct {
96 fn parse(args: []const []const u8) !Result { 98 fn newRequired(option: &const OptionT, old_required: u128, index: usize) u128 {
99 switch (option.kind) {
100 OptionT.Kind.Required => {
101 return bits.set(u128, old_required, u7(index), false);
102 },
103 OptionT.Kind.IgnoresRequired => return 0,
104 else => return old_required,
105 }
106 }
107
108 pub fn parse(args: []const []const u8) !Result {
97 var result = *defaults; 109 var result = *defaults;
98 var required = required_mask; 110 var required = required_mask;
99 111
@@ -111,57 +123,61 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default
111 const arg = pair.arg; 123 const arg = pair.arg;
112 const kind = pair.kind; 124 const kind = pair.kind;
113 125
114 var required_index : usize = 0; 126 success: {
115 for (options) |option, op_i| { 127 var required_index = usize(0);
128
116 switch (kind) { 129 switch (kind) {
117 Arg.Kind.None => { 130 Arg.Kind.None => {
118 if (option.short != null) continue; 131 inline for (options) |option| {
119 if (option.long != null) continue; 132 defer if (option.kind == OptionT.Kind.Required) required_index += 1;
120 133 if (option.short != null) continue;
121 try option.parser(&result, arg); 134 if (option.long != null) continue;
122 135
123 switch (option.kind) { 136 try option.parse(&result, arg);
124 OptionT.Kind.Required => { 137 required = newRequired(option, required, required_index);
125 required = bits.set(u128, required, u7(required_index), false); 138 break :success;
126 required_index += 1;
127 },
128 OptionT.Kind.IgnoresRequired => {
129 required = 0;
130 required_index += 1;
131 },
132 else => {}
133 } 139 }
134
135 break;
136 }, 140 },
137 Arg.Kind.Short => { 141 Arg.Kind.Short => {
138 const short = option.short ?? continue; 142 inline for (options) |option| {
139 if (arg.len != 1 or arg[0] != short) continue; 143 defer if (option.kind == OptionT.Kind.Required) required_index += 1;
144 const short = option.short ?? continue;
145 if (arg.len == 1 and arg[0] == short) {
146 if (option.takes_value) {
147 arg_i += 1;
148 if (args.len <= arg_i) return error.OptionMissingValue;
149
150 try option.parse(&result, args[arg_i]);
151 } else {
152 try option.parse(&result, []u8{});
153 }
154
155 required = newRequired(option, required, required_index);
156 break :success;
157 }
158 }
140 }, 159 },
141 Arg.Kind.Long => { 160 Arg.Kind.Long => {
142 const long = option.long ?? continue; 161 inline for (options) |option| {
143 if (!mem.eql(u8, long, arg)) continue; 162 defer if (option.kind == OptionT.Kind.Required) required_index += 1;
163 const long = option.long ?? continue;
164 if (mem.eql(u8, arg, long)) {
165 if (option.takes_value) {
166 arg_i += 1;
167 if (args.len <= arg_i) return error.OptionMissingValue;
168
169 try option.parse(&result, args[arg_i]);
170 } else {
171 try option.parse(&result, []u8{});
172 }
173
174 required = newRequired(option, required, required_index);
175 break :success;
176 }
177 }
144 } 178 }
145 } 179 }
146 180
147 if (option.takes_value) arg_i += 1;
148 if (args.len <= arg_i) return error.MissingValueToArgument;
149 try option.parser(&result, args[arg_i]);
150
151 switch (option.kind) {
152 OptionT.Kind.Required => {
153 required = bits.set(u128, required, u7(required_index), false);
154 required_index += 1;
155 },
156 OptionT.Kind.IgnoresRequired => {
157 required = 0;
158 required_index += 1;
159 },
160 else => {}
161 }
162
163 break;
164 } else {
165 return error.InvalidArgument; 181 return error.InvalidArgument;
166 } 182 }
167 } 183 }
@@ -294,7 +310,7 @@ test "clap.parse.Example" {
294 Case { 310 Case {
295 .args = [][]const u8 { "-g" }, 311 .args = [][]const u8 { "-g" },
296 .res = Color { .r = 0, .g = 0, .b = 0 }, 312 .res = Color { .r = 0, .g = 0, .b = 0 },
297 .err = error.MissingValueToArgument, 313 .err = error.OptionMissingValue,
298 }, 314 },
299 }; 315 };
300 316