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