Compare commits

..

10 Commits

45 changed files with 543 additions and 466 deletions

View File

@@ -22,12 +22,12 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
foreach (module ${b_modules}) foreach (module ${b_modules})
add_subdirectory(${module}) add_subdirectory(${module})
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${module}-test) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/${module})
message(STATUS "Building unit tests for module ${module}") message(STATUS "Building unit tests for module ${module}")
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${module}-test/${module}-units.c) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/${module}/${module}-units.c)
add_executable(blue-${module}-units add_executable(blue-${module}-units
${module}-test/${module}-units.c test/${module}/${module}-units.c
misc/AllTests.c misc/AllTests.c
misc/CuTest.c misc/CuTest.c
misc/CuTest.h) misc/CuTest.h)
@@ -37,8 +37,8 @@ foreach (module ${b_modules})
endif () endif ()
file(GLOB test_sources ${module}-test/*.c) file(GLOB test_sources test/${module}/*.c)
list(REMOVE_ITEM test_sources "${CMAKE_CURRENT_SOURCE_DIR}/${module}-test/${module}-units.c") list(REMOVE_ITEM test_sources "${CMAKE_CURRENT_SOURCE_DIR}/test/${module}/${module}-units.c")
foreach (test_file ${test_sources}) foreach (test_file ${test_sources})
get_filename_component(test_name ${test_file} NAME_WE) get_filename_component(test_name ${test_file} NAME_WE)

View File

@@ -24,7 +24,7 @@ struct argv_parser {
struct b_command *cmd; struct b_command *cmd;
struct b_arglist *arglist; struct b_arglist *arglist;
b_queue_iterator arg_it; b_queue_entry *arg_it;
int nr_values_cur_arg; int nr_values_cur_arg;
int argc; int argc;
@@ -66,7 +66,7 @@ static void move_to_subcommand(struct argv_parser *parser, struct b_command *cmd
{ {
parser->cmd = cmd; parser->cmd = cmd;
parser->arglist->list_command = cmd; parser->arglist->list_command = cmd;
b_queue_iterator_begin(&cmd->b_arg, &parser->arg_it); parser->arg_it = b_queue_first(&cmd->b_arg);
parser->nr_values_cur_arg = 0; parser->nr_values_cur_arg = 0;
} }
@@ -182,12 +182,12 @@ static void report_unexpected_arg(struct argv_parser *parser, const char *value)
static b_status check_required_args(struct argv_parser *parser) static b_status check_required_args(struct argv_parser *parser)
{ {
if (!b_queue_iterator_is_valid(&parser->arg_it)) { if (!parser->arg_it) {
return B_SUCCESS; return B_SUCCESS;
} }
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, parser->arg_it.entry, arg_entry); = b_unbox(struct b_command_arg, parser->arg_it, arg_entry);
if (!arg) { if (!arg) {
return B_SUCCESS; return B_SUCCESS;
} }
@@ -236,7 +236,7 @@ static b_status parse_arg(struct argv_parser *parser)
} }
struct b_command_arg *arg = b_unbox( struct b_command_arg *arg = b_unbox(
struct b_command_arg, parser->arg_it.entry, arg_entry); struct b_command_arg, parser->arg_it, arg_entry);
if (!arg) { if (!arg) {
b_arglist_report_unexpected_arg(parser->arglist, value); b_arglist_report_unexpected_arg(parser->arglist, value);
@@ -258,13 +258,13 @@ static b_status parse_arg(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(&parser->arg_it); parser->arg_it = b_queue_next(parser->arg_it);
parser->nr_values_cur_arg = 0; parser->nr_values_cur_arg = 0;
continue; continue;
} }
if (parser->nr_values_cur_arg == arg->arg_nr_values) { if (parser->nr_values_cur_arg == arg->arg_nr_values) {
b_queue_iterator_next(&parser->arg_it); parser->arg_it = b_queue_next(parser->arg_it);
parser->nr_values_cur_arg = 0; parser->nr_values_cur_arg = 0;
continue; continue;
} }
@@ -357,25 +357,19 @@ static b_status parse_short_opt(struct argv_parser *parser)
arglist_opt->opt_id = opt->opt_id; arglist_opt->opt_id = opt->opt_id;
put_arglist_option(&parser->arglist->list_options, arglist_opt); put_arglist_option(&parser->arglist->list_options, arglist_opt);
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
b_queue_iterator_begin(&opt->opt_args, &it);
const char *value = flags; const char *value = flags;
if (*value == '\0') { if (*value == '\0') {
advance(parser); advance(parser);
} }
while (b_queue_iterator_is_valid(&it)) { while (entry) {
value = peek(parser); value = peek(parser);
if (!value || *value == '-') { if (!value || *value == '-') {
value = NULL; value = NULL;
} }
arg = b_unbox(struct b_command_arg, it.entry, arg_entry); arg = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) {
b_queue_iterator_next(&it);
continue;
}
if (!value || *value == '\0' || *value == '-') { if (!value || *value == '\0' || *value == '-') {
value = NULL; value = NULL;
@@ -398,20 +392,17 @@ 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);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
goto next_value; 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);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
goto next_value; 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);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
goto next_value; goto next_value;
} }
@@ -423,7 +414,6 @@ 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);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
goto next_value; goto next_value;
} }
@@ -435,6 +425,7 @@ static b_status parse_short_opt(struct argv_parser *parser)
return B_ERR_BAD_FORMAT; return B_ERR_BAD_FORMAT;
} }
next_value: next_value:
entry = b_queue_next(entry);
value = advance(parser); value = advance(parser);
} }
@@ -493,16 +484,11 @@ static b_status parse_long_opt(struct argv_parser *parser)
arglist_opt->opt_id = opt->opt_id; arglist_opt->opt_id = opt->opt_id;
put_arglist_option(&parser->arglist->list_options, arglist_opt); put_arglist_option(&parser->arglist->list_options, arglist_opt);
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
b_queue_iterator_begin(&opt->opt_args, &it); struct b_command_arg *arg = NULL;
struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry);
while (b_queue_iterator_is_valid(&it)) { while (entry) {
arg = b_unbox(struct b_command_arg, it.entry, arg_entry); arg = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) {
break;
}
const char *value = peek(parser); const char *value = peek(parser);
if (!value || value[0] == '-') { if (!value || value[0] == '-') {
@@ -528,20 +514,20 @@ static b_status parse_long_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); entry = b_queue_next(entry);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; continue;
} }
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); entry = b_queue_next(entry);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; continue;
} }
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); entry = b_queue_next(entry);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; continue;
} }
@@ -553,7 +539,7 @@ static b_status parse_long_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); entry = b_queue_next(entry);
nr_args_cur_opt = 0; nr_args_cur_opt = 0;
continue; continue;
} }
@@ -666,34 +652,33 @@ static void arglist_value_destroy(struct b_arglist_value *val)
void b_arglist_destroy(struct b_arglist *args) void b_arglist_destroy(struct b_arglist *args)
{ {
b_btree_iterator opt_it, args_it; b_btree_node *opt_it, *args_it;
b_btree_node *opt_next, *args_next;
b_btree_iterator_begin(&args->list_options, &opt_it); opt_it = b_btree_first(&args->list_options);
while (b_btree_iterator_is_valid(&opt_it)) { while (opt_it) {
struct b_arglist_option *opt struct b_arglist_option *opt
= b_unbox(struct b_arglist_option, opt_it.node, opt_node); = b_unbox(struct b_arglist_option, opt_it, opt_node);
opt_next = b_btree_next(opt_it);
if (!opt) { args_it = b_btree_first(&opt->opt_values);
b_btree_iterator_next(&opt_it); while (args_it) {
continue;
}
b_btree_iterator_begin(&opt->opt_values, &args_it);
while (b_btree_iterator_is_valid(&args_it)) {
struct b_arglist_value *val = b_unbox( struct b_arglist_value *val = b_unbox(
struct b_arglist_value, args_it.node, val_node); struct b_arglist_value, args_it, val_node);
args_next = b_btree_next(args_it);
if (!val) { if (val) {
b_btree_iterator_next(&args_it); b_btree_delete(&opt->opt_values, args_it);
continue; arglist_value_destroy(val);
} }
b_btree_iterator_erase(&args_it); args_it = args_next;
arglist_value_destroy(val);
} }
b_btree_iterator_erase(&opt_it); b_btree_delete(&args->list_options, opt_it);
arglist_option_destroy(opt); arglist_option_destroy(opt);
opt_it = opt_next;
} }
free(args); free(args);
@@ -775,12 +760,13 @@ b_status b_arglist_get_option(
const b_arglist *args, unsigned int opt_id, unsigned int index, const b_arglist *args, unsigned int opt_id, unsigned int index,
b_arglist_option **out) b_arglist_option **out)
{ {
b_btree_iterator it = {0}; struct b_btree_node *node = b_btree_first(&args->list_options);
b_btree_foreach (&it, &args->list_options) {
b_arglist_option *cur while (node) {
= b_unbox(b_arglist_option, it.node, opt_node); b_arglist_option *cur = b_unbox(b_arglist_option, node, opt_node);
if (cur->opt_id != opt_id) { if (cur->opt_id != opt_id) {
node = b_btree_next(node);
continue; continue;
} }
@@ -789,6 +775,7 @@ b_status b_arglist_get_option(
return B_SUCCESS; return B_SUCCESS;
} }
node = b_btree_next(node);
index--; index--;
} }
@@ -813,11 +800,12 @@ b_status b_arglist_option_get_value(
const b_arglist_option *opt, unsigned int arg_id, unsigned int index, const b_arglist_option *opt, unsigned int arg_id, unsigned int index,
b_arglist_value **out) b_arglist_value **out)
{ {
b_btree_iterator it = {0}; struct b_btree_node *node = b_btree_first(&opt->opt_values);
b_btree_foreach (&it, &opt->opt_values) { while (node) {
b_arglist_value *cur = b_unbox(b_arglist_value, it.node, val_node); b_arglist_value *cur = b_unbox(b_arglist_value, node, val_node);
if (cur->val_id != arg_id) { if (cur->val_id != arg_id) {
node = b_btree_next(node);
continue; continue;
} }
@@ -826,6 +814,7 @@ b_status b_arglist_option_get_value(
return B_SUCCESS; return B_SUCCESS;
} }
node = b_btree_next(node);
index--; index--;
} }
@@ -834,24 +823,14 @@ b_status b_arglist_option_get_value(
/************************ arglist iterator functions **************************/ /************************ arglist iterator functions **************************/
static bool arglist_iterator_next(struct b_iterator *it)
{
return b_arglist_iterator_next((struct b_arglist_iterator *)it);
}
static bool arglist_iterator_is_valid(const struct b_iterator *it)
{
return b_arglist_iterator_is_valid((const struct b_arglist_iterator *)it);
}
static struct b_arglist_option *advance_to_next_opt(struct b_arglist_iterator *it) static struct b_arglist_option *advance_to_next_opt(struct b_arglist_iterator *it)
{ {
struct b_arglist_option *opt; struct b_arglist_option *opt;
// b_btree_iterator_next(&it->_opt_it); // b_btree_iterator_next(&it->_opt_it);
while (b_btree_iterator_is_valid(&it->_opt_it)) { while (it->_opt_it) {
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node); opt = b_unbox(struct b_arglist_option, it->_opt_it, opt_node);
if (opt if (opt
&& (opt->opt_id == it->_opt_filter && (opt->opt_id == it->_opt_filter
|| it->_opt_filter == B_COMMAND_INVALID_ID)) { || it->_opt_filter == B_COMMAND_INVALID_ID)) {
@@ -859,7 +838,7 @@ static struct b_arglist_option *advance_to_next_opt(struct b_arglist_iterator *i
return opt; return opt;
} }
b_btree_iterator_next(&it->_opt_it); it->_opt_it = b_btree_next(it->_opt_it);
} }
return NULL; return NULL;
@@ -871,8 +850,8 @@ static struct b_arglist_value *advance_to_next_arg(struct b_arglist_iterator *it
// b_btree_iterator_next(&it->_arg_it); // b_btree_iterator_next(&it->_arg_it);
while (b_btree_iterator_is_valid(&it->_arg_it)) { while (it->_arg_it) {
val = b_unbox(struct b_arglist_value, it->_arg_it.node, val_node); val = b_unbox(struct b_arglist_value, it->_arg_it, val_node);
if (val if (val
&& (val->val_id == it->_arg_filter && (val->val_id == it->_arg_filter
|| it->_arg_filter == B_COMMAND_INVALID_ID)) { || it->_arg_filter == B_COMMAND_INVALID_ID)) {
@@ -880,17 +859,12 @@ static struct b_arglist_value *advance_to_next_arg(struct b_arglist_iterator *it
return val; return val;
} }
b_btree_iterator_next(&it->_arg_it); it->_arg_it = b_btree_next(it->_arg_it);
} }
return NULL; return NULL;
} }
static b_iterator_ops it_ops = {
.it_next = arglist_iterator_next,
.it_is_valid = arglist_iterator_is_valid,
};
int b_arglist_iterator_begin( int b_arglist_iterator_begin(
const struct b_arglist *args, unsigned int opt_filter, const struct b_arglist *args, unsigned int opt_filter,
unsigned int arg_filter, struct b_arglist_iterator *it) unsigned int arg_filter, struct b_arglist_iterator *it)
@@ -899,33 +873,32 @@ int b_arglist_iterator_begin(
it->opt_id = B_COMMAND_INVALID_ID; it->opt_id = B_COMMAND_INVALID_ID;
it->_base.it_ops = &it_ops;
it->_opt_filter = opt_filter; it->_opt_filter = opt_filter;
it->_arg_filter = arg_filter; it->_arg_filter = arg_filter;
b_btree_iterator_begin(&args->list_options, &it->_opt_it); it->_opt_it = b_btree_first(&args->list_options);
struct b_arglist_option *opt = NULL; struct b_arglist_option *opt = NULL;
struct b_arglist_value *val = NULL; struct b_arglist_value *val = NULL;
while (1) { while (1) {
if (!b_btree_iterator_is_valid(&it->_opt_it)) { if (!it->_opt_it) {
opt = NULL; opt = NULL;
return -1; return -1;
} }
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node); opt = b_unbox(struct b_arglist_option, it->_opt_it, opt_node);
if (!opt if (!opt
|| (opt_filter != opt->opt_id || (opt_filter != opt->opt_id
&& opt_filter != B_COMMAND_INVALID_ID)) { && opt_filter != B_COMMAND_INVALID_ID)) {
b_btree_iterator_next(&it->_opt_it); it->_opt_it = b_btree_next(it->_opt_it);
continue; continue;
} }
b_btree_iterator_begin(&opt->opt_values, &it->_arg_it); it->_arg_it = b_btree_first(&opt->opt_values);
bool done = false; bool done = false;
while (1) { while (1) {
if (!b_btree_iterator_is_valid(&it->_arg_it)) { if (!it->_arg_it) {
if (arg_filter == B_COMMAND_INVALID_ID) { if (arg_filter == B_COMMAND_INVALID_ID) {
done = true; done = true;
} }
@@ -933,12 +906,11 @@ int b_arglist_iterator_begin(
break; break;
} }
val = b_unbox( val = b_unbox(struct b_arglist_value, it->_arg_it, val_node);
struct b_arglist_value, it->_arg_it.node, val_node);
if (!val if (!val
|| (arg_filter != val->val_id || (arg_filter != val->val_id
&& arg_filter != B_COMMAND_INVALID_ID)) { && arg_filter != B_COMMAND_INVALID_ID)) {
b_btree_iterator_next(&it->_arg_it); it->_arg_it = b_btree_next(it->_arg_it);
continue; continue;
} }
@@ -950,7 +922,7 @@ int b_arglist_iterator_begin(
break; break;
} }
b_btree_iterator_next(&it->_opt_it); it->_opt_it = b_btree_next(it->_opt_it);
} }
it->opt_id = opt->opt_id; it->opt_id = opt->opt_id;
@@ -964,7 +936,7 @@ bool b_arglist_iterator_next(struct b_arglist_iterator *it)
struct b_arglist_option *opt; struct b_arglist_option *opt;
struct b_arglist_value *val; struct b_arglist_value *val;
b_btree_iterator_next(&it->_arg_it); it->_arg_it = b_btree_next(it->_arg_it);
while (1) { while (1) {
val = advance_to_next_arg(it); val = advance_to_next_arg(it);
@@ -975,7 +947,7 @@ bool b_arglist_iterator_next(struct b_arglist_iterator *it)
return true; return true;
} }
b_btree_iterator_next(&it->_opt_it); it->_opt_it = b_btree_next(it->_opt_it);
opt = advance_to_next_opt(it); opt = advance_to_next_opt(it);
if (!opt) { if (!opt) {
it->value = NULL; it->value = NULL;
@@ -983,7 +955,7 @@ bool b_arglist_iterator_next(struct b_arglist_iterator *it)
return false; return false;
} }
b_btree_iterator_begin(&opt->opt_values, &it->_arg_it); it->_arg_it = b_btree_first(&opt->opt_values);
if (it->_arg_filter == B_COMMAND_INVALID_ID) { if (it->_arg_filter == B_COMMAND_INVALID_ID) {
return true; return true;
@@ -998,27 +970,13 @@ bool b_arglist_iterator_is_valid(const struct b_arglist_iterator *it)
/********************* arglist option iterator functions **********************/ /********************* arglist option iterator functions **********************/
static bool arglist_option_iterator_next(struct b_iterator *it)
{
return b_arglist_option_iterator_next(
(struct b_arglist_option_iterator *)it);
}
static bool arglist_option_iterator_is_valid(const struct b_iterator *it)
{
return b_arglist_option_iterator_is_valid(
(const struct b_arglist_option_iterator *)it);
}
static struct b_arglist_option *advance_to_next_opt2( static struct b_arglist_option *advance_to_next_opt2(
struct b_arglist_option_iterator *it) struct b_arglist_option_iterator *it)
{ {
struct b_arglist_option *opt; struct b_arglist_option *opt;
// b_btree_iterator_next(&it->_opt_it); while (it->_opt_it) {
opt = b_unbox(struct b_arglist_option, it->_opt_it, opt_node);
while (b_btree_iterator_is_valid(&it->_opt_it)) {
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node);
if (opt if (opt
&& (opt->opt_id == it->_opt_filter && (opt->opt_id == it->_opt_filter
|| it->_opt_filter == B_COMMAND_INVALID_ID)) { || it->_opt_filter == B_COMMAND_INVALID_ID)) {
@@ -1026,17 +984,12 @@ static struct b_arglist_option *advance_to_next_opt2(
return opt; return opt;
} }
b_btree_iterator_next(&it->_opt_it); it->_opt_it = b_btree_next(it->_opt_it);
} }
return NULL; return NULL;
} }
static b_iterator_ops option_it_ops = {
.it_next = arglist_option_iterator_next,
.it_is_valid = arglist_option_iterator_is_valid,
};
int b_arglist_option_iterator_begin( int b_arglist_option_iterator_begin(
const struct b_arglist *args, unsigned int opt_filter, const struct b_arglist *args, unsigned int opt_filter,
struct b_arglist_option_iterator *it) struct b_arglist_option_iterator *it)
@@ -1045,26 +998,26 @@ int b_arglist_option_iterator_begin(
it->opt_id = B_COMMAND_INVALID_ID; it->opt_id = B_COMMAND_INVALID_ID;
it->_base.it_ops = &it_ops;
it->_opt_filter = opt_filter; it->_opt_filter = opt_filter;
b_btree_iterator_begin(&args->list_options, &it->_opt_it); it->_opt_it = b_btree_first(&args->list_options);
struct b_arglist_option *opt = NULL; struct b_arglist_option *opt = NULL;
struct b_arglist_value *val = NULL; struct b_arglist_value *val = NULL;
while (1) { while (1) {
if (!b_btree_iterator_is_valid(&it->_opt_it)) { if (!it->_opt_it) {
opt = NULL; opt = NULL;
return -1; return -1;
} }
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node); opt = b_unbox(struct b_arglist_option, it->_opt_it, opt_node);
if (opt if (opt
&& (opt_filter == opt->opt_id && (opt_filter == opt->opt_id
|| opt_filter == B_COMMAND_INVALID_ID)) { || opt_filter == B_COMMAND_INVALID_ID)) {
break; break;
} }
b_btree_iterator_next(&it->_opt_it);
it->_opt_it = b_btree_next(it->_opt_it);
} }
it->opt_id = opt->opt_id; it->opt_id = opt->opt_id;
@@ -1078,7 +1031,7 @@ bool b_arglist_option_iterator_next(struct b_arglist_option_iterator *it)
struct b_arglist_option *opt; struct b_arglist_option *opt;
struct b_arglist_value *val; struct b_arglist_value *val;
b_btree_iterator_next(&it->_opt_it); it->_opt_it = b_btree_next(it->_opt_it);
opt = advance_to_next_opt2(it); opt = advance_to_next_opt2(it);
if (!opt) { if (!opt) {
it->opt = NULL; it->opt = NULL;

View File

@@ -24,16 +24,18 @@ enum item_type {
static void command_list_cleanup(void) static void command_list_cleanup(void)
{ {
struct b_btree_iterator it = {0}; struct b_btree_node *node = b_btree_first(&command_list);
b_btree_iterator_begin(&command_list, &it); while (node) {
while (b_btree_iterator_is_valid(&it)) { struct b_command *cmd = b_unbox(struct b_command, node, b_node);
struct b_command *cmd = b_unbox(struct b_command, it.node, b_node);
if (!cmd) { if (!cmd) {
break; break;
} }
b_btree_iterator_erase(&it); struct b_btree_node *next = b_btree_next(node);
b_btree_delete(&command_list, node);
b_command_destroy(cmd); b_command_destroy(cmd);
node = next;
} }
} }
@@ -53,18 +55,19 @@ struct b_command *b_command_create(unsigned int id)
static void command_usage_destroy(struct b_command_usage *usage) static void command_usage_destroy(struct b_command_usage *usage)
{ {
struct b_queue_iterator it = {0}; struct b_queue_entry *entry = b_queue_first(&usage->u_parts);
while (entry) {
b_queue_iterator_begin(&usage->u_parts, &it); struct b_command_usage_entry *arg
while (b_queue_iterator_is_valid(&it)) { = b_unbox(struct b_command_usage_entry, entry, e_entry);
struct b_command_usage_entry *arg = b_unbox(
struct b_command_usage_entry, it.entry, e_entry);
if (!arg) { if (!arg) {
continue; continue;
} }
b_queue_iterator_erase(&it); struct b_queue_entry *next = b_queue_next(entry);
b_queue_delete(&usage->u_parts, entry);
free(arg); free(arg);
entry = next;
} }
free(usage); free(usage);
@@ -72,8 +75,6 @@ static void command_usage_destroy(struct b_command_usage *usage)
void b_command_destroy(struct b_command *cmd) void b_command_destroy(struct b_command *cmd)
{ {
struct b_queue_iterator it = {0};
if (cmd->b_name) { if (cmd->b_name) {
free(cmd->b_name); free(cmd->b_name);
} }
@@ -86,52 +87,71 @@ void b_command_destroy(struct b_command *cmd)
free(cmd->b_description); free(cmd->b_description);
} }
b_queue_iterator_begin(&cmd->b_opt, &it); struct b_queue_entry *entry = b_queue_first(&cmd->b_opt);
while (b_queue_iterator_is_valid(&it)) { struct b_queue_entry *next = NULL;
while (entry) {
struct b_command_option *opt struct b_command_option *opt
= b_unbox(struct b_command_option, it.entry, opt_entry); = b_unbox(struct b_command_option, entry, opt_entry);
if (!opt) { if (!opt) {
break; break;
} }
b_queue_iterator_erase(&it); next = b_queue_next(entry);
b_queue_delete(&cmd->b_opt, entry);
b_command_option_destroy(opt); b_command_option_destroy(opt);
entry = next;
} }
b_queue_iterator_begin(&cmd->b_arg, &it); entry = b_queue_first(&cmd->b_arg);
while (b_queue_iterator_is_valid(&it)) { while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) { if (!arg) {
break; break;
} }
b_queue_iterator_erase(&it); next = b_queue_next(entry);
b_queue_delete(&cmd->b_arg, entry);
b_command_arg_destroy(arg); b_command_arg_destroy(arg);
entry = next;
} }
b_queue_iterator_begin(&cmd->b_arg, &it); #if 0
while (b_queue_iterator_is_valid(&it)) { entry = b_queue_first(&cmd->b_subcommands);
while (entry) {
struct b_command *subcmd struct b_command *subcmd
= b_unbox(struct b_command, it.entry, b_entry); = b_unbox(struct b_command, entry, b_entry);
if (!subcmd) { if (!subcmd) {
break; break;
} }
b_queue_iterator_erase(&it); next = b_queue_next(entry);
b_command_destroy(subcmd);
}
b_queue_iterator_begin(&cmd->b_usage, &it); b_command_destroy(subcmd);
while (b_queue_iterator_is_valid(&it)) {
entry = next;
}
#endif
entry = b_queue_first(&cmd->b_usage);
while (entry) {
struct b_command_usage *usage struct b_command_usage *usage
= b_unbox(struct b_command_usage, it.entry, u_entry); = b_unbox(struct b_command_usage, entry, u_entry);
if (!usage) { if (!usage) {
break; break;
} }
b_queue_iterator_erase(&it); next = b_queue_next(entry);
b_queue_delete(&cmd->b_usage, entry);
command_usage_destroy(usage); command_usage_destroy(usage);
entry = next;
} }
free(cmd); free(cmd);
@@ -382,10 +402,10 @@ static void get_usage_string(
b_string *cmd_name = b_string_create(); b_string *cmd_name = b_string_create();
b_queue_iterator it; struct b_queue_entry *q_entry = b_queue_first(&usage->u_parts);
b_queue_foreach (&it, &usage->u_parts) { while (q_entry) {
struct b_command_usage_entry *entry = b_unbox( struct b_command_usage_entry *entry
struct b_command_usage_entry, it.entry, e_entry); = b_unbox(struct b_command_usage_entry, q_entry, e_entry);
if (!entry) { if (!entry) {
break; break;
@@ -426,6 +446,8 @@ static void get_usage_string(
default: default:
break; break;
} }
q_entry = b_queue_next(q_entry);
} }
b_string_unref(cmd_name); b_string_unref(cmd_name);
@@ -445,13 +467,15 @@ b_string *z__b_command_default_usage_string(
b_string_append_cstr(str, " [OPTIONS]"); b_string_append_cstr(str, " [OPTIONS]");
} }
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_arg);
b_queue_foreach (&it, &cmd->b_arg) { while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
b_string_append_cstr(str, " "); b_string_append_cstr(str, " ");
z__b_get_arg_usage_string(arg, false, str); z__b_get_arg_usage_string(arg, false, str);
entry = b_queue_next(entry);
} }
if (!b_queue_empty(&cmd->b_subcommands)) { if (!b_queue_empty(&cmd->b_subcommands)) {
@@ -523,13 +547,10 @@ static void print_options_list(struct b_command *cmd)
b_string *opt_str = b_string_create(); b_string *opt_str = b_string_create();
b_string *desc_str = b_string_create(); b_string *desc_str = b_string_create();
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_opt);
b_queue_foreach (&it, &cmd->b_opt) { while (entry) {
struct b_command_option *opt struct b_command_option *opt
= b_unbox(struct b_command_option, it.entry, opt_entry); = b_unbox(struct b_command_option, entry, opt_entry);
if (!opt) {
continue;
}
b_string_clear(opt_str); b_string_clear(opt_str);
b_string_clear(desc_str); b_string_clear(desc_str);
@@ -544,12 +565,15 @@ static void print_options_list(struct b_command *cmd)
desc_str, B_STRLEN_IGNORE_ESC | B_STRLEN_IGNORE_MOD); desc_str, B_STRLEN_IGNORE_ESC | B_STRLEN_IGNORE_MOD);
if (description_on_separate_line(opt_len, desc_len)) { if (description_on_separate_line(opt_len, desc_len)) {
continue; goto skip;
} }
if (opt_len > desb_margin) { if (opt_len > desb_margin) {
desb_margin = opt_len; desb_margin = opt_len;
} }
skip:
entry = b_queue_next(entry);
} }
b_paragraph_format format = {0}; b_paragraph_format format = {0};
@@ -558,11 +582,12 @@ static void print_options_list(struct b_command *cmd)
format.p_right_margin = 4; format.p_right_margin = 4;
size_t i = 0; size_t i = 0;
b_queue_foreach (&it, &cmd->b_opt) { entry = b_queue_first(&cmd->b_opt);
while (entry) {
struct b_command_option *opt struct b_command_option *opt
= b_unbox(struct b_command_option, it.entry, opt_entry); = b_unbox(struct b_command_option, entry, opt_entry);
if (!opt) { if (!opt) {
continue; break;
} }
b_string_clear(opt_str); b_string_clear(opt_str);
@@ -609,6 +634,8 @@ static void print_options_list(struct b_command *cmd)
if (new_paragraph) { if (new_paragraph) {
b_tty_putc(OUTPUT_STREAM, 0, '\n'); b_tty_putc(OUTPUT_STREAM, 0, '\n');
} }
entry = b_queue_next(entry);
} }
b_string_unref(opt_str); b_string_unref(opt_str);
@@ -622,10 +649,11 @@ static void print_args_list(struct b_command *cmd)
size_t desb_margin = 0; size_t desb_margin = 0;
b_string *str = b_string_create(); b_string *str = b_string_create();
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_arg);
b_queue_foreach (&it, &cmd->b_arg) {
while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
b_string_clear(str); b_string_clear(str);
z__b_get_arg_usage_string(arg, true, str); z__b_get_arg_usage_string(arg, true, str);
@@ -636,6 +664,8 @@ static void print_args_list(struct b_command *cmd)
if (len > desb_margin) { if (len > desb_margin) {
desb_margin = len; desb_margin = len;
} }
entry = b_queue_next(entry);
} }
b_paragraph_format format = {0}; b_paragraph_format format = {0};
@@ -644,9 +674,10 @@ static void print_args_list(struct b_command *cmd)
format.p_right_margin = 4; format.p_right_margin = 4;
size_t i = 0; size_t i = 0;
b_queue_foreach (&it, &cmd->b_arg) { entry = b_queue_first(&cmd->b_arg);
while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
b_string_clear(str); b_string_clear(str);
z__b_get_arg_usage_string(arg, true, str); z__b_get_arg_usage_string(arg, true, str);
@@ -666,6 +697,7 @@ static void print_args_list(struct b_command *cmd)
z__b_get_arg_description(arg, str); z__b_get_arg_description(arg, str);
b_print_paragraph(b_string_ptr(str), OUTPUT_STREAM, &format); b_print_paragraph(b_string_ptr(str), OUTPUT_STREAM, &format);
entry = b_queue_next(entry);
} }
b_string_unref(str); b_string_unref(str);
@@ -678,10 +710,9 @@ static void print_commands_list(struct b_command *cmd)
size_t desb_margin = 0; size_t desb_margin = 0;
b_string *str = b_string_create(); b_string *str = b_string_create();
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_subcommands);
b_queue_foreach (&it, &cmd->b_subcommands) { while (entry) {
struct b_command *sub struct b_command *sub = b_unbox(struct b_command, entry, b_entry);
= b_unbox(struct b_command, it.entry, b_entry);
b_string_clear(str); b_string_clear(str);
get_command_string(sub, str); get_command_string(sub, str);
@@ -692,6 +723,8 @@ static void print_commands_list(struct b_command *cmd)
if (len > desb_margin) { if (len > desb_margin) {
desb_margin = len; desb_margin = len;
} }
entry = b_queue_next(entry);
} }
b_paragraph_format format = {0}; b_paragraph_format format = {0};
@@ -700,9 +733,9 @@ static void print_commands_list(struct b_command *cmd)
format.p_right_margin = 4; format.p_right_margin = 4;
size_t i = 0; size_t i = 0;
b_queue_foreach (&it, &cmd->b_subcommands) { entry = b_queue_first(&cmd->b_subcommands);
struct b_command *sub while (entry) {
= b_unbox(struct b_command, it.entry, b_entry); struct b_command *sub = b_unbox(struct b_command, entry, b_entry);
b_string_clear(str); b_string_clear(str);
get_command_string(sub, str); get_command_string(sub, str);
@@ -722,6 +755,8 @@ static void print_commands_list(struct b_command *cmd)
get_command_description(sub, str); get_command_description(sub, str);
b_print_paragraph(b_string_ptr(str), OUTPUT_STREAM, &format); b_print_paragraph(b_string_ptr(str), OUTPUT_STREAM, &format);
entry = b_queue_next(entry);
} }
b_string_unref(str); b_string_unref(str);
@@ -730,17 +765,20 @@ static void print_commands_list(struct b_command *cmd)
struct b_command *b_command_get_subcommand_with_name( struct b_command *b_command_get_subcommand_with_name(
struct b_command *cmd, const char *name) struct b_command *cmd, const char *name)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_subcommands);
b_queue_foreach (&it, &cmd->b_subcommands) { while (entry) {
struct b_command *subcmd struct b_command *subcmd
= b_unbox(struct b_command, it.entry, b_entry); = b_unbox(struct b_command, entry, b_entry);
if (!subcmd || !subcmd->b_name) { if (!subcmd || !subcmd->b_name) {
continue; goto skip;
} }
if (!strcmp(subcmd->b_name, name)) { if (!strcmp(subcmd->b_name, name)) {
return subcmd; return subcmd;
} }
skip:
entry = b_queue_next(entry);
} }
return NULL; return NULL;
@@ -749,17 +787,20 @@ struct b_command *b_command_get_subcommand_with_name(
struct b_command *b_command_get_subcommand_with_long_name( struct b_command *b_command_get_subcommand_with_long_name(
struct b_command *cmd, const char *long_name) struct b_command *cmd, const char *long_name)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_subcommands);
b_queue_foreach (&it, &cmd->b_subcommands) { while (entry) {
struct b_command *subcmd struct b_command *subcmd
= b_unbox(struct b_command, it.entry, b_entry); = b_unbox(struct b_command, entry, b_entry);
if (!subcmd || !subcmd->b_long_name) { if (!subcmd || !subcmd->b_long_name) {
continue; goto skip;
} }
if (!strcmp(subcmd->b_name, long_name)) { if (!strcmp(subcmd->b_name, long_name)) {
return subcmd; return subcmd;
} }
skip:
entry = b_queue_next(entry);
} }
return NULL; return NULL;
@@ -768,17 +809,20 @@ struct b_command *b_command_get_subcommand_with_long_name(
struct b_command *b_command_get_subcommand_with_short_name( struct b_command *b_command_get_subcommand_with_short_name(
struct b_command *cmd, char short_name) struct b_command *cmd, char short_name)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_subcommands);
b_queue_foreach (&it, &cmd->b_subcommands) { while (entry) {
struct b_command *subcmd struct b_command *subcmd
= b_unbox(struct b_command, it.entry, b_entry); = b_unbox(struct b_command, entry, b_entry);
if (!subcmd || !subcmd->b_short_name) { if (!subcmd || !subcmd->b_short_name) {
continue; goto skip;
} }
if (subcmd->b_short_name == short_name) { if (subcmd->b_short_name == short_name) {
return subcmd; return subcmd;
} }
skip:
entry = b_queue_next(entry);
} }
return NULL; return NULL;
@@ -787,17 +831,20 @@ struct b_command *b_command_get_subcommand_with_short_name(
struct b_command_option *b_command_get_option_with_long_name( struct b_command_option *b_command_get_option_with_long_name(
struct b_command *cmd, const char *long_name) struct b_command *cmd, const char *long_name)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_opt);
b_queue_foreach (&it, &cmd->b_opt) { while (entry) {
struct b_command_option *opt struct b_command_option *opt
= b_unbox(struct b_command_option, it.entry, opt_entry); = b_unbox(struct b_command_option, entry, opt_entry);
if (!opt || !opt->opt_long_name) { if (!opt || !opt->opt_long_name) {
continue; goto skip;
} }
if (!strcmp(opt->opt_long_name, long_name)) { if (!strcmp(opt->opt_long_name, long_name)) {
return opt; return opt;
} }
skip:
entry = b_queue_next(entry);
} }
return NULL; return NULL;
@@ -806,17 +853,20 @@ struct b_command_option *b_command_get_option_with_long_name(
struct b_command_option *b_command_get_option_with_short_name( struct b_command_option *b_command_get_option_with_short_name(
struct b_command *cmd, char short_name) struct b_command *cmd, char short_name)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_opt);
b_queue_foreach (&it, &cmd->b_opt) { while (entry) {
struct b_command_option *opt struct b_command_option *opt
= b_unbox(struct b_command_option, it.entry, opt_entry); = b_unbox(struct b_command_option, entry, opt_entry);
if (!opt || !opt->opt_long_name) { if (!opt || !opt->opt_long_name) {
continue; goto skip;
} }
if (opt->opt_short_name == short_name) { if (opt->opt_short_name == short_name) {
return opt; return opt;
} }
skip:
entry = b_queue_next(entry);
} }
return NULL; return NULL;
@@ -825,17 +875,16 @@ struct b_command_option *b_command_get_option_with_short_name(
struct b_command_option *b_command_get_option_with_id( struct b_command_option *b_command_get_option_with_id(
struct b_command *cmd, unsigned int id) struct b_command *cmd, unsigned int id)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_opt);
b_queue_foreach (&it, &cmd->b_opt) { while (entry) {
struct b_command_option *opt struct b_command_option *opt
= b_unbox(struct b_command_option, it.entry, opt_entry); = b_unbox(struct b_command_option, entry, opt_entry);
if (!opt) {
continue;
}
if (opt->opt_id == id) { if (opt->opt_id == id) {
return opt; return opt;
} }
entry = b_queue_next(entry);
} }
return NULL; return NULL;
@@ -844,17 +893,16 @@ struct b_command_option *b_command_get_option_with_id(
struct b_command_arg *b_command_get_arg_with_id( struct b_command_arg *b_command_get_arg_with_id(
struct b_command *cmd, unsigned int id) struct b_command *cmd, unsigned int id)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_arg);
b_queue_foreach (&it, &cmd->b_arg) { while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) {
continue;
}
if (arg->arg_id == id) { if (arg->arg_id == id) {
return arg; return arg;
} }
entry = b_queue_next(entry);
} }
return NULL; return NULL;
@@ -876,17 +924,16 @@ static void print_usage(struct b_command *cmd, struct b_arglist *args)
} }
b_string *str = b_string_create(); b_string *str = b_string_create();
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&cmd->b_usage);
b_queue_foreach (&it, &cmd->b_usage) { while (entry) {
struct b_command_usage *usage struct b_command_usage *usage
= b_unbox(struct b_command_usage, it.entry, u_entry); = b_unbox(struct b_command_usage, entry, u_entry);
if (!usage) {
break;
}
b_string_clear(str); b_string_clear(str);
get_usage_string(cmd, args, usage, str); get_usage_string(cmd, args, usage, str);
b_print_paragraph(b_string_ptr(str), OUTPUT_STREAM, &format); b_print_paragraph(b_string_ptr(str), OUTPUT_STREAM, &format);
entry = b_queue_next(entry);
} }
b_string_unref(str); b_string_unref(str);
@@ -960,12 +1007,12 @@ static b_status add_subcommand(struct b_command *parent, struct b_command *child
static int resolve_command_parents(struct b_btree *commands) static int resolve_command_parents(struct b_btree *commands)
{ {
struct b_btree_iterator it; struct b_btree_node *node = b_btree_first(commands);
b_btree_foreach (&it, commands) { while (node) {
struct b_command *cmd = b_unbox(struct b_command, it.node, b_node); struct b_command *cmd = b_unbox(struct b_command, node, b_node);
if (cmd->b_parent_id == B_COMMAND_INVALID_ID) { if (cmd->b_parent_id == B_COMMAND_INVALID_ID) {
continue; goto skip;
} }
cmd->b_parent = get_command(commands, cmd->b_parent_id); cmd->b_parent = get_command(commands, cmd->b_parent_id);
@@ -974,6 +1021,8 @@ static int resolve_command_parents(struct b_btree *commands)
} }
add_subcommand(cmd->b_parent, cmd); add_subcommand(cmd->b_parent, cmd);
skip:
node = b_btree_next(node);
} }
return 0; return 0;

View File

@@ -164,24 +164,22 @@ typedef struct b_arglist_value {
} b_arglist_value; } b_arglist_value;
typedef struct b_arglist_iterator { typedef struct b_arglist_iterator {
b_iterator _base;
size_t i; size_t i;
unsigned int opt_id; unsigned int opt_id;
struct b_arglist_value *value; struct b_arglist_value *value;
b_btree_iterator _opt_it, _arg_it; b_btree_node *_opt_it, *_arg_it;
unsigned int _opt_filter, _arg_filter; unsigned int _opt_filter, _arg_filter;
} b_arglist_iterator; } b_arglist_iterator;
typedef struct b_arglist_option_iterator { typedef struct b_arglist_option_iterator {
b_iterator _base;
size_t i; size_t i;
unsigned int opt_id; unsigned int opt_id;
struct b_arglist_option *opt; struct b_arglist_option *opt;
b_btree_iterator _opt_it; b_btree_node *_opt_it;
unsigned int _opt_filter; unsigned int _opt_filter;
} b_arglist_option_iterator; } b_arglist_option_iterator;

