release tizen_2.0 beta
[framework/telephony/tel-plugin-socket_communicator.git] / common / src / sipc_marshal.c
1 /*
2  * tel-plugin-socket-communicator
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Ja-young Gu <jygu@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "sipc_common.h"
26 #include "sipc.h"
27
28 static GHashTable* _sipc_util_marshal_object_deserializer(const gchar *inparam);
29
30 struct _sipc_marshal_object {
31         GHashTable *ht;
32 };
33
34 static void _sipc_util_remove_hashtable_value(gpointer value)
35 {
36         unsigned int gtype = 0;
37         struct _sipc_marshal_object *tmp_obj = value;
38
39         gtype = ((GValue *) value)->g_type;
40         if (gtype == G_TYPE_POINTER) {
41                 tmp_obj = g_value_get_pointer(value);
42                 g_hash_table_destroy(tmp_obj->ht);
43         }
44
45         g_value_unset((GValue *) value);
46         return;
47 }
48
49 static gboolean _sipc_util_create_gvalue(GValue *value, const void *data, sipc_marshal_data_type_e type)
50 {
51
52         switch (type) {
53                 case SIPC_MARSHAL_DATA_CHAR_TYPE:
54                         g_value_init(value, type);
55                         g_value_set_char(value, *((gchar *) data));
56                         break;
57
58                 case SIPC_MARSHAL_DATA_BOOLEAN_TYPE:
59                         g_value_init(value, type);
60                         g_value_set_boolean(value, *((gboolean *) data));
61                         break;
62
63                 case SIPC_MARSHAL_DATA_INT_TYPE:
64                         g_value_init(value, type);
65                         g_value_set_int(value, *((gint *) data));
66                         break;
67
68                 case SIPC_MARSHAL_DATA_DOUBLE_TYPE:
69                         g_value_init(value, type);
70                         g_value_set_double(value, *((gdouble *) data));
71                         break;
72
73                 case SIPC_MARSHAL_DATA_STRING_TYPE:
74                         g_value_init(value, type);
75                         g_value_set_string(value, (gchar *) data);
76                         break;
77
78                 case SIPC_MARSHAL_DATA_OBJECT_TYPE:
79                         g_value_init(value, type);
80                         g_value_set_pointer(value, (gpointer) data);
81                         break;
82
83                 default:
84                         return FALSE;
85                         break;
86         }
87
88         return TRUE;
89 }
90
91 static gboolean _sipc_util_return_value(GValue *src, void **dest, sipc_marshal_data_type_e type)
92 {
93         gboolean rv = FALSE;
94         struct _sipc_marshal_object *tmp = NULL;
95
96         switch (type) {
97                 case SIPC_MARSHAL_DATA_CHAR_TYPE:
98                         *dest = g_new0(gchar, 1);
99                         *((gchar *) *dest) = g_value_get_char(src);
100                         break;
101
102                 case SIPC_MARSHAL_DATA_BOOLEAN_TYPE:
103                         *dest = g_new0(gboolean, 1);
104                         *((gboolean *) *dest) = g_value_get_boolean(src);
105                         break;
106
107                 case SIPC_MARSHAL_DATA_INT_TYPE:
108                         *dest = g_new0(gint, 1);
109                         *((gint *) *dest) = g_value_get_int(src);
110                         break;
111
112                 case SIPC_MARSHAL_DATA_DOUBLE_TYPE:
113                         *dest = g_new0(gdouble, 1);
114                         *((gdouble *) *dest) = g_value_get_double(src);
115                         break;
116
117                 case SIPC_MARSHAL_DATA_STRING_TYPE:
118                         *dest = g_value_dup_string(src);
119                         break;
120
121                 case SIPC_MARSHAL_DATA_OBJECT_TYPE:
122                         tmp = g_new0(struct _sipc_marshal_object, 1);
123                         tmp->ht = g_value_get_pointer(src);
124                         *dest = tmp;
125                         break;
126
127                 default:
128                         return FALSE;
129                         break;
130         }
131
132         return TRUE;
133 }
134
135 static gboolean _sipc_util_str_to_type(GValue *src, GValue *dest, unsigned int dest_type)
136 {
137         gboolean rv = FALSE;
138
139         if(dest_type == G_TYPE_HASH_TABLE)
140                 dest_type = G_TYPE_POINTER;
141
142         switch (dest_type) {
143                 case G_TYPE_INT: {
144                         gint64 tmp = 0;
145                         tmp = g_ascii_strtoll(g_value_get_string(src), NULL, 10);
146                         g_value_set_int(dest, tmp);
147                 }
148                         break;
149                 case G_TYPE_BOOLEAN: {
150                         gboolean tmp = FALSE;
151                         tmp = g_ascii_strncasecmp(g_value_get_string(src), "TRUE", 4) == 0 ? TRUE : FALSE;
152                         g_value_set_boolean(dest, tmp);
153                 }
154                         break;
155                 case G_TYPE_STRING: {
156                         const gchar* tmp = NULL;
157                         tmp = g_value_get_string(src);
158                         g_value_set_string(dest, tmp);
159                 }
160                         break;
161                 case G_TYPE_DOUBLE: {
162                         gdouble tmp = 0;
163                         tmp = g_ascii_strtod(g_value_get_string(src), NULL);
164                         g_value_set_double(dest, tmp);
165                 }
166                         break;
167                 case G_TYPE_POINTER:{
168                         GHashTable* tmp;
169                         tmp = _sipc_util_marshal_object_deserializer(g_value_get_string(src));
170                         g_value_set_pointer(dest, tmp);
171                 }
172                         break;
173                 default: {
174                         return FALSE;
175                 }
176                         break;
177         }
178
179         return TRUE;
180 }
181
182 static GHashTable* _sipc_util_marshal_object_deserializer(const gchar *inparam)
183 {
184         int index = 0;
185         gchar **tuple = NULL;
186         GHashTable *ht = NULL;
187
188         ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
189                         _sipc_util_remove_hashtable_value);
190
191         if (strlen(inparam) == 0) {
192                 return ht;
193         }
194
195         tuple = g_strsplit((gchar *) inparam, "/", 0);
196
197         while (strlen(tuple[index]) > 3) {
198                 int tmp = 0;
199                 gchar *content = NULL;
200                 gchar **inner_tuple = NULL;
201                 GValue *src = g_new0(GValue, 1);
202                 GValue *dest = g_new0(GValue, 1);
203                 unsigned int type = 0;
204
205                 inner_tuple = g_strsplit(tuple[index], ":", 0);
206                 type = atoi(inner_tuple[1]);
207                 content = g_base64_decode(inner_tuple[2], &tmp);
208
209                 g_value_init(src, G_TYPE_STRING);
210                 g_value_init(dest, type);
211
212                 g_value_set_string(src, content);
213                 _sipc_util_str_to_type(src, dest, type);
214                 g_hash_table_insert(ht, g_strdup(inner_tuple[0]), dest);
215
216                 g_free(content);
217                 g_strfreev(inner_tuple);
218                 index++;
219         }
220
221         g_strfreev(tuple);
222         return ht;
223 }
224
225 struct _sipc_marshal_object* sipc_util_marshal_object_create()
226 {
227         struct _sipc_marshal_object *mo = 0;
228
229         mo = g_new0( struct _sipc_marshal_object, 1 );
230         mo->ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _sipc_util_remove_hashtable_value);
231
232         return mo;
233 }
234
235 gboolean sipc_util_marshal_object_add_data(struct _sipc_marshal_object *mo, const gchar* key, const void *data,
236                 sipc_marshal_data_type_e type)
237 {
238         gboolean rv = FALSE;
239         GValue *value;
240
241         SIPC_CHECK_DATA_NULL( (mo&&key&&data), FALSE);
242
243         if (type >= SIPC_MARSHAL_DATA_STRING_MAX)
244                 return FALSE;
245
246         value = g_new0(GValue, 1);
247
248         if (type != SIPC_MARSHAL_DATA_OBJECT_TYPE) {
249                 rv = _sipc_util_create_gvalue(value, data, type);
250         }
251         else {
252                 rv = _sipc_util_create_gvalue(value, (struct _sipc_marshal_object*) data, type);
253         }
254
255         if (!rv)
256                 return FALSE;
257
258         g_hash_table_insert(mo->ht, g_strdup(key), value);
259
260         return TRUE;
261 }
262
263 gboolean sipc_util_marshal_object_get_data(struct _sipc_marshal_object *mo, const gchar* key, void **data,
264                 sipc_marshal_data_type_e type)
265 {
266         gboolean rv = FALSE;
267         gpointer value;
268
269         SIPC_CHECK_DATA_NULL((mo&&key), FALSE);
270
271         value = g_hash_table_lookup(mo->ht, key);
272         rv = _sipc_util_return_value((GValue *) value, data, type);
273         if (!rv)
274                 FALSE;
275
276         return TRUE;
277 }
278
279 gchar sipc_util_marshal_object_get_char(struct _sipc_marshal_object *mo, const gchar* key)
280 {
281         gboolean rv = FALSE;
282         gchar rvalue, *tmp = NULL;
283         SIPC_CHECK_DATA_NULL((mo&&key), 0);
284
285         rv = sipc_util_marshal_object_get_data(mo, key, (void **)&tmp, SIPC_MARSHAL_DATA_CHAR_TYPE);
286         if (!rv) 0; if(!tmp) 0;
287
288         rvalue = *tmp;
289         g_free(tmp);
290
291         return rvalue;
292 }
293
294 gboolean sipc_util_marshal_object_get_boolean(struct _sipc_marshal_object *mo, const gchar* key)
295 {
296         gboolean rv = FALSE;
297         gboolean rvalue, *tmp = NULL;
298         SIPC_CHECK_DATA_NULL((mo&&key), FALSE);
299
300         rv = sipc_util_marshal_object_get_data(mo, key, (void **)&tmp, SIPC_MARSHAL_DATA_BOOLEAN_TYPE);
301         if (!rv) FALSE; if(!tmp) FALSE;
302
303         rvalue = *tmp;
304         g_free(tmp);
305
306         return rvalue;
307 }
308
309 gint sipc_util_marshal_object_get_int(struct _sipc_marshal_object *mo, const gchar* key)
310 {
311         gboolean rv = FALSE;
312         gint rvalue, *tmp = NULL;
313         SIPC_CHECK_DATA_NULL((mo&&key), 0);
314
315         rv = sipc_util_marshal_object_get_data(mo, key, (void **)&tmp, SIPC_MARSHAL_DATA_INT_TYPE);
316         if (!rv) 0; if(!tmp) 0;
317
318         rvalue = *tmp;
319         g_free(tmp);
320
321         return rvalue;
322 }
323
324 gdouble sipc_util_marshal_object_get_double(struct _sipc_marshal_object *mo, const gchar* key)
325 {
326         gboolean rv = FALSE;
327         gdouble rvalue, *tmp = NULL;
328         SIPC_CHECK_DATA_NULL((mo&&key), 0);
329
330         rv = sipc_util_marshal_object_get_data(mo, key, (void **)&tmp, SIPC_MARSHAL_DATA_DOUBLE_TYPE);
331         if (!rv) 0; if(!tmp) 0;
332
333         rvalue = *tmp;
334         g_free(tmp);
335
336         return rvalue;
337 }
338
339 gchar* sipc_util_marshal_object_get_string(struct _sipc_marshal_object *mo, const gchar* key)
340 {
341         gboolean rv = FALSE;
342         gchar *rvalue = NULL;
343         SIPC_CHECK_DATA_NULL((mo&&key), NULL);
344
345         rv = sipc_util_marshal_object_get_data(mo, key, (void **)&rvalue, SIPC_MARSHAL_DATA_STRING_TYPE);
346         if (!rv) NULL;
347
348         return rvalue;
349 }
350
351 struct _sipc_marshal_object * sipc_util_marshal_object_get_object(struct _sipc_marshal_object *mo, const gchar* key)
352 {
353         gboolean rv = FALSE;
354         struct _sipc_marshal_object *rvalue = NULL;
355         SIPC_CHECK_DATA_NULL((mo&&key), NULL);
356
357         rv = sipc_util_marshal_object_get_data(mo, key, (void **)&rvalue, SIPC_MARSHAL_DATA_OBJECT_TYPE);
358         if (!rv) NULL;
359
360         return rvalue;
361 }
362
363 gboolean sipc_util_marshal_object_remove_data(struct _sipc_marshal_object *mo, const gchar* key)
364 {
365         SIPC_CHECK_DATA_NULL((mo), TRUE);
366
367         return g_hash_table_remove(mo->ht, key);
368 }
369
370 gboolean sipc_util_marshal_object_remove_alldata(struct _sipc_marshal_object *mo)
371 {
372         SIPC_CHECK_DATA_NULL((mo), TRUE);
373
374         g_hash_table_remove_all(mo->ht);
375         return TRUE;
376 }
377
378 gboolean sipc_util_marshal_object_destory(struct _sipc_marshal_object *mo)
379 {
380         SIPC_CHECK_DATA_NULL((mo), TRUE);
381
382         g_hash_table_destroy(mo->ht);
383         g_free(mo);
384
385         return TRUE;
386 }
387
388 gchar* sipc_util_marshal_object_serializer(struct _sipc_marshal_object *mo)
389 {
390         gchar *rv_str = NULL;
391         GHashTableIter iter;
392         gpointer key, value;
393         GString *gstring_tmp = NULL;
394
395         gstring_tmp = g_string_new(NULL);
396         g_hash_table_iter_init(&iter, mo->ht);
397         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
398                 unsigned int gtype = 0;
399                 gchar *tmp = NULL, *encoded_d = NULL;
400                 GValue gval = { 0, { { 0 } } };
401
402                 g_value_init(&gval, G_TYPE_STRING);
403
404                 gtype = ((GValue *) value)->g_type;
405                 if (gtype != G_TYPE_POINTER) {
406                         g_value_transform((GValue *) value, &gval);
407                         tmp = g_value_dup_string(&gval);
408                 }
409                 else {
410                         struct _sipc_marshal_object *tmp_obj;
411                         tmp_obj = g_value_get_pointer((GValue *) value);
412                         tmp = sipc_util_marshal_object_serializer(tmp_obj);
413                 }
414
415                 encoded_d = g_base64_encode(tmp, strlen(tmp));
416                 g_free(tmp);
417
418                 g_string_append_printf(gstring_tmp, "%s:%d:%s/", key, gtype, encoded_d);
419                 g_free(encoded_d);
420                 g_value_unset(&gval);
421         }
422
423         rv_str = g_strdup(gstring_tmp->str);
424         g_string_free(gstring_tmp, TRUE);
425
426         dbg("serialized string [%s]", rv_str);
427         return rv_str;
428 }
429
430 struct _sipc_marshal_object* sipc_util_marshal_object_deserializer(const gchar *inparam)
431 {
432         struct _sipc_marshal_object *obj = NULL;
433         obj = g_new0(struct _sipc_marshal_object, 1);
434         obj->ht = _sipc_util_marshal_object_deserializer(inparam);
435
436         return obj;
437 }