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 { struct _notmuch_config_values {
const char *iterator; const char *iterator;
size_t tok_len; size_t tok_len;
const char *string;
void *children; /* talloc_context */
}; };
static const char * _notmuch_config_key_to_string (notmuch_config_key_t key); 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_values_t *
notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key) 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); const char *key_str = _notmuch_config_key_to_string (key);
if (! key_str) if (! key_str)
return NULL; goto DONE;
str = _notmuch_string_map_get (notmuch->config, key_str);
if (! str)
return NULL;
values = talloc (notmuch, notmuch_config_values_t); values = talloc (notmuch, notmuch_config_values_t);
if (unlikely(! values)) 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; return values;
} }
@ -289,6 +301,19 @@ notmuch_config_values_get (notmuch_config_values_t *values) {
return talloc_strndup (values, values->iterator, values->tok_len); 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 void
notmuch_config_values_move_to_next (notmuch_config_values_t *values) { notmuch_config_values_move_to_next (notmuch_config_values_t *values) {
values->iterator += values->tok_len; values->iterator += values->tok_len;

View file

@ -2509,6 +2509,18 @@ notmuch_config_values_get (notmuch_config_values_t *values);
void void
notmuch_config_values_move_to_next (notmuch_config_values_t *values); 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 * Destroy a config values iterator, along with any associated
* resources. * resources.

View file

@ -224,6 +224,38 @@ EOF
test_expect_equal_file EXPECTED OUTPUT test_expect_equal_file EXPECTED OUTPUT
restore_database 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 backup_database
test_begin_subtest "notmuch_config_get_values, trailing ;" test_begin_subtest "notmuch_config_get_values, trailing ;"
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%