View File

@@ -26,18 +26,17 @@ void b_command_option_destroy(struct b_command_option *opt)
free(opt->opt_description); free(opt->opt_description);
} }
b_queue_iterator it = {0}; struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
b_queue_iterator_begin(&opt->opt_args, &it); while (entry) {
while (b_queue_iterator_is_valid(&it)) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) {
break; struct b_queue_entry *next = b_queue_next(entry);
} b_queue_delete(&opt->opt_args, entry);
b_queue_iterator_erase(&it);
b_command_arg_destroy(arg); b_command_arg_destroy(arg);
entry = next;
} }
free(opt); free(opt);
@@ -107,15 +106,16 @@ void z__b_get_option_description(struct b_command_option *opt, b_string *out)
size_t nr_args = b_queue_length(&opt->opt_args); size_t nr_args = b_queue_length(&opt->opt_args);
bool close_bracket = false; bool close_bracket = false;
b_queue_iterator it; size_t i = 0;
b_queue_foreach (&it, &opt->opt_args) { struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg || !arg->arg_allowed_values) { if (!arg || !arg->arg_allowed_values) {
continue; goto skip;
} }
if (it.i > 0) { if (i > 0) {
b_string_append_cstr(out, "; "); b_string_append_cstr(out, "; ");
} else { } else {
b_string_append_cstr(out, " [["); b_string_append_cstr(out, " [[");
@@ -138,6 +138,10 @@ void z__b_get_option_description(struct b_command_option *opt, b_string *out)
out, " " F_GREEN "%s" F_RESET, out, " " F_GREEN "%s" F_RESET,
arg->arg_allowed_values[i]); arg->arg_allowed_values[i]);
} }
skip:
i++;
entry = b_queue_next(entry);
} }
if (close_bracket) { if (close_bracket) {
@@ -175,12 +179,12 @@ void z__b_get_option_usage_string(
b_string_append_cstr(out, "}"); b_string_append_cstr(out, "}");
} }
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
b_queue_foreach (&it, &opt->opt_args) { while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) { if (!arg) {
continue; goto skip;
} }
bool optional = false, multi = false; bool optional = false, multi = false;
@@ -228,23 +232,26 @@ void z__b_get_option_usage_string(
if (flags & CMD_STR_COLOUR) { if (flags & CMD_STR_COLOUR) {
b_string_append_cstr(out, F_RESET); b_string_append_cstr(out, F_RESET);
} }
skip:
entry = b_queue_next(entry);
} }
} }
struct b_command_arg *b_command_option_get_arg_with_id( struct b_command_arg *b_command_option_get_arg_with_id(
struct b_command_option *opt, unsigned int id) struct b_command_option *opt, unsigned int id)
{ {
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
b_queue_foreach (&it, &opt->opt_args) {
while (entry) {
struct b_command_arg *arg struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry); = b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) {
continue;
}
if (arg->arg_id == id) { if (arg->arg_id == id) {
return arg; return arg;
} }
entry = b_queue_next(entry);
} }
return NULL; return NULL;

