From 0a770cbaf0c9509415e6dabf880bf75d25a02606 Mon Sep 17 00:00:00 2001 From: Yaroslav de la Peña Smirnov Date: Sat, 13 Sep 2025 01:18:44 +0300 Subject: cli: header with extra option implementations For now just one, `struct cli_opt_data_size`. --- cli/cli-opts.h | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 cli/cli-opts.h (limited to 'cli/cli-opts.h') 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 + +/** + * 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 */ -- cgit v1.2.3