cmd: improve API for accessing multi-arg options

This commit is contained in:
2025-02-04 12:59:44 +00:00
parent 7452491427
commit 243c6651b0
2 changed files with 97 additions and 30 deletions

View File

@@ -1,3 +1,4 @@
#include "blue/core/misc.h"
#include "command.h" #include "command.h"
#include <blue/cmd.h> #include <blue/cmd.h>
@@ -174,23 +175,9 @@ static b_status put_arg(
} }
static b_status put_opt_arg( static b_status put_opt_arg(
struct b_arglist *args, struct b_command_option *opt, struct b_arglist_option *arglist_opt, struct b_command_option *opt,
struct b_command_arg *arg, const char *value) struct b_command_arg *arg, const char *value)
{ {
struct b_arglist_option *arglist_opt
= get_arglist_option(&args->list_options, opt->opt_id);
if (!arglist_opt) {
arglist_opt = malloc(sizeof *arglist_opt);
if (!arglist_opt) {
return B_ERR_NO_MEMORY;
}
memset(arglist_opt, 0x0, sizeof *arglist_opt);
arglist_opt->opt_id = opt->opt_id;
put_arglist_option(&args->list_options, arglist_opt);
}
if (arg->arg_allowed_values) { if (arg->arg_allowed_values) {
bool value_ok = false; bool value_ok = false;
@@ -438,23 +425,35 @@ static b_status parse_short_opt(struct argv_parser *parser)
break; break;
} }
advance(parser);
if (!opt || b_queue_empty(&opt->opt_args)) { if (!opt || b_queue_empty(&opt->opt_args)) {
advance(parser);
return B_SUCCESS; return B_SUCCESS;
} }
struct b_arglist_option *arglist_opt = malloc(sizeof *arglist_opt);
if (!arglist_opt) {
return B_ERR_NO_MEMORY;
}
memset(arglist_opt, 0x0, sizeof *arglist_opt);
arglist_opt->opt_id = opt->opt_id;
put_arglist_option(&parser->arglist->list_options, arglist_opt);
b_queue_iterator it; b_queue_iterator it;
b_queue_iterator_begin(&opt->opt_args, &it); b_queue_iterator_begin(&opt->opt_args, &it);
const char *value = flags; const char *value = flags;
if (*value == '\0') { if (*value == '\0') {
value = advance(parser); advance(parser);
if (!value || *value == '-') {
value = NULL;
}
} }
while (b_queue_iterator_is_valid(&it)) { while (b_queue_iterator_is_valid(&it)) {
value = peek(parser);
if (!value || *value == '-') {
value = NULL;
}
arg = b_unbox(struct b_command_arg, it.entry, arg_entry); arg = b_unbox(struct b_command_arg, it.entry, arg_entry);
if (!arg) { if (!arg) {
@@ -468,7 +467,7 @@ static b_status parse_short_opt(struct argv_parser *parser)
if (value) { if (value) {
b_status status b_status status
= put_opt_arg(parser->arglist, opt, arg, value); = put_opt_arg(arglist_opt, opt, arg, value);
nr_args_cur_opt++; nr_args_cur_opt++;
if (status == B_ERR_INVALID_ARGUMENT) { if (status == B_ERR_INVALID_ARGUMENT) {
@@ -483,20 +482,20 @@ static b_status parse_short_opt(struct argv_parser *parser)
if (arg->arg_nr_values == B_ARG_0_OR_1_VALUES) { if (arg->arg_nr_values == B_ARG_0_OR_1_VALUES) {
b_queue_iterator_next(&it); b_queue_iterator_next(&it);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; goto next_value;
} }
if (arg->arg_nr_values == B_ARG_0_OR_MORE_VALUES && !value) { if (arg->arg_nr_values == B_ARG_0_OR_MORE_VALUES && !value) {
b_queue_iterator_next(&it); b_queue_iterator_next(&it);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; goto next_value;
} }
if (arg->arg_nr_values == B_ARG_1_OR_MORE_VALUES && !value) { if (arg->arg_nr_values == B_ARG_1_OR_MORE_VALUES && !value) {
if (nr_args_cur_opt > 0) { if (nr_args_cur_opt > 0) {
b_queue_iterator_next(&it); b_queue_iterator_next(&it);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; goto next_value;
} }
report_missing_args(parser, opt, arg, nr_args_cur_opt); report_missing_args(parser, opt, arg, nr_args_cur_opt);
@@ -506,14 +505,14 @@ static b_status parse_short_opt(struct argv_parser *parser)
if (nr_args_cur_opt == arg->arg_nr_values) { if (nr_args_cur_opt == arg->arg_nr_values) {
b_queue_iterator_next(&it); b_queue_iterator_next(&it);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; goto next_value;
} }
if (!value) { if (!value) {
report_missing_args(parser, opt, arg, nr_args_cur_opt); report_missing_args(parser, opt, arg, nr_args_cur_opt);
return B_ERR_BAD_FORMAT; return B_ERR_BAD_FORMAT;
} }
next_value:
value = advance(parser); value = advance(parser);
} }
@@ -560,6 +559,17 @@ static b_status parse_long_opt(struct argv_parser *parser)
int nr_args_total = 0; int nr_args_total = 0;
int nr_args_cur_opt = 0; int nr_args_cur_opt = 0;
struct b_arglist_option *arglist_opt = malloc(sizeof *arglist_opt);
if (!arglist_opt) {
return B_ERR_NO_MEMORY;
}
memset(arglist_opt, 0x0, sizeof *arglist_opt);
arglist_opt->opt_id = opt->opt_id;
put_arglist_option(&parser->arglist->list_options, arglist_opt);
b_queue_iterator it; b_queue_iterator it;
b_queue_iterator_begin(&opt->opt_args, &it); b_queue_iterator_begin(&opt->opt_args, &it);
struct b_command_arg *arg struct b_command_arg *arg
@@ -578,7 +588,7 @@ static b_status parse_long_opt(struct argv_parser *parser)
if (value) { if (value) {
b_status status b_status status
= put_opt_arg(parser->arglist, opt, arg, value); = put_opt_arg(arglist_opt, opt, arg, value);
nr_args_total++; nr_args_total++;
nr_args_cur_opt++; nr_args_cur_opt++;
advance(parser); advance(parser);
@@ -811,6 +821,30 @@ b_status b_arglist_get_uint(
return B_ERR_NO_ENTRY; return B_ERR_NO_ENTRY;
} }
b_status b_arglist_get_option(
const b_arglist *args, unsigned int opt_id, unsigned int index,
b_arglist_option **out)
{
b_btree_iterator it = {0};
b_btree_foreach (&it, &args->list_options) {
b_arglist_option *cur
= b_unbox(b_arglist_option, it.node, opt_node);
if (cur->opt_id != opt_id) {
continue;
}
if (index == 0) {
*out = cur;
return B_SUCCESS;
}
index--;
}
return B_ERR_NO_ENTRY;
}
size_t b_arglist_get_count( size_t b_arglist_get_count(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id) const b_arglist *args, unsigned int opt_id, unsigned int arg_id)
{ {
@@ -825,6 +859,29 @@ size_t b_arglist_get_count(
return count; return count;
} }
b_status b_arglist_option_get_value(
const b_arglist_option *opt, unsigned int arg_id, unsigned int index,
b_arglist_value **out)
{
b_btree_iterator it = {0};
b_btree_foreach (&it, &opt->opt_values) {
b_arglist_value *cur = b_unbox(b_arglist_value, it.node, val_node);
if (cur->val_id != arg_id) {
continue;
}
if (index == 0) {
*out = cur;
return B_SUCCESS;
}
index--;
}
return B_ERR_NO_ENTRY;
}
static bool arglist_iterator_next(struct b_iterator *it) static bool arglist_iterator_next(struct b_iterator *it)
{ {
return b_arglist_iterator_next((struct b_arglist_iterator *)it); return b_arglist_iterator_next((struct b_arglist_iterator *)it);

View File

@@ -169,6 +169,7 @@ typedef struct b_command_option b_command_option;
typedef struct b_command_arg b_command_arg; typedef struct b_command_arg b_command_arg;
typedef struct b_command_usage b_command_usage; typedef struct b_command_usage b_command_usage;
typedef struct b_arglist b_arglist; typedef struct b_arglist b_arglist;
typedef struct b_arglist_option b_arglist_option;
typedef int (*b_command_callback)( typedef int (*b_command_callback)(
const b_command *, const b_arglist *, const b_array *); const b_command *, const b_arglist *, const b_array *);
@@ -183,7 +184,8 @@ BLUE_API b_status b_command_set_long_name(b_command *cmd, const char *name);
BLUE_API b_status b_command_set_short_name(b_command *cmd, char name); BLUE_API b_status b_command_set_short_name(b_command *cmd, char name);
BLUE_API b_status b_command_set_flags(b_command *cmd, b_command_flags flags); BLUE_API b_status b_command_set_flags(b_command *cmd, b_command_flags flags);
BLUE_API b_status b_command_set_description(b_command *cmd, const char *description); BLUE_API b_status b_command_set_description(b_command *cmd, const char *description);
BLUE_API b_status b_command_set_callback(b_command *cmd, b_command_callback callback); BLUE_API b_status b_command_set_callback(
b_command *cmd, b_command_callback callback);
BLUE_API b_status b_command_set_parent(b_command *cmd, unsigned int parent_id); BLUE_API b_status b_command_set_parent(b_command *cmd, unsigned int parent_id);
BLUE_API b_command_option *b_command_add_option(b_command *cmd, int id); BLUE_API b_command_option *b_command_add_option(b_command *cmd, int id);
BLUE_API b_command_arg *b_command_add_arg(b_command *cmd, int id); BLUE_API b_command_arg *b_command_add_arg(b_command *cmd, int id);
@@ -206,7 +208,8 @@ BLUE_API b_status b_command_arg_set_allowed_values(
BLUE_API b_status b_command_usage_add_option( BLUE_API b_status b_command_usage_add_option(
b_command_usage *usage, b_command_option *opt); b_command_usage *usage, b_command_option *opt);
BLUE_API b_status b_command_usage_add_arg(b_command_usage *usage, b_command_arg *opt); BLUE_API b_status b_command_usage_add_arg(
b_command_usage *usage, b_command_arg *opt);
BLUE_API b_status b_command_usage_add_command( BLUE_API b_status b_command_usage_add_command(
b_command_usage *usage, unsigned int cmd_id); b_command_usage *usage, unsigned int cmd_id);
@@ -219,9 +222,16 @@ BLUE_API b_status b_arglist_get_int(
BLUE_API b_status b_arglist_get_uint( BLUE_API b_status b_arglist_get_uint(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id, const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
unsigned int index, unsigned long long *out); unsigned int index, unsigned long long *out);
BLUE_API b_status b_arglist_get_option(
const b_arglist *args, unsigned int opt_id, unsigned int index,
b_arglist_option **out);
BLUE_API size_t b_arglist_get_count( BLUE_API size_t b_arglist_get_count(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id); const b_arglist *args, unsigned int opt_id, unsigned int arg_id);
BLUE_API b_status b_arglist_option_get_value(
const b_arglist_option *opt, unsigned int arg_id, unsigned int index,
b_arglist_value **out);
BLUE_API int b_arglist_iterator_begin( BLUE_API int b_arglist_iterator_begin(
const b_arglist *args, unsigned int opt_filter, unsigned int arg_filter, const b_arglist *args, unsigned int opt_filter, unsigned int arg_filter,
b_arglist_iterator *it); b_arglist_iterator *it);