View File

@@ -471,7 +471,7 @@ enum b_status z__b_error_add_submsg_template(
return B_SUCCESS; return B_SUCCESS;
} }
void b_error_release(struct b_error *error) void b_error_discard(struct b_error *error)
{ {
b_queue_delete(&allocated_errors, &error->err_entry); b_queue_delete(&allocated_errors, &error->err_entry);
b_queue_push_back(&free_errors, &error->err_entry); b_queue_push_back(&free_errors, &error->err_entry);

View File

@@ -372,7 +372,7 @@ BLUE_API enum b_status z__b_error_add_submsg_template(
error, type, msg_id, \ error, type, msg_id, \
(b_error_template_parameter[]) {__VA_ARGS__, {}})) (b_error_template_parameter[]) {__VA_ARGS__, {}}))
BLUE_API void b_error_release(b_error *error); BLUE_API void b_error_discard(b_error *error);
BLUE_API b_error_status_code b_error_get_status_code(const b_error *error); BLUE_API b_error_status_code b_error_get_status_code(const b_error *error);
BLUE_API const b_error_vendor *b_error_get_vendor(const b_error *error); BLUE_API const b_error_vendor *b_error_get_vendor(const b_error *error);

View File

@@ -68,7 +68,7 @@ struct _b_object *b_object_create(b_type type)
struct _b_object *out = NULL; struct _b_object *out = NULL;
b_result result = b_object_instantiate(type_reg, &out); b_result result = b_object_instantiate(type_reg, &out);
if (b_result_is_error(result)) { if (b_result_is_error(result)) {
b_error_release(result); b_error_discard(result);
return NULL; return NULL;
} }

