lib/config: make values iterators restartable

This is relatively cheap, and makes it easier to transform existing
code which uses arrays of pointers to store configuration lists.
This commit is contained in:
David Bremner 2021-01-01 09:28:24 -04:00
parent fd6f8e6c30
commit d071828bd5
3 changed files with 78 additions and 9 deletions

View file

@ -34,6 +34,8 @@ struct _notmuch_config_list {
struct _notmuch_config_values {
const char *iterator;
size_t tok_len;
const char *string;
void *children; /* talloc_context */
};
static const char * _notmuch_config_key_to_string (notmuch_config_key_t key);
@ -256,23 +258,33 @@ _notmuch_config_load_from_database (notmuch_database_t *notmuch)
notmuch_config_values_t *
notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key)
{
notmuch_config_values_t *values;
notmuch_config_values_t *values = NULL;
bool ok = false;
const char *str;
const char *key_str = _notmuch_config_key_to_string (key);
if (! key_str)
return NULL;
str = _notmuch_string_map_get (notmuch->config, key_str);
if (! str)
return NULL;
goto DONE;
values = talloc (notmuch, notmuch_config_values_t);
if (unlikely(! values))
return NULL;
goto DONE;
values->iterator = strsplit_len (str, ';', &(values->tok_len));
values->children = talloc_new (values);
values->string = _notmuch_string_map_get (notmuch->config, key_str);
if (! values->string)
goto DONE;
values->iterator = strsplit_len (values->string, ';', &(values->tok_len));
ok = true;
DONE:
if (!ok) {
if (values)
talloc_free(values);
return NULL;
}
return values;
}
@ -289,6 +301,19 @@ notmuch_config_values_get (notmuch_config_values_t *values) {
return talloc_strndup (values, values->iterator, values->tok_len);
}
void
notmuch_config_values_start (notmuch_config_values_t *values) {
if (values == NULL)
return;
if (values->children) {
talloc_free (values->children);
}
values->children = talloc_new (values);
values->iterator = strsplit_len (values->string, ';', &(values->tok_len));
}
void
notmuch_config_values_move_to_next (notmuch_config_values_t *values) {
values->iterator += values->tok_len;

View file

@ -2509,6 +2509,18 @@ notmuch_config_values_get (notmuch_config_values_t *values);
void
notmuch_config_values_move_to_next (notmuch_config_values_t *values);
/**
* reset the 'values' iterator to the first element
*
* @param[in,out] values iterator. A NULL value is ignored.
*
* @since libnotmuch 5.4 (notmuch 0.32)
*
*/
void
notmuch_config_values_start (notmuch_config_values_t *values);
/**
* Destroy a config values iterator, along with any associated
* resources.

View file

@ -224,6 +224,38 @@ EOF
test_expect_equal_file EXPECTED OUTPUT
restore_database
test_begin_subtest "notmuch_config_get_values (restart)"
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
{
notmuch_config_values_t *values;
EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c"));
for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
notmuch_config_values_valid (values);
notmuch_config_values_move_to_next (values))
{
puts (notmuch_config_values_get (values));
}
for (notmuch_config_values_start (values);
notmuch_config_values_valid (values);
notmuch_config_values_move_to_next (values))
{
puts (notmuch_config_values_get (values));
}
}
EOF
cat <<'EOF' >EXPECTED
== stdout ==
a
b
c
a
b
c
== stderr ==
EOF
test_expect_equal_file EXPECTED OUTPUT
restore_database
backup_database
test_begin_subtest "notmuch_config_get_values, trailing ;"
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%