lib/config: add config values iterator

This is intended to avoid duplicating the string splitting and
traversal code for all clients of the config API.
This commit is contained in:
David Bremner 2020-08-08 11:16:49 -03:00
parent 3fb123f215
commit fd6f8e6c30
4 changed files with 192 additions and 7 deletions

View file

@ -31,6 +31,11 @@ struct _notmuch_config_list {
char *current_val; char *current_val;
}; };
struct _notmuch_config_values {
const char *iterator;
size_t tok_len;
};
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);
static int static int
@ -248,6 +253,53 @@ _notmuch_config_load_from_database (notmuch_database_t *notmuch)
return status; return status;
} }
notmuch_config_values_t *
notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key)
{
notmuch_config_values_t *values;
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;
values = talloc (notmuch, notmuch_config_values_t);
if (unlikely(! values))
return NULL;
values->iterator = strsplit_len (str, ';', &(values->tok_len));
return values;
}
notmuch_bool_t
notmuch_config_values_valid (notmuch_config_values_t *values) {
if (! values)
return false;
return (values->iterator != NULL);
}
const char *
notmuch_config_values_get (notmuch_config_values_t *values) {
return talloc_strndup (values, values->iterator, values->tok_len);
}
void
notmuch_config_values_move_to_next (notmuch_config_values_t *values) {
values->iterator += values->tok_len;
values->iterator = strsplit_len (values->iterator, ';', &(values->tok_len));
}
void
notmuch_config_values_destroy (notmuch_config_values_t *values) {
talloc_free (values);
}
notmuch_status_t notmuch_status_t
_notmuch_config_load_from_file (notmuch_database_t *notmuch, _notmuch_config_load_from_file (notmuch_database_t *notmuch,
GKeyFile *file) GKeyFile *file)

View file

@ -236,6 +236,7 @@ typedef struct _notmuch_tags notmuch_tags_t;
typedef struct _notmuch_directory notmuch_directory_t; typedef struct _notmuch_directory notmuch_directory_t;
typedef struct _notmuch_filenames notmuch_filenames_t; typedef struct _notmuch_filenames notmuch_filenames_t;
typedef struct _notmuch_config_list notmuch_config_list_t; typedef struct _notmuch_config_list notmuch_config_list_t;
typedef struct _notmuch_config_values notmuch_config_values_t;
typedef struct _notmuch_indexopts notmuch_indexopts_t; typedef struct _notmuch_indexopts notmuch_indexopts_t;
#endif /* __DOXYGEN__ */ #endif /* __DOXYGEN__ */
@ -2456,6 +2457,69 @@ notmuch_config_get (notmuch_database_t *notmuch, notmuch_config_key_t key);
notmuch_status_t notmuch_status_t
notmuch_config_set (notmuch_database_t *notmuch, notmuch_config_key_t key, const char *val); notmuch_config_set (notmuch_database_t *notmuch, notmuch_config_key_t key, const char *val);
/**
* Returns an iterator for a ';'-delimited list of configuration values
*
* These values reflect all configuration information given at the
* time the database was opened.
*
* @param[in] notmuch database
* @param[in] key configuration key
*
* @since libnotmuch 5.4 (notmuch 0.32)
*
* @retval NULL in case of error.
*/
notmuch_config_values_t *
notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key);
/**
* Is the given 'config_values' iterator pointing at a valid element.
*
* @param[in] values iterator
*
* @since libnotmuch 5.4 (notmuch 0.32)
*
* @retval FALSE if passed a NULL pointer, or the iterator is exhausted.
*
*/
notmuch_bool_t
notmuch_config_values_valid (notmuch_config_values_t *values);
/**
* Get the current value from the 'values' iterator
*
* @param[in] values iterator
*
* @since libnotmuch 5.4 (notmuch 0.32)
*
* @retval a string with the same lifetime as the iterator
*/
const char *
notmuch_config_values_get (notmuch_config_values_t *values);
/**
* Move the 'values' iterator to the next element
*
* @param[in,out] values iterator
*
* @since libnotmuch 5.4 (notmuch 0.32)
*
*/
void
notmuch_config_values_move_to_next (notmuch_config_values_t *values);
/**
* Destroy a config values iterator, along with any associated
* resources.
*
* @param[in,out] values iterator
*
* @since libnotmuch 5.4 (notmuch 0.32)
*/
void
notmuch_config_values_destroy (notmuch_config_values_t *values);
/** /**
* get the current default indexing options for a given database. * get the current default indexing options for a given database.
* *

View file

@ -457,6 +457,7 @@ main (int argc, char *argv[])
command_t *command; command_t *command;
const char *config_file_name = NULL; const char *config_file_name = NULL;
notmuch_config_t *config = NULL; notmuch_config_t *config = NULL;
notmuch_database_t *notmuch = NULL;
int opt_index; int opt_index;
int ret; int ret;
@ -500,13 +501,35 @@ main (int argc, char *argv[])
goto DONE; goto DONE;
} }
config = notmuch_config_open (local, config_file_name, command->mode); if (command->mode & NOTMUCH_COMMAND_DATABASE_EARLY) {
if (! config) { char *status_string = NULL;
ret = EXIT_FAILURE; notmuch_database_mode_t mode;
goto DONE; if (command->mode & NOTMUCH_COMMAND_DATABASE_WRITE)
} mode = NOTMUCH_DATABASE_MODE_READ_WRITE;
else
mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
ret = (command->function)(config, NULL, argc - opt_index, argv + opt_index); if (notmuch_database_open_with_config (NULL,
mode,
config_file_name,
NULL,
&notmuch,
&status_string)) {
if (status_string) {
fputs (status_string, stderr);
free (status_string);
}
return EXIT_FAILURE;
}
} else {
config = notmuch_config_open (local, config_file_name, command->mode);
if (! config) {
ret = EXIT_FAILURE;
goto DONE;
}
}
ret = (command->function)(config, notmuch, argc - opt_index, argv + opt_index);
DONE: DONE:
if (config) if (config)

View file

@ -201,9 +201,55 @@ EOF
test_expect_equal_file EXPECTED OUTPUT test_expect_equal_file EXPECTED OUTPUT
restore_database restore_database
test_begin_subtest "notmuch_config_get_values"
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));
}
}
EOF
cat <<'EOF' >EXPECTED
== stdout ==
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%
{
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));
}
}
EOF
cat <<'EOF' >EXPECTED
== stdout ==
a
b
c
== stderr ==
EOF
test_expect_equal_file EXPECTED OUTPUT
restore_database
backup_database backup_database
test_begin_subtest "get config by key" test_begin_subtest "get config by key"
notmuch config set test.key1 overridden
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
{ {
printf("before = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS)); printf("before = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));