From 5ebe2be10b96410a6182a2aa66ff0d2bd43eed3f Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Fri, 1 Jun 2018 09:07:47 +0200 Subject: The arg iterator is now responsible for allocation instead of core.Clap --- src/core.zig | 67 ++++++++++++++++++++++++++++---------------------------- src/extended.zig | 9 ++++---- 2 files changed, 38 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/core.zig b/src/core.zig index 8570220..5e47714 100644 --- a/src/core.zig +++ b/src/core.zig @@ -136,34 +136,39 @@ pub fn Arg(comptime Id: type) type { } /// A interface for iterating over command line arguments -pub const ArgIterator = struct { - const Error = error{OutOfMemory}; +pub fn ArgIterator(comptime E: type) type { + return struct { + const Self = this; + const Error = E; - nextFn: fn(iter: &ArgIterator, allocator: &mem.Allocator) Error!?[]const u8, + nextFn: fn(iter: &Self) Error!?[]const u8, - pub fn next(iter: &ArgIterator, allocator: &mem.Allocator) Error!?[]const u8 { - return iter.nextFn(iter, allocator); - } -}; + pub fn next(iter: &Self) Error!?[]const u8 { + return iter.nextFn(iter); + } + }; +} /// An ::ArgIterator, which iterates over a slice of arguments. /// This implementation does not allocate. pub const ArgSliceIterator = struct { + const Error = error{}; + args: []const []const u8, index: usize, - iter: ArgIterator, + iter: ArgIterator(Error), pub fn init(args: []const []const u8) ArgSliceIterator { return ArgSliceIterator { .args = args, .index = 0, - .iter = ArgIterator { + .iter = ArgIterator(Error) { .nextFn = nextFn, }, }; } - fn nextFn(iter: &ArgIterator, allocator: &mem.Allocator) ArgIterator.Error!?[]const u8 { + fn nextFn(iter: &ArgIterator(Error)) Error!?[]const u8 { const self = @fieldParentPtr(ArgSliceIterator, "iter", iter); if (self.args.len <= self.index) return null; @@ -176,22 +181,30 @@ pub const ArgSliceIterator = struct { /// An ::ArgIterator, which wraps the ArgIterator in ::std. /// On windows, this iterator allocates. pub const OsArgIterator = struct { + const Error = os.ArgIterator.NextError; + + arena: heap.ArenaAllocator, args: os.ArgIterator, - iter: ArgIterator, + iter: ArgIterator(Error), - pub fn init() OsArgIterator { + pub fn init(allocator: &mem.Allocator) OsArgIterator { return OsArgIterator { + .arena = heap.ArenaAllocator.init(allocator), .args = os.args(), - .iter = ArgIterator { + .iter = ArgIterator(Error) { .nextFn = nextFn, }, }; } - fn nextFn(iter: &ArgIterator, allocator: &mem.Allocator) ArgIterator.Error!?[]const u8 { + pub fn deinit(iter: &OsArgIterator) void { + iter.arena.deinit(); + } + + fn nextFn(iter: &ArgIterator(Error)) Error!?[]const u8 { const self = @fieldParentPtr(OsArgIterator, "iter", iter); if (builtin.os == builtin.Os.windows) { - return try self.args.next(allocator) ?? return null; + return try self.args.next(self.allocator) ?? return null; } else { return self.args.nextPosix(); } @@ -201,7 +214,7 @@ pub const OsArgIterator = struct { /// A command line argument parser which, given an ::ArgIterator, will parse arguments according /// to the ::params. ::Clap parses in an iterating manner, so you have to use a loop together with /// ::Clap.next to parse all the arguments of your program. -pub fn Clap(comptime Id: type) type { +pub fn Clap(comptime Id: type, comptime ArgError: type) type { return struct { const Self = this; @@ -215,14 +228,12 @@ pub fn Clap(comptime Id: type) type { }; }; - arena: heap.ArenaAllocator, params: []const Param(Id), - iter: &ArgIterator, + iter: &ArgIterator(ArgError), state: State, - pub fn init(params: []const Param(Id), iter: &ArgIterator, allocator: &mem.Allocator) Self { + pub fn init(params: []const Param(Id), iter: &ArgIterator(ArgError)) Self { var res = Self { - .arena = heap.ArenaAllocator.init(allocator), .params = params, .iter = iter, .state = State.Normal, @@ -231,10 +242,6 @@ pub fn Clap(comptime Id: type) type { return res; } - pub fn deinit(clap: &Self) void { - clap.arena.deinit(); - } - /// Get the next ::Arg that matches a ::Param. pub fn next(clap: &Self) !?Arg(Id) { const ArgInfo = struct { @@ -246,7 +253,7 @@ pub fn Clap(comptime Id: type) type { switch (clap.state) { State.Normal => { - const full_arg = (try clap.nextNoParse()) ?? return null; + const full_arg = (try clap.iter.next()) ?? return null; const arg_info = blk: { var arg = full_arg; var kind = ArgInfo.Kind.Bare; @@ -294,7 +301,7 @@ pub fn Clap(comptime Id: type) type { if (maybe_value) |v| break :blk v; - break :blk (try clap.nextNoParse()) ?? return error.MissingValue; + break :blk (try clap.iter.next()) ?? return error.MissingValue; }; return Arg(Id).init(param, value); @@ -351,7 +358,7 @@ pub fn Clap(comptime Id: type) type { return Arg(Id).init(param, null); if (arg.len <= next_index) { - const value = (try clap.nextNoParse()) ?? return error.MissingValue; + const value = (try clap.iter.next()) ?? return error.MissingValue; return Arg(Id).init(param, value); } @@ -364,11 +371,5 @@ pub fn Clap(comptime Id: type) type { return error.InvalidArgument; } - - // Returns the next arg in the underlying arg iterator - pub fn nextNoParse(clap: &Self) !?[]const u8 { - clap.state = State.Normal; - return try clap.iter.next(&clap.arena.allocator); - } }; } diff --git a/src/extended.zig b/src/extended.zig index b94f6f5..31e6455 100644 --- a/src/extended.zig +++ b/src/extended.zig @@ -103,13 +103,13 @@ pub const Command = struct { return res; } - pub fn parse(comptime command: &const Command, allocator: &mem.Allocator, arg_iter: &core.ArgIterator) !command.Result { + pub fn parse(comptime command: &const Command, allocator: &mem.Allocator, arg_iter: var) !command.Result { const Parent = struct {}; var parent = Parent{}; return command.parseHelper(&parent, allocator, arg_iter); } - fn parseHelper(comptime command: &const Command, parent: var, allocator: &mem.Allocator, arg_iter: &core.ArgIterator) !command.Result { + fn parseHelper(comptime command: &const Command, parent: var, allocator: &mem.Allocator, arg_iter: var) !command.Result { const Result = struct { parent: @typeOf(parent), result: command.Result, @@ -159,11 +159,10 @@ pub const Command = struct { }; var pos: usize = 0; - var iter = core.Clap(usize).init(core_params, arg_iter, allocator); - defer iter.deinit(); + var clap = core.Clap(usize, @typeOf(arg_iter.*).Error).init(core_params, arg_iter); arg_loop: - while (try iter.next()) |arg| : (pos += 1) { + while (try clap.next()) |arg| : (pos += 1) { inline for(command.params) |param, i| { comptime const field = "result." ++ param.field; -- cgit v1.2.3