#CLI Helpers
#define FIO_CLI
#include "fio-stl.h"A small command-line parser with auto-generated help, typed flags, and unnamed-argument support. It is easier to set up than getopt and stays out of the way once you have your values.
Defining FIO_CLI also pulls in FIO_ATOL, FIO_RAND, and FIO_IMAP because the parser needs them internally.
Note: the module keeps a global data table. Parsing and setting values is not thread-safe. Reading values is safe after parsing is complete.
#Types
#fio_cli_arg_e
typedef enum {
FIO_CLI_ARG_STRING,
FIO_CLI_ARG_BOOL,
FIO_CLI_ARG_INT,
FIO_CLI_ARG_PRINT,
FIO_CLI_ARG_PRINT_LINE,
FIO_CLI_ARG_PRINT_HEADER,
} fio_cli_arg_e;Argument type tags used internally and returned by fio_cli_type.
Values:
FIO_CLI_ARG_STRING— accepts any string value.FIO_CLI_ARG_BOOL— a flag; presence means true.FIO_CLI_ARG_INT— validates the value as an integer.FIO_CLI_ARG_PRINT— indented help text line.FIO_CLI_ARG_PRINT_LINE— unindented help text line.FIO_CLI_ARG_PRINT_HEADER— section header in help output.
#Argument Definition Macros
Use these inside the fio_cli_start macro to describe each flag and help line.
#FIO_CLI_STRING
#define FIO_CLI_STRING(line) /* ... */Declares a string argument.
FIO_CLI_STRING("-o -output (stdout) output file path")#FIO_CLI_INT
#define FIO_CLI_INT(line) /* ... */Declares an integer argument. The parser validates the value with fio_atol.
FIO_CLI_INT("-p -port (8080) the port number to use")#FIO_CLI_BOOL
#define FIO_CLI_BOOL(line) /* ... */Declares a boolean flag. Boolean flags cannot have default values. They can be chained, e.g. -abc is treated as -a -b -c.
FIO_CLI_BOOL("-v -verbose enable verbose logging")#FIO_CLI_PRINT
#define FIO_CLI_PRINT(line) /* ... */Prints an extra indented help line after the previous argument.
FIO_CLI_INT("-p -port (8080) the port number"),
FIO_CLI_PRINT("Set to 0 for Unix socket mode.")#FIO_CLI_PRINT_LINE
#define FIO_CLI_PRINT_LINE(line) /* ... */Prints a help line without indentation.
#FIO_CLI_PRINT_HEADER
#define FIO_CLI_PRINT_HEADER(line) /* ... */Prints a section header in the help output.
FIO_CLI_PRINT_HEADER("Network Options:")#Initialization and Cleanup
#fio_cli_start
#define fio_cli_start(argc, argv, unnamed_min, unnamed_max, description, ...) \
fio_cli_start((argc), \
(argv), \
(unnamed_min), \
(unnamed_max), \
(description), \
(fio___cli_line_s[]){__VA_ARGS__, {0}})
SFUNC void fio_cli_start FIO_NOOP(int argc,
char const *argv[],
int unnamed_min,
int unnamed_max,
char const *description,
fio___cli_line_s *arguments);Parses argv into a dictionary of named and unnamed arguments, then prints help and exits on -h, -?, -help, or --help.
Named Arguments:
argc,argv— values passed tomain.unnamed_min— minimum required unnamed arguments.-1means no limit on unnamed arguments.unnamed_max— maximum allowed unnamed arguments.-1means unlimited.description— program description shown in help. The textNAMEis replaced withargv[0]....— argument description lines using the macros above.
Argument names must start with -. The first non-- word begins the description. Optional defaults go in parentheses: (default) or ("literal default").
Accepted input formats:
app -t=1 -p3000 -a localhost
app -t 1 -p 3000 -a localhost
app --threads=1 --port=3000 --address=localhostNote: this function is not thread-safe.
#define FIO_CLI
#include "fio-stl.h"
int main(int argc, char const *argv[]) {
fio_cli_start(argc, argv, 0, -1,
"NAME - a small CLI example.\n",
FIO_CLI_PRINT_HEADER("Options:"),
FIO_CLI_STRING("-s -str (hello) a string"),
FIO_CLI_INT("-i -int (42) an integer"),
FIO_CLI_BOOL("-b -bool a boolean flag"),
FIO_CLI_PRINT("Boolean flags do not take values."));
fprintf(stderr, "string: %s\n", fio_cli_get("-s"));
fprintf(stderr, "int: %" PRId64 "\n", fio_cli_get_i("-i"));
fprintf(stderr, "bool: %d\n", (int)fio_cli_get_bool("-b"));
fio_cli_end();
return 0;
}#fio_cli_end
SFUNC void fio_cli_end(void);Frees the parsed CLI dictionary.
A destructor runs this automatically at program exit, but calling it earlier lets the memory be reused.
Note: this function is not thread-safe.
#Getting Values
#fio_cli_get
SFUNC char const *fio_cli_get(char const *name);Returns the argument value as a NUL-terminated C string, or NULL if the argument was not provided. If name is NULL, returns the first unnamed argument.
#fio_cli_get_str
SFUNC fio_buf_info_s fio_cli_get_str(char const *name);Returns the argument value as a fio_buf_info_s with length. If name is NULL, returns the first unnamed argument.
#fio_cli_get_i
SFUNC int64_t fio_cli_get_i(char const *name);Returns the argument value parsed as an integer, or 0 if it was not provided. Integer parsing accepts decimal, hex, octal, and binary prefixes.
#fio_cli_get_bool
#define fio_cli_get_bool(name) (fio_cli_get((name)) != NULL)Returns non-zero if the argument was provided, including by default.
#fio_cli_type
SFUNC fio_cli_arg_e fio_cli_type(char const *name);Returns the declared argument type, or FIO_CLI_ARG_NONE if the name is unknown.
#Unnamed Arguments
#fio_cli_unnamed_count
SFUNC unsigned int fio_cli_unnamed_count(void);Returns the number of unnamed arguments collected.
#fio_cli_unnamed
SFUNC char const *fio_cli_unnamed(unsigned int index);Returns the unnamed argument at index as a NUL-terminated string, or NULL if index is out of bounds.
#fio_cli_unnamed_str
SFUNC fio_buf_info_s fio_cli_unnamed_str(unsigned int index);Returns the unnamed argument at index as a fio_buf_info_s, or an empty fio_buf_info_s if out of bounds.
#Setting Values
#fio_cli_set
SFUNC void fio_cli_set(char const *name, char const *value);Sets or overwrites a named argument's value. If name is NULL, appends value as a new unnamed argument.
Note: this function is not thread-safe.
#fio_cli_set_i
SFUNC void fio_cli_set_i(char const *name, int64_t i);Sets a named argument to a base-10 string representation of i.
Note: this function is not thread-safe.
#fio_cli_set_unnamed
SFUNC unsigned int fio_cli_set_unnamed(unsigned int index, const char *value);Sets or appends an unnamed argument. If index is past the end, the value is appended. Returns the stored index, or (unsigned int)-1 if value is NULL or empty.
Note: this function is not thread-safe.
#Iteration
#fio_cli_each
SFUNC size_t fio_cli_each(int (*task)(fio_buf_info_s name,
fio_buf_info_s value,
fio_cli_arg_e arg_type,
void *udata),
void *udata);Calls task for every argument that has a value, returning the number of calls made. If task returns non-zero, iteration stops. For unnamed arguments, name.buf is NULL and name.len is 0.