DPDK patches and discussions
 help / color / mirror / Atom feed
From: Chengwen Feng <fengchengwen@huawei.com>
To: <dev@dpdk.org>, <thomas@monjalon.net>, <ferruh.yigit@amd.com>
Subject: [24.03 RFC] argparse: add argparse library
Date: Tue, 21 Nov 2023 12:26:51 +0000	[thread overview]
Message-ID: <20231121122651.7078-1-fengchengwen@huawei.com> (raw)

Introduce argparse library (which was inspired by the thread [1]),
compared with getopt, the argparse has following advantages:
1) Set the help information when defining parameters.
2) Support positional parameters.

The parameters parsing according following:
1) positional: use callback to parse (passed the long-name as the key
   for callback).
2) optional:
   In addition to callback to parse, but also support:
2.1) no-val: support set default value to saver.
2.2) has-val: support set value to saver, the value must be conform
              RTE_ARGPARSE_ARG_VAL_xxx.
2.3) opt-val: if current without value then treat as no-val, else could
              treat as has-val.

Examples: (take dmafwd as example):
1) If parse with callback:
	static int
	func(const char *key, const char *value, const char *opaque)
	{
		if (!strcmp("--mac-updating", key)) {
			mac_updating = 1;
		} else if (!strcmp("--no-mac-updating", key)) {
			mac_updating = 0;
		} else if (!strcmp("--portmask", key)) {
			dma_enabled_port_mask = dma_parse_portmask(optarg);
			if (dma_enabled_port_mask & ~default_port_mask ||
						dma_enabled_port_mask <= 0) {
				...
			}
		} else {
			...
		}
	}

	static int
	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
	{
		static struct rte_argparse opts[] = {
			.prog = "dma",
			.usage = NULL,
			.descriptor = "dma and nic fwd example",
			.epilog = NULL,
			.exit_on_error = true,
			.opt = {
				{ "--mac-updating", NULL, "Enable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--no-mac-updating", NULL, "disable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
			}
		};
		return rte_argparse_parse(opts, argc, argv);
	}

2) If parse with value:
	static int
	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
	{
		static struct rte_argparse opts[] = {
			.prog = "dma",
			.usage = NULL,
			.descriptor = "dma and nic fwd example",
			.epilog = NULL,
			.exit_on_error = true,
			.opt = {
				{ "--mac-updating", NULL, "Enable MAC addresses updating", NULL, 0, &mac_updating, (void *)1, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--no-mac-updating", NULL, "disable MAC addresses updating", NULL, 0, &mac_updating, (void *)0, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", NULL, 0, &dma_enabled_port_mask, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
			}
		};
		int ret;
		ret = rte_argparse_parse(opts, argc, argv);
		if (ret != 0)
			return ret;
		if (dma_enabled_port_mask & ~default_port_mask ||
					dma_enabled_port_mask <= 0) {
			...
		}
	}

3) Also could mix parse with func and with value.

[1] https://patchwork.dpdk.org/project/dpdk/patch/20231105054539.22303-2-fengchengwen@huawei.com/

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
---
 lib/argparse/meson.build    |   6 ++
 lib/argparse/rte_argparse.h | 139 ++++++++++++++++++++++++++++++++++++
 lib/argparse/version.map    |   7 ++
 lib/meson.build             |   1 +
 4 files changed, 153 insertions(+)
 create mode 100644 lib/argparse/meson.build
 create mode 100644 lib/argparse/rte_argparse.h
 create mode 100644 lib/argparse/version.map

