ruby: First attempt at fixing gc for ruby-1.9
[notmuch] / bindings / ruby / gc.c
1 /* The Ruby interface to the notmuch mail library
2  *
3  * Copyright © 2010 Ali Polatel
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: Ali Polatel <alip@exherbo.org>
19  */
20
21 #include "defs.h"
22
23 #include <stdlib.h>
24
25 static notmuch_rb_database_t *
26 _notmuch_rb_messages_db(notmuch_rb_messages_t *messages);
27
28 static notmuch_rb_database_t *
29 _notmuch_rb_message_db(notmuch_rb_message_t *message)
30 {
31     notmuch_rb_messages_t *messages;
32     notmuch_rb_database_t *db;
33
34     if (rb_obj_is_instance_of(message->parent, notmuch_rb_cDatabase)) {
35         Data_Get_Struct(message->parent, notmuch_rb_database_t, db);
36     }
37     else if (rb_obj_is_instance_of(message->parent, notmuch_rb_cMessages)) {
38         Data_Get_Struct(message->parent, notmuch_rb_messages_t, messages);
39         db = _notmuch_rb_messages_db(messages);
40     }
41     else
42         db = NULL;
43
44     return db;
45 }
46
47 static notmuch_rb_database_t *
48 _notmuch_rb_messages_db(notmuch_rb_messages_t *messages)
49 {
50     notmuch_rb_query_t *query;
51     notmuch_rb_thread_t *thread;
52     notmuch_rb_message_t *message;
53     notmuch_rb_threads_t *threads;
54     notmuch_rb_database_t *db;
55
56     if (rb_obj_is_instance_of(messages->parent, notmuch_rb_cQuery)) {
57         Data_Get_Struct(messages->parent, notmuch_rb_query_t, query);
58         Data_Get_Struct(query->db, notmuch_rb_database_t, db);
59     }
60     else if (rb_obj_is_instance_of(messages->parent, notmuch_rb_cThread)) {
61         Data_Get_Struct(messages->parent, notmuch_rb_thread_t, thread);
62         Data_Get_Struct(thread->threads, notmuch_rb_threads_t, threads);
63         Data_Get_Struct(threads->query, notmuch_rb_query_t, query);
64         Data_Get_Struct(query->db, notmuch_rb_database_t, db);
65     }
66     else if (rb_obj_is_instance_of(messages->parent, notmuch_rb_cMessage)) {
67         Data_Get_Struct(messages->parent, notmuch_rb_message_t, message);
68         db = _notmuch_rb_message_db(message);
69     }
70     else
71         db = NULL;
72
73     return db;
74 }
75
76 static notmuch_rb_database_t *
77 _notmuch_rb_thread_db(notmuch_rb_thread_t *thread)
78 {
79     notmuch_rb_threads_t *threads;
80     notmuch_rb_query_t *query;
81     notmuch_rb_database_t *db;
82
83     Data_Get_Struct(thread->threads, notmuch_rb_threads_t, threads);
84     Data_Get_Struct(threads->query, notmuch_rb_query_t, query);
85     Data_Get_Struct(query->db, notmuch_rb_database_t, db);
86
87     return db;
88 }
89
90 void
91 notmuch_rb_database_free(notmuch_rb_database_t *db)
92 {
93     if (db->nm_db)
94         notmuch_database_close(db->nm_db);
95
96     free(db);
97 }
98
99 void
100 notmuch_rb_directory_mark(notmuch_rb_directory_t *dir)
101 {
102     rb_gc_mark(dir->db);
103 }
104
105 void
106 notmuch_rb_directory_free(notmuch_rb_directory_t *dir)
107 {
108     notmuch_rb_database_t *db;
109
110     if (rb_obj_is_instance_of(dir->db, notmuch_rb_cDatabase))
111         Data_Get_Struct(dir->db, notmuch_rb_database_t, db);
112     else
113         db = NULL;
114
115     if (db && db->nm_db && dir->nm_dir)
116         notmuch_directory_destroy(dir->nm_dir);
117
118     free(dir);
119 }
120
121 void
122 notmuch_rb_filenames_mark(notmuch_rb_filenames_t *flist)
123 {
124     rb_gc_mark(flist->dir);
125 }
126
127 void
128 notmuch_rb_filenames_free(notmuch_rb_filenames_t *flist)
129 {
130     notmuch_rb_directory_t *dir;
131     notmuch_rb_database_t *db;
132
133     if (rb_obj_is_instance_of(flist->dir, notmuch_rb_cDirectory)) {
134         Data_Get_Struct(flist->dir, notmuch_rb_directory_t, dir);
135         if (rb_obj_is_instance_of(dir->db, notmuch_rb_cDatabase))
136            Data_Get_Struct(dir->db, notmuch_rb_database_t, db);
137         else
138             db = NULL;
139     }
140     else
141         db = NULL;
142
143     if (db && db->nm_db && flist->nm_flist)
144         notmuch_filenames_destroy(flist->nm_flist);
145
146     free(flist);
147 }
148
149 void
150 notmuch_rb_query_mark(notmuch_rb_query_t *query)
151 {
152     rb_gc_mark(query->db);
153 }
154
155 void
156 notmuch_rb_query_free(notmuch_rb_query_t *query)
157 {
158     notmuch_rb_database_t *db;
159
160     if (rb_obj_is_instance_of(query->db, notmuch_rb_cDatabase))
161         Data_Get_Struct(query->db, notmuch_rb_database_t, db);
162     else
163         db = NULL;
164
165     if (db && db->nm_db && query->nm_query)
166         notmuch_query_destroy(query->nm_query);
167
168     free(query);
169 }
170
171 void
172 notmuch_rb_threads_mark(notmuch_rb_threads_t *threads)
173 {
174     rb_gc_mark(threads->query);
175 }
176
177 void
178 notmuch_rb_threads_free(notmuch_rb_threads_t *threads)
179 {
180     notmuch_rb_query_t *query;
181     notmuch_rb_database_t *db;
182
183     if (rb_obj_is_instance_of(threads->query, notmuch_rb_cQuery)) {
184         Data_Get_Struct(threads->query, notmuch_rb_query_t, query);
185         if (rb_obj_is_instance_of(query->db, notmuch_rb_cDatabase))
186             Data_Get_Struct(query->db, notmuch_rb_database_t, db);
187         else
188             db = NULL;
189     }
190     else
191         db = NULL;
192
193     if (db && db->nm_db && threads->nm_threads)
194         notmuch_threads_destroy(threads->nm_threads);
195
196     free(threads);
197 }
198
199 void
200 notmuch_rb_messages_mark(notmuch_rb_messages_t *messages)
201 {
202     rb_gc_mark(messages->parent);
203 }
204
205 void
206 notmuch_rb_messages_free(notmuch_rb_messages_t *messages)
207 {
208     notmuch_rb_database_t *db;
209
210     db = _notmuch_rb_messages_db(messages);
211
212     if (db && db->nm_db && messages->nm_messages)
213         notmuch_messages_destroy(messages->nm_messages);
214
215     free(messages);
216 }
217
218 void
219 notmuch_rb_thread_mark(notmuch_rb_thread_t *thread)
220 {
221     rb_gc_mark(thread->threads);
222 }
223
224 void
225 notmuch_rb_thread_free(notmuch_rb_thread_t *thread)
226 {
227     notmuch_rb_database_t *db;
228
229     db = _notmuch_rb_thread_db(thread);
230
231     if (db && db->nm_db && thread->nm_thread)
232         notmuch_thread_destroy(thread->nm_thread);
233
234     free(thread);
235 }
236
237 void
238 notmuch_rb_message_mark(notmuch_rb_message_t *message)
239 {
240     rb_gc_mark(message->parent);
241 }
242
243 void
244 notmuch_rb_message_free(notmuch_rb_message_t *message)
245 {
246     notmuch_rb_database_t *db;
247
248     db = _notmuch_rb_message_db(message);
249     if (db && db->nm_db && message->nm_message)
250         notmuch_message_destroy(message->nm_message);
251
252     free(message);
253 }
254
255 void
256 notmuch_rb_tags_mark(notmuch_rb_tags_t *tags)
257 {
258     rb_gc_mark(tags->parent);
259 }
260
261 void
262 notmuch_rb_tags_free(notmuch_rb_tags_t *tags)
263 {
264     notmuch_rb_message_t *message;
265     notmuch_rb_messages_t *messages;
266     notmuch_rb_thread_t *thread;
267     notmuch_rb_database_t *db;
268
269     if (rb_obj_is_instance_of(tags->parent, notmuch_rb_cThread)) {
270         Data_Get_Struct(tags->parent, notmuch_rb_thread_t, thread);
271         db = _notmuch_rb_thread_db(thread);
272     }
273     else if (rb_obj_is_instance_of(tags->parent, notmuch_rb_cMessage)) {
274         Data_Get_Struct(tags->parent, notmuch_rb_message_t, message);
275         db = _notmuch_rb_message_db(message);
276     }
277     else if (rb_obj_is_instance_of(tags->parent, notmuch_rb_cMessages)) {
278         Data_Get_Struct(tags->parent, notmuch_rb_messages_t, messages);
279         db = _notmuch_rb_messages_db(messages);
280     }
281     else
282         return;
283
284     if (db && db->nm_db && tags->nm_tags)
285         notmuch_tags_destroy(tags->nm_tags);
286
287     free(tags);
288 }