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