Fixes FWNULL 1/16 & 2/16
[modest] / src / modest-protocol.c
1 /* Copyright (c) 2008, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <modest-protocol.h>
31
32 enum {
33         PROP_0,
34         PROP_NAME,
35         PROP_DISPLAY_NAME,
36         PROP_TYPE_ID
37 };
38
39 typedef struct _ModestProtocolTranslation ModestProtocolTranslation;
40 struct _ModestProtocolTranslation {
41         TranslationFunc translation_func;
42         gpointer userdata;
43         GDestroyNotify data_destroy_func;
44 };
45
46 typedef struct _ModestProtocolPrivate ModestProtocolPrivate;
47 struct _ModestProtocolPrivate {
48         ModestProtocolType type_id;
49         gchar *name;
50         gchar *display_name;
51         GHashTable *properties;
52         GHashTable *translations;
53 };
54
55 /* 'private'/'protected' functions */
56 static void   modest_protocol_class_init (ModestProtocolClass *klass);
57 static void   modest_protocol_finalize   (GObject *obj);
58 static void   modest_protocol_get_property (GObject *obj,
59                                             guint property_id,
60                                             GValue *value,
61                                             GParamSpec *pspec);
62 static void   modest_protocol_set_property (GObject *obj,
63                                             guint property_id,
64                                             const GValue *value,
65                                             GParamSpec *pspec);
66 static void   modest_protocol_instance_init (ModestProtocol *obj);
67 static void   translation_free (ModestProtocolTranslation *translation);
68
69 #define MODEST_PROTOCOL_GET_PRIVATE(o)     (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
70                                                                          MODEST_TYPE_PROTOCOL, \
71                                                                          ModestProtocolPrivate))
72
73 /* globals */
74 static GObjectClass *parent_class = NULL;
75 static ModestProtocolType next_type_id = 0;
76 static GMutex *next_type_id_mutex = NULL;
77
78 GType
79 modest_protocol_get_type (void)
80 {
81         static GType my_type = 0;
82
83         if (!my_type) {
84                 static const GTypeInfo my_info = {
85                         sizeof(ModestProtocolClass),
86                         NULL,   /* base init */
87                         NULL,   /* base finalize */
88                         (GClassInitFunc) modest_protocol_class_init,
89                         NULL,   /* class finalize */
90                         NULL,   /* class data */
91                         sizeof(ModestProtocol),
92                         0,      /* n_preallocs */
93                         (GInstanceInitFunc) modest_protocol_instance_init,
94                         NULL
95                 };
96
97                 my_type = g_type_register_static (G_TYPE_OBJECT,
98                                                   "ModestProtocol",
99                                                   &my_info, 0);
100         }
101         return my_type;
102 }
103
104 static void
105 modest_protocol_class_init (ModestProtocolClass *klass)
106 {
107         GObjectClass *object_class;
108         object_class = (GObjectClass *) klass;
109
110         parent_class = g_type_class_peek_parent (klass);
111         next_type_id_mutex = g_mutex_new ();
112         object_class->finalize = modest_protocol_finalize;
113         object_class->set_property = modest_protocol_set_property;
114         object_class->get_property = modest_protocol_get_property;
115
116         g_object_class_install_property (object_class,
117                                          PROP_NAME,
118                                          g_param_spec_string ("name",
119                                                               _("Protocol name"),
120                                                               _("The unique name of the protocol"),
121                                                               NULL,
122                                                               G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
123
124         g_object_class_install_property (object_class,
125                                          PROP_DISPLAY_NAME,
126                                          g_param_spec_string ("display-name",
127                                                                _("Display name"),
128                                                                _("The name of the protocol that user will see"),
129                                                                NULL,
130                                                                G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
131
132         g_object_class_install_property (object_class,
133                                          PROP_TYPE_ID,
134                                          g_param_spec_int ("type",
135                                                            _("Protocol id"),
136                                                            _("Protocol type unique id"),
137                                                            G_MININT, G_MAXINT, MODEST_PROTOCOL_TYPE_INVALID,
138                                                            G_PARAM_READABLE));
139
140         g_type_class_add_private (object_class,
141                                   sizeof(ModestProtocolPrivate));
142 }
143
144 static void
145 translation_free (ModestProtocolTranslation *translation)
146 {
147         if (translation->data_destroy_func)
148                 translation->data_destroy_func (translation->userdata);
149         translation->data_destroy_func = NULL;
150         translation->userdata = NULL;
151         translation->translation_func = NULL;
152         g_slice_free (ModestProtocolTranslation, translation);
153 }
154
155 static void
156 modest_protocol_instance_init (ModestProtocol *obj)
157 {
158         ModestProtocolPrivate *priv;
159
160         priv = MODEST_PROTOCOL_GET_PRIVATE (obj);
161
162         priv->name = NULL;
163         priv->display_name = NULL;
164         g_mutex_lock (next_type_id_mutex);
165         priv->type_id = next_type_id;
166         next_type_id++;
167         g_mutex_unlock (next_type_id_mutex);
168
169         priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
170                                                   g_free, g_free);
171         priv->translations = g_hash_table_new_full (g_str_hash, g_str_equal,
172                                                     g_free, (GDestroyNotify) translation_free);
173 }
174
175 static void   
176 modest_protocol_finalize   (GObject *obj)
177 {
178         ModestProtocol *settings = MODEST_PROTOCOL (obj);
179         ModestProtocolPrivate *priv = MODEST_PROTOCOL_GET_PRIVATE (settings);
180
181         g_free (priv->name);
182         priv->name = NULL;
183         g_free (priv->display_name);
184         priv->display_name = NULL;
185
186         g_hash_table_unref (priv->properties);
187         priv->properties = NULL;
188
189         g_hash_table_unref (priv->translations);
190         priv->translations = NULL;
191
192         G_OBJECT_CLASS (parent_class)->finalize (obj);
193 }
194
195 static void   
196 modest_protocol_get_property (GObject *obj,
197                               guint property_id,
198                               GValue *value,
199                               GParamSpec *pspec)
200 {
201         ModestProtocol *protocol = MODEST_PROTOCOL (obj);
202         ModestProtocolPrivate *priv = MODEST_PROTOCOL_GET_PRIVATE (protocol);
203
204         switch (property_id) {
205         case PROP_NAME:
206                 g_value_set_static_string (value, priv->name);
207                 break;
208         case PROP_DISPLAY_NAME:
209                 g_value_set_static_string (value, priv->name);
210                 break;
211         case PROP_TYPE_ID:
212                 g_value_set_int (value, priv->type_id);
213                 break;
214         default:
215                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
216         }
217
218 }
219
220 static void   
221 modest_protocol_set_property (GObject *obj,
222                               guint property_id,
223                               const GValue *value,
224                               GParamSpec *pspec)
225 {
226         ModestProtocol *protocol = MODEST_PROTOCOL (obj);
227
228         switch (property_id) {
229         case PROP_NAME:
230                 modest_protocol_set_name (protocol, g_value_get_string (value));
231                 break;
232         case PROP_DISPLAY_NAME:
233                 modest_protocol_set_display_name (protocol, g_value_get_string (value));
234                 break;
235         default:
236                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
237         }
238
239 }
240
241
242 ModestProtocol*
243 modest_protocol_new (const gchar *name, const gchar *display_name)
244 {
245         return g_object_new (MODEST_TYPE_PROTOCOL, "display-name", display_name, "name", name, NULL);
246 }
247
248 const gchar* 
249 modest_protocol_get_name (ModestProtocol *self)
250 {
251         ModestProtocolPrivate *priv;
252
253         g_return_val_if_fail (MODEST_IS_PROTOCOL (self), NULL);
254
255         priv = MODEST_PROTOCOL_GET_PRIVATE (self);      
256         return priv->name;
257 }
258
259 void         
260 modest_protocol_set_name (ModestProtocol *self,
261                           const gchar *name)
262 {
263         ModestProtocolPrivate *priv;
264
265         g_return_if_fail (MODEST_IS_PROTOCOL (self));
266
267         priv = MODEST_PROTOCOL_GET_PRIVATE (self);
268         g_free (priv->name);
269         priv->name = g_strdup (name);
270 }
271
272 const gchar* 
273 modest_protocol_get_display_name (ModestProtocol *self)
274 {
275         ModestProtocolPrivate *priv;
276
277         g_return_val_if_fail (MODEST_IS_PROTOCOL (self), NULL);
278
279         priv = MODEST_PROTOCOL_GET_PRIVATE (self);      
280         return priv->display_name;
281 }
282
283 void         
284 modest_protocol_set_display_name (ModestProtocol *self,
285                                   const gchar *display_name)
286 {
287         ModestProtocolPrivate *priv;
288
289         g_return_if_fail (MODEST_IS_PROTOCOL (self));
290
291         priv = MODEST_PROTOCOL_GET_PRIVATE (self);
292         g_free (priv->display_name);
293         priv->display_name = g_strdup (display_name);
294 }
295
296 ModestProtocolType  
297 modest_protocol_get_type_id (ModestProtocol *self)
298 {
299         ModestProtocolPrivate *priv;
300
301         g_return_val_if_fail (MODEST_IS_PROTOCOL (self), MODEST_PROTOCOL_TYPE_INVALID);
302
303         priv = MODEST_PROTOCOL_GET_PRIVATE (self);
304         return priv->type_id;
305 }
306
307 void
308 modest_protocol_set (ModestProtocol *self,
309                      const gchar *key, 
310                      const gchar *value)
311 {
312         ModestProtocolPrivate *priv;
313
314         g_return_if_fail (MODEST_IS_PROTOCOL (self));
315
316         priv = MODEST_PROTOCOL_GET_PRIVATE (self);
317
318         g_hash_table_replace (priv->properties,g_strdup (key), g_strdup (value));
319 }
320
321 const gchar *
322 modest_protocol_get (ModestProtocol *self,
323                      const gchar *key)
324 {
325         ModestProtocolPrivate *priv;
326
327         g_return_val_if_fail (MODEST_IS_PROTOCOL (self), NULL);
328
329         priv = MODEST_PROTOCOL_GET_PRIVATE (self);
330
331         return g_hash_table_lookup (priv->properties, key);
332 }
333
334 void
335 modest_protocol_set_translation (ModestProtocol *self,
336                                  const gchar *id,
337                                  TranslationFunc translation_func,
338                                  gpointer userdata,
339                                  GDestroyNotify data_destroy_func)
340 {
341         ModestProtocolPrivate *priv;
342         ModestProtocolTranslation *translation;
343
344         g_return_if_fail (MODEST_IS_PROTOCOL (self));
345
346         priv = MODEST_PROTOCOL_GET_PRIVATE (self);
347
348         translation = g_slice_new0 (ModestProtocolTranslation);
349         translation->translation_func = translation_func;
350         translation->userdata = userdata;
351         translation->data_destroy_func = data_destroy_func;
352
353         g_hash_table_replace (priv->translations, g_strdup(id), (gpointer) translation);
354 }
355
356 gchar *
357 modest_protocol_get_translation (ModestProtocol *self,
358                                  const gchar *id,
359                                  ...)
360 {
361         va_list args;
362         gchar *result;
363
364         g_return_val_if_fail (MODEST_IS_PROTOCOL (self), NULL);
365
366         va_start (args, id);
367         result = modest_protocol_va_get_translation (self, id, args);
368         va_end (args);
369
370         return result;
371 }
372
373 gchar *
374 modest_protocol_va_get_translation (ModestProtocol *self,
375                                     const gchar *id,
376                                     va_list args)
377 {
378         ModestProtocolPrivate *priv;
379         ModestProtocolTranslation *translation;
380         va_list dest;
381         gchar *result;
382
383         g_return_val_if_fail (MODEST_IS_PROTOCOL (self), NULL);
384
385         priv = MODEST_PROTOCOL_GET_PRIVATE (self);
386
387         translation = g_hash_table_lookup (priv->translations, id);
388         if (translation == NULL)
389                 return NULL;
390         g_return_val_if_fail (translation->translation_func != NULL, NULL);
391
392         G_VA_COPY (dest, args);
393         result = translation->translation_func (translation->userdata, dest);
394         va_end (dest);
395
396         return result;
397 }