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