cmd: improve API for accessing multi-arg options
This commit is contained in:
113
cmd/arglist.c
113
cmd/arglist.c
@@ -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);
|
||||
|
||||
@@ -169,6 +169,7 @@ typedef struct b_command_option b_command_option;
|
||||
typedef struct b_command_arg b_command_arg;
|
||||
typedef struct b_command_usage b_command_usage;
|
||||
typedef struct b_arglist b_arglist;
|
||||
typedef struct b_arglist_option b_arglist_option;
|
||||
|
||||
typedef int (*b_command_callback)(
|
||||
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_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_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_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);
|
||||
@@ -206,7 +208,8 @@ BLUE_API b_status b_command_arg_set_allowed_values(
|
||||
|
||||
BLUE_API b_status b_command_usage_add_option(
|
||||
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(
|
||||
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(
|
||||
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
||||
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(
|
||||
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(
|
||||
const b_arglist *args, unsigned int opt_filter, unsigned int arg_filter,
|
||||
b_arglist_iterator *it);
|
||||
|
||||
Reference in New Issue
Block a user