diff options
author | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2025-09-13 01:18:44 +0300 |
---|---|---|
committer | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2025-09-13 01:18:44 +0300 |
commit | 0a770cbaf0c9509415e6dabf880bf75d25a02606 (patch) | |
tree | 797c09e7e80bbee0e4af96d572684ac7cc4dff6d /cli/cli-opts.h | |
parent | 0a8ee7a194e598d9c277b019503f7119b32bd17f (diff) | |
download | c-wares-0a770cbaf0c9509415e6dabf880bf75d25a02606.tar.gz c-wares-0a770cbaf0c9509415e6dabf880bf75d25a02606.zip |
cli: header with extra option implementations
For now just one, `struct cli_opt_data_size`.
Diffstat (limited to 'cli/cli-opts.h')
-rw-r--r-- | cli/cli-opts.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/cli/cli-opts.h b/cli/cli-opts.h new file mode 100644 index 0000000..4a94bcc --- /dev/null +++ b/cli/cli-opts.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/** + * cli-opts.h - Extra cli_opt implementations for cli.h + * + * Copyright (c) 2025 - Yaroslav de la Peña Smirnov + */ +#ifndef CLI_OPTS_H +#define CLI_OPTS_H +#include "cli.h" +#include <ctype.h> + +/** + * struct cli_opt_data_size - an option that represents data size in bytes. + * @opt: parent class. + * @bytes: the amount given by the user in bytes. + * + * This CLI option can parse units in bytes, KiB, MiB, GiB, TiB. By giving the + * number a suffix, it multiplies the number by the equivalent in bytes. E.g. + * `1K` == `1024`. + */ +struct cli_opt_data_size { + struct cli_opt opt; + uint64_t bytes; +}; + +#define CLI_OPT_DATA_SIZE(name, sh, ln, dsc) \ + struct cli_opt_data_size name = { \ + .opt = \ + { \ + .type = CLI_OT_VALUE, \ + .shor = sh, \ + .lon = ln, \ + .desc = dsc, \ + .set = cli_opt_data_size_set, \ + }, \ + } + +int cli_opt_data_size_set(struct cli_opt *self, const char *val) +{ + struct cli_opt_data_size *opt = + container_of(self, struct cli_opt_data_size, opt); + + char *endptr = NULL; + errno = 0; + unsigned long long num = strtoull(val, &endptr, 10); + if (errno != 0) + goto invalid; + + if (endptr && *endptr != '\0') { + switch (toupper(*endptr)) { + case 'K': + opt->bytes = num <<= 10; + break; + case 'M': + opt->bytes = num <<= 20; + break; + case 'G': + opt->bytes = num <<= 30; + break; + case 'T': + opt->bytes = num <<= 40; + break; + default: + goto invalid; + } + } else { + opt->bytes = num; + } + + return CLI_RC_OK; +invalid: + fprintf(stderr, + "invalid value \"%s\", expected a number optionally followed " + "by a multiplicative suffix (K, M, G, T).", + val); + return CLI_RC_ERR; +} + +#endif /* CLI_OPTS_H */ |