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