xref: /dpdk/lib/argparse/rte_argparse.h (revision 51a639ca804234462df0a8c72523fa71181cea24)
1e3e579f5SChengwen Feng /* SPDX-License-Identifier: BSD-3-Clause
2e3e579f5SChengwen Feng  * Copyright(c) 2024 HiSilicon Limited
3e3e579f5SChengwen Feng  */
4e3e579f5SChengwen Feng 
5e3e579f5SChengwen Feng #ifndef RTE_ARGPARSE_H
6e3e579f5SChengwen Feng #define RTE_ARGPARSE_H
7e3e579f5SChengwen Feng 
8e3e579f5SChengwen Feng /**
9e3e579f5SChengwen Feng  * @file rte_argparse.h
10e3e579f5SChengwen Feng  *
11e3e579f5SChengwen Feng  * Argument parsing API.
12e3e579f5SChengwen Feng  *
13e3e579f5SChengwen Feng  * The argument parsing API makes it easy to write user-friendly command-line
14e3e579f5SChengwen Feng  * program. The program defines what arguments it requires,
15e3e579f5SChengwen Feng  * and the API will parse those arguments from [argc, argv].
16e3e579f5SChengwen Feng  *
17e3e579f5SChengwen Feng  * The API provides the following functions:
18e3e579f5SChengwen Feng  * 1) Support parsing optional argument (which could take with no-value,
19e3e579f5SChengwen Feng  *    required-value and optional-value.
20e3e579f5SChengwen Feng  * 2) Support parsing positional argument (which must take with required-value).
21e3e579f5SChengwen Feng  * 3) Support automatic generate usage information.
22e3e579f5SChengwen Feng  * 4) Support issue errors when provided with invalid arguments.
23e3e579f5SChengwen Feng  *
24e3e579f5SChengwen Feng  * There are two ways to parse arguments:
25e3e579f5SChengwen Feng  * 1) AutoSave: for which known value types, the way can be used.
26e3e579f5SChengwen Feng  * 2) Callback: will invoke user callback to parse.
27e3e579f5SChengwen Feng  *
28e3e579f5SChengwen Feng  */
29e3e579f5SChengwen Feng 
30e3e579f5SChengwen Feng #include <stdbool.h>
31e3e579f5SChengwen Feng #include <stdint.h>
32e3e579f5SChengwen Feng 
33e3e579f5SChengwen Feng #include <rte_bitops.h>
34e3e579f5SChengwen Feng #include <rte_compat.h>
35e3e579f5SChengwen Feng 
36e3e579f5SChengwen Feng #ifdef __cplusplus
37e3e579f5SChengwen Feng extern "C" {
38e3e579f5SChengwen Feng #endif
39e3e579f5SChengwen Feng 
40bd0d68bdSChengwen Feng /**@{@name Flag definition (in bitmask form) for an argument
41bd0d68bdSChengwen Feng  *
42bd0d68bdSChengwen Feng  * @note Bits[0~1] represent the argument whether has value,
43bd0d68bdSChengwen Feng  * bits[2~9] represent the value type which used when autosave.
44bd0d68bdSChengwen Feng  *
45bd0d68bdSChengwen Feng  * @see struct rte_argparse_arg::flags
46e3e579f5SChengwen Feng  */
47e3e579f5SChengwen Feng /** The argument has no value. */
48bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_NO_VALUE       RTE_SHIFT_VAL64(1, 0)
49e3e579f5SChengwen Feng /** The argument must have a value. */
50bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_REQUIRED_VALUE RTE_SHIFT_VAL64(2, 0)
51e3e579f5SChengwen Feng /** The argument has optional value. */
52bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_OPTIONAL_VALUE RTE_SHIFT_VAL64(3, 0)
53e3e579f5SChengwen Feng /** The argument's value is int type. */
54bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_VALUE_INT      RTE_SHIFT_VAL64(1, 2)
555357c248SChengwen Feng /** The argument's value is uint8 type. */
56bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_VALUE_U8       RTE_SHIFT_VAL64(2, 2)
575357c248SChengwen Feng /** The argument's value is uint16 type. */
58bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_VALUE_U16      RTE_SHIFT_VAL64(3, 2)
595357c248SChengwen Feng /** The argument's value is uint32 type. */
60bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_VALUE_U32      RTE_SHIFT_VAL64(4, 2)
615357c248SChengwen Feng /** The argument's value is uint64 type. */
62bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_VALUE_U64      RTE_SHIFT_VAL64(5, 2)
63e3e579f5SChengwen Feng /** Max value type. */
64bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_VALUE_MAX      RTE_SHIFT_VAL64(6, 2)
65e3e579f5SChengwen Feng /**
66bd0d68bdSChengwen Feng  * Flag for that argument support occur multiple times.
67e3e579f5SChengwen Feng  * This flag can be set only when the argument is optional.
68e3e579f5SChengwen Feng  * When this flag is set, the callback type must be used for parsing.
69e3e579f5SChengwen Feng  */
70bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_SUPPORT_MULTI  RTE_BIT64(10)
71bd0d68bdSChengwen Feng /** Reserved for this library implementation usage. */
72bd0d68bdSChengwen Feng #define RTE_ARGPARSE_ARG_RESERVED_FIELD RTE_GENMASK64(63, 48)
73bd0d68bdSChengwen Feng /**@}*/
74e3e579f5SChengwen Feng 
75f48e4eedSChengwen Feng /** Bitmask used to get the argument whether has value. */
76f48e4eedSChengwen Feng #define RTE_ARGPARSE_HAS_VAL_BITMASK	RTE_GENMASK64(1, 0)
77f48e4eedSChengwen Feng /** Bitmask used to get the argument's value type. */
78f48e4eedSChengwen Feng #define RTE_ARGPARSE_VAL_TYPE_BITMASK	RTE_GENMASK64(9, 2)
79f48e4eedSChengwen Feng 
80e3e579f5SChengwen Feng /**
81e3e579f5SChengwen Feng  * A structure used to hold argument's configuration.
82e3e579f5SChengwen Feng  */
83e3e579f5SChengwen Feng struct rte_argparse_arg {
84e3e579f5SChengwen Feng 	/**
85e3e579f5SChengwen Feng 	 * Long name of the argument:
86*51a639caSChengwen Feng 	 * 1) If the argument is optional, it must start with ``--``.
87*51a639caSChengwen Feng 	 * 2) If the argument is positional, it must not start with ``-``.
88e3e579f5SChengwen Feng 	 * 3) Other case will be considered as error.
89e3e579f5SChengwen Feng 	 */
90e3e579f5SChengwen Feng 	const char *name_long;
91e3e579f5SChengwen Feng 	/**
92e3e579f5SChengwen Feng 	 * Short name of the argument:
93e3e579f5SChengwen Feng 	 * 1) This field could be set only when name_long is optional, and
94e3e579f5SChengwen Feng 	 *    must start with a hyphen (-) followed by an English letter.
95e3e579f5SChengwen Feng 	 * 2) Other case it should be set NULL.
96e3e579f5SChengwen Feng 	 */
97e3e579f5SChengwen Feng 	const char *name_short;
98e3e579f5SChengwen Feng 
99e3e579f5SChengwen Feng 	/** Help information of the argument, must not be NULL. */
100e3e579f5SChengwen Feng 	const char *help;
101e3e579f5SChengwen Feng 
102e3e579f5SChengwen Feng 	/**
103e3e579f5SChengwen Feng 	 * Saver for the argument's value.
104e3e579f5SChengwen Feng 	 * 1) If the filed is NULL, the callback way is used for parsing
105e3e579f5SChengwen Feng 	 *    argument.
106e3e579f5SChengwen Feng 	 * 2) If the field is not NULL, the autosave way is used for parsing
107e3e579f5SChengwen Feng 	 *    argument.
108e3e579f5SChengwen Feng 	 */
109e3e579f5SChengwen Feng 	void *val_saver;
110e3e579f5SChengwen Feng 	/**
111e3e579f5SChengwen Feng 	 * If val_saver is NULL, this filed (cast as (uint32_t)val_set) will be
112e3e579f5SChengwen Feng 	 * used as the first parameter to invoke callback.
113e3e579f5SChengwen Feng 	 *
114e3e579f5SChengwen Feng 	 * If val_saver is not NULL, then:
115e3e579f5SChengwen Feng 	 * 1) If argument has no value, *val_saver will be set to val_set.
116e3e579f5SChengwen Feng 	 * 2) If argument has optional value but doesn't take value this
117e3e579f5SChengwen Feng 	 *    time, *val_saver will be set to val_set.
118e3e579f5SChengwen Feng 	 * 3) Other case it should be set NULL.
119e3e579f5SChengwen Feng 	 */
120e3e579f5SChengwen Feng 	void *val_set;
121e3e579f5SChengwen Feng 
122bd0d68bdSChengwen Feng 	/** Flag definition (RTE_ARGPARSE_ARG_*) for the argument. */
123e3e579f5SChengwen Feng 	uint64_t flags;
124e3e579f5SChengwen Feng };
125e3e579f5SChengwen Feng 
126e3e579f5SChengwen Feng /**
127e3e579f5SChengwen Feng  * Callback prototype used by parsing specified arguments.
128e3e579f5SChengwen Feng  *
129e3e579f5SChengwen Feng  * @param index
130e3e579f5SChengwen Feng  *   The argument's index, coming from argument's val_set field.
131e3e579f5SChengwen Feng  * @param value
132e3e579f5SChengwen Feng  *   The value corresponding to the argument, it may be NULL (e.g. the
133e3e579f5SChengwen Feng  *   argument has no value, or the argument has optional value but doesn't
134e3e579f5SChengwen Feng  *   provided value).
135e3e579f5SChengwen Feng  * @param opaque
136e3e579f5SChengwen Feng  *   An opaque pointer coming from the caller.
137e3e579f5SChengwen Feng  * @return
138e3e579f5SChengwen Feng  *   0 on success. Otherwise negative value is returned.
139e3e579f5SChengwen Feng  */
140edb10170SDavid Marchand typedef int (*rte_arg_parser_t)(uint32_t index, const char *value, void *opaque);
141e3e579f5SChengwen Feng 
142e3e579f5SChengwen Feng /**
143e3e579f5SChengwen Feng  * A structure used to hold argparse's configuration.
144e3e579f5SChengwen Feng  */
145e3e579f5SChengwen Feng struct rte_argparse {
146e3e579f5SChengwen Feng 	/** Program name. Must not be NULL. */
147e3e579f5SChengwen Feng 	const char *prog_name;
148e3e579f5SChengwen Feng 	/** How to use the program. Must not be NULL. */
149e3e579f5SChengwen Feng 	const char *usage;
150e3e579f5SChengwen Feng 	/** Explain what the program does. Could be NULL. */
151e3e579f5SChengwen Feng 	const char *descriptor;
152e3e579f5SChengwen Feng 	/** Text at the bottom of help. Could be NULL. */
153e3e579f5SChengwen Feng 	const char *epilog;
154e3e579f5SChengwen Feng 	/** Whether exit when error. */
155e3e579f5SChengwen Feng 	bool exit_on_error;
156e3e579f5SChengwen Feng 	/** User callback for parsing arguments. */
157edb10170SDavid Marchand 	rte_arg_parser_t callback;
158e3e579f5SChengwen Feng 	/** Opaque which used to invoke callback. */
159e3e579f5SChengwen Feng 	void *opaque;
160e3e579f5SChengwen Feng 	/** Reserved field used for future extension. */
161e3e579f5SChengwen Feng 	void *reserved[16];
162e3e579f5SChengwen Feng 	/** Arguments configuration. Must ended with ARGPARSE_ARG_END(). */
163e3e579f5SChengwen Feng 	struct rte_argparse_arg args[];
164e3e579f5SChengwen Feng };
165e3e579f5SChengwen Feng 
166e3e579f5SChengwen Feng #define ARGPARSE_ARG_END() { NULL }
167e3e579f5SChengwen Feng 
168e3e579f5SChengwen Feng /**
169e3e579f5SChengwen Feng  * @warning
170e3e579f5SChengwen Feng  * @b EXPERIMENTAL: this API may change without prior notice.
171e3e579f5SChengwen Feng  *
172e3e579f5SChengwen Feng  * Parse parameters.
173e3e579f5SChengwen Feng  *
174e3e579f5SChengwen Feng  * @param obj
175e3e579f5SChengwen Feng  *   Parser object.
176e3e579f5SChengwen Feng  * @param argc
177e3e579f5SChengwen Feng  *   Parameters count.
178e3e579f5SChengwen Feng  * @param argv
179e3e579f5SChengwen Feng  *   Array of parameters points.
180e3e579f5SChengwen Feng  *
181e3e579f5SChengwen Feng  * @return
182e3e579f5SChengwen Feng  *   0 on success. Otherwise negative value is returned.
183e3e579f5SChengwen Feng  */
184e3e579f5SChengwen Feng __rte_experimental
185e3e579f5SChengwen Feng int rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv);
186e3e579f5SChengwen Feng 
1879ccd7b27SChengwen Feng /**
1889ccd7b27SChengwen Feng  * @warning
1899ccd7b27SChengwen Feng  * @b EXPERIMENTAL: this API may change without prior notice.
1909ccd7b27SChengwen Feng  *
1919ccd7b27SChengwen Feng  * Parse the value from the input string based on the value type.
1929ccd7b27SChengwen Feng  *
1939ccd7b27SChengwen Feng  * @param str
1949ccd7b27SChengwen Feng  *   Input string.
1959ccd7b27SChengwen Feng  * @param val_type
1969ccd7b27SChengwen Feng  *   The value type, @see RTE_ARGPARSE_ARG_VALUE_INT or other type.
1979ccd7b27SChengwen Feng  * @param val
1989ccd7b27SChengwen Feng  *   Saver for the value.
1999ccd7b27SChengwen Feng  *
2009ccd7b27SChengwen Feng  * @return
2019ccd7b27SChengwen Feng  *   0 on success. Otherwise negative value is returned.
2029ccd7b27SChengwen Feng  */
2039ccd7b27SChengwen Feng __rte_experimental
2049ccd7b27SChengwen Feng int rte_argparse_parse_type(const char *str, uint64_t val_type, void *val);
2059ccd7b27SChengwen Feng 
206e3e579f5SChengwen Feng #ifdef __cplusplus
207e3e579f5SChengwen Feng }
208e3e579f5SChengwen Feng #endif
209e3e579f5SChengwen Feng 
210e3e579f5SChengwen Feng #endif /* RTE_ARGPARSE_H */
211