/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2024 HiSilicon Limited */ #ifndef RTE_ARGPARSE_H #define RTE_ARGPARSE_H /** * @file rte_argparse.h * * Argument parsing API. * * The argument parsing API makes it easy to write user-friendly command-line * program. The program defines what arguments it requires, * and the API will parse those arguments from [argc, argv]. * * The API provides the following functions: * 1) Support parsing optional argument (which could take with no-value, * required-value and optional-value. * 2) Support parsing positional argument (which must take with required-value). * 3) Support automatic generate usage information. * 4) Support issue errors when provided with invalid arguments. * * There are two ways to parse arguments: * 1) AutoSave: for which known value types, the way can be used. * 2) Callback: will invoke user callback to parse. * */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /**@{@name Flag definition (in bitmask form) for an argument * * @note Bits[0~1] represent the argument whether has value, * bits[2~9] represent the value type which used when autosave. * * @see struct rte_argparse_arg::flags */ /** The argument has no value. */ #define RTE_ARGPARSE_ARG_NO_VALUE RTE_SHIFT_VAL64(1, 0) /** The argument must have a value. */ #define RTE_ARGPARSE_ARG_REQUIRED_VALUE RTE_SHIFT_VAL64(2, 0) /** The argument has optional value. */ #define RTE_ARGPARSE_ARG_OPTIONAL_VALUE RTE_SHIFT_VAL64(3, 0) /** The argument's value is int type. */ #define RTE_ARGPARSE_ARG_VALUE_INT RTE_SHIFT_VAL64(1, 2) /** The argument's value is uint8 type. */ #define RTE_ARGPARSE_ARG_VALUE_U8 RTE_SHIFT_VAL64(2, 2) /** The argument's value is uint16 type. */ #define RTE_ARGPARSE_ARG_VALUE_U16 RTE_SHIFT_VAL64(3, 2) /** The argument's value is uint32 type. */ #define RTE_ARGPARSE_ARG_VALUE_U32 RTE_SHIFT_VAL64(4, 2) /** The argument's value is uint64 type. */ #define RTE_ARGPARSE_ARG_VALUE_U64 RTE_SHIFT_VAL64(5, 2) /** Max value type. */ #define RTE_ARGPARSE_ARG_VALUE_MAX RTE_SHIFT_VAL64(6, 2) /** * Flag for that argument support occur multiple times. * This flag can be set only when the argument is optional. * When this flag is set, the callback type must be used for parsing. */ #define RTE_ARGPARSE_ARG_SUPPORT_MULTI RTE_BIT64(10) /** Reserved for this library implementation usage. */ #define RTE_ARGPARSE_ARG_RESERVED_FIELD RTE_GENMASK64(63, 48) /**@}*/ /** Bitmask used to get the argument whether has value. */ #define RTE_ARGPARSE_HAS_VAL_BITMASK RTE_GENMASK64(1, 0) /** Bitmask used to get the argument's value type. */ #define RTE_ARGPARSE_VAL_TYPE_BITMASK RTE_GENMASK64(9, 2) /** * A structure used to hold argument's configuration. */ struct rte_argparse_arg { /** * Long name of the argument: * 1) If the argument is optional, it must start with ``--``. * 2) If the argument is positional, it must not start with ``-``. * 3) Other case will be considered as error. */ const char *name_long; /** * Short name of the argument: * 1) This field could be set only when name_long is optional, and * must start with a hyphen (-) followed by an English letter. * 2) Other case it should be set NULL. */ const char *name_short; /** Help information of the argument, must not be NULL. */ const char *help; /** * Saver for the argument's value. * 1) If the filed is NULL, the callback way is used for parsing * argument. * 2) If the field is not NULL, the autosave way is used for parsing * argument. */ void *val_saver; /** * If val_saver is NULL, this filed (cast as (uint32_t)val_set) will be * used as the first parameter to invoke callback. * * If val_saver is not NULL, then: * 1) If argument has no value, *val_saver will be set to val_set. * 2) If argument has optional value but doesn't take value this * time, *val_saver will be set to val_set. * 3) Other case it should be set NULL. */ void *val_set; /** Flag definition (RTE_ARGPARSE_ARG_*) for the argument. */ uint64_t flags; }; /** * Callback prototype used by parsing specified arguments. * * @param index * The argument's index, coming from argument's val_set field. * @param value * The value corresponding to the argument, it may be NULL (e.g. the * argument has no value, or the argument has optional value but doesn't * provided value). * @param opaque * An opaque pointer coming from the caller. * @return * 0 on success. Otherwise negative value is returned. */ typedef int (*rte_arg_parser_t)(uint32_t index, const char *value, void *opaque); /** * A structure used to hold argparse's configuration. */ struct rte_argparse { /** Program name. Must not be NULL. */ const char *prog_name; /** How to use the program. Must not be NULL. */ const char *usage; /** Explain what the program does. Could be NULL. */ const char *descriptor; /** Text at the bottom of help. Could be NULL. */ const char *epilog; /** Whether exit when error. */ bool exit_on_error; /** User callback for parsing arguments. */ rte_arg_parser_t callback; /** Opaque which used to invoke callback. */ void *opaque; /** Reserved field used for future extension. */ void *reserved[16]; /** Arguments configuration. Must ended with ARGPARSE_ARG_END(). */ struct rte_argparse_arg args[]; }; #define ARGPARSE_ARG_END() { NULL } /** * @warning * @b EXPERIMENTAL: this API may change without prior notice. * * Parse parameters. * * @param obj * Parser object. * @param argc * Parameters count. * @param argv * Array of parameters points. * * @return * 0 on success. Otherwise negative value is returned. */ __rte_experimental int rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice. * * Parse the value from the input string based on the value type. * * @param str * Input string. * @param val_type * The value type, @see RTE_ARGPARSE_ARG_VALUE_INT or other type. * @param val * Saver for the value. * * @return * 0 on success. Otherwise negative value is returned. */ __rte_experimental int rte_argparse_parse_type(const char *str, uint64_t val_type, void *val); #ifdef __cplusplus } #endif #endif /* RTE_ARGPARSE_H */