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