aboutsummaryrefslogtreecommitdiff
path: root/cli/cli-opts.h
diff options
context:
space:
mode:
Diffstat (limited to 'cli/cli-opts.h')
-rw-r--r--cli/cli-opts.h79
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 */