View File

@@ -371,6 +371,7 @@ static b_iterator *iterable_begin(b_object *obj)
if (it->_a_p->ar_len > 0) { if (it->_a_p->ar_len > 0) {
it->value = it->_a_p->ar_data[0]; it->value = it->_a_p->ar_data[0];
} else { } else {
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
it->value = NULL; it->value = NULL;
} }
@@ -389,6 +390,7 @@ static const b_iterator *iterable_cbegin(const b_object *obj)
if (it->_a_p->ar_len > 0) { if (it->_a_p->ar_len > 0) {
it->value = it->_a_p->ar_data[0]; it->value = it->_a_p->ar_data[0];
} else { } else {
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
it->value = NULL; it->value = NULL;
} }

View File

@@ -48,7 +48,6 @@ struct b_string_iterator_p {
const char **_d; const char **_d;
size_t _nd, _ds; size_t _nd, _ds;
b_status status;
size_t iteration_index; size_t iteration_index;
size_t byte_index; size_t byte_index;
size_t codepoint_index; size_t codepoint_index;
@@ -1412,7 +1411,7 @@ static b_iterator *iterator_begin(b_object *obj)
struct b_string_p *p = b_object_get_private(obj, B_TYPE_STRING); struct b_string_p *p = b_object_get_private(obj, B_TYPE_STRING);
if (!p->s_len) { if (!p->s_len) {
it->status = B_ERR_NO_DATA; b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj; return it_obj;
} }
@@ -1422,12 +1421,17 @@ static b_iterator *iterator_begin(b_object *obj)
it->char_value = b_wchar_utf8_codepoint_decode(s); it->char_value = b_wchar_utf8_codepoint_decode(s);
if (it->char_value == B_WCHAR_INVALID) { if (it->char_value == B_WCHAR_INVALID) {
it->status = B_ERR_BAD_FORMAT; b_iterator_set_status(it_obj, B_ERR_BAD_FORMAT);
} }
return it_obj; return it_obj;
} }
static const b_iterator *iterator_cbegin(const b_object *obj)
{
return iterator_begin((b_object *)obj);
}
static enum b_status chars_iterator_move_next(struct b_string_iterator_p *it) static enum b_status chars_iterator_move_next(struct b_string_iterator_p *it)
{ {
if (!it->_s_p) { if (!it->_s_p) {
@@ -1513,6 +1517,21 @@ static b_iterator_value iterator_get_value(b_iterator *obj)
} }
} }
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_string_iterator_p *it
= b_object_get_private(obj, B_TYPE_STRING_ITERATOR);
switch (it->_m) {
case ITERATOR_MODE_CHARS:
return chars_iterator_get_value(it);
case ITERATOR_MODE_TOKENS:
return tokens_iterator_get_value(it);
default:
return B_ITERATOR_VALUE_NULL;
}
}
/*** CLASS DEFINITION *********************************************************/ /*** CLASS DEFINITION *********************************************************/
// ---- b_string DEFINITION // ---- b_string DEFINITION
@@ -1520,10 +1539,16 @@ B_TYPE_CLASS_DEFINITION_BEGIN(b_string)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = string_to_string; B_INTERFACE_ENTRY(to_string) = string_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT) B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = iterator_begin;
B_INTERFACE_ENTRY(it_cbegin) = iterator_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_string) B_TYPE_CLASS_DEFINITION_END(b_string)
B_TYPE_DEFINITION_BEGIN(b_string) B_TYPE_DEFINITION_BEGIN(b_string)
B_TYPE_ID(0x200194f6, 0x0327, 0x4a82, 0xb9c9, 0xb62ddd038c33); B_TYPE_ID(0x200194f6, 0x0327, 0x4a82, 0xb9c9, 0xb62ddd038c33);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_CLASS(b_string_class); B_TYPE_CLASS(b_string_class);
B_TYPE_INSTANCE_PRIVATE(struct b_string_p); B_TYPE_INSTANCE_PRIVATE(struct b_string_p);
B_TYPE_INSTANCE_INIT(string_init); B_TYPE_INSTANCE_INIT(string_init);
@@ -1540,6 +1565,7 @@ B_TYPE_CLASS_DEFINITION_BEGIN(b_string_iterator)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next; B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = NULL; B_INTERFACE_ENTRY(it_erase) = NULL;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value; B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR) B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_string_iterator) B_TYPE_CLASS_DEFINITION_END(b_string_iterator)

