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 "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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user