* Re: [PATCH] Added regress option to tags iterator
2010-03-09 17:36 ` Carl Worth
@ 2010-03-11 14:28 ` Ruben Pollan
2010-03-20 10:23 ` reverse iterators Ruben Pollan
` (5 subsequent siblings)
6 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-11 14:28 UTC (permalink / raw)
To: Carl Worth; +Cc: notmuch
[-- Attachment #1: Type: text/plain, Size: 1389 bytes --]
On 09:36, Tue 09 Mar 10, Carl Worth wrote:
> So the final proposal for iteration in either direction is:
>
> move_to_first
> valid
> move_to_next
>
> move_to_last
> valid
> move_to_previous
>
> get
Fine for me.
> I've just pushed commits changing the existing functions (which allow
> only forward iteration) to use this naming scheme. I haven't added any
> of the reverse-iteration functions yet, so Ruben, if you'd like to do
> those within this scheme, that would be find. (Or we could wait until we
> have an actual use in mind for them.)
I'll implemented them again and we'll decide if make sense to have them even if
there is no code now using them. I think is a useful feature to create a client
based on notmuch library, but I also think is bad behavior to keep code that is
not in use.
I'm still thinking in a ncurses client (but I didn't hack on that on a while)
and I guess I'll use this functions on it. But I don't mind to have them just in
my own repository until I have something working.
I'm not having too much hacking time lately, so I don't know when I'll have
some time for it. I hope in few days.
--
Rubén Pollán | jabber:meskio@jabber.org
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Cuando los que mandan pierden la vergüenza,
los que obedecen pierden el respeto.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 34+ messages in thread
* reverse iterators
2010-03-09 17:36 ` Carl Worth
2010-03-11 14:28 ` Ruben Pollan
@ 2010-03-20 10:23 ` Ruben Pollan
2010-03-21 20:07 ` Sebastian Spaeth
` (3 more replies)
2010-03-20 10:23 ` [PATCH 1/5] Convert notmuch_message_list_t in a doubly linked Ruben Pollan
` (4 subsequent siblings)
6 siblings, 4 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-20 10:23 UTC (permalink / raw)
To: notmuch
Adds support to reverse iteration on messages, threads and tags. To revew and
think if makes sense to include them on notmuch or wait until they have a real
use.
The patch 3 "Move the logic of threads iterator out of 'valid'" is just a
reorganization of the code, I think it makes sense to include it in notmuch even
if we decide that the reverse iterators are not included.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: reverse iterators
2010-03-20 10:23 ` reverse iterators Ruben Pollan
@ 2010-03-21 20:07 ` Sebastian Spaeth
2010-03-22 10:18 ` Ruben Pollan
2010-03-21 21:32 ` [PATCH] sending again patches 3 & 4 Ruben Pollan
` (2 subsequent siblings)
3 siblings, 1 reply; 34+ messages in thread
From: Sebastian Spaeth @ 2010-03-21 20:07 UTC (permalink / raw)
To: Ruben Pollan, notmuch
On Sat, 20 Mar 2010 11:23:20 +0100, Ruben Pollan <meskio@sindominio.net> wrote:
>
> Adds support to reverse iteration on messages, threads and tags. To revew and
> think if makes sense to include them on notmuch or wait until they have a real
> use.
/me raises arm. Real use case here! Personally, I don't need the
backwards operator (and I don't see the case where I would need to go
back very often). But a _move_to_first() for threads, messages (and
probably tags), would be really useful to me now:
Having bound notmuch.so to python, I am in a situation, where I can only
offer iteration once, with subsequent iterations failing. This is very
unexpected and very un-pythonesque. I fell myself over it:
#the below len() iterates and exhausts msgs
if len(msgs) > 0:
for msg in msgs: print msg
#above line fails horribly already...
else: print "No message for me!"
So, having a way to reset the iterator would be a real boon already now.
Sebastian
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: reverse iterators
2010-03-21 20:07 ` Sebastian Spaeth
@ 2010-03-22 10:18 ` Ruben Pollan
0 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-22 10:18 UTC (permalink / raw)
To: Sebastian Spaeth; +Cc: notmuch
[-- Attachment #1: Type: text/plain, Size: 1088 bytes --]
On 21:07, Sun 21 Mar 10, Sebastian Spaeth wrote:
> On Sat, 20 Mar 2010 11:23:20 +0100, Ruben Pollan <meskio@sindominio.net> wrote:
> >
> > Adds support to reverse iteration on messages, threads and tags. To revew and
> > think if makes sense to include them on notmuch or wait until they have a real
> > use.
>
> /me raises arm. Real use case here! Personally, I don't need the
> backwards operator (and I don't see the case where I would need to go
> back very often).
For me is pretty useful because I use the iterator as a cursor on an ncurses
notmuch interface. So the selected thread is where the iterator is and the user
can to go forward or backwards.
> But a _move_to_first() for threads, messages (and
> probably tags), would be really useful to me now:
:) Happy to see there is someone else needing it.
--
Rubén Pollán | jabber:meskio@jabber.org
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Lo hago para no volverme loco cuando noto
que solo me queda un demonio en un hombro
por que se ha cortado las venas
el ángel que había en el otro.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH] sending again patches 3 & 4
2010-03-20 10:23 ` reverse iterators Ruben Pollan
2010-03-21 20:07 ` Sebastian Spaeth
@ 2010-03-21 21:32 ` Ruben Pollan
2010-03-21 21:32 ` [PATCH 1/2] Move the logic of threads iterator out of 'valid' Ruben Pollan
2010-03-21 21:32 ` [PATCH 2/2] Added backwards iterator to threads Ruben Pollan
3 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-21 21:32 UTC (permalink / raw)
To: notmuch
I send again the patches 3 and 4, beacuse I found a bug on them. The previous
implementation did a segfault when the search didn't have results.
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 1/2] Move the logic of threads iterator out of 'valid'
2010-03-20 10:23 ` reverse iterators Ruben Pollan
2010-03-21 20:07 ` Sebastian Spaeth
2010-03-21 21:32 ` [PATCH] sending again patches 3 & 4 Ruben Pollan
@ 2010-03-21 21:32 ` Ruben Pollan
2010-03-21 21:32 ` [PATCH 2/2] Added backwards iterator to threads Ruben Pollan
3 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-21 21:32 UTC (permalink / raw)
To: notmuch
The logic of notmuch_threads_move_to_next iterator was on
notmuch_threads_valid function. Now notmuch_threads_valid just check if
the iterator is valid and is notmuch_threads_move_to_next wich actually
update the iterator.
---
lib/query.cc | 54 ++++++++++++++++++++++++++++++------------------------
1 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/lib/query.cc b/lib/query.cc
index 9266d35..514a156 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -233,6 +233,7 @@ notmuch_threads_t *
notmuch_query_search_threads (notmuch_query_t *query)
{
notmuch_threads_t *threads;
+ notmuch_message_t *message;
threads = talloc (query, notmuch_threads_t);
if (threads == NULL)
@@ -243,8 +244,17 @@ notmuch_query_search_threads (notmuch_query_t *query)
free, NULL);
threads->messages = notmuch_query_search_messages (query);
+ if (!notmuch_messages_valid (threads->messages))
+ {
+ threads->thread_id = NULL;
+ return threads;
+ }
- threads->thread_id = NULL;
+ message = notmuch_messages_get (threads->messages);
+ threads->thread_id = notmuch_message_get_thread_id (message);
+ g_hash_table_insert (threads->threads,
+ xstrdup (threads->thread_id),
+ NULL);
talloc_set_destructor (threads, _notmuch_threads_destructor);
@@ -260,10 +270,25 @@ notmuch_query_destroy (notmuch_query_t *query)
notmuch_bool_t
notmuch_threads_valid (notmuch_threads_t *threads)
{
- notmuch_message_t *message;
+ return (threads->thread_id != NULL);
+}
+
+notmuch_thread_t *
+notmuch_threads_get (notmuch_threads_t *threads)
+{
+ if (! notmuch_threads_valid (threads))
+ return NULL;
+
+ return _notmuch_thread_create (threads->query,
+ threads->query->notmuch,
+ threads->thread_id,
+ threads->query->query_string);
+}
- if (threads->thread_id)
- return TRUE;
+void
+notmuch_threads_move_to_next (notmuch_threads_t *threads)
+{
+ notmuch_message_t *message;
while (notmuch_messages_valid (threads->messages))
{
@@ -278,32 +303,13 @@ notmuch_threads_valid (notmuch_threads_t *threads)
g_hash_table_insert (threads->threads,
xstrdup (threads->thread_id), NULL);
notmuch_messages_move_to_next (threads->messages);
- return TRUE;
+ return;
}
notmuch_messages_move_to_next (threads->messages);
}
threads->thread_id = NULL;
- return FALSE;
-}
-
-notmuch_thread_t *
-notmuch_threads_get (notmuch_threads_t *threads)
-{
- if (! notmuch_threads_valid (threads))
- return NULL;
-
- return _notmuch_thread_create (threads->query,
- threads->query->notmuch,
- threads->thread_id,
- threads->query->query_string);
-}
-
-void
-notmuch_threads_move_to_next (notmuch_threads_t *threads)
-{
- threads->thread_id = NULL;
}
void
--
1.7.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 2/2] Added backwards iterator to threads
2010-03-20 10:23 ` reverse iterators Ruben Pollan
` (2 preceding siblings ...)
2010-03-21 21:32 ` [PATCH 1/2] Move the logic of threads iterator out of 'valid' Ruben Pollan
@ 2010-03-21 21:32 ` Ruben Pollan
3 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-21 21:32 UTC (permalink / raw)
To: notmuch
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 | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 222 insertions(+), 15 deletions(-)
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 0d9cb0f..62f4ad4 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 514a156..727f449 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -35,16 +35,29 @@ typedef struct _notmuch_mset_messages {
notmuch_messages_t base;
notmuch_database_t *notmuch;
Xapian::MSetIterator iterator;
+ Xapian::MSetIterator iterator_begin;
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 *
@@ -86,6 +99,7 @@ static int
_notmuch_messages_destructor (notmuch_mset_messages_t *messages)
{
messages->iterator.~MSetIterator ();
+ messages->iterator_begin.~MSetIterator ();
messages->iterator_end.~MSetIterator ();
return 0;
@@ -108,6 +122,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
messages->base.iterator = NULL;
messages->notmuch = notmuch;
new (&messages->iterator) Xapian::MSetIterator ();
+ new (&messages->iterator_begin) Xapian::MSetIterator ();
new (&messages->iterator_end) Xapian::MSetIterator ();
talloc_set_destructor (messages, _notmuch_messages_destructor);
@@ -157,6 +172,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());
messages->iterator = mset.begin ();
+ messages->iterator_begin = mset.begin ();
messages->iterator_end = mset.end ();
} catch (const Xapian::Error &error) {
@@ -208,6 +224,16 @@ _notmuch_mset_messages_get (notmuch_messages_t *messages)
}
void
+_notmuch_mset_messages_move_to_first (notmuch_messages_t *messages)
+{
+ notmuch_mset_messages_t *mset_messages;
+
+ mset_messages = (notmuch_mset_messages_t *) messages;
+
+ mset_messages->iterator = mset_messages->iterator_begin;
+}
+
+void
_notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)
{
notmuch_mset_messages_t *mset_messages;
@@ -217,6 +243,113 @@ _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)
mset_messages->iterator++;
}
+void
+_notmuch_mset_messages_move_to_last (notmuch_messages_t *messages)
+{
+ notmuch_mset_messages_t *mset_messages;
+
+ mset_messages = (notmuch_mset_messages_t *) messages;
+
+ mset_messages->iterator = mset_messages->iterator_end;
+ mset_messages->iterator--;
+}
+
+void
+_notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages)
+{
+ notmuch_mset_messages_t *mset_messages;
+
+ mset_messages = (notmuch_mset_messages_t *) messages;
+
+ if (mset_messages->iterator == mset_messages->iterator_begin)
+ {
+ /*
+ * Xapian iterators can not be beyond the first element, so we
+ * assign the iterator_end to mark the iterator as invalid in case
+ * of move_to_previous with the iterator at the beginning
+ */
+ mset_messages->iterator = mset_messages->iterator_end;
+ }
+ else if (_notmuch_mset_messages_valid (messages))
+ {
+ /*
+ * If is valid move the iterator. To emulate the same behavior
+ * than notmuch_messages_t the iterator won't be updated if is
+ * not valid
+ */
+ mset_messages->iterator--;
+ }
+}
+
+static notmuch_thread_list_t *
+_notmuch_thread_list_create (void *ctx)
+{
+ notmuch_thread_list_t *list;
+
+ list = talloc (ctx, notmuch_thread_list_t);
+ list->tail = NULL;
+ list->head = NULL;
+ list->iterator = NULL;
+
+ return list;
+}
+
+static void
+_notmuch_thread_list_append (notmuch_thread_list_t *list, const char *thread_id)
+{
+ list->iterator = talloc (list, notmuch_thread_node_t);
+ if (list->head == NULL)
+ {
+ list->head = list->iterator;
+ list->iterator->prev = NULL;
+ }
+ else
+ {
+ list->tail->next = list->iterator;
+ list->iterator->prev = list->tail;
+ }
+
+ list->iterator->thread_id = thread_id;
+ list->iterator->next = NULL;
+ 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
@@ -244,16 +377,15 @@ notmuch_query_search_threads (notmuch_query_t *query)
free, NULL);
threads->messages = notmuch_query_search_messages (query);
+ threads->list = _notmuch_thread_list_create (threads);
if (!notmuch_messages_valid (threads->messages))
- {
- threads->thread_id = NULL;
return threads;
- }
message = notmuch_messages_get (threads->messages);
- threads->thread_id = notmuch_message_get_thread_id (message);
+ _notmuch_thread_list_append (threads->list,
+ notmuch_message_get_thread_id (message));
g_hash_table_insert (threads->threads,
- xstrdup (threads->thread_id),
+ xstrdup (_notmuch_thread_list_get_id (threads->list)),
NULL);
talloc_set_destructor (threads, _notmuch_threads_destructor);
@@ -270,7 +402,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 *
@@ -281,35 +413,82 @@ 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);
+ }
+
+ 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;
- threads->thread_id = NULL;
+ _notmuch_thread_list_move_to_previous (threads->list);
}
void
--
1.7.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 1/5] Convert notmuch_message_list_t in a doubly linked
2010-03-09 17:36 ` Carl Worth
2010-03-11 14:28 ` Ruben Pollan
2010-03-20 10:23 ` reverse iterators Ruben Pollan
@ 2010-03-20 10:23 ` Ruben Pollan
2010-03-20 10:23 ` [PATCH 2/5] Added backwards iterator to messages Ruben Pollan
` (3 subsequent siblings)
6 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-20 10:23 UTC (permalink / raw)
To: notmuch
The messages list now have pointers to previous nodes, so it is possible
to iterate backwards.
---
lib/messages.c | 18 +++++++++++++-----
lib/notmuch-private.h | 3 ++-
lib/thread.cc | 4 ++--
3 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/lib/messages.c b/lib/messages.c
index db2b7a1..2a85774 100644
--- a/lib/messages.c
+++ b/lib/messages.c
@@ -37,20 +37,28 @@ _notmuch_message_list_create (const void *ctx)
return NULL;
list->head = NULL;
- list->tail = &list->head;
+ list->tail = NULL;
return list;
}
-/* Append 'node' (which can of course point to an arbitrarily long
- * list of nodes) to the end of 'list'.
+/* Append 'node' to the end of 'list'.
*/
void
_notmuch_message_list_append (notmuch_message_list_t *list,
notmuch_message_node_t *node)
{
- *(list->tail) = node;
- list->tail = &node->next;
+ node->prev = list->tail;
+ if (list->head)
+ {
+ list->tail->next = node;
+ }
+ else
+ {
+ list->head = node;
+ list->tail = node;
+ }
+ list->tail = node;
}
/* Allocate a new node for 'message' and append it to the end of
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index d52d84d..3b3f0eb 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -349,11 +349,12 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
typedef struct _notmuch_message_node {
notmuch_message_t *message;
struct _notmuch_message_node *next;
+ struct _notmuch_message_node *prev;
} notmuch_message_node_t;
typedef struct _notmuch_message_list {
notmuch_message_node_t *head;
- notmuch_message_node_t **tail;
+ notmuch_message_node_t *tail;
} notmuch_message_list_t;
/* There's a rumor that there's an alternate struct _notmuch_messages
diff --git a/lib/thread.cc b/lib/thread.cc
index ec80f85..05d2c39 100644
--- a/lib/thread.cc
+++ b/lib/thread.cc
@@ -169,8 +169,8 @@ _resolve_thread_relationships (unused (notmuch_thread_t *thread))
(void **) &parent))
{
*prev = node->next;
- if (thread->message_list->tail == &node->next)
- thread->message_list->tail = prev;
+ if (thread->message_list->tail == node)
+ thread->message_list->tail = node->prev;
node->next = NULL;
_notmuch_message_add_reply (parent, node);
} else {
--
1.7.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 2/5] Added backwards iterator to messages
2010-03-09 17:36 ` Carl Worth
` (2 preceding siblings ...)
2010-03-20 10:23 ` [PATCH 1/5] Convert notmuch_message_list_t in a doubly linked Ruben Pollan
@ 2010-03-20 10:23 ` Ruben Pollan
2010-03-20 10:23 ` [PATCH 3/5] Move the logic of threads iterator out of 'valid' Ruben Pollan
` (2 subsequent siblings)
6 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-20 10:23 UTC (permalink / raw)
To: notmuch
Added the functions notmuch_messages_move_to_prevoius,
notmuch_messages_move_to_last and notmuch_messages_move_to_first to
notmuch library. With them is possible to iterate backwards on messages.
* notmuch_messages_move_to_prevoius do the opposite than
notmuch_messages_move_to_next, getting the messages iterator one
position backwards.
* notmuch_messages_move_to_last move the iterator to the first last
message.
* notmuch_messages_move_to_first move the iterator to the first valid
message.
---
lib/messages.c | 31 +++++++++++++++++++++++++++++
lib/notmuch-private.h | 10 +++++++++
lib/notmuch.h | 28 ++++++++++++++++++++++++++
lib/query.cc | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 121 insertions(+), 0 deletions(-)
diff --git a/lib/messages.c b/lib/messages.c
index 2a85774..975e4b1 100644
--- a/lib/messages.c
+++ b/lib/messages.c
@@ -90,6 +90,7 @@ _notmuch_messages_create (notmuch_message_list_t *list)
messages->is_of_list_type = TRUE;
messages->iterator = list->head;
+ messages->list = list;
return messages;
}
@@ -134,6 +135,15 @@ notmuch_messages_get (notmuch_messages_t *messages)
}
void
+notmuch_messages_move_to_first (notmuch_messages_t *messages)
+{
+ if (! messages->is_of_list_type)
+ return _notmuch_mset_messages_move_to_first (messages);
+
+ messages->iterator = messages->list->head;
+}
+
+void
notmuch_messages_move_to_next (notmuch_messages_t *messages)
{
if (! messages->is_of_list_type)
@@ -146,6 +156,27 @@ notmuch_messages_move_to_next (notmuch_messages_t *messages)
}
void
+notmuch_messages_move_to_last (notmuch_messages_t *messages)
+{
+ if (! messages->is_of_list_type)
+ return _notmuch_mset_messages_move_to_last (messages);
+
+ messages->iterator = messages->list->tail;
+}
+
+void
+notmuch_messages_move_to_previous (notmuch_messages_t *messages)
+{
+ if (! messages->is_of_list_type)
+ return _notmuch_mset_messages_move_to_previous (messages);
+
+ if (messages->iterator == NULL)
+ return;
+
+ messages->iterator = messages->iterator->prev;
+}
+
+void
notmuch_messages_destroy (notmuch_messages_t *messages)
{
talloc_free (messages);
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 3b3f0eb..2269d2b 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -364,6 +364,7 @@ typedef struct _notmuch_message_list {
struct _notmuch_messages {
notmuch_bool_t is_of_list_type;
notmuch_message_node_t *iterator;
+ notmuch_message_list_t *list;
};
notmuch_message_list_t *
@@ -389,8 +390,17 @@ notmuch_message_t *
_notmuch_mset_messages_get (notmuch_messages_t *messages);
void
+_notmuch_mset_messages_move_to_first (notmuch_messages_t *messages);
+
+void
_notmuch_mset_messages_move_to_next (notmuch_messages_t *messages);
+void
+_notmuch_mset_messages_move_to_last (notmuch_messages_t *messages);
+
+void
+_notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages);
+
/* message.cc */
void
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 0d9cb0f..753f3bb 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -645,6 +645,15 @@ notmuch_messages_valid (notmuch_messages_t *messages);
notmuch_message_t *
notmuch_messages_get (notmuch_messages_t *messages);
+/* Move the 'messages' iterator to the first message.
+ *
+ * After that the 'messages' iterator will be set to the first valid
+ * message, so it can be use to iterate with
+ * notmuch_messages_move_to_next.
+ */
+void
+notmuch_messages_move_to_first (notmuch_messages_t *messages);
+
/* Move the 'messages' iterator to the next message.
*
* If 'messages' is already pointing at the last message then the
@@ -658,6 +667,25 @@ notmuch_messages_get (notmuch_messages_t *messages);
void
notmuch_messages_move_to_next (notmuch_messages_t *messages);
+/* Move the 'messages' iterator to the last message.
+ *
+ * After that the 'messages' iterator will be set to the last valid
+ * message, so it can be use to iterate with
+ * notmuch_messages_move_to_previous.
+ */
+void
+notmuch_messages_move_to_last (notmuch_messages_t *messages);
+
+/* Move the 'messages' iterator to the previous message.
+ *
+ * If 'messages' is already pointing at the first message then the
+ * iterator will be moved to a point just beyond that first message,
+ * (where notmuch_messages_valid will return FALSE and
+ * notmuch_messages_get will return NULL).
+ */
+void
+notmuch_messages_move_to_previous (notmuch_messages_t *messages);
+
/* Destroy a notmuch_messages_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 9266d35..970c35a 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -35,6 +35,7 @@ typedef struct _notmuch_mset_messages {
notmuch_messages_t base;
notmuch_database_t *notmuch;
Xapian::MSetIterator iterator;
+ Xapian::MSetIterator iterator_begin;
Xapian::MSetIterator iterator_end;
} notmuch_mset_messages_t;
@@ -86,6 +87,7 @@ static int
_notmuch_messages_destructor (notmuch_mset_messages_t *messages)
{
messages->iterator.~MSetIterator ();
+ messages->iterator_begin.~MSetIterator ();
messages->iterator_end.~MSetIterator ();
return 0;
@@ -108,6 +110,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
messages->base.iterator = NULL;
messages->notmuch = notmuch;
new (&messages->iterator) Xapian::MSetIterator ();
+ new (&messages->iterator_begin) Xapian::MSetIterator ();
new (&messages->iterator_end) Xapian::MSetIterator ();
talloc_set_destructor (messages, _notmuch_messages_destructor);
@@ -157,6 +160,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());
messages->iterator = mset.begin ();
+ messages->iterator_begin = mset.begin ();
messages->iterator_end = mset.end ();
} catch (const Xapian::Error &error) {
@@ -208,6 +212,16 @@ _notmuch_mset_messages_get (notmuch_messages_t *messages)
}
void
+_notmuch_mset_messages_move_to_first (notmuch_messages_t *messages)
+{
+ notmuch_mset_messages_t *mset_messages;
+
+ mset_messages = (notmuch_mset_messages_t *) messages;
+
+ mset_messages->iterator = mset_messages->iterator_begin;
+}
+
+void
_notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)
{
notmuch_mset_messages_t *mset_messages;
@@ -217,6 +231,44 @@ _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)
mset_messages->iterator++;
}
+void
+_notmuch_mset_messages_move_to_last (notmuch_messages_t *messages)
+{
+ notmuch_mset_messages_t *mset_messages;
+
+ mset_messages = (notmuch_mset_messages_t *) messages;
+
+ mset_messages->iterator = mset_messages->iterator_end;
+ mset_messages->iterator--;
+}
+
+void
+_notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages)
+{
+ notmuch_mset_messages_t *mset_messages;
+
+ mset_messages = (notmuch_mset_messages_t *) messages;
+
+ if (mset_messages->iterator == mset_messages->iterator_begin)
+ {
+ /*
+ * Xapian iterators can not be beyond the first element, so we
+ * assign the iterator_end to mark the iterator as invalid in case
+ * of move_to_previous with the iterator at the beginning
+ */
+ mset_messages->iterator = mset_messages->iterator_end;
+ }
+ else if (_notmuch_mset_messages_valid (messages))
+ {
+ /*
+ * If is valid move the iterator. To emulate the same behavior
+ * than notmuch_messages_t the iterator won't be updated if is
+ * not valid
+ */
+ mset_messages->iterator--;
+ }
+}
+
/* 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
--
1.7.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 3/5] Move the logic of threads iterator out of 'valid'
2010-03-09 17:36 ` Carl Worth
` (3 preceding siblings ...)
2010-03-20 10:23 ` [PATCH 2/5] Added backwards iterator to messages Ruben Pollan
@ 2010-03-20 10:23 ` Ruben Pollan
2010-03-20 10:23 ` [PATCH 4/5] Added backwards iterator to threads Ruben Pollan
2010-03-20 10:23 ` [PATCH 5/5] Added backwards iterator to tags Ruben Pollan
6 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-20 10:23 UTC (permalink / raw)
To: notmuch
The logic of notmuch_threads_move_to_next iterator was on
notmuch_threads_valid function. Now notmuch_threads_valid just check if
the iterator is valid and is notmuch_threads_move_to_next wich actually
update the iterator.
---
lib/query.cc | 47 ++++++++++++++++++++++++-----------------------
1 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/lib/query.cc b/lib/query.cc
index 970c35a..44950c1 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -285,6 +285,7 @@ notmuch_threads_t *
notmuch_query_search_threads (notmuch_query_t *query)
{
notmuch_threads_t *threads;
+ notmuch_message_t *message;
threads = talloc (query, notmuch_threads_t);
if (threads == NULL)
@@ -296,7 +297,10 @@ notmuch_query_search_threads (notmuch_query_t *query)
threads->messages = notmuch_query_search_messages (query);
- threads->thread_id = NULL;
+ message = notmuch_messages_get (threads->messages);
+ threads->thread_id = notmuch_message_get_thread_id (message);
+ g_hash_table_insert (threads->threads,
+ xstrdup (threads->thread_id), NULL);
talloc_set_destructor (threads, _notmuch_threads_destructor);
@@ -312,10 +316,25 @@ notmuch_query_destroy (notmuch_query_t *query)
notmuch_bool_t
notmuch_threads_valid (notmuch_threads_t *threads)
{
- notmuch_message_t *message;
+ return (threads->thread_id != NULL);
+}
- if (threads->thread_id)
- return TRUE;
+notmuch_thread_t *
+notmuch_threads_get (notmuch_threads_t *threads)
+{
+ if (! notmuch_threads_valid (threads))
+ return NULL;
+
+ return _notmuch_thread_create (threads->query,
+ threads->query->notmuch,
+ threads->thread_id,
+ threads->query->query_string);
+}
+
+void
+notmuch_threads_move_to_next (notmuch_threads_t *threads)
+{
+ notmuch_message_t *message;
while (notmuch_messages_valid (threads->messages))
{
@@ -330,33 +349,15 @@ notmuch_threads_valid (notmuch_threads_t *threads)
g_hash_table_insert (threads->threads,
xstrdup (threads->thread_id), NULL);
notmuch_messages_move_to_next (threads->messages);
- return TRUE;
+ return;
}
notmuch_messages_move_to_next (threads->messages);
}
threads->thread_id = NULL;
- return FALSE;
-}
-
-notmuch_thread_t *
-notmuch_threads_get (notmuch_threads_t *threads)
-{
- if (! notmuch_threads_valid (threads))
- return NULL;
-
- return _notmuch_thread_create (threads->query,
- threads->query->notmuch,
- threads->thread_id,
- threads->query->query_string);
}
-void
-notmuch_threads_move_to_next (notmuch_threads_t *threads)
-{
- threads->thread_id = NULL;
-}
void
notmuch_threads_destroy (notmuch_threads_t *threads)
--
1.7.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 4/5] Added backwards iterator to threads
2010-03-09 17:36 ` Carl Worth
` (4 preceding siblings ...)
2010-03-20 10:23 ` [PATCH 3/5] Move the logic of threads iterator out of 'valid' Ruben Pollan
@ 2010-03-20 10:23 ` Ruben Pollan
2010-03-20 10:23 ` [PATCH 5/5] Added backwards iterator to tags Ruben Pollan
6 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-20 10:23 UTC (permalink / raw)
To: notmuch
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
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 5/5] Added backwards iterator to tags
2010-03-09 17:36 ` Carl Worth
` (5 preceding siblings ...)
2010-03-20 10:23 ` [PATCH 4/5] Added backwards iterator to threads Ruben Pollan
@ 2010-03-20 10:23 ` Ruben Pollan
6 siblings, 0 replies; 34+ messages in thread
From: Ruben Pollan @ 2010-03-20 10:23 UTC (permalink / raw)
To: notmuch
Added the functions notmuch_tags_move_to_prevoius,
notmuch_tags_move_to_last and notmuch_tags_move_to_first to notmuch
library. With them is possible to iterate backwards on tags.
* notmuch_tags_move_to_prevoius do the opposite than
notmuch_tags_move_to_next, getting the tags iterator one
position backwards.
* notmuch_tags_move_to_last move the iterator to the first last tag.
* notmuch_tags_move_to_first move the iterator to the first valid tag.
---
lib/notmuch.h | 28 ++++++++++++++++++++++++++++
lib/tags.c | 21 +++++++++++++++++++++
2 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/lib/notmuch.h b/lib/notmuch.h
index b96b624..dc668dc 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -1022,6 +1022,15 @@ notmuch_tags_valid (notmuch_tags_t *tags);
const char *
notmuch_tags_get (notmuch_tags_t *tags);
+/* Move the 'tags' iterator to the first tag.
+ *
+ * After that the 'tags' iterator will be set to the first valid
+ * tag, so it can be use to iterate with
+ * notmuch_tags_move_to_next.
+ */
+void
+notmuch_tags_move_to_first (notmuch_tags_t *tags);
+
/* Move the 'tags' iterator to the next tag.
*
* If 'tags' is already pointing at the last tag then the iterator
@@ -1035,6 +1044,25 @@ notmuch_tags_get (notmuch_tags_t *tags);
void
notmuch_tags_move_to_next (notmuch_tags_t *tags);
+/* Move the 'tags' iterator to the last tag.
+ *
+ * After that the 'tags' iterator will be set to the last valid
+ * tag, so it can be use to iterate with
+ * notmuch_tags_move_to_previous.
+ */
+void
+notmuch_tags_move_to_last (notmuch_tags_t *tags);
+
+/* Move the 'tags' iterator to the previous tag.
+ *
+ * If 'tags' is already pointing at the first tag then the
+ * iterator will be moved to a point just beyond that first tag,
+ * (where notmuch_tags_valid will return FALSE and
+ * notmuch_tags_get will return NULL).
+ */
+void
+notmuch_tags_move_to_previous (notmuch_tags_t *tags);
+
/* Destroy a notmuch_tags_t object.
*
* It's not strictly necessary to call this function. All memory from
diff --git a/lib/tags.c b/lib/tags.c
index 8fe4a3f..9c9a897 100644
--- a/lib/tags.c
+++ b/lib/tags.c
@@ -105,6 +105,12 @@ notmuch_tags_get (notmuch_tags_t *tags)
}
void
+notmuch_tags_move_to_first (notmuch_tags_t *tags)
+{
+ tags->iterator = g_list_first (tags->tags);
+}
+
+void
notmuch_tags_move_to_next (notmuch_tags_t *tags)
{
if (tags->iterator == NULL)
@@ -114,6 +120,21 @@ notmuch_tags_move_to_next (notmuch_tags_t *tags)
}
void
+notmuch_tags_move_to_last (notmuch_tags_t *tags)
+{
+ tags->iterator = g_list_last (tags->tags);
+}
+
+void
+notmuch_tags_move_to_previous (notmuch_tags_t *tags)
+{
+ if (tags->iterator == NULL)
+ return;
+
+ tags->iterator = tags->iterator->prev;
+}
+
+void
notmuch_tags_destroy (notmuch_tags_t *tags)
{
talloc_free (tags);
--
1.7.0
^ permalink raw reply related [flat|nested] 34+ messages in thread