lib/messages.c: Make message searches stream as well.
[notmuch] / lib / messages.c
1 /* messages.c - Iterator for a set of messages
2  *
3  * Copyright © 2009 Carl Worth
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see http://www.gnu.org/licenses/ .
17  *
18  * Author: Carl Worth <cworth@cworth.org>
19  */
20
21 #include "notmuch-private.h"
22
23 /* Create a new notmuch_message_list_t object, with 'ctx' as its
24  * talloc owner.
25  *
26  * This function can return NULL in case of out-of-memory.
27  */
28 notmuch_message_list_t *
29 _notmuch_message_list_create (const void *ctx)
30 {
31     notmuch_message_list_t *list;
32
33     list = talloc (ctx, notmuch_message_list_t);
34     if (unlikely (list == NULL))
35         return NULL;
36
37     list->head = NULL;
38     list->tail = &list->head;
39
40     return list;
41 }
42
43 /* Append 'node' (which can of course point to an arbitrarily long
44  * list of nodes) to the end of 'list'.
45  */
46 void
47 _notmuch_message_list_append (notmuch_message_list_t *list,
48                               notmuch_message_node_t *node)
49 {
50     *(list->tail) = node;
51     list->tail = &node->next;
52 }
53
54 /* Allocate a new node for 'message' and append it to the end of
55  * 'list'.
56  */
57 void
58 _notmuch_message_list_add_message (notmuch_message_list_t *list,
59                                    notmuch_message_t *message)
60 {
61     notmuch_message_node_t *node = talloc (list, notmuch_message_node_t);
62
63     node->message = message;
64     node->next = NULL;
65
66     _notmuch_message_list_append (list, node);
67 }
68
69 notmuch_messages_t *
70 _notmuch_messages_create (notmuch_message_list_t *list)
71 {
72     notmuch_messages_t *messages;
73
74     if (list->head == NULL)
75         return NULL;
76
77     messages = talloc (list, notmuch_messages_t);
78     if (unlikely (messages == NULL))
79         return NULL;
80
81     messages->is_of_list_type = TRUE;
82     messages->iterator = list->head;
83
84     return messages;
85 }
86
87 /* We're using the "is_of_type_list" to conditionally defer to the
88  * notmuch_mset_messages_t implementation of notmuch_messages_t in
89  * query.cc. It's ugly that that's over in query.cc, and it's ugly
90  * that we're not using a union here. Both of those uglies are due to
91  * C++:
92  *
93  *      1. I didn't want to force a C++ header file onto
94  *         notmuch-private.h and suddenly subject all our code to a
95  *         C++ compiler and its rules.
96  *
97  *      2. C++ won't allow me to put C++ objects, (with non-trivial
98  *         constructors) into a union anyway. Even though I'd
99  *         carefully control object construction with placement new
100  *         anyway. *sigh*
101  */
102 notmuch_bool_t
103 notmuch_messages_has_more (notmuch_messages_t *messages)
104 {
105     if (messages == NULL)
106         return FALSE;
107
108     if (! messages->is_of_list_type)
109         return _notmuch_mset_messages_has_more (messages);
110
111     return (messages->iterator != NULL);
112 }
113
114 notmuch_message_t *
115 notmuch_messages_get (notmuch_messages_t *messages)
116 {
117     if (! messages->is_of_list_type)
118         return _notmuch_mset_messages_get (messages);
119
120     if (messages->iterator == NULL)
121         return NULL;
122
123     return messages->iterator->message;
124 }
125
126 void
127 notmuch_messages_advance (notmuch_messages_t *messages)
128 {
129     if (! messages->is_of_list_type)
130         return _notmuch_mset_messages_advance (messages);
131
132     if (messages->iterator == NULL)
133         return;
134
135     messages->iterator = messages->iterator->next;
136 }
137
138 void
139 notmuch_messages_destroy (notmuch_messages_t *messages)
140 {
141     talloc_free (messages);
142 }