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