get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/134786/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 134786,
    "url": "http://patches.dpdk.org/api/patches/134786/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20231204075048.894-2-fengchengwen@huawei.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20231204075048.894-2-fengchengwen@huawei.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231204075048.894-2-fengchengwen@huawei.com",
    "date": "2023-12-04T07:50:43",
    "name": "[RFC,v2,1/6] argparse: add argparse library",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "b4695a9b4c45db4d3794cc7ae7b60659ead1f750",
    "submitter": {
        "id": 2146,
        "url": "http://patches.dpdk.org/api/people/2146/?format=api",
        "name": "fengchengwen",
        "email": "fengchengwen@huawei.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20231204075048.894-2-fengchengwen@huawei.com/mbox/",
    "series": [
        {
            "id": 30439,
            "url": "http://patches.dpdk.org/api/series/30439/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=30439",
            "date": "2023-12-04T07:50:42",
            "name": "add argparse library",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/30439/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/134786/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/134786/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id AB8284365D;\n\tMon,  4 Dec 2023 08:54:35 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 18EA940DCA;\n\tMon,  4 Dec 2023 08:54:06 +0100 (CET)",
            "from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187])\n by mails.dpdk.org (Postfix) with ESMTP id 3B2D24067D\n for <dev@dpdk.org>; Mon,  4 Dec 2023 08:53:59 +0100 (CET)",
            "from dggpeml500024.china.huawei.com (unknown [172.30.72.54])\n by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4SkGB66Pl5zvRWN;\n Mon,  4 Dec 2023 15:53:18 +0800 (CST)",
            "from localhost.localdomain (10.50.165.33) by\n dggpeml500024.china.huawei.com (7.185.36.10) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id\n 15.1.2507.35; Mon, 4 Dec 2023 15:53:55 +0800"
        ],
        "From": "Chengwen Feng <fengchengwen@huawei.com>",
        "To": "<dev@dpdk.org>, <thomas@monjalon.net>, <ferruh.yigit@amd.com>,\n <stephen@networkplumber.org>",
        "CC": "<tangkunshan@huawei.com>",
        "Subject": "[RFC v2 1/6] argparse: add argparse library",
        "Date": "Mon, 4 Dec 2023 07:50:43 +0000",
        "Message-ID": "<20231204075048.894-2-fengchengwen@huawei.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20231204075048.894-1-fengchengwen@huawei.com>",
        "References": "<20231121122651.7078-1-fengchengwen@huawei.com>\n <20231204075048.894-1-fengchengwen@huawei.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.50.165.33]",
        "X-ClientProxiedBy": "dggems701-chm.china.huawei.com (10.3.19.178) To\n dggpeml500024.china.huawei.com (7.185.36.10)",
        "X-CFilter-Loop": "Reflected",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Introduce argparse library (which was inspired by the thread [1]). This\ncommit provides public API and doc.\n\n[1] https://patchwork.dpdk.org/project/dpdk/patch/20231105054539.22303-2-fengchengwen@huawei.com/\n\nSigned-off-by: Chengwen Feng <fengchengwen@huawei.com>\n---\n doc/api/doxy-api-index.md              |   1 +\n doc/api/doxy-api.conf.in               |   1 +\n doc/guides/prog_guide/argparse_lib.rst | 142 ++++++++++++++++++++\n doc/guides/prog_guide/index.rst        |   1 +\n lib/argparse/meson.build               |   7 +\n lib/argparse/rte_argparse.c            |  14 ++\n lib/argparse/rte_argparse.h            | 179 +++++++++++++++++++++++++\n lib/argparse/version.map               |   7 +\n lib/meson.build                        |   1 +\n 9 files changed, 353 insertions(+)\n create mode 100644 doc/guides/prog_guide/argparse_lib.rst\n create mode 100644 lib/argparse/meson.build\n create mode 100644 lib/argparse/rte_argparse.c\n create mode 100644 lib/argparse/rte_argparse.h\n create mode 100644 lib/argparse/version.map",
    "diff": "diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md\nindex a6a768bd7c..fe41fba6ec 100644\n--- a/doc/api/doxy-api-index.md\n+++ b/doc/api/doxy-api-index.md\n@@ -220,6 +220,7 @@ The public API headers are grouped by topics:\n   [random](@ref rte_random.h),\n   [config file](@ref rte_cfgfile.h),\n   [key/value args](@ref rte_kvargs.h),\n+  [argument parse](@ref rte_argparse.h),\n   [string](@ref rte_string_fns.h),\n   [thread](@ref rte_thread.h)\n \ndiff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in\nindex e94c9e4e46..76f89afe71 100644\n--- a/doc/api/doxy-api.conf.in\n+++ b/doc/api/doxy-api.conf.in\n@@ -28,6 +28,7 @@ INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \\\n                           @TOPDIR@/lib/eal/include \\\n                           @TOPDIR@/lib/eal/include/generic \\\n                           @TOPDIR@/lib/acl \\\n+                          @TOPDIR@/lib/argparse \\\n                           @TOPDIR@/lib/bbdev \\\n                           @TOPDIR@/lib/bitratestats \\\n                           @TOPDIR@/lib/bpf \\\ndiff --git a/doc/guides/prog_guide/argparse_lib.rst b/doc/guides/prog_guide/argparse_lib.rst\nnew file mode 100644\nindex 0000000000..d9813cbeff\n--- /dev/null\n+++ b/doc/guides/prog_guide/argparse_lib.rst\n@@ -0,0 +1,142 @@\n+.. SPDX-License-Identifier: BSD-3-Clause\n+   Copyright 2023 HiSilicon Limited\n+\n+Argparse Library\n+================\n+\n+The argparse library provides argument parse functionality, this library makes\n+it easy to write user-friendly command-line program.\n+\n+Features and Capabilities\n+-------------------------\n+\n+- Support parse optional argument (which could take with no-value,\n+  required-value and optional-value).\n+\n+- Support parse positional argument (which must take with required-value).\n+\n+- Support automatic generate usage information.\n+\n+- Support issue errors when provide with invalid arguments.\n+\n+- Support parse argument by two way: 1) autosave: for which known value types,\n+  this way can be used; 2) callback: will invoke user callback to parse.\n+\n+Usage Guide\n+-----------\n+\n+The following code demonstrates how to initialize:\n+\n+.. code-block:: C\n+\n+   static int\n+   argparse_user_callback(uint32_t index, const char *value, void *opaque)\n+   {\n+      if (index == 1) {\n+         /* process \"--ddd\" argument, because it has no-value, the parameter value is NULL. */\n+         ...\n+      } else if (index == 2) {\n+         /* process \"--eee\" argument, because it has required-value, the parameter value must not NULL. */\n+         ...\n+      } else if (index == 3) {\n+         /* process \"--fff\" argument, because it has optional-value, the parameter value maybe NULL or not NULL, depend on input. */\n+         ...\n+      } else if (index == 300) {\n+         /* process \"ppp\" argument, because it's a positional argument, the parameter value must not NULL. */\n+         ...\n+      } else {\n+         return -EINVAL;\n+      }\n+   }\n+\n+   int aaa_val, bbb_val, ccc_val, ooo_val;\n+\n+   static struct rte_argparse obj = {\n+      .prog_name = \"test-demo\",\n+      .usage = \"[EAL options] -- [optional parameters] [positional parameters]\",\n+      .descriptor = NULL,\n+      .epilog = NULL,\n+      .exit_on_error = true,\n+      .callback = argparse_user_callback,\n+      .args = {\n+         { \"--aaa\", \"-a\", \"aaa argument\", (void *)&aaa_val, (void *)100, RTE_ARGPARSE_ARG_NO_VALUE       | RTE_ARGPARSE_ARG_VALUE_INT },\n+         { \"--bbb\", \"-b\", \"bbb argument\", (void *)&bbb_val, NULL,        RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT },\n+         { \"--ccc\", \"-c\", \"ccc argument\", (void *)&ccc_val, (void *)200, RTE_ARGPARSE_ARG_OPTIONAL_VALUE | RTE_ARGPARSE_ARG_VALUE_INT },\n+         { \"--ddd\", \"-d\", \"ddd argument\", NULL,             (void *)1,   RTE_ARGPARSE_ARG_NO_VALUE       },\n+         { \"--eee\", \"-e\", \"eee argument\", NULL,             (void *)2,   RTE_ARGPARSE_ARG_REQUIRED_VALUE },\n+         { \"--fff\", \"-f\", \"fff argument\", NULL,             (void *)3,   RTE_ARGPARSE_ARG_OPTIONAL_VALUE },\n+         { \"ooo\",   NULL, \"ooo argument\", (void *)&ooo_val, NULL,        RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT },\n+         { \"ppp\",   NULL, \"ppp argument\", NULL,             (void *)300, RTE_ARGPARSE_ARG_REQUIRED_VALUE },\n+      },\n+   };\n+\n+   int\n+   main(int argc, char **argv)\n+   {\n+      ...\n+      ret = rte_argparse_parse(&obj, argc, argv);\n+      ...\n+   }\n+\n+Parsing by autosave way\n+~~~~~~~~~~~~~~~~~~~~~~~\n+\n+For which known value types (just like ``RTE_ARGPARSE_ARG_VALUE_INT``\"), could\n+parse by autosave way, just like above \"--aaa\"/\"--bbb\"/\"--ccc\" optional\n+arguments:\n+\n+If the user input parameter are: \"program --aaa --bbb 1234 --ccc=20 ...\", then\n+the aaa_val will equal 100, the bbb_val will equal 1234 and the ccc_val will\n+equal 20.\n+\n+If the user input parameter are: \"program --ccc ...\", then the aaa_val and\n+bbb_val will not modify, and ccc_val will equal 200.\n+\n+Parsing by callback way\n+~~~~~~~~~~~~~~~~~~~~~~~\n+\n+It could also choose to use callback to parse, just define a unique index for\n+the argument and make the field val_save to be NULL also zero value-type. Just\n+like above \"--ddd\"/\"--eee\"/\"--fff\" optional arguments:\n+\n+If the user input parameter are: \"program --ddd --eee 2345 --fff=30 ...\", the\n+function argparse_user_callback() will be invoke to parse the value.\n+\n+Positional arguments\n+~~~~~~~~~~~~~~~~~~~~\n+\n+The positional arguments could not start with a hyphen (-). The above code show\n+that there are two positional arguments \"ooo\"/\"ppp\", it must be flags with\n+``RTE_ARGPARSE_ARG_REQUIRED_VALUE``, and it also could use autosave or callback\n+to parsing:\n+\n+If the user input parameter are: \"program [optionals] 456 789\", then the ooo_val\n+will equal 456, and ppp_val will equal 789.\n+\n+Multiple times argument\n+~~~~~~~~~~~~~~~~~~~~~~~\n+\n+If want to support the ability to enter the same argument multiple times, then\n+should mark ``RTE_ARGPARSE_ARG_SUPPORT_MULTI`` in flags field. For examples:\n+\n+.. code-block:: C\n+\n+   ...\n+   { \"--xyz\", \"-x\", \"xyz argument\", NULL, (void *)10, RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_SUPPORT_MULTI },\n+   ...\n+\n+Then the user input parameter could be: \"program --xyz 123 --xyz 456 ...\".\n+\n+It's important to note that the multiple times flag only support with optional\n+argument and must be parsing by callback way.\n+\n+Other Notes\n+~~~~~~~~~~~\n+\n+For optional arguments, short-name can be defined or not defined. For arguments\n+that have required value, the following inputs are supported:\n+\"program --bbb=123 --eee 456 ...\" or \"program -b=123 -e 456 ...\".\n+\n+For arguments that have optional value, the following inputs are supported:\n+\"program --ccc --fff=100 ...\" or \"program -c -f=100\".\n+\ndiff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst\nindex 94964357ff..d09d958e6c 100644\n--- a/doc/guides/prog_guide/index.rst\n+++ b/doc/guides/prog_guide/index.rst\n@@ -13,6 +13,7 @@ Programmer's Guide\n     source_org\n     env_abstraction_layer\n     log_lib\n+    argparse_lib\n     cmdline\n     service_cores\n     trace_lib\ndiff --git a/lib/argparse/meson.build b/lib/argparse/meson.build\nnew file mode 100644\nindex 0000000000..14ea735fc0\n--- /dev/null\n+++ b/lib/argparse/meson.build\n@@ -0,0 +1,7 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2023 HiSilicon Limited.\n+\n+sources = files('rte_argparse.c')\n+headers = files('rte_argparse.h')\n+\n+deps += ['log']\ndiff --git a/lib/argparse/rte_argparse.c b/lib/argparse/rte_argparse.c\nnew file mode 100644\nindex 0000000000..bf14c56858\n--- /dev/null\n+++ b/lib/argparse/rte_argparse.c\n@@ -0,0 +1,14 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 HiSilicon Limited\n+ */\n+\n+#include \"rte_argparse.h\"\n+\n+int\n+rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv)\n+{\n+\t(void)obj;\n+\t(void)argc;\n+\t(void)argv;\n+\treturn 0;\n+}\ndiff --git a/lib/argparse/rte_argparse.h b/lib/argparse/rte_argparse.h\nnew file mode 100644\nindex 0000000000..45f7a58607\n--- /dev/null\n+++ b/lib/argparse/rte_argparse.h\n@@ -0,0 +1,179 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 HiSilicon Limited\n+ */\n+\n+#ifndef RTE_ARGPARSE_H\n+#define RTE_ARGPARSE_H\n+\n+/**\n+ * @file rte_argparse.h\n+ *\n+ * Argument parse API.\n+ *\n+ * The argument parse API makes it easy to write user-friendly command-line\n+ * program. The program defines what arguments it requires, and the API\n+ * will parse those arguments which described in [argc, argv].\n+ *\n+ * The API provides following functions:\n+ * 1) Support parse optional argument (which could take with no-value,\n+ *    required-value and optional-value.\n+ * 2) Support parse positional argument (which must take with required-value).\n+ * 3) Support automatic generate usage information.\n+ * 4) Support issue errors when provided with invalid arguments.\n+ *\n+ * There are two ways to parse arguments:\n+ * 1) AutoSave: for which known value types, the way can be used.\n+ * 2) Callback: will invoke user callback to parse.\n+ *\n+ */\n+\n+#include <stdbool.h>\n+#include <stdint.h>\n+\n+#include <rte_compat.h>\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/**\n+ * Flag definition (in bitmask form) for an argument.\n+ */\n+enum rte_argparse_flag {\n+\t/**\n+\t * Bit0-1: represent the argument whether has value.\n+\t */\n+\tRTE_ARGPARSE_ARG_NO_VALUE = 1u << 0, /**< The argument has no value. */\n+\tRTE_ARGPARSE_ARG_REQUIRED_VALUE = 2u << 0, /**< The argument must have a value. */\n+\tRTE_ARGPARSE_ARG_OPTIONAL_VALUE = 3u << 0, /**< The argument has optional value. */\n+\n+\t/**\n+\t * Bit2-10: represent the value type which used when autosave\n+\t */\n+\tRTE_ARGPARSE_ARG_VALUE_INT = 1u << 2, /**< The argument's value is int type. */\n+\tRTE_ARGPARSE_ARG_VALUE_MAX = 2u << 2, /**< Max value type. */\n+\n+\t/**\n+\t * Bit16: flag for that argument support occur multiple times.\n+\t * This flag can be set only when the argument is optional.\n+\t * When this flag is set, the callback type must be used for parsing.\n+\t */\n+\tRTE_ARGPARSE_ARG_SUPPORT_MULTI = 1u << 16,\n+\n+\t/**\n+\t * Bit30-31: reserved for this library implement usage.\n+\t */\n+\tRTE_ARGPARSE_ARG_RESERVED_FIELD = 3u << 30,\n+};\n+\n+/**\n+ * A structure used to hold argument's configuration.\n+ */\n+struct rte_argparse_arg {\n+\t/**\n+\t * Long name of the argument:\n+\t * 1) If the argument is optional, it must start with '--'.\n+\t * 2) If the argument is positional, it must not start with '-'.\n+\t * 3) Other case will be considered as error.\n+\t */\n+\tconst char *name_long;\n+\t/**\n+\t * Short name of the argument:\n+\t * 1) This field could be set only when name_long is optional, and\n+\t *    must start with a hyphen (-) followed by an English letter.\n+\t * 2) Other case it should be set NULL.\n+\t */\n+\tconst char *name_short;\n+\n+\t/** Help information of the argument, must not be NULL. */\n+\tconst char *help;\n+\n+\t/**\n+\t * Saver for the argument's value.\n+\t * 1) If the filed is NULL, the callback way is used for parsing\n+\t *    argument.\n+\t * 2) If the field is not NULL, the autosave way is used for parsing\n+\t *    argument.\n+\t */\n+\tvoid *val_saver;\n+\t/**\n+\t * If val_saver is NULL, this filed (cast as (uint32_t)val_set) will be\n+\t * used as the first parameter to invoke callback.\n+\t *\n+\t * If val_saver is not NULL, then:\n+\t * 1) If argument has no value, val_saver will set to val_set when\n+\t *    argument found.\n+\t * 2) If argument has optional value but doesn't take value this\n+\t *    time, val_saver will set to val_set when argument found.\n+\t * 3) Other case it should be set NULL.\n+\t */\n+\tvoid *val_set;\n+\n+\t/** @see rte_argparse_flag */\n+\tuint32_t flags;\n+};\n+\n+/**\n+ * Callback prototype used by parsing specified arguments.\n+ *\n+ * @param index\n+ *   The argument's index, coming from argument's val_set.\n+ * @param value\n+ *   The value corresponding to the argument, it may be NULL (e.g. the\n+ *   argument has no value, or the argument has optional value but doesn't\n+ *   provided value).\n+ * @param opaque\n+ *   An opaque pointer coming from the caller.\n+ * @return\n+ *   0 on success. Otherwise negative value is returned.\n+ */\n+typedef int (*arg_parser_t)(uint32_t index, const char *value, void *opaque);\n+\n+/**\n+ * A structure used to hold argparse's configuration.\n+ */\n+struct rte_argparse {\n+\t/** Program name. Must not be NULL. */\n+\tconst char *prog_name;\n+\t/** How to use the program. Must not be NULL. */\n+\tconst char *usage;\n+\t/** Explain what the program does. Could be NULL. */\n+\tconst char *descriptor;\n+\t/** Text at the bottom of help. Could be NULL. */\n+\tconst char *epilog;\n+\t/** Whether exit when error. */\n+\tbool exit_on_error;\n+\t/** User callback for parsing arguments. */\n+\targ_parser_t callback;\n+\t/** Opaque which used to invoke callback. */\n+\tvoid *opaque;\n+\t/** Arguments configuration. Must ended with ARGPARSE_ARG_END(). */\n+\tstruct rte_argparse_arg args[];\n+};\n+\n+#define ARGPARSE_ARG_END() { NULL }\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Parse parameters.\n+ *\n+ * @param obj\n+ *   Parser object.\n+ * @param argc\n+ *   Parameters count.\n+ * @param argv\n+ *   Array of parameters points.\n+ *\n+ * @return\n+ *   0 on success. Otherwise negative value is returned.\n+ */\n+__rte_experimental\n+int rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* RTE_ARGPARSE_H */\ndiff --git a/lib/argparse/version.map b/lib/argparse/version.map\nnew file mode 100644\nindex 0000000000..1c176f69e9\n--- /dev/null\n+++ b/lib/argparse/version.map\n@@ -0,0 +1,7 @@\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\trte_argparse_parse;\n+\n+\tlocal: *;\n+};\ndiff --git a/lib/meson.build b/lib/meson.build\nindex 6c143ce5a6..cdd2d3c536 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -11,6 +11,7 @@\n libraries = [\n         'log',\n         'kvargs', # eal depends on kvargs\n+        'argparse',\n         'telemetry', # basic info querying\n         'eal', # everything depends on eal\n         'ring',\n",
    "prefixes": [
        "RFC",
        "v2",
        "1/6"
    ]
}