View File

@@ -14,13 +14,18 @@ B_DECLS_BEGIN;
struct b_directory_p; struct b_directory_p;
#define B_TYPE_DIRECTORY (b_directory_get_type()) #define B_TYPE_DIRECTORY (b_directory_get_type())
#define B_TYPE_DIRECTORY_ITERATOR (b_directory_iterator_get_type())
B_DECLARE_TYPE(b_directory); B_DECLARE_TYPE(b_directory);
B_DECLARE_TYPE(b_directory_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_directory) B_TYPE_CLASS_DECLARATION_BEGIN(b_directory)
B_TYPE_CLASS_DECLARATION_END(b_directory) B_TYPE_CLASS_DECLARATION_END(b_directory)
B_TYPE_CLASS_DECLARATION_BEGIN(b_directory_iterator)
B_TYPE_CLASS_DECLARATION_END(b_directory_iterator)
struct z__b_directory_iterator; struct z__b_directory_iterator;
typedef enum b_directory_iterator_flags { typedef enum b_directory_iterator_flags {
@@ -34,24 +39,14 @@ typedef enum b_directory_open_flags {
B_DIRECTORY_OPEN_DELETE_ON_CLOSE = 0x04u, B_DIRECTORY_OPEN_DELETE_ON_CLOSE = 0x04u,
} b_directory_open_flags; } b_directory_open_flags;
typedef struct b_directory_iterator { typedef struct b_directory_entry {
b_iterator _base;
struct z__b_directory_iterator *_z;
struct b_directory_p *_p;
b_directory_iterator_flags flags;
b_directory *root;
const b_path *filepath; const b_path *filepath;
char *filename; char *filename;
b_file_info info; b_file_info info;
} b_directory_iterator; } b_directory_entry;
#define b_directory_foreach(it, dir, flags) \
for (int z__b_unique_name() = b_directory_iterator_begin(dir, it, flags); \
b_directory_iterator_is_valid(it); b_directory_iterator_next(it))
BLUE_API b_type b_directory_get_type(void); BLUE_API b_type b_directory_get_type(void);
BLUE_API b_type b_directory_iterator_get_type(void);
BLUE_API b_result b_directory_open( BLUE_API b_result b_directory_open(
b_directory *root, const b_path *path, b_directory_open_flags flags, b_directory *root, const b_path *path, b_directory_open_flags flags,
@@ -72,12 +67,8 @@ BLUE_API b_result b_directory_path_stat(
BLUE_API b_result b_directory_path_unlink( BLUE_API b_result b_directory_path_unlink(
const b_directory *root, const b_path *path); const b_directory *root, const b_path *path);
BLUE_API int b_directory_iterator_begin( BLUE_API b_iterator *b_directory_begin(
b_directory *directory, b_directory_iterator *it, b_directory *dir, b_directory_iterator_flags flags);
b_directory_iterator_flags flags);
BLUE_API bool b_directory_iterator_next(b_directory_iterator *it);
BLUE_API b_status b_directory_iterator_erase(b_directory_iterator *it);
BLUE_API bool b_directory_iterator_is_valid(const b_directory_iterator *it);
B_DECLS_END; B_DECLS_END;

View File

@@ -25,9 +25,16 @@ struct b_directory_p {
b_path *d_path_abs; b_path *d_path_abs;
}; };
struct z__b_directory_iterator { struct b_directory_iterator_p {
struct b_directory_p *_p;
FTS *fts; FTS *fts;
FTSENT *ent; FTSENT *ent;
b_directory_iterator_flags flags;
b_directory *root;
b_directory_entry entry;
}; };
/*** PRIVATE FUNCTIONS ********************************************************/ /*** PRIVATE FUNCTIONS ********************************************************/
@@ -55,13 +62,14 @@ static b_result directory_delete(b_directory *dir, struct b_directory_p *dir_p)
{ {
enum b_status status = B_SUCCESS; enum b_status status = B_SUCCESS;
struct b_directory_iterator it; b_iterator *it = b_directory_begin(dir, B_DIRECTORY_ITERATE_PARENT_LAST);
b_directory_iterator_begin(dir, &it, B_DIRECTORY_ITERATE_PARENT_LAST); while (B_OK(b_iterator_get_status(it))) {
while (b_directory_iterator_is_valid(&it)) { b_iterator_erase(it);
status = b_directory_iterator_erase(&it); }
if (!B_OK(status)) {
return B_RESULT_STATUS(status); status = b_iterator_get_status(it);
} if (!B_OK(status) && status != B_ERR_NO_DATA) {
return B_RESULT_STATUS(status);
} }
status = b_path_unlink(dir_p->d_path_abs); status = b_path_unlink(dir_p->d_path_abs);
@@ -190,7 +198,7 @@ static b_result create_directory(struct b_directory_p *root, const char *path)
static b_result create_directory_hierarchy( static b_result create_directory_hierarchy(
struct b_directory_p *root, const char *path) struct b_directory_p *root, const char *path)
{ {
int root_fd = root->d_fd; int root_fd = root ? root->d_fd : AT_FDCWD;
char *path_buf = b_strdup(path); char *path_buf = b_strdup(path);
if (!path_buf) { if (!path_buf) {
@@ -417,22 +425,6 @@ static void directory_fini(b_object *obj, void *priv)
b_path_unref(dir->d_path_abs); b_path_unref(dir->d_path_abs);
} }
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_directory)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_directory)
B_TYPE_DEFINITION_BEGIN(b_directory)
B_TYPE_ID(0x10d36546, 0x7f96, 0x464b, 0xbc4d, 0xe504b283fa45);
B_TYPE_CLASS(b_directory_class);
B_TYPE_INSTANCE_PRIVATE(struct b_directory_p);
B_TYPE_INSTANCE_INIT(directory_init);
B_TYPE_INSTANCE_FINI(directory_fini);
B_TYPE_DEFINITION_END(b_directory)
/*** ITERATOR FUNCTIONS *******************************************************/ /*** ITERATOR FUNCTIONS *******************************************************/
static int ftsent_compare(const FTSENT **one, const FTSENT **two) static int ftsent_compare(const FTSENT **one, const FTSENT **two)
@@ -440,89 +432,71 @@ static int ftsent_compare(const FTSENT **one, const FTSENT **two)
return (strcmp((*one)->fts_name, (*two)->fts_name)); return (strcmp((*one)->fts_name, (*two)->fts_name));
} }
static void update_iterator_data(struct b_directory_iterator *it) static void update_iterator_data(struct b_directory_iterator_p *it)
{ {
struct z__b_directory_iterator *it_data = it->_z; if (it->entry.filepath) {
b_path_unref((b_path *)it->entry.filepath);
if (it->filepath) { it->entry.filepath = NULL;
b_path_unref((b_path *)it->filepath);
it->filepath = NULL;
} }
FTSENT *ent = it_data->ent; FTSENT *ent = it->ent;
b_path *path = b_path_create_from_cstr( b_path *path = b_path_create_from_cstr(
ent->fts_path + b_path_length(it->_p->d_path_abs) + 1); ent->fts_path + b_path_length(it->_p->d_path_abs) + 1);
it->filename = ent->fts_name; it->entry.filename = ent->fts_name;
it->filepath = path; it->entry.filepath = path;
memset(&it->info, 0x0, sizeof it->info); memset(&it->entry.info, 0x0, sizeof it->entry.info);
it->info.length = ent->fts_statp->st_size; it->entry.info.length = ent->fts_statp->st_size;
if (S_ISREG(ent->fts_statp->st_mode)) { if (S_ISREG(ent->fts_statp->st_mode)) {
it->info.attrib |= B_FILE_ATTRIB_NORMAL; it->entry.info.attrib |= B_FILE_ATTRIB_NORMAL;
} }
if (S_ISDIR(ent->fts_statp->st_mode)) { if (S_ISDIR(ent->fts_statp->st_mode)) {
it->info.attrib |= B_FILE_ATTRIB_DIRECTORY; it->entry.info.attrib |= B_FILE_ATTRIB_DIRECTORY;
} }
if (S_ISBLK(ent->fts_statp->st_mode)) { if (S_ISBLK(ent->fts_statp->st_mode)) {
it->info.attrib |= B_FILE_ATTRIB_BLOCK_DEVICE; it->entry.info.attrib |= B_FILE_ATTRIB_BLOCK_DEVICE;
} }
if (S_ISCHR(ent->fts_statp->st_mode)) { if (S_ISCHR(ent->fts_statp->st_mode)) {
it->info.attrib |= B_FILE_ATTRIB_CHAR_DEVICE; it->entry.info.attrib |= B_FILE_ATTRIB_CHAR_DEVICE;
} }
if (S_ISLNK(ent->fts_statp->st_mode)) { if (S_ISLNK(ent->fts_statp->st_mode)) {
it->info.attrib |= B_FILE_ATTRIB_SYMLINK; it->entry.info.attrib |= B_FILE_ATTRIB_SYMLINK;
} }
} }
static void cleanup_iterator(struct b_directory_iterator *it) static void iterator_fini(b_object *obj, void *priv)
{ {
if (it->filepath) { struct b_directory_iterator_p *it = priv;
b_path_unref((b_path *)it->filepath);
it->filepath = NULL; if (it->entry.filepath) {
b_path_unref((b_path *)it->entry.filepath);
it->entry.filepath = NULL;
} }
struct z__b_directory_iterator *it_data = it->_z; if (it->fts) {
memset(it, 0x0, sizeof *it); fts_close(it->fts);
if (!it_data) {
return;
} }
if (it_data->fts) {
fts_close(it_data->fts);
}
free(it_data);
} }
int b_directory_iterator_begin( b_iterator *b_directory_begin(
b_directory *directory, struct b_directory_iterator *it, b_directory *directory, enum b_directory_iterator_flags flags)
enum b_directory_iterator_flags flags)
{ {
memset(it, 0x0, sizeof *it); b_iterator *it_obj = b_object_create(B_TYPE_DIRECTORY_ITERATOR);
struct b_directory_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_DIRECTORY_ITERATOR);
it->flags = flags; it->flags = flags;
it->root = directory; it->root = directory;
it->_p = b_object_get_private(directory, B_TYPE_DIRECTORY); it->_p = b_object_get_private(directory, B_TYPE_DIRECTORY);
struct z__b_directory_iterator *it_data = malloc(sizeof *it_data);
if (!it_data) {
return -1;
}
memset(it_data, 0x0, sizeof *it_data);
it->_z = it_data;
int fts_flags = FTS_COMFOLLOW | FTS_NOCHDIR; int fts_flags = FTS_COMFOLLOW | FTS_NOCHDIR;
const char *path_list[] = { const char *path_list[] = {
@@ -530,24 +504,23 @@ int b_directory_iterator_begin(
NULL, NULL,
}; };
it_data->fts it->fts = fts_open((char *const *)path_list, fts_flags, ftsent_compare);
= fts_open((char *const *)path_list, fts_flags, ftsent_compare);
bool done = false; bool done = false;
while (!done) { while (!done) {
it_data->ent = fts_read(it_data->fts); it->ent = fts_read(it->fts);
if (!it_data->ent) { if (!it->ent) {
cleanup_iterator(it); b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return -1; return it_obj;
} }
if (it_data->ent->fts_level == 0) { if (it->ent->fts_level == 0) {
continue; continue;
} }
switch (it_data->ent->fts_info) { switch (it->ent->fts_info) {
case FTS_DOT: case FTS_DOT:
continue; continue;
case FTS_F: case FTS_F:
@@ -573,31 +546,41 @@ int b_directory_iterator_begin(
} }
update_iterator_data(it); update_iterator_data(it);
return 0; return it_obj;
} }
bool b_directory_iterator_next(struct b_directory_iterator *it) static b_iterator *iterator_begin(b_object *obj)
{ {
struct z__b_directory_iterator *it_data = it->_z; return b_directory_begin(obj, B_DIRECTORY_ITERATE_PARENT_FIRST);
if (!it_data || !it_data->fts) { }
return false;
static const b_iterator *iterator_cbegin(const b_object *obj)
{
return b_directory_begin((b_object *)obj, B_DIRECTORY_ITERATE_PARENT_FIRST);
}
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_directory_iterator_p *it
= b_object_get_private(obj, B_TYPE_DIRECTORY_ITERATOR);
if (!it || !it->fts) {
return B_ERR_NO_DATA;
} }
bool done = false; bool done = false;
while (!done) { while (!done) {
it_data->ent = fts_read(it_data->fts); it->ent = fts_read(it->fts);
if (!it_data->ent) { if (!it->ent) {
cleanup_iterator(it); return B_ERR_NO_DATA;
return false;
} }
if (it_data->ent->fts_level == 0) { if (it->ent->fts_level == 0) {
continue; continue;
} }
switch (it_data->ent->fts_info) { switch (it->ent->fts_info) {
case FTS_DOT: case FTS_DOT:
continue; continue;
case FTS_F: case FTS_F:
@@ -622,31 +605,79 @@ bool b_directory_iterator_next(struct b_directory_iterator *it)
} }
update_iterator_data(it); update_iterator_data(it);
return true;
}
enum b_status b_directory_iterator_erase(struct b_directory_iterator *it)
{
b_result result = b_directory_path_unlink(it->root, it->filepath);
if (b_result_is_error(result)) {
enum b_status status = b_error_get_status_code(result);
b_error_release(result);
return status;
}
b_directory_iterator_next(it);
return B_SUCCESS; return B_SUCCESS;
} }
bool b_directory_iterator_is_valid(const struct b_directory_iterator *it) static enum b_status iterator_erase(b_iterator *obj)
{ {
if (!it->_z) { struct b_directory_iterator_p *it
return false; = b_object_get_private(obj, B_TYPE_DIRECTORY_ITERATOR);
b_result result = b_directory_path_unlink(it->root, it->entry.filepath);
if (b_result_is_error(result)) {
enum b_status status = b_error_get_status_code(result);
b_error_discard(result);
return status;
} }
if (!it->_z->ent) { return iterator_move_next(obj);
return false;
}
return true;
} }
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_directory_iterator_p *it
= b_object_get_private(obj, B_TYPE_DIRECTORY_ITERATOR);
return B_ITERATOR_VALUE_PTR(&it->entry);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_directory_iterator_p *it
= b_object_get_private(obj, B_TYPE_DIRECTORY_ITERATOR);
return B_ITERATOR_VALUE_CPTR(&it->entry);
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_directory DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_directory)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = iterator_begin;
B_INTERFACE_ENTRY(it_cbegin) = iterator_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_directory)
B_TYPE_DEFINITION_BEGIN(b_directory)
B_TYPE_ID(0x10d36546, 0x7f96, 0x464b, 0xbc4d, 0xe504b283fa45);
B_TYPE_CLASS(b_directory_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_directory_p);
B_TYPE_INSTANCE_INIT(directory_init);
B_TYPE_INSTANCE_FINI(directory_fini);
B_TYPE_DEFINITION_END(b_directory)
// ---- b_directory_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_directory_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_directory_iterator)
B_TYPE_DEFINITION_BEGIN(b_directory_iterator)
B_TYPE_ID(0xc707fce6, 0xc895, 0x4925, 0x8700, 0xa60641dee0cc);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_directory_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_directory_iterator_p);
B_TYPE_DEFINITION_END(b_directory_iterator)

View File

@@ -111,7 +111,7 @@ struct ctx {
b_stream *ctx_src; b_stream *ctx_src;
b_string *ctx_wordbuf; b_string *ctx_wordbuf;
b_string *ctx_linebuf; b_string *ctx_linebuf;
b_string_iterator ctx_linebuf_ptr; b_iterator *ctx_linebuf_ptr;
enum b_status ctx_status; enum b_status ctx_status;
b_hashmap *ctx_objects_flags; b_hashmap *ctx_objects_flags;
@@ -207,16 +207,16 @@ static enum b_status data_available(struct ctx *ctx)
return B_ERR_NO_DATA; return B_ERR_NO_DATA;
} }
if (!B_OK(ctx->ctx_linebuf_ptr.status)) { return b_iterator_get_status(ctx->ctx_linebuf_ptr);
return ctx->ctx_linebuf_ptr.status;
}
return b_string_iterator_is_valid(&ctx->ctx_linebuf_ptr) ? B_SUCCESS
: B_ERR_NO_DATA;
} }
static enum b_status refill_linebuf(struct ctx *ctx) static enum b_status refill_linebuf(struct ctx *ctx)
{ {
if (ctx->ctx_linebuf_ptr) {
b_iterator_unref(ctx->ctx_linebuf_ptr);
ctx->ctx_linebuf_ptr = NULL;
}
b_string_clear(ctx->ctx_linebuf); b_string_clear(ctx->ctx_linebuf);
b_stringstream *buf = b_stringstream_create(); b_stringstream *buf = b_stringstream_create();
@@ -233,7 +233,7 @@ static enum b_status refill_linebuf(struct ctx *ctx)
b_stringstream_unref(buf); b_stringstream_unref(buf);
b_string_iterator_begin(ctx->ctx_linebuf, &ctx->ctx_linebuf_ptr); ctx->ctx_linebuf_ptr = b_iterator_begin(ctx->ctx_linebuf);
return B_SUCCESS; return B_SUCCESS;
} }
@@ -282,19 +282,15 @@ static b_wchar advance_char(struct ctx *ctx)
} }
const char *s = b_string_ptr(ctx->ctx_linebuf); const char *s = b_string_ptr(ctx->ctx_linebuf);
if (!B_OK(ctx->ctx_linebuf_ptr.status)) {
ctx->ctx_status = B_ERR_BAD_FORMAT;
return -1;
}
b_wchar c = ctx->ctx_linebuf_ptr.char_value; b_wchar c = b_iterator_get_value(ctx->ctx_linebuf_ptr).v_int;
if (!is_valid_char(c)) { if (!is_valid_char(c)) {
ctx->ctx_status = B_ERR_BAD_FORMAT; ctx->ctx_status = B_ERR_BAD_FORMAT;
return -1; return -1;
} }
b_string_iterator_next(&ctx->ctx_linebuf_ptr); b_iterator_move_next(ctx->ctx_linebuf_ptr);
return c; return c;
} }
@@ -318,12 +314,8 @@ static b_wchar peek_char(struct ctx *ctx)
} }
const char *s = b_string_ptr(ctx->ctx_linebuf); const char *s = b_string_ptr(ctx->ctx_linebuf);
if (!B_OK(ctx->ctx_linebuf_ptr.status)) {
ctx->ctx_status = B_ERR_BAD_FORMAT;
return -1;
}
b_wchar c = ctx->ctx_linebuf_ptr.char_value; b_wchar c = b_iterator_get_value(ctx->ctx_linebuf_ptr).v_int;
if (!is_valid_char(c)) { if (!is_valid_char(c)) {
ctx->ctx_status = B_ERR_BAD_FORMAT; ctx->ctx_status = B_ERR_BAD_FORMAT;
@@ -909,23 +901,26 @@ static void split_word(struct ctx *ctx, b_string *wordbuf)
#endif #endif
const char *delims[] = {"."}; const char *delims[] = {"."};
size_t nr_delims = sizeof delims / sizeof delims[0]; size_t nr_delims = sizeof delims / sizeof delims[0];
b_string_iterator it; b_iterator *it = b_string_tokenise(
b_string_tokenise( wordbuf, delims, nr_delims, B_STRING_TOK_F_INCLUDE_EMPTY_TOKENS);
wordbuf, delims, nr_delims, B_STRING_TOK_F_INCLUDE_EMPTY_TOKENS,
&it);
while (b_string_iterator_is_valid(&it)) { size_t i = 0;
if (it.iteration_index > 0) { b_foreach_c(const char *, tok, it)
{
if (i > 0) {
enqueue_token(ctx, TOK_DOT); enqueue_token(ctx, TOK_DOT);
} }
if (it.string_length > 0) { size_t len = strlen(tok);
if (len > 0) {
struct token *word = enqueue_token(ctx, TOK_WORD); struct token *word = enqueue_token(ctx, TOK_WORD);
word->tok_str = b_string_create_from_cstr(it.string_value); word->tok_str = b_string_create_from_cstr(tok);
} }
b_string_iterator_next(&it); i++;
} }
b_iterator_unref(it);
} }
static void read_number(struct ctx *ctx) static void read_number(struct ctx *ctx)
@@ -1012,17 +1007,17 @@ static void read_word(struct ctx *ctx)
return; return;
} }
b_string_iterator it; b_iterator *it = b_iterator_begin(wordbuf);
b_string_foreach(&it, wordbuf) b_foreach(b_wchar, c, it)
{ {
/* only allow ASCII numbers/letters here */ /* only allow ASCII numbers/letters here */
bool ok = isalnum(it.char_value) || it.char_value == '_' bool ok = isalnum(c) || c == '_' || c == '-' || c == '.';
|| it.char_value == '-' || it.char_value == '.';
if (!ok) { if (!ok) {
ctx->ctx_status = B_ERR_BAD_FORMAT; ctx->ctx_status = B_ERR_BAD_FORMAT;
return; return;
} }
} }
b_iterator_unref(it);
split_word(ctx, wordbuf); split_word(ctx, wordbuf);
} }
@@ -1514,6 +1509,11 @@ static struct token *peek_token(struct ctx *ctx)
static void ctx_cleanup(struct ctx *ctx) static void ctx_cleanup(struct ctx *ctx)
{ {
if (ctx->ctx_linebuf_ptr) {
b_iterator_unref(ctx->ctx_linebuf_ptr);
ctx->ctx_linebuf_ptr = NULL;
}
if (ctx->ctx_linebuf) { if (ctx->ctx_linebuf) {
b_string_unref(ctx->ctx_linebuf); b_string_unref(ctx->ctx_linebuf);
ctx->ctx_linebuf = NULL; ctx->ctx_linebuf = NULL;

View File

@@ -74,19 +74,21 @@ void test_btree_iterate(CuTest *tc)
} }
int prev = -1; int prev = -1;
b_btree_iterator it; b_btree_node *bnode = b_btree_first(&tree);
b_btree_foreach (&it, &tree) { while (bnode) {
struct test_tree_node *node struct test_tree_node *node
= b_unbox(struct test_tree_node, it.node, node); = b_unbox(struct test_tree_node, bnode, node);
CuAssertPtrNotNull(tc, node); CuAssertPtrNotNull(tc, node);
if (prev == -1) { if (prev == -1) {
prev = node->value; prev = node->value;
bnode = b_btree_next(bnode);
continue; continue;
} }
CuAssertTrue(tc, prev <= node->value); CuAssertTrue(tc, prev <= node->value);
prev = node->value; prev = node->value;
bnode = b_btree_next(bnode);
} }
free(nodes); free(nodes);
@@ -134,19 +136,21 @@ void test_queue_iterate(CuTest *tc)
} }
int prev = -1; int prev = -1;
b_queue_iterator it; struct b_queue_entry *entry = b_queue_first(&q);
b_queue_foreach (&it, &q) { while (entry) {
struct test_queue_entry *e struct test_queue_entry *e
= b_unbox(struct test_queue_entry, it.entry, entry); = b_unbox(struct test_queue_entry, entry, entry);
CuAssertPtrNotNull(tc, e); CuAssertPtrNotNull(tc, e);
if (prev == -1) { if (prev == -1) {
prev = e->value; prev = e->value;
continue; goto skip;
} }
CuAssertTrue(tc, prev < e->value); CuAssertTrue(tc, prev < e->value);
prev = e->value; prev = e->value;
skip:
entry = b_queue_next(entry);
} }
} }

