Rename our talloc destructor functions to _destructor.
[notmuch] / message.cc
1 /* message.cc - Results of message-based searches from a notmuch database
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 #include "database-private.h"
23
24 #include <xapian.h>
25
26 struct _notmuch_message {
27     Xapian::Document doc;
28 };
29
30 struct _notmuch_tags {
31     Xapian::TermIterator iterator;
32     Xapian::TermIterator iterator_end;
33 };
34
35 /* We end up having to call the destructor explicitly because we had
36  * to use "placement new" in order to initialize C++ objects within a
37  * block that we allocated with talloc. So C++ is making talloc
38  * slightly less simple to use, (we wouldn't need
39  * talloc_set_destructor at all otherwise).
40  */
41 static int
42 _notmuch_message_destructor (notmuch_message_t *message)
43 {
44     message->doc.~Document ();
45
46     return 0;
47 }
48
49 notmuch_message_t *
50 _notmuch_message_create (notmuch_results_t *owner,
51                          notmuch_database_t *notmuch,
52                          Xapian::docid doc_id)
53 {
54     notmuch_message_t *message;
55
56     message = talloc (owner, notmuch_message_t);
57     if (unlikely (message == NULL))
58         return NULL;
59
60     new (&message->doc) Xapian::Document;
61
62     talloc_set_destructor (message, _notmuch_message_destructor);
63
64     message->doc = notmuch->xapian_db->get_document (doc_id);
65
66     return message;
67 }
68
69 const char *
70 notmuch_message_get_message_id (notmuch_message_t *message)
71 {
72     Xapian::TermIterator i;
73
74     i = message->doc.termlist_begin ();
75     i.skip_to ("Q");
76     if (i != message->doc.termlist_end ())
77         return talloc_strdup (message, (*i).c_str () + 1);
78     else
79         return NULL;
80 }
81
82 /* We end up having to call the destructors explicitly because we had
83  * to use "placement new" in order to initialize C++ objects within a
84  * block that we allocated with talloc. So C++ is making talloc
85  * slightly less simple to use, (we wouldn't need
86  * talloc_set_destructor at all otherwise).
87  */
88 static int
89 _notmuch_tags_destructor (notmuch_tags_t *tags)
90 {
91     tags->iterator.~TermIterator ();
92     tags->iterator_end.~TermIterator ();
93
94     return 0;
95 }
96
97 notmuch_tags_t *
98 notmuch_message_get_tags (notmuch_message_t *message)
99 {
100     notmuch_tags_t *tags;
101
102     tags = talloc (message, notmuch_tags_t);
103     if (unlikely (tags == NULL))
104         return NULL;
105
106     new (&tags->iterator) Xapian::TermIterator;
107     new (&tags->iterator_end) Xapian::TermIterator;
108
109     talloc_set_destructor (tags, _notmuch_tags_destructor);
110
111     tags->iterator = message->doc.termlist_begin ();
112     tags->iterator.skip_to ("L");
113     tags->iterator_end = message->doc.termlist_end ();
114
115     return tags;
116 }
117
118 notmuch_bool_t
119 notmuch_tags_has_more (notmuch_tags_t *tags)
120 {
121     std::string s;
122
123     if (tags->iterator == tags->iterator_end)
124         return FALSE;
125
126     s = *tags->iterator;
127     if (s.size () && s[0] == 'L')
128         return TRUE;
129     else
130         return FALSE;
131 }
132
133 const char *
134 notmuch_tags_get (notmuch_tags_t *tags)
135 {
136     return talloc_strdup (tags, (*tags->iterator).c_str () + 1);
137 }
138
139 void
140 notmuch_tags_advance (notmuch_tags_t *tags)
141 {
142     tags->iterator++;
143 }