af2aa12a6add68ea801db49b85efc5f893be97dd
[platform/core/base/bundle.git] / src / keyval_array.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  * keyval_array.c
26  * Implementation of keyval_array object
27  */
28
29 #include "keyval_array.h"
30 #include "keyval.h"
31 #include "keyval_type.h"
32 #include "bundle.h"
33 #include "bundle_log.h"
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <errno.h>
38
39
40 static keyval_method_collection_t method = {
41         (keyval_method_free_t) keyval_array_free,
42         (keyval_method_compare_t) keyval_array_compare,
43         (keyval_method_get_encoded_size_t) keyval_array_get_encoded_size,
44         (keyval_method_encode_t) keyval_array_encode,
45         (keyval_method_decode_t) keyval_array_decode
46 };
47
48 keyval_array_t *
49 keyval_array_new(keyval_array_t *kva, const char *key, const int type, const void **array_val, const unsigned int len)
50 {
51         int must_free_obj;
52         must_free_obj = kva ? 0 : 1;
53
54         if(!kva) {
55                 kva = calloc(1, sizeof(keyval_array_t));
56                 if(unlikely(NULL==kva)) {
57                         errno = ENOMEM;
58                         return NULL;
59                 }
60         }
61
62         // keyval setting
63         keyval_t *kv = keyval_new((keyval_t *)kva, key, type, NULL, 0);
64         if(unlikely(NULL==kv))
65         {
66                         errno = ENOMEM;
67                         return NULL;
68         }
69
70         kv->type = kv->type | BUNDLE_TYPE_ARRAY;
71
72         kva->len = len;
73
74         // Set array value, if exist
75         if(kva->array_val) {
76                 errno=EINVAL;
77                 if(must_free_obj) keyval_array_free(kva, 1);
78                 return NULL;
79         }
80         kva->array_val = calloc(len, sizeof(void *));
81         if(!(kva->array_val)) {
82                 errno = ENOMEM;
83                 keyval_array_free(kva, 1);
84                 return NULL;
85         }
86         // array_element_size
87         kva->array_element_size = calloc(len, sizeof(size_t));
88         if(!(kva->array_element_size)) {
89                 errno = ENOMEM;
90                 keyval_array_free(kva, 1);
91                 return NULL;
92         }
93         // If avaliable, copy array val
94         if(array_val
95                 && keyval_type_is_measurable(type)
96                 && keyval_type_get_measure_size_func(type)) {
97                 // array_val have original data array. copy it!
98
99                 if(keyval_array_copy_array((keyval_array_t*)kv,
100                                         (void**)array_val,
101                                         len,
102                                         keyval_type_get_measure_size_func(type))
103                                 ) {
104                         keyval_array_free(kva, 1);
105                         return NULL;
106                 }
107         }
108
109         // Set methods
110         kv->method = &method;
111
112         return kva;
113 }
114
115 void
116 keyval_array_free(keyval_array_t *kva, int do_free_object)
117 {
118         if(!kva) return;
119
120         // free keyval_array elements
121         free(kva->array_element_size);
122         int i;
123         for(i=0; i<kva->len; i++) {
124                 if(kva->array_val[i]) free(kva->array_val[i]);
125         }
126         free(kva->array_val);
127         
128         // free parent
129         keyval_free((keyval_t *)kva, 0);
130
131         // free object
132         if(do_free_object) free(kva);
133 }
134
135 int 
136 keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2)
137 {
138         keyval_t *kv1, *kv2;
139         if(!kva1 || !kva2) return -1;
140
141         kv1 = (keyval_t *)kva1;
142         kv2 = (keyval_t *)kva2;
143
144         if(0 != strcmp(kv1->key, kv2->key)) return 1;
145         if(kv1->type != kv2->type) return 1;
146         if(kva1->len != kva2->len) return 1;
147         int i;
148         for(i=0; i<kva1->len; i++) {
149                 if(kva1->array_val[i] == NULL && kva2->array_val[i] == NULL) continue;
150                 if(kva1->array_val[i] == NULL || kva2->array_val[i] == NULL) return 1;
151                 if(0 != memcmp(kva1->array_val[i], kva2->array_val[i], kva1->array_element_size[i])) return 1;
152         }
153
154         return 0;
155 }
156
157 int
158 keyval_array_copy_array(keyval_array_t *kva, void **array_val, unsigned int array_len, size_t (*measure_val_len)(void * val))
159 {
160         keyval_t *kv = (keyval_t *)kva;
161
162         // Get measure_size function of the value type
163         keyval_type_measure_size_func_t measure_size = keyval_type_get_measure_size_func(kv->type);
164         if(!measure_size) return -1;
165         
166         // Copy each array item
167         int i;
168         for(i=0; i < array_len; i++) {
169                 kva->array_val[i] = malloc(measure_size(array_val[i]));
170                 if(!(kva->array_val[i])) {
171                         errno = ENOMEM;
172                         goto cleanup_exit;
173                 }
174                 memcpy(kva->array_val[i], array_val[i], measure_size(array_val[i]));
175                 kva->array_element_size[i] = measure_size(array_val[i]);
176         }
177         return 0;
178
179 cleanup_exit:
180         for(i=0; i<array_len; i++) {
181                 if(kva->array_val[i]) {
182                         free(kva->array_val[i]);
183                         kva->array_val[i] = NULL;
184                 }
185         }
186         return -1;
187 }
188
189 int
190 keyval_array_is_idx_valid(keyval_array_t *kva, int idx)
191 {
192         //keyval_t *kv = (keyval_t *)kva;
193         if(kva && kva->len > idx && 0 <= idx) return 1;
194         return 0;
195 }
196
197 int
198 keyval_array_set_element(keyval_array_t *kva, int idx, void *val, size_t size)
199 {
200         if(kva->array_val[idx]) {       // An element is already exist in the idx!
201                 if(!val) {      // val==NULL means 'Free this element!' 
202                         free(kva->array_val[idx]);
203                         kva->array_val[idx] = NULL;
204                         kva->array_element_size[idx] = 0;
205                 }
206                 else {
207                         // Error case!
208                         errno = EINVAL;
209                         return -1;
210                 }
211         }
212         else {
213                 // Normal case. Copy value into the array.
214                 kva->array_val[idx] = malloc(size);
215                 if(!(kva->array_val[idx])) {
216                         errno = ENOMEM;
217                         return -1;
218                 }
219                 if(val) {
220                         memcpy(kva->array_val[idx], val, size); // val
221                         kva->array_element_size[idx] = size;    // size
222                 }
223         }
224
225         return 0;
226 }
227
228 int
229 keyval_array_get_data(keyval_array_t *kva, int *type,
230                 void ***array_val, unsigned int *len, size_t **array_element_size)
231 {
232         if(!kva) return -EINVAL;
233         keyval_t *kv = (keyval_t *)kva;
234         if(!keyval_type_is_array(kv->type)) return -EINVAL;
235         
236         // Return values
237         if(type) *type = kv->type;
238         if(array_val) *array_val = kva->array_val;
239         if(len) *len = kva->len;
240         if(array_element_size) *array_element_size = kva->array_element_size;
241
242         return 0;
243 }
244
245 size_t
246 keyval_array_get_encoded_size(keyval_array_t *kva)
247 {
248         size_t sum_array_element_size = 0;
249         int i;
250         for(i=0; i < kva->len; i++) {
251                 sum_array_element_size += kva->array_element_size[i];
252         }
253         size_t encoded_size
254                 = sizeof(size_t) // total size
255                 + sizeof(int) // type
256                 + sizeof(size_t) // keysize
257                 + strlen(((keyval_t *)kva)->key) + 1 // key (+ null byte)
258                 + sizeof(int) // len
259                 + kva->len * sizeof(size_t) // array_element_size
260                 + sum_array_element_size;
261
262         return encoded_size;
263 }
264
265 size_t
266 keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len)
267 {
268         keyval_t *kv = (keyval_t *)kva;
269         int i;
270
271         // Calculate memory size for kva
272         static const size_t sz_type = sizeof(int);
273         static const size_t sz_keysize = sizeof(size_t);
274         size_t sz_key = strlen(kv->key) + 1;
275         static const unsigned int sz_len = sizeof(int);
276         size_t sz_array_element_size = kva->len * sizeof(size_t);
277         size_t sz_array_val = 0;
278         for(i=0; i < kva->len; i++) {
279                 sz_array_val += kva->array_element_size[i];
280         }
281
282         // Allocate memory
283         *byte_len = keyval_array_get_encoded_size(kva);
284         *byte = calloc(1, *byte_len);
285         if(!*byte) return 0;
286         
287         // Copy data
288         unsigned char *p = *byte;
289
290         memcpy(p, byte_len, sizeof(size_t)); p += sizeof(size_t);
291         memcpy(p, &(kv->type), sz_type); p += sz_type;
292         memcpy(p, &sz_key, sz_keysize); p += sz_keysize;
293         memcpy(p, kv->key, sz_key); p += sz_key;
294         memcpy(p, &(kva->len), sz_len); p += sz_len;
295         memcpy(p, kva->array_element_size, sz_array_element_size); p += sz_array_element_size;
296         for(i=0; i < kva->len; i++) {
297                 memcpy(p, kva->array_val[i], kva->array_element_size[i]);
298                 p += kva->array_element_size[i];
299         }
300
301         return *byte_len;
302 }
303
304 size_t
305 keyval_array_decode(void *byte, keyval_array_t **kva)
306 {
307         static const size_t sz_byte_len = sizeof(size_t);
308         static const size_t sz_type = sizeof(int);
309         static const size_t sz_keysize = sizeof(size_t);
310         static const int sz_len = sizeof(unsigned int);
311
312         unsigned char *p = byte;
313
314         // Get data
315         size_t byte_len = *((size_t *)p); p += sz_byte_len;
316         int type = *((int *)p); p += sz_type;
317         size_t keysize = *((size_t *)p); p += sz_keysize;
318         char *key = (char *)p; p += keysize;
319         unsigned int len = *((unsigned int *)p); p += sz_len;
320         size_t *array_element_size = (size_t *) p; p += sizeof(size_t) * len;
321         void *array_val = (void *)p;
322
323         *kva = keyval_array_new(NULL, key, type, NULL, len);
324         int i;
325         size_t elem_size = 0;
326         for(i=0; i < len; i++) {
327                 elem_size += i ? array_element_size[i-1] : 0;
328                 if(keyval_array_set_element(*kva, i, (void *)(array_val+elem_size), array_element_size[i])) {
329                         keyval_array_free(*kva, 1);
330                         *kva = NULL;
331                         return 0;
332                 }
333         }
334
335         return byte_len;
336 }
337