View File

@@ -9,11 +9,12 @@ int main(void)
b_array_append(array, B_RV_INT(64)); b_array_append(array, B_RV_INT(64));
b_array_append(array, B_RV_INT(128)); b_array_append(array, B_RV_INT(128));
b_array_iterator it; b_iterator *it = b_iterator_begin(array);
b_array_foreach(&it, array) b_foreach_ptr(b_object, obj, it)
{ {
printf("object %p\n", it.value); printf("object %p\n", obj);
} }
b_iterator_unref(it);
b_array_unref(array); b_array_unref(array);
return 0; return 0;

View File

@@ -1,4 +1,5 @@
#include <blue/core/btree.h> #include <blue/core/btree.h>
#include <blue/core/iterator.h>
#include <blue/ds/dict.h> #include <blue/ds/dict.h>
#include <blue/ds/number.h> #include <blue/ds/number.h>
#include <blue/ds/tree.h> #include <blue/ds/tree.h>
@@ -21,21 +22,23 @@ B_BTREE_DEFINE_SIMPLE_INSERT(struct btree_item, node, value, put_node)
int main(void) int main(void)
{ {
b_dict_item items[] b_dict *dict = b_dict_create();
= {B_DICT_ITEM("hello", B_RV_INT(32)), b_dict_put(dict, "hello", B_RV_INT(32));
B_DICT_ITEM("world", B_RV_INT(64)), b_dict_put(dict, "world", B_RV_INT(64));
B_DICT_ITEM("more", B_RV_INT(128)), b_dict_put(dict, "more", B_RV_INT(128));
B_DICT_ITEM("other", B_RV_INT(256)), B_DICT_ITEM_END}; b_dict_put(dict, "other", B_RV_INT(256));
b_dict *dict = b_dict_create_with_items(items); b_iterator *it = b_iterator_begin(dict);
b_dict_iterator it; size_t i = 0;
b_dict_foreach(&it, dict) b_foreach(b_dict_item *, item, it)
{ {
printf("item %zu: %s=%d\n", it.i, b_string_ptr(it.key), printf("item %zu: %s=%d\n", i++, b_string_ptr(item->key),
b_number_get_int(it.value)); b_number_get_int(item->value));
} }
b_iterator_unref(it);
b_tree *tree = b_tree_create(); b_tree *tree = b_tree_create();
struct tree_item items2[NITEMS]; struct tree_item items2[NITEMS];
@@ -54,6 +57,8 @@ int main(void)
b_tree_node_add_child(&items2[1].node, &items2[5].node); b_tree_node_add_child(&items2[1].node, &items2[5].node);
b_tree_node_add_child(&items2[4].node, &items2[6].node); b_tree_node_add_child(&items2[4].node, &items2[6].node);
#if 0
it = b_iterator_begin(tree);
b_tree_iterator it2; b_tree_iterator it2;
b_tree_foreach(&it2, tree) b_tree_foreach(&it2, tree)
{ {
@@ -113,6 +118,7 @@ int main(void)
} }
b_tree_unref(tree); b_tree_unref(tree);
#endif
b_dict_unref(dict); b_dict_unref(dict);
return 0; return 0;

View File

@@ -12,15 +12,16 @@ int main(void)
printf("len: %zu\n", b_string_get_size(str, B_STRLEN_NORMAL)); printf("len: %zu\n", b_string_get_size(str, B_STRLEN_NORMAL));
printf("codepoints: %zu\n", b_string_get_size(str, B_STRLEN_CODEPOINTS)); printf("codepoints: %zu\n", b_string_get_size(str, B_STRLEN_CODEPOINTS));
b_string_iterator it;
const char *delims[] = {"в"}; const char *delims[] = {"в"};
size_t nr_delims = sizeof delims / sizeof delims[0]; size_t nr_delims = sizeof delims / sizeof delims[0];
b_string_tokenise(str, delims, nr_delims, 0, &it); b_iterator *it = b_string_tokenise(str, delims, nr_delims, 0);
while (b_string_iterator_is_valid(&it)) { b_foreach(const char *, tok, it)
printf("%s\n", it.string_value); {
b_string_iterator_next(&it); printf("%s\n", tok);
} }
b_iterator_unref(it);
b_string_unref(str);
return 0; return 0;
} }

