cleanup specfile for packaging
[profile/ivi/bundle.git] / src / bundle.c
1 /*
2  * bundle
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23
24
25 /**
26  * bundle.c
27  */
28
29 #include "bundle.h"
30 #include "keyval.h"
31 #include "keyval_array.h"
32 #include "keyval_type.h"
33 #include "bundle_log.h"
34 #include <glib/gbase64.h>
35
36 #include <stdlib.h>             /* calloc, free */
37 #include <string.h>             /* strdup */
38 #include <errno.h>
39
40
41 /* ADT */
42 struct _bundle_t
43 {
44         keyval_t *kv_head;
45 };
46
47
48 /**
49  * Find a kv from bundle
50  */
51 static keyval_t *
52 _bundle_find_kv(bundle *b, const char *key)
53 {
54         keyval_t *kv;
55
56         if(NULL == b) { errno  = EINVAL; return NULL; }
57         if(NULL == key) { errno = EKEYREJECTED; return NULL; }
58
59         kv = b->kv_head;
60         while (kv != NULL) {
61                 if(0 == strcmp(key, kv->key)) return kv;
62                 kv = kv->next;
63         } 
64         /* Not found */
65         errno = ENOKEY;
66         return NULL;
67 }
68
69 /**
70  * Append kv into bundle
71  */
72 static int
73 _bundle_append_kv(bundle *b, keyval_t *new_kv)
74 {
75         keyval_t *kv;
76
77         if (NULL == b->kv_head) b->kv_head = new_kv;
78         else {
79                 kv = b->kv_head;
80                 while (NULL != kv->next) kv = kv->next;
81                 kv->next = new_kv;
82         }
83         return 0;
84 }
85
86 static int
87 _bundle_add_kv(bundle *b, const char *key, const void *val, const size_t size, const int type, const unsigned int len)
88 {
89         /* basic value check */
90         if(NULL == b) { errno = EINVAL; return -1; }
91         if(NULL == key) { errno = EKEYREJECTED; return -1; }
92         if(0 == strlen(key)) { errno = EKEYREJECTED; return -1; }
93
94         keyval_t *kv = _bundle_find_kv(b, key);
95         if(kv) {        /* Key already exists */
96                 errno = EPERM;
97                 return -1;
98         }
99         errno = 0;
100
101         keyval_t *new_kv = NULL;
102         if(keyval_type_is_array(type)) {
103                 // array type
104                 keyval_array_t *kva = keyval_array_new(NULL, key, type, (const void **) val, len);
105                 new_kv = (keyval_t *)kva;
106         }
107         else {
108                 // normal type
109                 new_kv = keyval_new(NULL, key, type, val, size);
110         }
111         if(!new_kv) {
112                 // NOTE: errno is already set. (ENOMEM, ...)
113                 return -1;
114         }
115
116         _bundle_append_kv(b, new_kv);
117
118         return 0;
119
120 }
121
122 static int
123 _bundle_get_val(bundle *b, const char *key, const int type, void **val, size_t *size, unsigned int *len, size_t **array_element_size)
124 {
125         keyval_t *kv = _bundle_find_kv(b, key);
126         if(!kv) {       /* Key doesn't exist */
127                 /* NOTE: errno is already set. */
128                 return -1;
129         }
130         if(BUNDLE_TYPE_ANY != type && type != kv->type) {
131                 errno = ENOTSUP;
132                 return -1;
133         }
134
135         if(keyval_type_is_array(type)) {
136                 keyval_array_t *kva = (keyval_array_t *)kv;
137                 keyval_array_get_data(kva, NULL, (void ***)val, len, array_element_size);
138         }
139         else {
140                 keyval_get_data(kv, NULL, val, size);
141         }
142
143         return 0;
144 }
145
146 /** global initialization
147  *  Run only once.
148  */
149 static void
150 _bundle_global_init(void)
151 {
152         static int _is_done = 0;
153         if(_is_done) return;
154         
155         // Run init functions
156         keyval_type_init();
157
158         _is_done = 1;
159         return;
160 }
161
162
163 /* APIs */
164 bundle *
165 bundle_create(void)
166 {
167         bundle *b = NULL;
168         
169         _bundle_global_init();
170
171         b = calloc(1, sizeof(bundle));  /* fill mem with NULL */
172         if(NULL == b) {
173                 BUNDLE_EXCEPTION_PRINT("Unable to allocate memory for bundle\n");
174                 errno = ENOMEM;
175                 goto EXCEPTION;
176         }
177
178         return b;
179
180 EXCEPTION:
181         if(NULL != b) bundle_free(b);
182         return NULL;
183 }
184
185 int
186 bundle_free(bundle *b)
187 {
188         keyval_t *kv, *tmp_kv; 
189
190         if(NULL == b) {
191                 BUNDLE_EXCEPTION_PRINT("Bundle is already freed\n");
192                 errno = EINVAL;
193                 return -1;
194         }
195
196         /* Free keyval list */
197         kv = b->kv_head;
198         while(kv != NULL) {
199                 tmp_kv = kv;
200                 kv = kv->next;
201                 tmp_kv->method->free(tmp_kv, 1);
202         }
203
204         /* free bundle */
205         free(b);
206
207         return 0;
208 }
209 // str type
210 int
211 bundle_add_str(bundle *b, const char *key, const char *str)
212 {
213         if(!str) { errno = EINVAL; return -1; }
214         return _bundle_add_kv(b, key, str, strlen(str)+1, BUNDLE_TYPE_STR, 1);
215 }
216
217 int
218 bundle_get_str(bundle *b, const char *key, char **str)
219 {
220         return _bundle_get_val(b, key, BUNDLE_TYPE_STR, (void **) str, NULL, NULL, NULL);
221 }
222
223 int
224 bundle_add(bundle *b, const char *key, const char *val)
225 {
226         return bundle_add_str(b, key, val);
227 }
228
229 int
230 bundle_del(bundle *b, const char *key)
231 {
232         keyval_t *kv = NULL, *prev_kv = NULL;
233
234         /* basic value check */
235         if(NULL == b) { errno = EINVAL; return -1; }
236         if(NULL == key) { errno = EKEYREJECTED; return -1; }
237         if(0 == strlen(key)) { errno = EKEYREJECTED; return -1; }
238
239         kv = b->kv_head;
240         while (kv != NULL) {
241                 if(0 == strcmp(key, kv->key)) break;
242                 prev_kv = kv;
243                 kv = kv->next;
244         } 
245         if (NULL == kv) { errno = ENOKEY; return -1; }
246         else {
247                 if(NULL != prev_kv) {
248                         prev_kv->next = kv->next;
249                 }
250                 if(kv == b->kv_head) b->kv_head = kv->next;
251                 kv->method->free(kv, 1);
252         }
253         return 0;
254
255 }
256
257 const char *
258 bundle_get_val(bundle *b, const char *key)
259 {
260         char *val = NULL;
261         int r = 0;
262
263         r = bundle_get_str(b, key, &val);
264         return val;
265
266 }
267
268 /**
269  * @brief used by bundle_get_count() API, to count number of items in a bundle
270  */
271 static void
272 _bundle_get_count_iter(const char *k, const int type, const bundle_keyval_t *kv, void *user_data)
273 {
274         int *count = (int *)user_data;
275         *count += 1;
276 }
277
278 int
279 bundle_get_count (bundle *b)
280 {
281         int count = 0;
282         if (NULL == b) return count;
283         bundle_foreach(b, _bundle_get_count_iter, &count);
284         return count;
285 }
286
287 void
288 bundle_iterate(bundle *b, bundle_iterate_cb_t callback, void *data)
289 {
290         keyval_t *kv = b->kv_head;
291         if(callback) {
292                 while(NULL != kv) {
293                         callback(kv->key, kv->val, data);
294                         kv = kv->next;
295                 }
296         }
297 }
298
299 void
300 bundle_foreach(bundle *b, bundle_iterator_t iter, void *user_data)
301 {
302         if(NULL==b)
303         {
304                 return;         /*TC_FIX if b=NULL- error handling */
305         }
306         keyval_t *kv = b->kv_head;
307         if(iter) {
308                 while(NULL != kv) {
309                         iter(kv->key, kv->type, kv, user_data);
310                         kv = kv->next;
311                 }
312         }
313 }
314
315 /* keyval functions */
316 int 
317 bundle_keyval_get_type(bundle_keyval_t *kv)
318 {
319         return kv->type;
320 }
321
322 int 
323 bundle_keyval_type_is_array(bundle_keyval_t *kv)
324 {
325         return keyval_type_is_array(kv->type);
326 }
327
328 int 
329 bundle_keyval_get_basic_val(bundle_keyval_t *kv, void **val, size_t *size)
330 {
331         return keyval_get_data(kv, NULL, val, size);
332 }
333
334 int 
335 bundle_keyval_get_array_val(bundle_keyval_t *kv, void ***array_val, unsigned int *array_len, size_t **array_item_size)
336 {
337         return keyval_array_get_data((keyval_array_t *)kv, NULL, array_val, array_len, array_item_size);
338 }
339
340
341 /*static void
342 _iter_do_bundle_dup(const char *key, const void *val, const int type, const size_t size, const unsigned int len, void *user_data)
343 {
344         //int r;
345         bundle *b_to = (bundle *)user_data;
346
347         _bundle_add_kv(b_to, key, val, size, type, len);
348
349 }
350 */
351 bundle *
352 bundle_dup(bundle *b_from)
353 {
354         bundle *b_to = NULL;
355         int i;
356
357         if(NULL == b_from) { errno = EINVAL; return NULL; }
358         b_to = bundle_create();
359         if(NULL == b_to) return NULL;
360
361         keyval_t *kv_from = b_from->kv_head;
362         keyval_t *kv_to = NULL;
363         while(kv_from != NULL) {
364                 if(keyval_type_is_array(kv_from->type)) {
365                         keyval_array_t *kva_from = (keyval_array_t *)kv_from;
366                         kv_to = (keyval_t *) keyval_array_new(NULL, kv_from->key, kv_from->type, NULL, kva_from->len);
367                         if(!kv_to) goto ERR_CLEANUP;
368                         for(i=0; i < kva_from->len; i++) {
369                                 if(((keyval_array_t *)kv_from)->array_val[i]) {
370                                         keyval_array_set_element((keyval_array_t*)kv_to, i, ((keyval_array_t *)kv_from)->array_val[i], ((keyval_array_t *)kv_from)->array_element_size[i]);
371                                 }
372                         }
373                         _bundle_append_kv(b_to, kv_to);
374                 }
375                 else {
376                         if(_bundle_add_kv(b_to, kv_from->key, kv_from->val, kv_from->size, kv_from->type, 0)) goto ERR_CLEANUP;
377                 }
378
379                 kv_from = kv_from->next;
380         }
381         return b_to;
382
383 ERR_CLEANUP:
384         bundle_free(b_to);
385         return NULL;
386 }
387
388
389 int
390 bundle_encode(bundle *b, bundle_raw **r, int *len)
391 {
392         keyval_t *kv;
393
394         if(NULL == b) {
395                 errno = EINVAL;
396                 return -1;
397         }
398
399         /* calculate memory size */
400         size_t msize = 0;       // Sum of required size
401
402         kv = b->kv_head;
403         while(kv != NULL) {
404                 msize += kv->method->get_encoded_size(kv);
405                 kv = kv->next;
406         }
407         unsigned char *m = calloc(msize, sizeof(unsigned char));
408         if ( NULL == m )  { errno = ENOMEM; return -1; }
409
410         unsigned char *p_m = m; /* temporary pointer */
411
412         unsigned char *byte;
413         size_t byte_len;
414
415         kv = b->kv_head;
416         while(kv != NULL) {
417                 byte = NULL;
418                 byte_len = 0;
419
420                 kv->method->encode(kv, &byte, &byte_len);
421                 memcpy(p_m, byte, byte_len);
422
423                 p_m += byte_len;
424                 kv = kv->next;
425
426                 free(byte);
427         }
428
429         if ( NULL != r ) {
430                 *r =(unsigned char*)g_base64_encode(m, msize);
431                 if ( NULL != len ) *len = strlen((char*)*r);
432         }
433         free(m);
434
435         return 0;
436 }
437
438 int
439 bundle_free_encoded_rawdata(bundle_raw **r)
440 {
441         if(!*r) return -1;              /*TC_FIX - double free sigabrt handling */
442
443         free(*r);
444         *r=NULL;
445         return 0;
446 }
447
448 bundle *
449 bundle_decode(const bundle_raw *r, const int data_size)
450 {
451         bundle *b;
452         bundle_raw *p_r;
453
454         if(NULL == r) {
455                 errno = EINVAL;
456                 return NULL;
457         }
458
459         unsigned char *d_r;
460         unsigned int d_len;
461         d_r = g_base64_decode((char*)r, &d_len);
462
463         /* re-construct bundle */
464         b = bundle_create();
465
466         p_r = (bundle_raw *)d_r;
467
468         size_t bytes_read;
469         keyval_t *kv;
470
471         while(p_r < d_r + d_len - 1) {
472                 kv = NULL;      // To get a new kv
473
474                 // Find type, and use decode function according to type
475                 int type = keyval_get_type_from_encoded_byte(p_r);      
476
477                 if(keyval_type_is_array(type)) {
478                         bytes_read = keyval_array_decode(p_r, (keyval_array_t **) &kv);
479                 }
480                 else {
481                         bytes_read = keyval_decode(p_r, &kv);
482                 }
483
484                 if(kv) _bundle_append_kv(b, kv);
485                 else { break; }
486                 p_r += bytes_read;
487         }
488
489         free(d_r);
490
491         return b; 
492 }
493
494 struct _argv_idx {
495         int argc;
496         char **argv;
497         int idx;
498 };
499
500
501 void 
502 _iter_export_to_argv(const char *key, const int type, const keyval_t *kv, void *user_data)
503 {
504         struct _argv_idx *vi = (struct _argv_idx *)user_data;
505
506         vi->argv[vi->idx] = (char *)key;
507
508         unsigned char *byte = NULL, *encoded_byte = NULL;
509         size_t byte_len = 0;
510
511         if(0 == kv->method->encode((struct keyval_t *)kv, &byte, &byte_len)) {
512                 // TODO: encode FAILED!
513                 BUNDLE_EXCEPTION_PRINT("bundle: FAILED to encode keyval: %s\n", key);
514                 return;
515         }
516         // bas64 encode
517
518         encoded_byte =(unsigned char *) g_base64_encode(byte, byte_len);
519         if(NULL == encoded_byte) {
520                 BUNDLE_EXCEPTION_PRINT("bundle: failed to encode byte\n");
521                 return;
522         }
523         
524         vi->argv[vi->idx + 1] =(char*)encoded_byte;
525         (vi->idx) += 2;
526
527         free(byte);
528 }
529
530 int
531 bundle_export_to_argv(bundle *b, char ***argv)
532 {
533         int argc, item_count;
534
535         item_count = bundle_get_count(b);
536         argc = 2 * item_count + 2;      /* 2 more count for argv[0] and arv[1] = encoded */
537         *argv = calloc(argc + 1, sizeof(char *));
538         if(!*argv) return -1;
539
540         struct _argv_idx vi;
541         vi.argc = argc;
542         vi.argv = *argv;
543         vi.idx = 2;                      /* start from index 2*/
544         vi.argv[1]="`zaybxcwdveuftgsh`";                /* set argv[1] as encoded*/
545         /*BUNDLE_LOG_PRINT("\nargument 1 is %s",vi.argv[1]);*/
546
547         bundle_foreach(b, _iter_export_to_argv, &vi);
548
549         return argc;
550 }
551
552 int bundle_free_exported_argv(int argc, char ***argv)
553 {
554         if(!*argv) return -1;           /*TC_FIX : fix for double free- sigabrt */
555         
556         int i;
557         for(i=1; i < argc; i+=2) {
558                 free((*argv)[i+1]);
559         }
560
561         free(*argv);
562         *argv= NULL;
563         return 0;
564 }
565
566 bundle *
567 bundle_import_from_argv(int argc, char **argv)
568 {
569         if(!argv) return NULL;  /* TC_FIX error handling for argv =NULL*/
570
571         bundle *b = bundle_create();
572         if(!b) return NULL;
573
574
575         /*
576         int i;
577         for(i=0; i<argc; i++) {
578                 BUNDLE_LOG_PRINT("[bundle-dbg] argv[%d]='%s'\n", i, argv[i]);
579         }
580         */
581
582         if(!argv[1]||strcmp(argv[1],"`zaybxcwdveuftgsh`"))
583         {
584         /*BUNDLE_LOG_PRINT("\nit is not encoded");*/
585                 int idx;
586                 for (idx = 1; idx < argc; idx = idx + 2) {        /*start idx from one as argv[1] is user given argument*/
587                         bundle_add(b, argv[idx], argv[idx + 1]);
588                 }
589                 return b;
590         }
591         /*BUNDLE_LOG_PRINT("\nit is encoded");*/
592         int idx, type;
593         keyval_t *kv = NULL;
594         keyval_array_t *kva = NULL;
595         unsigned char *byte = NULL;
596         char *encoded_byte;
597         unsigned int byte_size;
598         for(idx = 2; idx < argc; idx = idx+2) {  // start idx from 2 as argv[1] is encoded
599                 kv = NULL;
600                 kva = NULL;
601
602                 encoded_byte = argv[idx+1];
603
604                 // base64_decode
605                 byte = g_base64_decode(encoded_byte, &byte_size);
606                 if(NULL == byte) goto err_cleanup;
607
608                 type = keyval_get_type_from_encoded_byte(byte);
609                 if(keyval_type_is_array(type)) {
610                         if(0 == keyval_array_decode(byte, &kva)) {
611                                 // TODO: error!
612                                 BUNDLE_EXCEPTION_PRINT("Unable to Decode array\n");
613                         }
614                         kv = (keyval_t *)kva;
615                 }
616                 else {
617                         if(0 == keyval_decode(byte, &kv)) {
618                                 // TODO: error!
619                                 BUNDLE_EXCEPTION_PRINT("Unable to Decode\n");
620                         }
621                 }
622                 _bundle_append_kv(b, kv);
623
624                 free(byte);
625                 byte = NULL;
626         }
627         return b;
628
629
630 err_cleanup:
631         if(b) bundle_free(b);
632         if(byte) free(byte);
633         return NULL;
634
635 }
636
637
638 int
639 bundle_get_type(bundle *b, const char *key)
640 {
641         keyval_t *kv = _bundle_find_kv(b, key);
642         if(kv) return kv->type;
643         else {
644                 errno = ENOKEY;
645                 return BUNDLE_TYPE_NONE;
646         }
647 }
648
649 // array functions
650 /** Get length of an array
651  */
652 unsigned int
653 bundle_get_array_len(bundle *b, const char *key)
654 {
655         return 0;
656 }
657
658 /** Get size of an item in byte, of given pointer
659  */
660 size_t
661 bundle_get_array_val_size(bundle *b, const char *key, const void *val_ptr)
662 {
663         return 0;
664 }
665 /*static int
666 bundle_set_array_val(bundle *b, const char *key, const int type, const unsigned int idx, const void *val, const size_t size)
667 {
668         //void **array = NULL;
669
670         keyval_t *kv = _bundle_find_kv(b, key);
671         if(NULL == kv) return -1;
672
673         if(type != kv->type) {
674                 errno = EINVAL;
675                 return -1;
676         }
677
678         if(! keyval_type_is_array(kv->type)) {  // TODO: Is this needed?
679                 errno = EINVAL;
680                 return -1;
681         }
682
683         keyval_array_t *kva = (keyval_array_t *)kv;
684
685         if(! keyval_array_is_idx_valid(kva, idx)) {
686                 errno = EINVAL;
687                 return -1;
688         }
689
690         if(!kva->array_val) {   // NULL value test (TODO: is this needed?)
691                 errno = ENOMEM;
692                 return -1;
693         }
694
695         return keyval_array_set_element(kva, idx, val, size);
696 }*/
697
698
699 int
700 bundle_add_str_array(bundle *b, const char *key, const char **str_array, const int len)
701 {
702         return _bundle_add_kv(b, key, str_array, 0, BUNDLE_TYPE_STR_ARRAY, len);
703 }
704
705
706 int
707 bundle_get_val_array(bundle *b, const char *key, char ***str_array, int *len)
708 {
709         return _bundle_get_val(b, key, BUNDLE_TYPE_STR_ARRAY, (void **) str_array, NULL,(unsigned int *)len, NULL);
710 }
711
712 const char ** bundle_get_str_array(bundle *b, const char *key,int *len)
713 {
714         const char **arr_val = NULL;
715         int r = 0;
716
717         r = bundle_get_val_array(b,key,(char***)&arr_val,len);
718         return arr_val;
719
720 }
721
722
723 int
724 bundle_compare(bundle *b1, bundle *b2)
725 {
726         if(!b1 || !b2) return -1;
727
728         keyval_t *kv1, *kv2;
729         //keyval_array_t *kva1, *kva2;
730         //char *key;
731
732         if(bundle_get_count(b1) != bundle_get_count(b2)) return 1;
733         for(kv1 = b1->kv_head; kv1 != NULL; kv1 = kv1->next) {
734                 kv2 = _bundle_find_kv(b2, kv1->key);
735                 if(!kv2) return 1;
736                 if(kv1->method->compare(kv1, kv2)) return 1;
737         }
738         return 0;
739 }
740
741
742
743 #if 0
744 int
745 bundle_set_str_array_element(bundle *b, const char *key, const unsigned int idx, const char *val)
746 {
747         if(!val) {
748                 errno = EINVAL;
749                 return -1;
750         }
751         return bundle_set_array_val(b, key, BUNDLE_TYPE_STR_ARRAY, idx, val, strlen(val)+1);
752 }
753
754
755 // byte type 
756 int
757 bundle_add_byte(bundle *b, const char *key, const void *byte, const size_t size)
758 {
759         return _bundle_add_kv(b, key, byte, size, BUNDLE_TYPE_BYTE, 1);
760 }
761
762 int
763 bundle_get_byte(bundle *b, const char *key, void **byte, size_t *size)
764 {
765         return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE, (void **) byte, size, NULL, NULL);
766 }
767
768 int
769 bundle_add_byte_array(bundle *b, const char *key, void **byte_array, const unsigned int len)
770 {
771         return _bundle_add_kv(b, key, byte_array, 0, BUNDLE_TYPE_BYTE_ARRAY, len);
772 }
773
774 int
775 bundle_get_byte_array(bundle *b, const char *key, void ***byte_array, unsigned int *len, unsigned int **array_element_size)
776 {
777         return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE_ARRAY, (void **)byte_array, NULL, len, array_element_size);
778 }
779
780
781 int
782 bundle_set_byte_array_element(bundle *b, const char *key, const unsigned int idx, const void *val, const size_t size)
783 {
784         return bundle_set_array_val(b, key, BUNDLE_TYPE_BYTE_ARRAY, idx, val, size);
785 }
786
787 #endif
788