aboutsummaryrefslogtreecommitdiff
path: root/src/supplemental/util/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/supplemental/util/options.c')
-rw-r--r--src/supplemental/util/options.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/supplemental/util/options.c b/src/supplemental/util/options.c
new file mode 100644
index 00000000..d8f78deb
--- /dev/null
+++ b/src/supplemental/util/options.c
@@ -0,0 +1,124 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "core/nng_impl.h"
+#include "supplemental/util/options.h"
+
+// Call with optidx set to 1 to start parsing.
+int
+nng_opts_parse(int argc, const char **argv, const nng_optspec *opts, int *val,
+ const char **optarg, int *optidx)
+{
+ const nng_optspec *opt;
+ int matches;
+ bool shortopt;
+ size_t l;
+ const char * arg = argv[*optidx];
+ int i;
+
+ if ((i = *optidx) >= argc) {
+ return (-1);
+ }
+
+ if (arg[0] != '-') {
+ return (-1);
+ }
+ if (arg[1] == '\0') {
+ *optidx = i + 1;
+ return (-1);
+ }
+
+ if ((arg[0] == '-') && (arg[1] == '-')) {
+ arg += 2;
+ shortopt = false;
+ for (l = 0; arg[l] != '\0'; l++) {
+ if ((arg[l] == '=') || (arg[l] == ':')) {
+ break;
+ }
+ }
+ } else {
+ arg++;
+ shortopt = true;
+ l = 1;
+ }
+
+ matches = 0;
+ opt = NULL;
+
+ for (int x = 0; opts[x].o_val != 0; x++) {
+
+ if (shortopt) {
+ if (arg[0] == opts[x].o_short) {
+ matches = 1;
+ opt = &opts[x];
+ break;
+ }
+ continue;
+ }
+
+ if ((opts[x].o_name == NULL) ||
+ (strncmp(arg, opts[x].o_name, l) != 0)) {
+ continue;
+ }
+ matches++;
+ opt = &opts[x];
+
+ if (strlen(opts[x].o_name) == l) {
+ // Perfect match.
+ matches = 1;
+ break;
+ }
+ }
+
+ switch (matches) {
+ case 1:
+ // Exact match
+ break;
+ case 0:
+ // No such option
+ return (NNG_EINVAL);
+ break;
+ default:
+ // Ambiguous (not match)
+ return (NNG_EINVAL);
+ break;
+ }
+
+ if (!opt->o_arg) {
+ // No option clustering for short options yet.
+ if (arg[l] != '\0') {
+ return (NNG_EINVAL);
+ }
+ *val = opt->o_val;
+ *optidx = i + 1;
+ return (0);
+ }
+
+ if (arg[l] != '\0') {
+ if (shortopt) {
+ *optarg = arg + l;
+ } else {
+ *optarg = arg + l + 1;
+ }
+ } else {
+ i++;
+ if (i >= argc) {
+ return (NNG_EINVAL);
+ }
+ *optarg = argv[i];
+ }
+ *optidx = ++i;
+ *val = opt->o_val;
+
+ return (0);
+}