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