2d51933c32e99cea4811c60067e776e1a4e1fc26
[platform/core/api/maps-service.git] / src / api / maps_extra_types.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <glib.h>
18 #include "maps_error.h"
19 #include "maps_extra_types.h"
20 #include "maps_util.h"
21 #include "maps_condition.h"
22
23 typedef struct _maps_item_list_s
24 {
25         GList *l;
26 } maps_item_list_s;
27
28 EXPORT_API int maps_item_list_create(maps_item_list_h *list)
29 {
30         if (!maps_condition_check_maps_feature())
31                 return MAPS_ERROR_NOT_SUPPORTED;
32         if (!list)
33                 return MAPS_ERROR_INVALID_PARAMETER;
34         maps_item_list_s *l = g_slice_new0(maps_item_list_s);
35
36         if (!l) {
37                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
38                 return MAPS_ERROR_OUT_OF_MEMORY;
39         }
40
41         l->l = NULL;
42
43         *list = (maps_item_list_h *) l;
44         return MAPS_ERROR_NONE;
45 }
46
47 EXPORT_API int maps_item_list_destroy(maps_item_list_h list)
48 {
49         if (!maps_condition_check_maps_feature())
50                 return MAPS_ERROR_NOT_SUPPORTED;
51         if (!list)
52                 return MAPS_ERROR_INVALID_PARAMETER;
53         maps_item_list_s *l = (maps_item_list_s *) list;
54         if (l->l)
55                 g_list_free(l->l);
56         g_slice_free(maps_item_list_s, l);
57         return MAPS_ERROR_NONE;
58 }
59
60 EXPORT_API int maps_item_list_append(maps_item_list_h list, const void *data,
61                                      maps_item_list_clone_cb clone_func)
62 {
63         if (!maps_condition_check_maps_feature())
64                 return MAPS_ERROR_NOT_SUPPORTED;
65         if (!list || !data)
66                 return MAPS_ERROR_INVALID_PARAMETER;
67         void *p = NULL;
68         if (clone_func) {
69                 const int error = clone_func((void *) data, &p);
70                 if (error != MAPS_ERROR_NONE)
71                         return error;
72         } else {
73                 p = (void*)data;
74         }
75         maps_item_list_s *l = (maps_item_list_s *) list;
76         l->l = g_list_append(l->l, (gpointer) p);
77         return MAPS_ERROR_NONE;
78 }
79
80 EXPORT_API int maps_item_list_foreach(maps_item_list_h list,
81                                       maps_item_list_clone_cb clone_func,
82                                       maps_item_list_foreach_cb callback,
83                                       void *user_data)
84 {
85         if (!maps_condition_check_maps_feature())
86                 return MAPS_ERROR_NOT_SUPPORTED;
87         if (!list || !callback)
88                 return MAPS_ERROR_INVALID_PARAMETER;
89         maps_item_list_s *l = (maps_item_list_s *) list;
90         if (!l->l)
91                 return MAPS_ERROR_NOT_FOUND;
92
93         const int total = g_list_length(l->l);
94         GList *head = g_list_first(l->l);
95         int index = 0;
96         while (head) {
97                 void *data = head->data;
98                 head = head->next;
99                 void *clone = NULL;
100                 if (clone_func) {
101                         if (clone_func(data, &clone) != MAPS_ERROR_NONE)
102                                 continue;
103                 } else {
104                         clone = data;
105                 }
106                 if (!callback(index++, total, clone, user_data))
107                         break;
108         }
109
110         return MAPS_ERROR_NONE;
111 }
112
113 EXPORT_API int maps_item_list_remove(maps_item_list_h list,
114                                      void *item,
115                                      maps_item_list_free_cb free_func)
116 {
117         if (!maps_condition_check_maps_feature())
118                 return MAPS_ERROR_NOT_SUPPORTED;
119         if (!list)
120                 return MAPS_ERROR_INVALID_PARAMETER;
121         maps_item_list_s *l = (maps_item_list_s *) list;
122         if (l->l) {
123                 l->l = g_list_remove(l->l, item);
124                 if (free_func)
125                         free_func(item);
126         }
127         return MAPS_ERROR_NONE;
128 }
129
130 EXPORT_API int maps_item_list_foreach_noclone(maps_item_list_h list, maps_item_list_foreach_noclone_cb callback, void *user_data)
131 {
132         if (!maps_condition_check_maps_feature())
133                 return MAPS_ERROR_NOT_SUPPORTED;
134         if (!list || !callback)
135                 return MAPS_ERROR_INVALID_PARAMETER;
136         maps_item_list_s *l = (maps_item_list_s *) list;
137
138         if (!l->l)
139                 return MAPS_ERROR_NOT_FOUND;
140
141         GList *head = g_list_first(l->l);
142         int index = 0;
143         while (head) {
144                 void *data = head->data;
145                 head = head->next;
146                 if (!callback(index++, data, user_data))
147                         break;
148         }
149         return MAPS_ERROR_NONE;
150 }
151
152 EXPORT_API int maps_item_list_remove_all(maps_item_list_h list,
153                                          maps_item_list_free_cb free_func)
154 {
155         if (!maps_condition_check_maps_feature())
156                 return MAPS_ERROR_NOT_SUPPORTED;
157         if (!list)
158                 return MAPS_ERROR_INVALID_PARAMETER;
159
160         maps_item_list_s *l = (maps_item_list_s *) list;
161         if (l->l) {
162                 GList *head = g_list_first(l->l);
163                 while (head) {
164                         if (free_func)
165                                 free_func(head->data);
166                         head = head->next;
167                 }
168
169                 g_list_free(l->l);
170                 l->l = NULL;
171         }
172         return MAPS_ERROR_NONE;
173 }
174
175 EXPORT_API int maps_item_list_clone(const maps_item_list_h origin,
176                                     maps_item_list_clone_cb clone_func,
177                                     maps_item_list_h *cloned)
178 {
179         if (!maps_condition_check_maps_feature())
180                 return MAPS_ERROR_NOT_SUPPORTED;
181         if (!cloned || !origin || !clone_func)
182                 return MAPS_ERROR_INVALID_PARAMETER;
183
184         int error = MAPS_ERROR_NONE;
185         do {
186                 error = maps_item_list_create(cloned);
187                 if (!(*cloned) || (error != MAPS_ERROR_NONE))
188                         break;
189
190                 maps_item_list_s *l = (maps_item_list_s *) origin;
191                 if (!l->l)
192                         return MAPS_ERROR_NONE;
193
194                 maps_item_list_s *l_cloned = (maps_item_list_s *) (*cloned);
195
196                 /* It would be cool when we will have glib v 2.34 */
197                 /*l_cloned->l = g_list_copy_deep(l->l, clone_func, NULL); */
198                 /* Now we iterate */
199                 GList *head = g_list_first(l->l);
200                 while (head) {
201                         void *cloned_item = NULL;
202                         const int error = clone_func(head->data, &cloned_item);
203                         if (error == MAPS_ERROR_NONE)
204                                 l_cloned->l =
205                                         g_list_append(l_cloned->l,
206                                         (gpointer) cloned_item);
207                         head = head->next;
208                 }
209                 return MAPS_ERROR_NONE;
210         } while (false);
211
212         maps_item_list_destroy(*cloned);
213         *cloned = NULL;
214         return error;
215 }
216
217 EXPORT_API int maps_item_list_get_length(maps_item_list_h list, int *length)
218 {
219         if (!maps_condition_check_maps_feature())
220                 return MAPS_ERROR_NOT_SUPPORTED;
221         if (!list || !length)
222                 return MAPS_ERROR_INVALID_PARAMETER;
223         maps_item_list_s *l = (maps_item_list_s *)list;
224         if (!l->l)
225                 *length = 0;
226         else
227                 *length = g_list_length(l->l);
228         return MAPS_ERROR_NONE;
229 }
230
231 /*----------------------------------------------------------------------------*/
232
233 typedef struct _maps_string_hashtable_s
234 {
235         GHashTable *t;
236 } maps_string_hashtable_s;
237
238 EXPORT_API int maps_string_hashtable_create(maps_string_hashtable_h *table)
239 {
240         if (!maps_condition_check_maps_feature())
241                 return MAPS_ERROR_NOT_SUPPORTED;
242         if (!table)
243                 return MAPS_ERROR_INVALID_PARAMETER;
244
245         maps_string_hashtable_s *t = g_slice_new0(maps_string_hashtable_s);
246         if (!t) {
247                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
248                 return MAPS_ERROR_OUT_OF_MEMORY;
249         }
250
251         t->t = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
252         *table = t;
253         return MAPS_ERROR_NONE;
254 }
255
256 EXPORT_API int maps_string_hashtable_destroy(maps_string_hashtable_h table)
257 {
258         if (!maps_condition_check_maps_feature())
259                 return MAPS_ERROR_NOT_SUPPORTED;
260         if (!table)
261                 return MAPS_ERROR_INVALID_PARAMETER;
262         maps_string_hashtable_s *t = (maps_string_hashtable_s *) table;
263         if (t->t)
264                 g_hash_table_unref(t->t);
265         g_slice_free(maps_string_hashtable_s, t);
266         return MAPS_ERROR_NONE;
267 }
268
269 EXPORT_API int maps_string_hashtable_set(maps_string_hashtable_h table,
270                                          const char *key, const char *value)
271 {
272         if (!maps_condition_check_maps_feature())
273                 return MAPS_ERROR_NOT_SUPPORTED;
274         if (!table || !key || !value)
275                 return MAPS_ERROR_INVALID_PARAMETER;
276         maps_string_hashtable_s *t = (maps_string_hashtable_s *) table;
277         if (t->t)
278                 g_hash_table_insert(t->t, (gpointer) g_strdup(key),
279                         (gpointer) g_strdup(value));
280         return MAPS_ERROR_NONE;
281 }
282
283 EXPORT_API int maps_string_hashtable_get(maps_string_hashtable_h table,
284                                          const char *key, char **value)
285 {
286         if (!maps_condition_check_maps_feature())
287                 return MAPS_ERROR_NOT_SUPPORTED;
288         if (!table || !key || !value)
289                 return MAPS_ERROR_INVALID_PARAMETER;
290         maps_string_hashtable_s *t = (maps_string_hashtable_s *) table;
291         if (!t->t)
292                 return MAPS_ERROR_NOT_FOUND;
293         char *table_value = (char *) g_hash_table_lookup(t->t, key);
294         if (!table_value)
295                 return MAPS_ERROR_NONE;
296         return maps_get_string(table_value, strlen(table_value), value);
297 }
298
299 EXPORT_API int maps_string_hashtable_remove(maps_string_hashtable_h table,
300                                             const char *key)
301 {
302         if (!maps_condition_check_maps_feature())
303                 return MAPS_ERROR_NOT_SUPPORTED;
304         if (!table || !key)
305                 return MAPS_ERROR_INVALID_PARAMETER;
306         maps_string_hashtable_s *t = (maps_string_hashtable_s *) table;
307         if (t->t)
308                 g_hash_table_remove(t->t, (gpointer) key);
309         return MAPS_ERROR_NONE;
310 }
311
312 EXPORT_API int maps_string_hashtable_foreach(maps_string_hashtable_h table,
313                                              maps_string_hashtable_foreach_cb
314                                              callback,
315                                              void *user_data)
316 {
317         if (!maps_condition_check_maps_feature())
318                 return MAPS_ERROR_NOT_SUPPORTED;
319         if (!table || !callback)
320                 return MAPS_ERROR_INVALID_PARAMETER;
321         maps_string_hashtable_s *t = (maps_string_hashtable_s *) table;
322
323         if (!t->t)
324                 return MAPS_ERROR_NOT_FOUND;
325
326         GHashTableIter iter;
327         gpointer key, value;
328         const int total = g_hash_table_size(t->t);
329         int index = 0;
330         g_hash_table_iter_init(&iter, t->t);
331         while (g_hash_table_iter_next(&iter, &key, &value)) {
332                 char *key_clone = NULL;
333                 if (maps_item_hashtable_clone_string(key,
334                                 (void **) &key_clone) != MAPS_ERROR_NONE)
335                         continue;
336                 char *value_clone = NULL;
337                 if (maps_item_hashtable_clone_string(value,
338                                 (void **) &value_clone) != MAPS_ERROR_NONE)
339                         continue;
340
341                 if (!callback(index++, total, key_clone, value_clone,
342                                 user_data))
343                         break;
344         }
345         return MAPS_ERROR_NONE;
346 }
347
348 EXPORT_API int maps_string_hashtable_clone(const maps_string_hashtable_h origin,
349                                            maps_string_hashtable_h *cloned)
350 {
351         if (!maps_condition_check_maps_feature())
352                 return MAPS_ERROR_NOT_SUPPORTED;
353         if (!cloned || !origin)
354                 return MAPS_ERROR_INVALID_PARAMETER;
355
356         int error = MAPS_ERROR_NONE;
357         do {
358                 error = maps_string_hashtable_create(cloned);
359                 if (!(*cloned) || (error != MAPS_ERROR_NONE))
360                         break;
361
362                 maps_string_hashtable_s *t = (maps_string_hashtable_s *) origin;
363
364                 if (!t->t)
365                         return MAPS_ERROR_NONE;
366
367                 maps_string_hashtable_s *t_cloned =
368                         (maps_string_hashtable_s *) (*cloned);
369
370                 GHashTableIter iter;
371                 gpointer key, value;
372                 g_hash_table_iter_init(&iter, t->t);
373                 while (g_hash_table_iter_next(&iter, &key, &value)) {
374                         g_hash_table_insert(t_cloned->t,
375                                 (gpointer) g_strdup((const gchar *) key),
376                                 (gpointer) g_strdup((const gchar *) value));
377                 }
378
379                 return MAPS_ERROR_NONE;
380         } while (false);
381
382         maps_string_hashtable_destroy(*cloned);
383         *cloned = NULL;
384         return error;
385 }
386
387 EXPORT_API int maps_string_hashtable_contains(maps_string_hashtable_h table,
388                                               const char * key, bool * contains)
389 {
390         if (!maps_condition_check_maps_feature())
391                 return MAPS_ERROR_NOT_SUPPORTED;
392         if (!table || !key || !contains)
393                 return MAPS_ERROR_INVALID_PARAMETER;
394         maps_string_hashtable_s *t = (maps_string_hashtable_s *) table;
395         if (t->t)
396                 *contains = g_hash_table_contains(t->t, (gpointer) key);
397         return MAPS_ERROR_NONE;
398 }
399
400 /*----------------------------------------------------------------------------*/
401 typedef struct _maps_int_hashtable_s
402 {
403         GHashTable *t;
404 } maps_int_hashtable_s;
405
406 EXPORT_API int maps_int_hashtable_create(maps_int_hashtable_h *table)
407 {
408         if (!maps_condition_check_maps_feature())
409                 return MAPS_ERROR_NOT_SUPPORTED;
410         if (!table)
411                 return MAPS_ERROR_INVALID_PARAMETER;
412         maps_int_hashtable_s *t = g_slice_new0(maps_int_hashtable_s);
413
414         if (!t) {
415                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
416                 return MAPS_ERROR_OUT_OF_MEMORY;
417         }
418
419         t->t = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
420         *table = t;
421         return MAPS_ERROR_NONE;
422 }
423
424 EXPORT_API int maps_int_hashtable_destroy(maps_int_hashtable_h table)
425 {
426         if (!maps_condition_check_maps_feature())
427                 return MAPS_ERROR_NOT_SUPPORTED;
428         if (!table)
429                 return MAPS_ERROR_INVALID_PARAMETER;
430         maps_int_hashtable_s *t = (maps_int_hashtable_s *) table;
431         if (t->t)
432                 g_hash_table_unref(t->t);
433         g_slice_free(maps_int_hashtable_s, t);
434         return MAPS_ERROR_NONE;
435 }
436
437 EXPORT_API int maps_int_hashtable_set(maps_int_hashtable_h table,
438                                       const int key, const int value)
439 {
440         if (!maps_condition_check_maps_feature())
441                 return MAPS_ERROR_NOT_SUPPORTED;
442         if (!table)
443                 return MAPS_ERROR_INVALID_PARAMETER;
444         maps_int_hashtable_s *t = (maps_int_hashtable_s *) table;
445         if (t->t) {
446                 int *new_key = g_new0(int, 1);
447                 *new_key = key;
448                 int *new_value = g_new0(int, 1);
449                 *new_value = value;
450                 g_hash_table_insert(t->t,
451                                     (gpointer)new_key,
452                                     (gpointer)new_value);
453         }
454         return MAPS_ERROR_NONE;
455 }
456
457 EXPORT_API int maps_int_hashtable_get(maps_int_hashtable_h table,
458                                       const int key, int *value)
459 {
460         if (!maps_condition_check_maps_feature())
461                 return MAPS_ERROR_NOT_SUPPORTED;
462         if (!table || !value)
463                 return MAPS_ERROR_INVALID_PARAMETER;
464         maps_int_hashtable_s *t = (maps_int_hashtable_s *) table;
465         if (!t->t)
466                 return MAPS_ERROR_NOT_FOUND;
467         const int *table_value = (const int *) g_hash_table_lookup(t->t, &key);
468         if (!table_value)
469                 return MAPS_ERROR_NONE;
470         *value = *table_value;
471         return MAPS_ERROR_NONE;
472 }
473
474 EXPORT_API int maps_int_hashtable_remove(maps_int_hashtable_h table,
475                                          const int key)
476 {
477         if (!maps_condition_check_maps_feature())
478                 return MAPS_ERROR_NOT_SUPPORTED;
479         if (!table)
480                 return MAPS_ERROR_INVALID_PARAMETER;
481         maps_int_hashtable_s *t = (maps_int_hashtable_s *) table;
482         if (t->t)
483                 g_hash_table_remove(t->t, (gpointer) &key);
484         return MAPS_ERROR_NONE;
485 }
486
487 EXPORT_API int maps_int_hashtable_foreach(maps_int_hashtable_h table,
488                                           maps_int_hashtable_foreach_cb callback,
489                                           void *user_data)
490 {
491         if (!maps_condition_check_maps_feature())
492                 return MAPS_ERROR_NOT_SUPPORTED;
493         if (!table || !callback)
494                 return MAPS_ERROR_INVALID_PARAMETER;
495         maps_int_hashtable_s *t = (maps_int_hashtable_s *) table;
496
497         if (!t->t)
498                 return MAPS_ERROR_NOT_FOUND;
499
500         GHashTableIter iter;
501         gpointer key, value;
502         const int total = g_hash_table_size(t->t);
503         int index = 0;
504         g_hash_table_iter_init(&iter, t->t);
505         while (g_hash_table_iter_next(&iter, &key, &value)) {
506                 if(!key || !value)
507                         continue;
508
509                 int *key_ptr = (int *)key;
510                 int *value_ptr = (int *)value;
511                 if (!callback(index++, total, *key_ptr, *value_ptr, user_data))
512                         break;
513         }
514         return MAPS_ERROR_NONE;
515 }
516
517 EXPORT_API int maps_int_hashtable_clone(const maps_int_hashtable_h origin,
518                                         maps_int_hashtable_h *cloned)
519 {
520         if (!maps_condition_check_maps_feature())
521                 return MAPS_ERROR_NOT_SUPPORTED;
522         if (!cloned || !origin)
523                 return MAPS_ERROR_INVALID_PARAMETER;
524
525         int error = MAPS_ERROR_NONE;
526         do {
527                 error = maps_int_hashtable_create(cloned);
528                 if (!(*cloned) || (error != MAPS_ERROR_NONE))
529                         break;
530
531                 maps_int_hashtable_s *t = (maps_int_hashtable_s *) origin;
532
533                 if (!t->t)
534                         return MAPS_ERROR_NONE;
535
536                 maps_int_hashtable_s *t_cloned =
537                         (maps_int_hashtable_s *) (*cloned);
538
539                 GHashTableIter iter;
540                 gpointer key, value;
541                 g_hash_table_iter_init(&iter, t->t);
542                 while (g_hash_table_iter_next(&iter, &key, &value)) {
543                         int *new_key = g_new0(int, 1);
544                         *new_key = *((int *)key);
545                         int *new_value = g_new0(int, 1);
546                         *new_value = *((int *)value);
547                         g_hash_table_insert(t_cloned->t,
548                                 (gpointer) new_key,
549                                 (gpointer) new_value);
550                 }
551
552                 return MAPS_ERROR_NONE;
553         } while (false);
554
555         maps_int_hashtable_destroy(*cloned);
556         *cloned = NULL;
557         return error;
558 }
559
560 EXPORT_API int maps_int_hashtable_contains(maps_int_hashtable_h table,
561                                            const int key, bool *contains)
562 {
563         if (!maps_condition_check_maps_feature())
564                 return MAPS_ERROR_NOT_SUPPORTED;
565         if (!table || !contains)
566                 return MAPS_ERROR_INVALID_PARAMETER;
567         maps_int_hashtable_s *t = (maps_int_hashtable_s *) table;
568         if (t->t)
569                 *contains = g_hash_table_contains(t->t, (gpointer)&key);
570         return MAPS_ERROR_NONE;
571 }
572
573 /*----------------------------------------------------------------------------*/
574
575 typedef struct _maps_hashtable_item_s
576 {
577         void *value;
578         maps_item_hashtable_clone_cb clone_func;
579         maps_item_hashtable_free_cb free_func;
580 } maps_hashtable_item_s;
581
582 void _maps_hashtable_item_create(maps_hashtable_item_s **item)
583 {
584         *item = g_slice_new0(maps_hashtable_item_s);
585
586         if (*item == NULL)
587                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
588 }
589
590 void _maps_hashtable_item_destroy(gpointer data)
591 {
592         if (!data)
593                 return;
594
595         maps_hashtable_item_s *item = (maps_hashtable_item_s *) data;
596         if (item && item->value && item->free_func)
597                 item->free_func(item->value);
598
599         g_slice_free(maps_hashtable_item_s, item);
600 }
601
602 /*----------------------------------------------------------------------------*/
603
604 typedef struct _maps_item_hashtable_s
605 {
606         GHashTable *t;
607 } maps_item_hashtable_s;
608
609 EXPORT_API int maps_item_hashtable_create(maps_item_hashtable_h *table)
610 {
611         if (!maps_condition_check_maps_feature())
612                 return MAPS_ERROR_NOT_SUPPORTED;
613         if (!table)
614                 return MAPS_ERROR_INVALID_PARAMETER;
615         maps_item_hashtable_s *t = g_slice_new0(maps_item_hashtable_s);
616
617         if (!t) {
618                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
619                 return MAPS_ERROR_OUT_OF_MEMORY;
620         }
621
622         t->t = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
623                 _maps_hashtable_item_destroy);
624         *table = t;
625         return MAPS_ERROR_NONE;
626 }
627
628 EXPORT_API int maps_item_hashtable_destroy(maps_item_hashtable_h table)
629 {
630         if (!maps_condition_check_maps_feature())
631                 return MAPS_ERROR_NOT_SUPPORTED;
632         if (!table)
633                 return MAPS_ERROR_INVALID_PARAMETER;
634         maps_item_hashtable_s *t = (maps_item_hashtable_s *) table;
635         if (t->t)
636                 g_hash_table_unref(t->t);
637         g_slice_free(maps_item_hashtable_s, t);
638         return MAPS_ERROR_NONE;
639 }
640
641 EXPORT_API int maps_item_hashtable_clone_string(void *origin, void **cloned)
642 {
643         if (!maps_condition_check_maps_feature())
644                 return MAPS_ERROR_NOT_SUPPORTED;
645         if (!origin || !cloned)
646                 return MAPS_ERROR_INVALID_PARAMETER;
647         return maps_get_string((char *) origin, strlen((char *) origin),
648                 (char **) cloned);
649 }
650
651 EXPORT_API int maps_item_hashtable_free_string(void *data)
652 {
653         if (!maps_condition_check_maps_feature())
654                 return MAPS_ERROR_NOT_SUPPORTED;
655         g_free(data);
656         return MAPS_ERROR_NONE;
657 }
658
659 EXPORT_API int maps_item_hashtable_clone_int(void *origin, void **cloned)
660 {
661         if (!maps_condition_check_maps_feature())
662                 return MAPS_ERROR_NOT_SUPPORTED;
663         if (!origin || !cloned)
664                 return MAPS_ERROR_INVALID_PARAMETER;
665         int *n_cloned = g_new0(int, 1);
666
667         if (n_cloned == NULL) {
668                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
669                 return MAPS_ERROR_OUT_OF_MEMORY;
670         }
671
672         int *n_origin = (int *) origin;
673         *n_cloned = *n_origin;
674         *cloned = n_cloned;
675         return MAPS_ERROR_NONE;
676 }
677
678 EXPORT_API int maps_item_hashtable_free_int(void *data)
679 {
680         if (!maps_condition_check_maps_feature())
681                 return MAPS_ERROR_NOT_SUPPORTED;
682         g_free(data);
683         return MAPS_ERROR_NONE;
684 }
685
686 EXPORT_API int maps_item_hashtable_clone_float(void *origin, void **cloned)
687 {
688         if (!maps_condition_check_maps_feature())
689                 return MAPS_ERROR_NOT_SUPPORTED;
690         if (!origin || !cloned)
691                 return MAPS_ERROR_INVALID_PARAMETER;
692         double *n_cloned = g_new0(double, 1);
693
694         if (n_cloned == NULL) {
695                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
696                 return MAPS_ERROR_OUT_OF_MEMORY;
697         }
698
699         double *n_origin = (double *) origin;
700         *n_cloned = *n_origin;
701         *cloned = n_cloned;
702         return MAPS_ERROR_NONE;
703 }
704
705 EXPORT_API int maps_item_hashtable_free_float(void *data)
706 {
707         if (!maps_condition_check_maps_feature())
708                 return MAPS_ERROR_NOT_SUPPORTED;
709         g_free(data);
710         return MAPS_ERROR_NONE;
711 }
712
713 EXPORT_API int maps_item_hashtable_set_string(maps_item_hashtable_h table,
714                                               const char *key,
715                                               const char *value)
716 {
717         if (!maps_condition_check_maps_feature())
718                 return MAPS_ERROR_NOT_SUPPORTED;
719         return maps_item_hashtable_set(table, key, value,
720                 maps_item_hashtable_clone_string,
721                 maps_item_hashtable_free_string);
722 }
723
724 EXPORT_API int maps_item_hashtable_set_int(maps_item_hashtable_h table,
725                                            const char *key, const int value)
726 {
727         if (!maps_condition_check_maps_feature())
728                 return MAPS_ERROR_NOT_SUPPORTED;
729         return maps_item_hashtable_set(table, key, &value,
730                 maps_item_hashtable_clone_int, maps_item_hashtable_free_int);
731 }
732
733 EXPORT_API int maps_item_hashtable_set_float(maps_item_hashtable_h table,
734                                              const char *key,
735                                              const double value)
736 {
737         if (!maps_condition_check_maps_feature())
738                 return MAPS_ERROR_NOT_SUPPORTED;
739         return maps_item_hashtable_set(table, key, &value,
740                 maps_item_hashtable_clone_float,
741                 maps_item_hashtable_free_float);
742 }
743
744 EXPORT_API int maps_item_hashtable_set(maps_item_hashtable_h table,
745                                        const char *key, const void *value,
746         maps_item_hashtable_clone_cb clone_func,
747         maps_item_hashtable_free_cb free_func)
748 {
749         if (!maps_condition_check_maps_feature())
750                 return MAPS_ERROR_NOT_SUPPORTED;
751         if (!table || !key || !value || !clone_func || !free_func)
752                 return MAPS_ERROR_INVALID_PARAMETER;
753         maps_item_hashtable_s *t = (maps_item_hashtable_s *) table;
754
755         if (t->t) {
756                 maps_hashtable_item_s *item = NULL;
757                 _maps_hashtable_item_create(&item);
758
759                 const int error = clone_func((void *) value, &item->value);
760                 if (error != MAPS_ERROR_NONE) {
761                         _maps_hashtable_item_destroy(item);
762                         return error;
763                 }
764                 item->clone_func = clone_func;
765                 item->free_func = free_func;
766                 if (t->t)
767                         g_hash_table_insert(t->t, (gpointer) g_strdup(key),
768                                 (gpointer) item);
769         }
770
771         return MAPS_ERROR_NONE;
772 }
773
774 EXPORT_API int maps_item_hashtable_get_string(maps_item_hashtable_h table,
775                                               const char *key, char **value)
776 {
777         if (!maps_condition_check_maps_feature())
778                 return MAPS_ERROR_NOT_SUPPORTED;
779         return maps_item_hashtable_get(table, key, (void **) value);
780 }
781
782 EXPORT_API int maps_item_hashtable_get_int(maps_item_hashtable_h table,
783                                            const char *key, int *value)
784 {
785         if (!maps_condition_check_maps_feature())
786                 return MAPS_ERROR_NOT_SUPPORTED;
787         if (!table || !key || !value)
788                 return MAPS_ERROR_INVALID_PARAMETER;
789         int *data = NULL;
790         const int error = maps_item_hashtable_get(table, key, (void **) &data);
791         if (error == MAPS_ERROR_NONE) {
792                 *value = *data;
793                 maps_item_hashtable_free_int(data);
794         }
795         return error;
796 }
797
798 EXPORT_API int maps_item_hashtable_get_float(maps_item_hashtable_h table,
799                                              const char *key, double *value)
800 {
801         if (!maps_condition_check_maps_feature())
802                 return MAPS_ERROR_NOT_SUPPORTED;
803         if (!table || !key || !value)
804                 return MAPS_ERROR_INVALID_PARAMETER;
805         double *data = NULL;
806         const int error = maps_item_hashtable_get(table, key, (void **) &data);
807         if (error == MAPS_ERROR_NONE) {
808                 *value = *data;
809                 maps_item_hashtable_free_float(data);
810         }
811         return error;
812 }
813
814 EXPORT_API int maps_item_hashtable_get(maps_item_hashtable_h table,
815                                        const char *key, void **value)
816 {
817         if (!maps_condition_check_maps_feature())
818                 return MAPS_ERROR_NOT_SUPPORTED;
819         if (!table || !key || !value)
820                 return MAPS_ERROR_INVALID_PARAMETER;
821         maps_item_hashtable_s *t = (maps_item_hashtable_s *) table;
822         if (!t->t)
823                 return MAPS_ERROR_NOT_FOUND;
824         maps_hashtable_item_s *item =
825                 (maps_hashtable_item_s *) g_hash_table_lookup(t->t, key);
826         if (!item || !item->clone_func)
827                 return MAPS_ERROR_NOT_FOUND;
828         return item->clone_func(item->value, value);
829 }
830
831 EXPORT_API int maps_item_hashtable_remove(maps_item_hashtable_h table,
832                                           const char *key)
833 {
834         if (!maps_condition_check_maps_feature())
835                 return MAPS_ERROR_NOT_SUPPORTED;
836         if (!table || !key)
837                 return MAPS_ERROR_INVALID_PARAMETER;
838         maps_item_hashtable_s *t = (maps_item_hashtable_s *) table;
839         if (t->t)
840                 g_hash_table_remove(t->t, (gpointer) key);
841         return MAPS_ERROR_NONE;
842 }
843
844 EXPORT_API int maps_item_hashtable_foreach(maps_item_hashtable_h table,
845                                            maps_item_hashtable_foreach_cb
846                                            callback,
847                                            void *user_data)
848 {
849         if (!maps_condition_check_maps_feature())
850                 return MAPS_ERROR_NOT_SUPPORTED;
851         if (!table || !callback)
852                 return MAPS_ERROR_INVALID_PARAMETER;
853         maps_item_hashtable_s *t = (maps_item_hashtable_s *) table;
854         if (!t->t)
855                 return MAPS_ERROR_NOT_FOUND;
856
857         GHashTableIter iter;
858         gpointer key, value;
859         const int total = g_hash_table_size(t->t);
860         int index = 0;
861         g_hash_table_iter_init(&iter, t->t);
862         while (g_hash_table_iter_next(&iter, &key, &value)) {
863                 maps_hashtable_item_s *item = (maps_hashtable_item_s *) value;
864                 if (!item || !item->clone_func)
865                         continue;
866
867                 char *key_clone = NULL;
868                 if (maps_item_hashtable_clone_string(key,
869                                 (void **) &key_clone) != MAPS_ERROR_NONE)
870                         continue;
871                 void *value_clone = NULL;
872                 if (item->clone_func(item->value,
873                                 &value_clone) != MAPS_ERROR_NONE)
874                         continue;
875
876                 if (!callback(index++, total, key_clone, value_clone,
877                                 user_data))
878                         break;
879         }
880
881         return MAPS_ERROR_NONE;
882 }
883
884 EXPORT_API int maps_item_hashtable_clone(const maps_item_hashtable_h origin,
885                                          maps_item_hashtable_h* cloned)
886 {
887         if (!maps_condition_check_maps_feature())
888                 return MAPS_ERROR_NOT_SUPPORTED;
889         if (!cloned || !origin)
890                 return MAPS_ERROR_INVALID_PARAMETER;
891
892         int error = MAPS_ERROR_NONE;
893         do {
894                 error = maps_item_hashtable_create(cloned);
895                 if (!(*cloned) || (error != MAPS_ERROR_NONE))
896                         break;
897
898                 maps_item_hashtable_s *t = (maps_item_hashtable_s *) origin;
899
900                 if (!t->t)
901                         return MAPS_ERROR_NONE;
902
903                 GHashTableIter iter;
904                 gpointer key, value;
905                 g_hash_table_iter_init(&iter, t->t);
906                 while (g_hash_table_iter_next(&iter, &key, &value)) {
907                         maps_hashtable_item_s *item =
908                                 (maps_hashtable_item_s *) value;
909                         if (!item)
910                                 continue;
911                         maps_item_hashtable_set(*cloned, (const char *) key,
912                                 (const void *) item->value, item->clone_func,
913                                 item->free_func);
914                 }
915
916                 return MAPS_ERROR_NONE;
917         } while (false);
918
919         maps_item_hashtable_destroy(*cloned);
920         *cloned = NULL;
921         return error;
922 }
923
924 EXPORT_API int maps_item_hashtable_contains(maps_item_hashtable_h table,
925                                             const char *key, bool *contains)
926 {
927         if (!maps_condition_check_maps_feature())
928                 return MAPS_ERROR_NOT_SUPPORTED;
929         if (!table || !key || !contains)
930                 return MAPS_ERROR_INVALID_PARAMETER;
931         maps_item_hashtable_s *t = (maps_item_hashtable_s *) table;
932         if (t->t)
933                 *contains = g_hash_table_contains(t->t, (gpointer) key);
934         return MAPS_ERROR_NONE;
935 }