xref: /dpdk/lib/argparse/rte_argparse.h (revision 9ccd7b27d0831219e2068e487609933be8df5d7a)
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),
62e3e579f5SChengwen Feng 	/** Max value type. */
63e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_VALUE_MAX = RTE_SHIFT_VAL64(2, 2),
64e3e579f5SChengwen Feng 
65e3e579f5SChengwen Feng 
66e3e579f5SChengwen Feng 	/**
67e3e579f5SChengwen Feng 	 * Bit 10: flag for that argument support occur multiple times.
68e3e579f5SChengwen Feng 	 * This flag can be set only when the argument is optional.
69e3e579f5SChengwen Feng 	 * When this flag is set, the callback type must be used for parsing.
70e3e579f5SChengwen Feng 	 */
71e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_SUPPORT_MULTI = RTE_BIT64(10),
72e3e579f5SChengwen Feng 
73e3e579f5SChengwen Feng 	/**
74e3e579f5SChengwen Feng 	 * Bits 48-63: reserved for this library implementation usage.
75e3e579f5SChengwen Feng 	 */
76e3e579f5SChengwen Feng 	RTE_ARGPARSE_ARG_RESERVED_FIELD = RTE_GENMASK64(63, 48),
77e3e579f5SChengwen Feng };
78e3e579f5SChengwen Feng 
79e3e579f5SChengwen Feng /**
80e3e579f5SChengwen Feng  * A structure used to hold argument's configuration.
81e3e579f5SChengwen Feng  */
82e3e579f5SChengwen Feng struct rte_argparse_arg {
83e3e579f5SChengwen Feng 	/**
84e3e579f5SChengwen Feng 	 * Long name of the argument:
85e3e579f5SChengwen Feng 	 * 1) If the argument is optional, it must start with '--'.
86e3e579f5SChengwen Feng 	 * 2) If the argument is positional, it must not start with '-'.
87e3e579f5SChengwen Feng 	 * 3) Other case will be considered as error.
88e3e579f5SChengwen Feng 	 */
89e3e579f5SChengwen Feng 	const char *name_long;
90e3e579f5SChengwen Feng 	/**
91e3e579f5SChengwen Feng 	 * Short name of the argument:
92e3e579f5SChengwen Feng 	 * 1) This field could be set only when name_long is optional, and
93e3e579f5SChengwen Feng 	 *    must start with a hyphen (-) followed by an English letter.
94e3e579f5SChengwen Feng 	 * 2) Other case it should be set NULL.
95e3e579f5SChengwen Feng 	 */
96e3e579f5SChengwen Feng 	const char *name_short;
97e3e579f5SChengwen Feng 
98e3e579f5SChengwen Feng 	/** Help information of the argument, must not be NULL. */
99e3e579f5SChengwen Feng 	const char *help;
100e3e579f5SChengwen Feng 
101e3e579f5SChengwen Feng 	/**
102e3e579f5SChengwen Feng 	 * Saver for the argument's value.
103e3e579f5SChengwen Feng 	 * 1) If the filed is NULL, the callback way is used for parsing
104e3e579f5SChengwen Feng 	 *    argument.
105e3e579f5SChengwen Feng 	 * 2) If the field is not NULL, the autosave way is used for parsing
106e3e579f5SChengwen Feng 	 *    argument.
107e3e579f5SChengwen Feng 	 */
108e3e579f5SChengwen Feng 	void *val_saver;
109e3e579f5SChengwen Feng 	/**
110e3e579f5SChengwen Feng 	 * If val_saver is NULL, this filed (cast as (uint32_t)val_set) will be
111e3e579f5SChengwen Feng 	 * used as the first parameter to invoke callback.
112e3e579f5SChengwen Feng 	 *
113e3e579f5SChengwen Feng 	 * If val_saver is not NULL, then:
114e3e579f5SChengwen Feng 	 * 1) If argument has no value, *val_saver will be set to val_set.
115e3e579f5SChengwen Feng 	 * 2) If argument has optional value but doesn't take value this
116e3e579f5SChengwen Feng 	 *    time, *val_saver will be set to val_set.
117e3e579f5SChengwen Feng 	 * 3) Other case it should be set NULL.
118e3e579f5SChengwen Feng 	 */
119e3e579f5SChengwen Feng 	void *val_set;
120e3e579f5SChengwen Feng 
121e3e579f5SChengwen Feng 	/** @see rte_argparse_flag */
122e3e579f5SChengwen Feng 	uint64_t flags;
123e3e579f5SChengwen Feng };
124e3e579f5SChengwen Feng 
125e3e579f5SChengwen Feng /**
126e3e579f5SChengwen Feng  * Callback prototype used by parsing specified arguments.
127e3e579f5SChengwen Feng  *
128e3e579f5SChengwen Feng  * @param index
129e3e579f5SChengwen Feng  *   The argument's index, coming from argument's val_set field.
130e3e579f5SChengwen Feng  * @param value
131e3e579f5SChengwen Feng  *   The value corresponding to the argument, it may be NULL (e.g. the
132e3e579f5SChengwen Feng  *   argument has no value, or the argument has optional value but doesn't
133e3e579f5SChengwen Feng  *   provided value).
134e3e579f5SChengwen Feng  * @param opaque
135e3e579f5SChengwen Feng  *   An opaque pointer coming from the caller.
136e3e579f5SChengwen Feng  * @return
137e3e579f5SChengwen Feng  *   0 on success. Otherwise negative value is returned.
138e3e579f5SChengwen Feng  */
139e3e579f5SChengwen Feng typedef int (*arg_parser_t)(uint32_t index, const char *value, void *opaque);
140e3e579f5SChengwen Feng 
141e3e579f5SChengwen Feng /**
142e3e579f5SChengwen Feng  * A structure used to hold argparse's configuration.
143e3e579f5SChengwen Feng  */
144e3e579f5SChengwen Feng struct rte_argparse {
145e3e579f5SChengwen Feng 	/** Program name. Must not be NULL. */
146e3e579f5SChengwen Feng 	const char *prog_name;
147e3e579f5SChengwen Feng 	/** How to use the program. Must not be NULL. */
148e3e579f5SChengwen Feng 	const char *usage;
149e3e579f5SChengwen Feng 	/** Explain what the program does. Could be NULL. */
150e3e579f5SChengwen Feng 	const char *descriptor;
151e3e579f5SChengwen Feng 	/** Text at the bottom of help. Could be NULL. */
152e3e579f5SChengwen Feng 	const char *epilog;
153e3e579f5SChengwen Feng 	/** Whether exit when error. */
154e3e579f5SChengwen Feng 	bool exit_on_error;
155e3e579f5SChengwen Feng 	/** User callback for parsing arguments. */
156e3e579f5SChengwen Feng 	arg_parser_t callback;
157e3e579f5SChengwen Feng 	/** Opaque which used to invoke callback. */
158e3e579f5SChengwen Feng 	void *opaque;
159e3e579f5SChengwen Feng 	/** Reserved field used for future extension. */
160e3e579f5SChengwen Feng 	void *reserved[16];
161e3e579f5SChengwen Feng 	/** Arguments configuration. Must ended with ARGPARSE_ARG_END(). */
162e3e579f5SChengwen Feng 	struct rte_argparse_arg args[];
163e3e579f5SChengwen Feng };
164e3e579f5SChengwen Feng 
165e3e579f5SChengwen Feng #define ARGPARSE_ARG_END() { NULL }
166e3e579f5SChengwen Feng 
167e3e579f5SChengwen Feng /**
168e3e579f5SChengwen Feng  * @warning
169e3e579f5SChengwen Feng  * @b EXPERIMENTAL: this API may change without prior notice.
170e3e579f5SChengwen Feng  *
171e3e579f5SChengwen Feng  * Parse parameters.
172e3e579f5SChengwen Feng  *
173e3e579f5SChengwen Feng  * @param obj
174e3e579f5SChengwen Feng  *   Parser object.
175e3e579f5SChengwen Feng  * @param argc
176e3e579f5SChengwen Feng  *   Parameters count.
177e3e579f5SChengwen Feng  * @param argv
178e3e579f5SChengwen Feng  *   Array of parameters points.
179e3e579f5SChengwen Feng  *
180e3e579f5SChengwen Feng  * @return
181e3e579f5SChengwen Feng  *   0 on success. Otherwise negative value is returned.
182e3e579f5SChengwen Feng  */
183e3e579f5SChengwen Feng __rte_experimental
184e3e579f5SChengwen Feng int rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv);
185e3e579f5SChengwen Feng 
186*9ccd7b27SChengwen Feng /**
187*9ccd7b27SChengwen Feng  * @warning
188*9ccd7b27SChengwen Feng  * @b EXPERIMENTAL: this API may change without prior notice.
189*9ccd7b27SChengwen Feng  *
190*9ccd7b27SChengwen Feng  * Parse the value from the input string based on the value type.
191*9ccd7b27SChengwen Feng  *
192*9ccd7b27SChengwen Feng  * @param str
193*9ccd7b27SChengwen Feng  *   Input string.
194*9ccd7b27SChengwen Feng  * @param val_type
195*9ccd7b27SChengwen Feng  *   The value type, @see RTE_ARGPARSE_ARG_VALUE_INT or other type.
196*9ccd7b27SChengwen Feng  * @param val
197*9ccd7b27SChengwen Feng  *   Saver for the value.
198*9ccd7b27SChengwen Feng  *
199*9ccd7b27SChengwen Feng  * @return
200*9ccd7b27SChengwen Feng  *   0 on success. Otherwise negative value is returned.
201*9ccd7b27SChengwen Feng  */
202*9ccd7b27SChengwen Feng __rte_experimental
203*9ccd7b27SChengwen Feng int rte_argparse_parse_type(const char *str, uint64_t val_type, void *val);
204*9ccd7b27SChengwen Feng 
205e3e579f5SChengwen Feng #ifdef __cplusplus
206e3e579f5SChengwen Feng }
207e3e579f5SChengwen Feng #endif
208e3e579f5SChengwen Feng 
209e3e579f5SChengwen Feng #endif /* RTE_ARGPARSE_H */
210