ruby: Kill garbage collection related cruft.
[notmuch] / bindings / ruby / message.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 /*
24  * call-seq: MESSAGE.destroy => nil
25  *
26  * Destroys the message, freeing all resources allocated for it.
27  */
28 VALUE
29 notmuch_rb_message_destroy(VALUE self)
30 {
31     notmuch_message_t *message;
32
33     Data_Get_Struct(self, notmuch_message_t, message);
34
35     notmuch_message_destroy(message);
36
37     return Qnil;
38 }
39
40 /*
41  * call-seq: MESSAGE.message_id => String
42  *
43  * Get the message ID of 'message'.
44  */
45 VALUE
46 notmuch_rb_message_get_message_id(VALUE self)
47 {
48     const char *msgid;
49     notmuch_message_t *message;
50
51     Data_Get_Struct(self, notmuch_message_t, message);
52
53     msgid = notmuch_message_get_message_id(message);
54
55     return rb_str_new2(msgid);
56 }
57
58 /*
59  * call-seq: MESSAGE.thread_id => String
60  *
61  * Get the thread ID of 'message'.
62  */
63 VALUE
64 notmuch_rb_message_get_thread_id(VALUE self)
65 {
66     const char *tid;
67     notmuch_message_t *message;
68
69     Data_Get_Struct(self, notmuch_message_t, message);
70
71     tid = notmuch_message_get_thread_id(message);
72
73     return rb_str_new2(tid);
74 }
75
76 /*
77  * call-seq: MESSAGE.replies => MESSAGES
78  *
79  * Get a Notmuch::Messages enumerable for all of the replies to 'message'.
80  */
81 VALUE
82 notmuch_rb_message_get_replies(VALUE self)
83 {
84     notmuch_messages_t *messages;
85     notmuch_message_t *message;
86
87     Data_Get_Struct(self, notmuch_message_t, message);
88
89     messages = notmuch_message_get_replies(message);
90
91     return Data_Wrap_Struct(notmuch_rb_cMessages, NULL, NULL, messages);
92 }
93
94 /*
95  * call-seq: MESSAGE.filename => String
96  *
97  * Get a filename for the email corresponding to 'message'
98  */
99 VALUE
100 notmuch_rb_message_get_filename(VALUE self)
101 {
102     const char *fname;
103     notmuch_message_t *message;
104
105     Data_Get_Struct(self, notmuch_message_t, message);
106
107     fname = notmuch_message_get_filename(message);
108
109     return rb_str_new2(fname);
110 }
111
112 /*
113  * call-seq: MESSAGE.get_flag(flag) => true or false
114  *
115  * Get a value of a flag for the email corresponding to 'message'
116  */
117 VALUE
118 notmuch_rb_message_get_flag(VALUE self, VALUE flagv)
119 {
120     notmuch_message_t *message;
121
122     Data_Get_Struct(self, notmuch_message_t, message);
123
124     if (!FIXNUM_P(flagv))
125         rb_raise(rb_eTypeError, "Flag not a Fixnum");
126
127     return notmuch_message_get_flag(message, FIX2INT(flagv)) ? Qtrue : Qfalse;
128 }
129
130 /*
131  * call-seq: MESSAGE.set_flag(flag, value) => nil
132  *
133  * Set a value of a flag for the email corresponding to 'message'
134  */
135 VALUE
136 notmuch_rb_message_set_flag(VALUE self, VALUE flagv, VALUE valuev)
137 {
138     notmuch_message_t *message;
139
140     Data_Get_Struct(self, notmuch_message_t, message);
141
142     if (!FIXNUM_P(flagv))
143         rb_raise(rb_eTypeError, "Flag not a Fixnum");
144
145     notmuch_message_set_flag(message, FIX2INT(flagv), RTEST(valuev));
146
147     return Qnil;
148 }
149
150 /*
151  * call-seq: MESSAGE.date => Fixnum
152  *
153  * Get the date of 'message'
154  */
155 VALUE
156 notmuch_rb_message_get_date(VALUE self)
157 {
158     notmuch_message_t *message;
159
160     Data_Get_Struct(self, notmuch_message_t, message);
161
162     return UINT2NUM(notmuch_message_get_date(message));
163 }
164
165 /*
166  * call-seq: MESSAGE.header(name) => String
167  *
168  * Get the value of the specified header from 'message'
169  */
170 VALUE
171 notmuch_rb_message_get_header(VALUE self, VALUE headerv)
172 {
173     const char *header, *value;
174     notmuch_message_t *message;
175
176     Data_Get_Struct(self, notmuch_message_t, message);
177
178 #if !defined(RSTRING_PTR)
179 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
180 #endif /* !defined(RSTRING_PTR) */
181
182     SafeStringValue(headerv);
183     header = RSTRING_PTR(headerv);
184
185     value = notmuch_message_get_header(message, header);
186     if (!value)
187         rb_raise(notmuch_rb_eMemoryError, "Out of memory");
188
189     return rb_str_new2(value);
190 }
191
192 /*
193  * call-seq: MESSAGE.tags => TAGS
194  *
195  * Get a Notmuch::Tags enumerable for all of the tags of 'message'.
196  */
197 VALUE
198 notmuch_rb_message_get_tags(VALUE self)
199 {
200     notmuch_message_t *message;
201     notmuch_tags_t *tags;
202
203     Data_Get_Struct(self, notmuch_message_t, message);
204
205     tags = notmuch_message_get_tags(message);
206     if (!tags)
207         rb_raise(notmuch_rb_eMemoryError, "Out of memory");
208
209     return Data_Wrap_Struct(notmuch_rb_cTags, NULL, NULL, tags);
210 }
211
212 /*
213  * call-seq: MESSAGE.add_tag(tag) => true
214  *
215  * Add a tag to the 'message'
216  */
217 VALUE
218 notmuch_rb_message_add_tag(VALUE self, VALUE tagv)
219 {
220     const char *tag;
221     notmuch_status_t ret;
222     notmuch_message_t *message;
223
224     Data_Get_Struct(self, notmuch_message_t, message);
225
226 #if !defined(RSTRING_PTR)
227 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
228 #endif /* !defined(RSTRING_PTR) */
229
230     SafeStringValue(tagv);
231     tag = RSTRING_PTR(tagv);
232
233     ret = notmuch_message_add_tag(message, tag);
234     notmuch_rb_status_raise(ret);
235
236     return Qtrue;
237 }
238
239 /*
240  * call-seq: MESSAGE.remove_tag(tag) => true
241  *
242  * Remove a tag from the 'message'
243  */
244 VALUE
245 notmuch_rb_message_remove_tag(VALUE self, VALUE tagv)
246 {
247     const char *tag;
248     notmuch_status_t ret;
249     notmuch_message_t *message;
250
251     Data_Get_Struct(self, notmuch_message_t, message);
252
253 #if !defined(RSTRING_PTR)
254 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
255 #endif /* !defined(RSTRING_PTR) */
256
257     SafeStringValue(tagv);
258     tag = RSTRING_PTR(tagv);
259
260     ret = notmuch_message_remove_tag(message, tag);
261     notmuch_rb_status_raise(ret);
262
263     return Qtrue;
264 }
265
266 /*
267  * call-seq: MESSAGE.remove_all_tags => true
268  *
269  * Remove all tags of the 'message'
270  */
271 VALUE
272 notmuch_rb_message_remove_all_tags(VALUE self)
273 {
274     notmuch_status_t ret;
275     notmuch_message_t *message;
276
277     Data_Get_Struct(self, notmuch_message_t, message);
278
279     ret = notmuch_message_remove_all_tags(message);
280     notmuch_rb_status_raise(ret);
281
282     return Qtrue;
283 }
284
285 /*
286  * call-seq: MESSAGE.freeze => true
287  *
288  * Freeze the 'message'
289  */
290 VALUE
291 notmuch_rb_message_freeze(VALUE self)
292 {
293     notmuch_status_t ret;
294     notmuch_message_t *message;
295
296     Data_Get_Struct(self, notmuch_message_t, message);
297
298     ret = notmuch_message_freeze(message);
299     notmuch_rb_status_raise(ret);
300
301     return Qtrue;
302 }
303
304 /*
305  * call-seq: MESSAGE.thaw => true
306  *
307  * Thaw a 'message'
308  */
309 VALUE
310 notmuch_rb_message_thaw(VALUE self)
311 {
312     notmuch_status_t ret;
313     notmuch_message_t *message;
314
315     Data_Get_Struct(self, notmuch_message_t, message);
316
317     ret = notmuch_message_thaw(message);
318     notmuch_rb_status_raise(ret);
319
320     return Qtrue;
321 }