[notmuch] [PATCH 4/5] Added backwards iterator to threads

Ruben Pollan meskio at sindominio.net
Sat Mar 20 03:23:24 PDT 2010


Added the functions notmuch_threads_move_to_prevoius,
notmuch_threads_move_to_last and  notmuch_threads_move_to_first to
notmuch library. With them is possible to iterate backwards on threads.

* notmuch_threads_move_to_prevoius do the opposite than
  notmuch_threads_move_to_next, getting the threads iterator one
  position backwards.

* notmuch_threads_move_to_last move the iterator to the first last thread.

* notmuch_threads_move_to_first move the iterator to the first valid
  thread.

For it has been implemented notmuch_thread_list_t structur that stores
the thread_ids so the backwards iteration gets the thread_id in the same
order that was show on forward iteration.
---
 lib/notmuch.h |   28 +++++++++++
 lib/query.cc  |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 159 insertions(+), 12 deletions(-)

diff --git a/lib/notmuch.h b/lib/notmuch.h
index 753f3bb..b96b624 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -466,6 +466,15 @@ notmuch_threads_valid (notmuch_threads_t *threads);
 notmuch_thread_t *
 notmuch_threads_get (notmuch_threads_t *threads);
 
+/* Move the 'threads' iterator to the first thread.
+ *
+ * After that the 'threads' iterator will be set to the first valid 
+ * thread, so it can be use to iterate with 
+ * notmuch_threads_move_to_next.
+ */
+void
+notmuch_threads_move_to_first (notmuch_threads_t *threads);
+
 /* Move the 'threads' iterator to the next thread.
  *
  * If 'threads' is already pointing at the last thread then the
@@ -479,6 +488,25 @@ notmuch_threads_get (notmuch_threads_t *threads);
 void
 notmuch_threads_move_to_next (notmuch_threads_t *threads);
 
+/* Move the 'threads' iterator to the last thread.
+ *
+ * After that the 'threads' iterator will be set to the last valid 
+ * thread, so it can be use to iterate with 
+ * notmuch_threads_move_to_previous.
+ */
+void
+notmuch_threads_move_to_last (notmuch_threads_t *threads);
+
+/* Move the 'threads' iterator to the previous thread.
+ *
+ * If 'threads' is already pointing at the first thread then the
+ * iterator will be moved to a point just beyond that first thread,
+ * (where notmuch_threads_valid will return FALSE and
+ * notmuch_threads_get will return NULL).
+ */
+void
+notmuch_threads_move_to_previous (notmuch_threads_t *threads);
+
 /* Destroy a notmuch_threads_t object.
  *
  * It's not strictly necessary to call this function. All memory from
diff --git a/lib/query.cc b/lib/query.cc
index 44950c1..39985e7 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -39,13 +39,25 @@ typedef struct _notmuch_mset_messages {
     Xapian::MSetIterator iterator_end;
 } notmuch_mset_messages_t;
 
+typedef struct _notmuch_thread_node {
+    const char *thread_id;
+    struct _notmuch_thread_node *next;
+    struct _notmuch_thread_node *prev;
+} notmuch_thread_node_t;
+
+typedef struct _notmuch_thread_list {
+    notmuch_thread_node_t *head;
+    notmuch_thread_node_t *tail;
+    notmuch_thread_node_t *iterator;
+} notmuch_thread_list_t;
+
 struct _notmuch_threads {
     notmuch_query_t *query;
     GHashTable *threads;
     notmuch_messages_t *messages;
 
-    /* This thread ID is our iterator state. */
-    const char *thread_id;
+    /* thread list with the thread_id of the showed messages */
+    notmuch_thread_list_t *list;
 };
 
 notmuch_query_t *
@@ -269,6 +281,64 @@ _notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages)
     }
 }
 