View File

@@ -19,5 +19,8 @@ int main(int argc, const char **argv)
b_stream_read_all_bytes_s(b_stdin, dest, buf, &nr_read); b_stream_read_all_bytes_s(b_stdin, dest, buf, &nr_read);
printf("done. read %zu bytes total.\n", nr_read); printf("done. read %zu bytes total.\n", nr_read);
b_path_unref(path);
b_file_unref(dest);
return 0; return 0;
} }

View File

@@ -20,12 +20,13 @@ int main(int argc, const char **argv)
return -1; return -1;
} }
b_directory_iterator it = {0}; b_iterator *it = b_directory_begin(dir, B_DIRECTORY_ITERATE_PARENT_FIRST);
b_directory_iterator_begin(dir, &it, B_DIRECTORY_ITERATE_PARENT_FIRST); b_foreach(b_directory_entry *, entry, it)
while (b_directory_iterator_is_valid(&it)) { {
printf("%s\n", b_path_ptr(it.filepath)); printf("%s\n", b_path_ptr(entry->filepath));
b_directory_iterator_next(&it);
} }
b_iterator_unref(it);
return 0; return 0;
} }

View File

@@ -12,11 +12,9 @@ void write_raw_string(const b_string *data)
{ {
b_stream_write_string(b_stdout, "\"", NULL); b_stream_write_string(b_stdout, "\"", NULL);
b_string_iterator it; const b_iterator *it = b_iterator_cbegin(data);
b_string_foreach(&it, data) b_foreach_c(b_wchar, c, it)
{ {
b_wchar c = it.char_value;
if (c >= 0x10000) { if (c >= 0x10000) {
c -= 0x10000; c -= 0x10000;
long hi = 0xD800 | ((c >> 10) & 0x3FF); long hi = 0xD800 | ((c >> 10) & 0x3FF);
@@ -30,6 +28,7 @@ void write_raw_string(const b_string *data)
b_stream_write_char(b_stdout, c); b_stream_write_char(b_stdout, c);
} }
} }
b_iterator_unref(it);
b_stream_write_string(b_stdout, "\"", NULL); b_stream_write_string(b_stdout, "\"", NULL);
} }
@@ -134,17 +133,18 @@ void write_tagged_dict(b_dict *data)
int i = 0; int i = 0;
b_dict_iterator it; b_iterator *it = b_iterator_begin(data);
b_dict_foreach(&it, data) b_foreach(b_dict_item *, item, it)
{ {
if (i++ > 0) { if (i++ > 0) {
b_stream_write_string(b_stdout, ", ", NULL); b_stream_write_string(b_stdout, ", ", NULL);
} }
write_raw_string(it.key); write_raw_string(item->key);
b_stream_write_string(b_stdout, ": ", NULL); b_stream_write_string(b_stdout, ": ", NULL);
write_tagged_value(it.value); write_tagged_value(item->value);
} }
b_iterator_unref(it);
b_stream_write_string(b_stdout, " }", NULL); b_stream_write_string(b_stdout, " }", NULL);
} }
@@ -154,15 +154,16 @@ void write_tagged_array(b_array *data)
b_stream_write_string(b_stdout, "[ ", NULL); b_stream_write_string(b_stdout, "[ ", NULL);
int i = 0; int i = 0;
b_array_iterator it; b_iterator *it = b_iterator_begin(data);
b_array_foreach(&it, data) b_foreach(b_object *, obj, it)
{ {
if (i++ > 0) { if (i++ > 0) {
b_stream_write_string(b_stdout, ", ", NULL); b_stream_write_string(b_stdout, ", ", NULL);
} }
write_tagged_value(it.value); write_tagged_value(obj);
} }
b_iterator_unref(it);
b_stream_write_string(b_stdout, " ]", NULL); b_stream_write_string(b_stdout, " ]", NULL);
} }

View File

@@ -1 +1,4 @@
k = "v" # "No newlines are allowed between the curly braces unless they are valid within
# a value"
a = []