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 <blue/cmd.h>
@@ -174,23 +175,9 @@ static b_status put_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_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) {
bool value_ok = false;
@@ -438,23 +425,35 @@ static b_status parse_short_opt(struct argv_parser *parser)
break;
}
advance(parser);
if (!opt || b_queue_empty(&opt->opt_args)) {
advance(parser);
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_begin(&opt->opt_args, &it);
const char *value = flags;
if (*value == '\0') {
value = advance(parser);
if (!value || *value == '-') {
value = NULL;
}
advance(parser);
}
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);
if (!arg) {
@@ -468,7 +467,7 @@ static b_status parse_short_opt(struct argv_parser *parser)
if (value) {
b_status status
= put_opt_arg(parser->arglist, opt, arg, value);
= put_opt_arg(arglist_opt, opt, arg, value);
nr_args_cur_opt++;
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) {
b_queue_iterator_next(&it);
nr_args_cur_opt = 0;
continue;
goto next_value;
}
if (arg->arg_nr_values == B_ARG_0_OR_MORE_VALUES && !value) {
b_queue_iterator_next(&it);
nr_args_cur_opt = 0;
continue;
goto next_value;
}
if (arg->arg_nr_values == B_ARG_1_OR_MORE_VALUES && !value) {
if (nr_args_cur_opt > 0) {
b_queue_iterator_next(&it);
nr_args_cur_opt = 0;
continue;
goto next_value;
}
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) {
b_queue_iterator_next(&it);
nr_args_cur_opt = 0;
continue;
goto next_value;
}
if (!value) {
report_missing_args(parser, opt, arg, nr_args_cur_opt);
return B_ERR_BAD_FORMAT;
}
next_value:
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_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_begin(&opt->opt_args, &it);
struct b_command_arg *arg
@@ -578,7 +588,7 @@ static b_status parse_long_opt(struct argv_parser *parser)
if (value) {
b_status status
= put_opt_arg(parser->arglist, opt, arg, value);
= put_opt_arg(arglist_opt, opt, arg, value);
nr_args_total++;
nr_args_cur_opt++;
advance(parser);
@@ -811,6 +821,30 @@ b_status b_arglist_get_uint(
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(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id)
{
@@ -825,6 +859,29 @@ size_t b_arglist_get_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)
{
return b_arglist_iterator_next((struct b_arglist_iterator *)it);