+static void
+_notmuch_thread_list_create (notmuch_thread_list_t *list, const char *thread_id)
+{
+    list->head = talloc (list, notmuch_thread_node_t);
+    list->tail = list->head;
+    list->iterator = list->head;
+    list->iterator->thread_id = thread_id;
+    list->iterator->next = NULL;
+    list->iterator->prev = NULL;
+}
+
+static void
+_notmuch_thread_list_append (notmuch_thread_list_t *list, const char *thread_id)
+{
+    list->tail->next = talloc (list, notmuch_thread_node_t);
+    list->iterator = list->tail->next;
+    list->iterator->thread_id = thread_id;
+    list->iterator->next = NULL;
+    list->iterator->prev = list->tail;
+    list->tail = list->iterator;
+}
+
+static const char *
+_notmuch_thread_list_get_id (notmuch_thread_list_t *list)
+{
+    return list->iterator->thread_id;
+}
+
+static notmuch_bool_t
+_notmuch_thread_list_valid (notmuch_thread_list_t *list)
+{
+    return (list->iterator != NULL);
+}
+
+static void
+_notmuch_thread_list_move_to_first (notmuch_thread_list_t *list)
+{
+    list->iterator = list->head;
+}
+
+static void
+_notmuch_thread_list_move_to_next (notmuch_thread_list_t *list)
+{
+    list->iterator = list->iterator->next;
+}
+
+static void
+_notmuch_thread_list_move_to_last (notmuch_thread_list_t *list)
+{
+    list->iterator = list->tail;
+}
+
+static void
+_notmuch_thread_list_move_to_previous (notmuch_thread_list_t *list)
+{
+    list->iterator = list->iterator->prev;
+}
+
 /* Glib objects force use to use a talloc destructor as well, (but not
  * nearly as ugly as the for messages due to C++ objects). At
  * this point, I'd really like to have some talloc-friendly
@@ -297,10 +367,13 @@ notmuch_query_search_threads (notmuch_query_t *query)
 
     threads->messages = notmuch_query_search_messages (query);
 
+    threads->list = talloc (threads, notmuch_thread_list_t);
     message = notmuch_messages_get (threads->messages);
-    threads->thread_id = notmuch_message_get_thread_id (message);
+    _notmuch_thread_list_create (threads->list,
+                                  notmuch_message_get_thread_id (message));
     g_hash_table_insert (threads->threads,
-                         xstrdup (threads->thread_id), NULL);
+                         xstrdup (_notmuch_thread_list_get_id (threads->list)),
+                         NULL);
 
     talloc_set_destructor (threads, _notmuch_threads_destructor);
 
@@ -316,7 +389,7 @@ notmuch_query_destroy (notmuch_query_t *query)
 notmuch_bool_t
 notmuch_threads_valid (notmuch_threads_t *threads)
 {
-    return (threads->thread_id != NULL);
+    return _notmuch_thread_list_valid (threads->list);
 }
 
 notmuch_thread_t *
@@ -327,37 +400,83 @@ notmuch_threads_get (notmuch_threads_t *threads)
 
     return _notmuch_thread_create (threads->query,
 				   threads->query->notmuch,
-				   threads->thread_id,
+				   _notmuch_thread_list_get_id (threads->list),
 				   threads->query->query_string);
 }
 
 void
+notmuch_threads_move_to_first (notmuch_threads_t *threads)
+{
+    _notmuch_thread_list_move_to_first (threads->list);
+}
+
+void
 notmuch_threads_move_to_next (notmuch_threads_t *threads)
 {
-    notmuch_message_t *message;
+    if (!_notmuch_thread_list_valid (threads->list))
+        return;
+
+    _notmuch_thread_list_move_to_next (threads->list);
+    if (_notmuch_thread_list_valid (threads->list))
+        return;
 
     while (notmuch_messages_valid (threads->messages))
     {
-	message = notmuch_messages_get (threads->messages);
+        notmuch_message_t *message;
+        const char *thread_id;
 
-	threads->thread_id = notmuch_message_get_thread_id (message);
+	message = notmuch_messages_get (threads->messages);
+	thread_id = notmuch_message_get_thread_id (message);
 
 	if (! g_hash_table_lookup_extended (threads->threads,
-					    threads->thread_id,
+					    thread_id,
 					    NULL, NULL))
 	{
 	    g_hash_table_insert (threads->threads,
-				 xstrdup (threads->thread_id), NULL);
+				 xstrdup (thread_id), NULL);
+            _notmuch_thread_list_append (threads->list, thread_id);
 	    notmuch_messages_move_to_next (threads->messages);
 	    return;
 	}
 
 	notmuch_messages_move_to_next (threads->messages);
     }
+}
+
+void
+notmuch_threads_move_to_last (notmuch_threads_t *threads)
+{
+    _notmuch_thread_list_move_to_last (threads->list);
+
+    while (notmuch_messages_valid (threads->messages))
+    {
+        notmuch_message_t *message;
+        const char *thread_id;
+
+	message = notmuch_messages_get (threads->messages);
+	thread_id = notmuch_message_get_thread_id (message);
+
+	if (! g_hash_table_lookup_extended (threads->threads,
+					    thread_id,
+					    NULL, NULL))
+	{
+	    g_hash_table_insert (threads->threads,
+				 xstrdup (thread_id), NULL);
+            _notmuch_thread_list_append (threads->list, thread_id);
+        }
 
-    threads->thread_id = NULL;
+	notmuch_messages_move_to_next (threads->messages);
+    }
 }
 
+void
+notmuch_threads_move_to_previous (notmuch_threads_t *threads)
+{
+    if (!_notmuch_thread_list_valid (threads->list))
+        return;
+
+    _notmuch_thread_list_move_to_previous (threads->list);
+}
 
 void
 notmuch_threads_destroy (notmuch_threads_t *threads)
-- 
1.7.0



More information about the notmuch mailing list