[PATCH 11/38] lib/config: make values iterators restartable

Subject: [PATCH 11/38] lib/config: make values iterators restartable

Date: Sat, 16 Jan 2021 13:03:39 -0400

To: notmuch@notmuchmail.org

Cc: David Bremner

From: David Bremner


This is relatively cheap, and makes it easier to transform existing
code which uses arrays of pointers to store configuration lists.
---
 lib/config.cc          | 43 +++++++++++++++++++++++++++++++++---------
 lib/notmuch.h          | 12 ++++++++++++
 test/T590-libconfig.sh | 32 +++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 9 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 4500fe1a..51e359b8 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -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->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;
 
-    values->iterator = strsplit_len (str, ';', &(values->tok_len));
+ 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;
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 7aeff567..39f39423 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -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.
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 6eaec101..5ffe967b 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -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%
-- 
2.29.2
_______________________________________________
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-leave@notmuchmail.org

Thread: