xref: /dpdk/lib/argparse/rte_argparse.h (revision edb10170e29697bc7a9ed59fcf81e403be41cf7b)
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 
40e3e579f5SChengwen Feng /**
41e3e579f5SChengwen Feng  * Flag definition (in bitmask form) for an argument.
42e3e579f5SChengwen Feng  */
43e3e579f5SChengwen Feng enum rte_argparse_flag {
44e3e579f5SChengwen Feng 	/*
45e3e579f5SChengwen Feng 	 * Bits 0-1: represent the argument whether has value.
46e3e579f5SChengwen Feng 	 */
47e3e579f5SChengwen Feng 
48e3e579f5SChengwen Feng 	/** The argument has no value. */
49e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_NO_VALUE = RTE_SHIFT_VAL64(1, 0),
50e3e579f5SChengwen Feng 	/** The argument must have a value. */
51e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_REQUIRED_VALUE = RTE_SHIFT_VAL64(2, 0),
52e3e579f5SChengwen Feng 	/** The argument has optional value. */
53e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_OPTIONAL_VALUE = RTE_SHIFT_VAL64(3, 0),
54e3e579f5SChengwen Feng 
55e3e579f5SChengwen Feng 
56e3e579f5SChengwen Feng 	/*
57e3e579f5SChengwen Feng 	 * Bits 2-9: represent the value type which used when autosave
58e3e579f5SChengwen Feng 	 */
59e3e579f5SChengwen Feng 
60e3e579f5SChengwen Feng 	/** The argument's value is int type. */
61e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_VALUE_INT = RTE_SHIFT_VAL64(1, 2),
625357c248SChengwen Feng 	/** The argument's value is uint8 type. */
635357c248SChengwen Feng 	RTE_ARGPARSE_ARG_VALUE_U8 = RTE_SHIFT_VAL64(2, 2),
645357c248SChengwen Feng 	/** The argument's value is uint16 type. */
655357c248SChengwen Feng 	RTE_ARGPARSE_ARG_VALUE_U16 = RTE_SHIFT_VAL64(3, 2),
665357c248SChengwen Feng 	/** The argument's value is uint32 type. */
675357c248SChengwen Feng 	RTE_ARGPARSE_ARG_VALUE_U32 = RTE_SHIFT_VAL64(4, 2),
685357c248SChengwen Feng 	/** The argument's value is uint64 type. */
695357c248SChengwen Feng 	RTE_ARGPARSE_ARG_VALUE_U64 = RTE_SHIFT_VAL64(5, 2),
70e3e579f5SChengwen Feng 	/** Max value type. */
715357c248SChengwen Feng 	RTE_ARGPARSE_ARG_VALUE_MAX = RTE_SHIFT_VAL64(6, 2),
72e3e579f5SChengwen Feng 
73e3e579f5SChengwen Feng 
74e3e579f5SChengwen Feng 	/**
75e3e579f5SChengwen Feng 	 * Bit 10: flag for that argument support occur multiple times.
76e3e579f5SChengwen Feng 	 * This flag can be set only when the argument is optional.
77e3e579f5SChengwen Feng 	 * When this flag is set, the callback type must be used for parsing.
78e3e579f5SChengwen Feng 	 */
79e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_SUPPORT_MULTI = RTE_BIT64(10),
80e3e579f5SChengwen Feng 
81e3e579f5SChengwen Feng 	/**
82e3e579f5SChengwen Feng 	 * Bits 48-63: reserved for this library implementation usage.
83e3e579f5SChengwen Feng 	 */
84e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_RESERVED_FIELD = RTE_GENMASK64(63, 48),
85e3e579f5SChengwen Feng };
86e3e579f5SChengwen Feng 
87e3e579f5SChengwen Feng /**
88e3e579f5SChengwen Feng  * A structure used to hold argument's configuration.
89e3e579f5SChengwen Feng  */
90e3e579f5SChengwen Feng struct rte_argparse_arg {
91e3e579f5SChengwen Feng 	/**
92e3e579f5SChengwen Feng 	 * Long name of the argument:
93e3e579f5SChengwen Feng 	 * 1) If the argument is optional, it must start with '--'.
94e3e579f5SChengwen Feng 	 * 2) If the argument is positional, it must not start with '-'.
95e3e579f5SChengwen Feng 	 * 3) Other case will be considered as error.
96e3e579f5SChengwen Feng 	 */
97e3e579f5SChengwen Feng 	const char *name_long;
98e3e579f5SChengwen Feng 	/**
99e3e579f5SChengwen Feng 	 * Short name of the argument:
100e3e579f5SChengwen Feng 	 * 1) This field could be set only when name_long is optional, and
101e3e579f5SChengwen Feng 	 *    must start with a hyphen (-) followed by an English letter.
102e3e579f5SChengwen Feng 	 * 2) Other case it should be set NULL.
103e3e579f5SChengwen Feng 	 */
104e3e579f5SChengwen Feng 	const char *name_short;
105e3e579f5SChengwen Feng 
106e3e579f5SChengwen Feng 	/** Help information of the argument, must not be NULL. */
107e3e579f5SChengwen Feng 	const char *help;
108e3e579f5SChengwen Feng 
109e3e579f5SChengwen Feng 	/**
110e3e579f5SChengwen Feng 	 * Saver for the argument's value.
111e3e579f5SChengwen Feng 	 * 1) If the filed is NULL, the callback way is used for parsing
112e3e579f5SChengwen Feng 	 *    argument.
113e3e579f5SChengwen Feng 	 * 2) If the field is not NULL, the autosave way is used for parsing
114e3e579f5SChengwen Feng 	 *    argument.
115e3e579f5SChengwen Feng 	 */
116e3e579f5SChengwen Feng 	void *val_saver;
117e3e579f5SChengwen Feng 	/**
118e3e579f5SChengwen Feng 	 * If val_saver is NULL, this filed (cast as (uint32_t)val_set) will be
119e3e579f5SChengwen Feng 	 * used as the first parameter to invoke callback.
120e3e579f5SChengwen Feng 	 *
121e3e579f5SChengwen Feng 	 * If val_saver is not NULL, then:
122e3e579f5SChengwen Feng 	 * 1) If argument has no value, *val_saver will be set to val_set.
123e3e579f5SChengwen Feng 	 * 2) If argument has optional value but doesn't take value this
124e3e579f5SChengwen Feng 	 *    time, *val_saver will be set to val_set.
125e3e579f5SChengwen Feng 	 * 3) Other case it should be set NULL.
126e3e579f5SChengwen Feng 	 */
127e3e579f5SChengwen Feng 	void *val_set;
128e3e579f5SChengwen Feng 
129e3e579f5SChengwen Feng 	/** @see rte_argparse_flag */
130e3e579f5SChengwen Feng 	uint64_t flags;
131e3e579f5SChengwen Feng };
132e3e579f5SChengwen Feng 
133e3e579f5SChengwen Feng /**
134e3e579f5SChengwen Feng  * Callback prototype used by parsing specified arguments.
135e3e579f5SChengwen Feng  *
136e3e579f5SChengwen Feng  * @param index
137e3e579f5SChengwen Feng  *   The argument's index, coming from argument's val_set field.
138e3e579f5SChengwen Feng  * @param value
139e3e579f5SChengwen Feng  *   The value corresponding to the argument, it may be NULL (e.g. the
140e3e579f5SChengwen Feng  *   argument has no value, or the argument has optional value but doesn't
141e3e579f5SChengwen Feng  *   provided value).
142e3e579f5SChengwen Feng  * @param opaque
143e3e579f5SChengwen Feng  *   An opaque pointer coming from the caller.
144e3e579f5SChengwen Feng  * @return
145e3e579f5SChengwen Feng  *   0 on success. Otherwise negative value is returned.
146e3e579f5SChengwen Feng  */
147*edb10170SDavid Marchand typedef int (*rte_arg_parser_t)(uint32_t index, const char *value, void *opaque);
148e3e579f5SChengwen Feng 
149e3e579f5SChengwen Feng /**
150e3e579f5SChengwen Feng  * A structure used to hold argparse's configuration.
151e3e579f5SChengwen Feng  */
152e3e579f5SChengwen Feng struct rte_argparse {
153e3e579f5SChengwen Feng 	/** Program name. Must not be NULL. */
154e3e579f5SChengwen Feng 	const char *prog_name;
155e3e579f5SChengwen Feng 	/** How to use the program. Must not be NULL. */
156e3e579f5SChengwen Feng 	const char *usage;
157e3e579f5SChengwen Feng 	/** Explain what the program does. Could be NULL. */
158e3e579f5SChengwen Feng 	const char *descriptor;
159e3e579f5SChengwen Feng 	/** Text at the bottom of help. Could be NULL. */
160e3e579f5SChengwen Feng 	const char *epilog;
161e3e579f5SChengwen Feng 	/** Whether exit when error. */
162e3e579f5SChengwen Feng 	bool exit_on_error;
163e3e579f5SChengwen Feng 	/** User callback for parsing arguments. */
164*edb10170SDavid Marchand 	rte_arg_parser_t callback;
165e3e579f5SChengwen Feng 	/** Opaque which used to invoke callback. */
166e3e579f5SChengwen Feng 	void *opaque;
167e3e579f5SChengwen Feng 	/** Reserved field used for future extension. */
168e3e579f5SChengwen Feng 	void *reserved[16];
169e3e579f5SChengwen Feng 	/** Arguments configuration. Must ended with ARGPARSE_ARG_END(). */
170e3e579f5SChengwen Feng 	struct rte_argparse_arg args[];
171e3e579f5SChengwen Feng };
172e3e579f5SChengwen Feng 
173e3e579f5SChengwen Feng #define ARGPARSE_ARG_END() { NULL }
174e3e579f5SChengwen Feng 
175e3e579f5SChengwen Feng /**
176e3e579f5SChengwen Feng  * @warning
177e3e579f5SChengwen Feng  * @b EXPERIMENTAL: this API may change without prior notice.
178e3e579f5SChengwen Feng  *
179e3e579f5SChengwen Feng  * Parse parameters.
180e3e579f5SChengwen Feng  *
181e3e579f5SChengwen Feng  * @param obj
182e3e579f5SChengwen Feng  *   Parser object.
183e3e579f5SChengwen Feng  * @param argc
184e3e579f5SChengwen Feng  *   Parameters count.
185e3e579f5SChengwen Feng  * @param argv
186e3e579f5SChengwen Feng  *   Array of parameters points.
187e3e579f5SChengwen Feng  *
188e3e579f5SChengwen Feng  * @return
189e3e579f5SChengwen Feng  *   0 on success. Otherwise negative value is returned.
190e3e579f5SChengwen Feng  */
191e3e579f5SChengwen Feng __rte_experimental
192e3e579f5SChengwen Feng int rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv);
193e3e579f5SChengwen Feng 
1949ccd7b27SChengwen Feng /**
1959ccd7b27SChengwen Feng  * @warning
1969ccd7b27SChengwen Feng  * @b EXPERIMENTAL: this API may change without prior notice.
1979ccd7b27SChengwen Feng  *
1989ccd7b27SChengwen Feng  * Parse the value from the input string based on the value type.
1999ccd7b27SChengwen Feng  *
2009ccd7b27SChengwen Feng  * @param str
2019ccd7b27SChengwen Feng  *   Input string.
2029ccd7b27SChengwen Feng  * @param val_type
2039ccd7b27SChengwen Feng  *   The value type, @see RTE_ARGPARSE_ARG_VALUE_INT or other type.
2049ccd7b27SChengwen Feng  * @param val
2059ccd7b27SChengwen Feng  *   Saver for the value.
2069ccd7b27SChengwen Feng  *
2079ccd7b27SChengwen Feng  * @return
2089ccd7b27SChengwen Feng  *   0 on success. Otherwise negative value is returned.
2099ccd7b27SChengwen Feng  */
2109ccd7b27SChengwen Feng __rte_experimental
2119ccd7b27SChengwen Feng int rte_argparse_parse_type(const char *str, uint64_t val_type, void *val);
2129ccd7b27SChengwen Feng 
213e3e579f5SChengwen Feng #ifdef __cplusplus
214e3e579f5SChengwen Feng }
215e3e579f5SChengwen Feng #endif
216e3e579f5SChengwen Feng 
217e3e579f5SChengwen Feng #endif /* RTE_ARGPARSE_H */
218