diff options
author | Holger Eitzenberger <holger@eitzenberger.org> | 2011-02-01 18:13:10 +0100 |
---|---|---|
committer | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2011-02-01 18:13:10 +0100 |
commit | ff1939dd4f7e1ccb2e98e2a17d8d2b8088fc2ac6 (patch) | |
tree | 2c55402ba1a20474a2f33b36b2d8a11ec5c62497 /src | |
parent | 004f06f32dd28f225a00d3ba7648a29eab28132e (diff) | |
download | ipset-ff1939dd4f7e1ccb2e98e2a17d8d2b8088fc2ac6.tar.gz |
ipset: improve command argument parsing
The number of comparisons for a matching a command name can be
made smaller by just checking on argv[1].
As an example consider the following 'create' arguments 'hashsize',
'family' and 'timeout'. When having the command
create foo hash:ip timeout 60 family inet hashsize 64
it compares without this patch:
strcmp("timeout", "hashsize")
strcmp("64", "hashsize")
strcmp("family", "hashsize")
strcmp("inet", "hashsize")
strcmp("hashsize", "hashsize")
It is worse in practice, as 'create' has more arguments than this.
Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/ipset.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/src/ipset.c b/src/ipset.c index 7dbb303..634ad90 100644 --- a/src/ipset.c +++ b/src/ipset.c @@ -206,40 +206,37 @@ restore(char *argv0) static int call_parser(int *argc, char *argv[], const struct ipset_arg *args) { - int i = 1, ret = 0; + int ret = 0; const struct ipset_arg *arg; const char *optstr; /* Currently CREATE and ADT may have got additional arguments */ - if (!args) - goto done; - for (arg = args; arg->opt; arg++) { - for (i = 1; i < *argc; ) { - D("argc: %u, i: %u: %s vs %s", - *argc, i, argv[i], arg->name[0]); - if (!(ipset_match_option(argv[i], arg->name))) { - i++; + if (!args && *argc > 1) + goto err_unknown; + while (*argc > 1) { + for (arg = args; arg->opt; arg++) { + D("argc: %u, %s vs %s", *argc, argv[1], arg->name[0]); + if (!(ipset_match_option(argv[1], arg->name))) continue; - } - optstr = argv[i]; + + optstr = argv[1]; /* Shift off matched option */ D("match %s", arg->name[0]); - ipset_shift_argv(argc, argv, i); - D("argc: %u, i: %u", *argc, i); + ipset_shift_argv(argc, argv, 1); switch (arg->has_arg) { case IPSET_MANDATORY_ARG: - if (i + 1 > *argc) + if (*argc < 2) return exit_error(PARAMETER_PROBLEM, "Missing mandatory argument " "of option `%s'", arg->name[0]); /* Fall through */ case IPSET_OPTIONAL_ARG: - if (i + 1 <= *argc) { - ret = ipset_call_parser(session, arg, argv[i]); + if (*argc >= 2) { + ret = ipset_call_parser(session, arg, argv[1]); if (ret < 0) return ret; - ipset_shift_argv(argc, argv, i); + ipset_shift_argv(argc, argv, 1); break; } /* Fall through */ @@ -248,14 +245,15 @@ call_parser(int *argc, char *argv[], const struct ipset_arg *args) if (ret < 0) return ret; } + break; } + if (!arg->opt) + goto err_unknown; } -done: - if (i < *argc) - return exit_error(PARAMETER_PROBLEM, - "Unknown argument: `%s'", - argv[i]); return ret; + +err_unknown: + return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'", argv[1]); } static enum ipset_adt |