diff --git a/lib/argparse/meson.build b/lib/argparse/meson.build
new file mode 100644
index 0000000000..ac4a883b8d
--- /dev/null
+++ b/lib/argparse/meson.build
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 HiSilicon Limited.
+
+headers = files('rte_argparse.h')
+
+deps += ['kvargs']
diff --git a/lib/argparse/rte_argparse.h b/lib/argparse/rte_argparse.h
new file mode 100644
index 0000000000..21157a9436
--- /dev/null
+++ b/lib/argparse/rte_argparse.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 HiSilicon Limited
+ */
+
+#ifndef RTE_ARGPARSE_H
+#define RTE_ARGPARSE_H
+
+/**
+ * @file rte_argparse.h
+ *
+ * This API provides argparse function.
+ *
+ * Compare with getopt, the argparse has following advantages:
+ * 1) Set the help information when defining parameters.
+ * 2) Support positional parameters.
+ *
+ * The parameters parsing according following:
+ * 1) positional: use callback to parse (passed the long-name as the key for
+ *    callback).
+ * 2) optional:
+ *    In addition to callback to parse, but also support:
+ *    2.1) no-val: support set default value to saver.
+ *    2.2) has-val: support set value to saver, the value must be conform
+ *                  RTE_ARGPARSE_ARG_VAL_xxx.
+ *    2.3) opt-val: if current without value then treat as no-val, else could
+ *                  treat as has-val.
+ *
+ */
+
+#include <stdint.h>
+
+#include <rte_kvargs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum rte_argparse_arg_flags {
+	/**
+	 * Bit0-1 represent whether has value
+	 */
+	RTE_ARGPARSE_ARG_NO_VAL = 1u << 0, /**< The arg has no value. */
+	RTE_ARGPARSE_ARG_HAS_VAL = 2u << 0, /**< The arg has value. */
+	RTE_ARGPARSE_ARG_OPT_VAL = 3u << 0, /**< The arg has optional value. */
+
+	/**
+	 * Bit2-4 represent the value type
+	 */
+	RTE_ARGPARSE_ARG_VAL_INT = 1u << 2, /**< The arg's value is int type. */
+	RTE_ARGPARSE_ARG_VAL_FLOAT = 2u << 2, /**< The arg's value is float type. */
+	RTE_ARGPARSE_ARG_VAL_BOOL = 3u << 2, /**< The arg's value is bool type. */
+	RTE_ARGPARSE_ARG_VAL_STRING = 4u << 2, /**< The arg's value is string type. */
+};
+
+/**
+ * A structure used to hold opt config.
+ */
+struct rte_argparse_arg {
+	/**
+	 * The long name of arg:
+	 *   1) If the arg is optional, it must start with '--',
+	 *   2) If it is a positional arg, it must not start with '-'.
+	 * Note: only one '-' will treat as error.
+	 */
+	const char *long_name;
+	/**
+	 * The short name of arg:
+	 *   1) This field could be set only if long_name is optional, and must
+	 *      start with only one '-' and one letter,
+	 *   2) Other case it should be set NULL.
+	 */
+	const char *short_name;
+	/** The help info of arg. */
+	const char *help;
+
+	/*
+	 * Parse the arg's callback, it will be used to parse the arg if
+	 * it is not NULL.
+	 */
+	arg_handler_t callback;
+	/** The opaque which used to invoke callback */
+	void *opaque;
+
+	/*
+	 * The saver for the arg. If not NULL, set value to default_val or
+	 * parse from input.
+	 * Note: the flags of the arg must be RTE_ARGPARSE_VAL_* if this value
+	 * is not NULL.
+	 */
+	void *saver;
+	/*
+	 * Default value for the arg, cover following case:
+	 *   1) The arg don't require value, the saver will set to default_val
+	 *      when option found.
+	 *   2) The arg has option value but don't take value this time, the
+	 *      saver will set to default_val when option found.
+	 */
+	void *default_val;
+
+	/** @see rte_argparse_arg_flags. */
+	uint32_t flags;
+};
+
+/**
+ * A structure used to hold argparse basic info.
+ */
+struct rte_argparse {
+	const char *prog;       /**< Program name */
+	const char *usage;      /**< How to use the program */
+	const char *descriptor; /**< Explain what the program does */
+	const char *epilog;     /**< Text at the bottom of help */
+	bool exit_on_error;     /**< Whether exit when error */
+	struct rte_argparse_arg opt[]; /**< */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Parse parameters
+ *
+ * @param self
+ *   Parser handler.
+ * @param argc
+ *   Parameters count
+ * @param argv
+ *   Array of parameters points.
+ *
+ * @return
+ *   0 on success. Otherwise negative value is returned.
+ */
+__rte_experimental
+int rte_argparse_parse(struct rte_argparse *self, int argc, char **argv);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_ARGPARSE_H */
diff --git a/lib/argparse/version.map b/lib/argparse/version.map
new file mode 100644
index 0000000000..36b0902167
--- /dev/null
+++ b/lib/argparse/version.map
@@ -0,0 +1,7 @@
+EXPERIMENTAL  {
+	global:
+
+	rte_argparse_parse;
+
+	local: *;
+};
diff --git a/lib/meson.build b/lib/meson.build
index 6c143ce5a6..cdd2d3c536 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -11,6 +11,7 @@
 libraries = [
         'log',
         'kvargs', # eal depends on kvargs
+        'argparse',
         'telemetry', # basic info querying
         'eal', # everything depends on eal
         'ring',
-- 
2.17.1


             reply	other threads:[~2023-11-21 12:29 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-21 12:26 Chengwen Feng [this message]
2023-11-21 16:36 ` Stephen Hemminger
2023-11-22  6:28   ` fengchengwen
2023-12-04  7:50 ` [RFC v2 0/6] " Chengwen Feng
2023-12-04  7:50   ` [RFC v2 1/6] argparse: " Chengwen Feng
2023-12-04 17:10     ` Stephen Hemminger
2023-12-05  1:22       ` fengchengwen
2023-12-04  7:50   ` [RFC v2 2/6] argparse: support verify argument config Chengwen Feng
2023-12-04  7:50   ` [RFC v2 3/6] test/argparse: add verify argument config test Chengwen Feng
2023-12-04  7:50   ` [RFC v2 4/6] argparse: support parse parameters Chengwen Feng
2023-12-04  7:50   ` [RFC v2 5/6] test/argparse: add parse parameters test Chengwen Feng
2023-12-04  7:50   ` [RFC v2 6/6] examples/dma: replace getopt with argparse Chengwen Feng
2023-12-11  9:50 ` [RFC v3 00/12] add argparse library Chengwen Feng
2023-12-11  9:50   ` [RFC v3 01/12] eal: introduce more macro for bit definition Chengwen Feng
2023-12-11  9:51   ` [RFC v3 02/12] argparse: add argparse library Chengwen Feng
2023-12-11  9:51   ` [RFC v3 03/12] argparse: support verify argument config Chengwen Feng
2023-12-11  9:51   ` [RFC v3 04/12] test/argparse: add verify argument config test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 05/12] argparse: support parse parameters Chengwen Feng
2023-12-11  9:51   ` [RFC v3 06/12] test/argparse: add parse parameters test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 07/12] argparse: provide parsing known type API Chengwen Feng
2023-12-11  9:51   ` [RFC v3 08/12] test/argparse: add parse type test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 09/12] argparse: support parse unsigned base type Chengwen Feng
2023-12-11  9:51   ` [RFC v3 10/12] test/argparse: add parse unsigned base type test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 11/12] argparse: pretty help info Chengwen Feng
2023-12-11  9:51   ` [RFC v3 12/12] examples/dma: replace getopt with argparse Chengwen Feng
2024-01-22  3:57 ` [PATCH 00/12] add argparse library Chengwen Feng
2024-01-22  3:57   ` [PATCH 01/12] eal: introduce more macro for bit definition Chengwen Feng
2024-01-24 13:00     ` Thomas Monjalon
2024-01-22  3:57   ` [PATCH 02/12] argparse: add argparse library Chengwen Feng
2024-01-22  4:54     ` Stephen Hemminger
2024-01-22  6:06       ` fengchengwen
2024-01-24 13:24     ` Thomas Monjalon
2024-01-25  3:44       ` fengchengwen
2024-01-22  3:57   ` [PATCH 03/12] argparse: support verify argument config Chengwen Feng
2024-01-22  3:57   ` [PATCH 04/12] test/argparse: add verify argument config test Chengwen Feng
2024-01-24 13:01     ` Thomas Monjalon
2024-01-22  3:57   ` [PATCH 05/12] argparse: support parse parameters Chengwen Feng
2024-01-22  3:57   ` [PATCH 06/12] test/argparse: add parse parameters test Chengwen Feng
2024-01-22  3:57   ` [PATCH 07/12] argparse: provide parsing known type API Chengwen Feng
2024-01-22  3:57   ` [PATCH 08/12] test/argparse: add parse type test Chengwen Feng
2024-01-22  3:57   ` [PATCH 09/12] argparse: support parse unsigned base type Chengwen Feng
2024-01-22  3:58   ` [PATCH 10/12] test/argparse: add parse unsigned base type test Chengwen Feng
2024-01-22  3:58   ` [PATCH 11/12] argparse: pretty help info Chengwen Feng
2024-01-22  3:58   ` [PATCH 12/12] examples/dma: replace getopt with argparse Chengwen Feng
2024-01-24 13:26     ` Thomas Monjalon
2024-01-24 15:54 ` [24.03 RFC] argparse: add argparse library Stephen Hemminger
2024-01-25  6:31   ` fengchengwen
2024-01-26 16:38     ` Stephen Hemminger
2024-01-25 11:52 ` [PATCH v2 0/8] " Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 1/8] eal: introduce more macro for bit definition Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 2/8] argparse: add argparse library Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 3/8] argparse: support verify argument config Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 4/8] argparse: support parse parameters Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 5/8] argparse: provide parsing known type API Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 6/8] argparse: support parse unsigned base type Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 7/8] argparse: pretty help info Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 8/8] examples/dma: replace getopt with argparse Chengwen Feng
2024-01-26  6:10 ` [PATCH v3 0/8] add argparse library Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 1/8] eal: introduce more macro for bit definition Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 2/8] argparse: add argparse library Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 3/8] argparse: support verify argument config Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 4/8] argparse: support parse parameters Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 5/8] argparse: provide parsing known type API Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 6/8] argparse: support parse unsigned base type Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 7/8] argparse: pretty help info Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 8/8] examples/dma: replace getopt with argparse Chengwen Feng
2024-02-14 16:53   ` [PATCH v3 0/8] add argparse library Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231121122651.7078-1-fengchengwen@huawei.com \
    --to=fengchengwen@huawei.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).