866667880769515adf37a22abf9e658a7cca8066
[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
38
39 static keyval_method_collection_t method = {
40         (keyval_method_free_t) keyval_array_free,
41         (keyval_method_compare_t) keyval_array_compare,
42         (keyval_method_get_encoded_size_t) keyval_array_get_encoded_size,
43         (keyval_method_encode_t) keyval_array_encode,
44         (keyval_method_decode_t) keyval_array_decode
45 };
46
47 keyval_array_t *
48 keyval_array_new(keyval_array_t *kva, const char *key, const int type,
49                 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                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
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                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
66                         return NULL;
67         }
68
69         kv->type = kv->type | BUNDLE_TYPE_ARRAY;
70
71         kva->len = len;
72
73         /* Set array value, if exist */
74         if (kva->array_val) {
75                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
76                 if (must_free_obj)
77                         keyval_array_free(kva, 1);
78                 return NULL;
79         }
80         kva->array_val = calloc(len, sizeof(void *));
81         if (!(kva->array_val)) {
82                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
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                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
90                 keyval_array_free(kva, 1);
91                 return NULL;
92         }
93         /* If available, 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)
119                 return;
120
121         /* free keyval_array elements */
122         free(kva->array_element_size);
123         int i;
124         for (i = 0; i < kva->len; i++) {
125                 if (kva->array_val[i])
126                         free(kva->array_val[i]);
127         }
128         free(kva->array_val);
129
130         /* free parent */
131         keyval_free((keyval_t *)kva, 0);
132
133         /* free object */
134         if (do_free_object)
135                 free(kva);
136 }
137
138 int
139 keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2)
140 {
141         keyval_t *kv1, *kv2;
142         if (!kva1 || !kva2)
143                 return -1;
144
145         kv1 = (keyval_t *)kva1;
146         kv2 = (keyval_t *)kva2;
147
148         if (0 != strcmp(kv1->key, kv2->key))
149                 return 1;
150         if (kv1->type != kv2->type)
151                 return 1;
152         if (kva1->len != kva2->len)
153                 return 1;
154         int i;
155         for (i = 0; i < kva1->len; i++) {
156                 if (kva1->array_val[i] == NULL && kva2->array_val[i] == NULL)
157                         continue;
158                 if (kva1->array_val[i] == NULL || kva2->array_val[i] == NULL)
159                         return 1;
160                 if (0 != memcmp(kva1->array_val[i], kva2->array_val[i],
161                                         kva1->array_element_size[i]))
162                         return 1;
163         }
164
165         return 0;
166 }
167
168 int
169 keyval_array_copy_array(keyval_array_t *kva, void **array_val,
170                 unsigned int array_len, size_t (*measure_val_len)(void *val))
171 {
172         keyval_t *kv = (keyval_t *)kva;
173         int i;
174
175         /* Get measure_size function of the value type */
176         keyval_type_measure_size_func_t measure_size =
177                 keyval_type_get_measure_size_func(kv->type);
178         if (!measure_size)
179                 return -1;
180
181         /* Copy each array item */
182         for (i = 0; i < array_len; i++) {
183                 kva->array_val[i] = malloc(measure_size(array_val[i]));
184                 if (!(kva->array_val[i])) {
185                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
186                         goto cleanup_exit;
187                 }
188                 memcpy(kva->array_val[i], array_val[i],
189                                 measure_size(array_val[i]));
190                 kva->array_element_size[i] = measure_size(array_val[i]);
191         }
192         return 0;
193
194 cleanup_exit:
195         for (i = 0; i < array_len; i++) {
196                 if (kva->array_val[i]) {
197                         free(kva->array_val[i]);
198                         kva->array_val[i] = NULL;
199                 }
200         }
201         return -1;
202 }
203
204 int
205 keyval_array_is_idx_valid(keyval_array_t *kva, int idx)
206 {
207         if (kva && kva->len > idx && 0 <= idx)
208                 return 1;
209         return 0;
210 }
211
212 int
213 keyval_array_set_element(keyval_array_t *kva, int idx, void *val, size_t size)
214 {
215         /* An element is already exist in the idx! */
216         if (kva->array_val[idx]) {
217                 /* val==NULL means 'Free this element!' */
218                 if (!val) {
219                         free(kva->array_val[idx]);
220                         kva->array_val[idx] = NULL;
221                         kva->array_element_size[idx] = 0;
222                 } else {
223                         /* Error case! */
224                         return BUNDLE_ERROR_INVALID_PARAMETER;
225                 }
226         } else {
227                 /* Normal case. Copy value into the array. */
228                 kva->array_val[idx] = malloc(size);
229                 if (!(kva->array_val[idx]))
230                         return BUNDLE_ERROR_OUT_OF_MEMORY;
231                 if (val) {
232                         memcpy(kva->array_val[idx], val, size);
233                         kva->array_element_size[idx] = size;
234                 }
235         }
236
237         return BUNDLE_ERROR_NONE;
238 }
239
240 int
241 keyval_array_get_data(keyval_array_t *kva, int *type,
242                 void ***array_val, unsigned int *len, size_t **array_element_size)
243 {
244         if (!kva)
245                 return BUNDLE_ERROR_INVALID_PARAMETER;
246         keyval_t *kv = (keyval_t *)kva;
247         if (!keyval_type_is_array(kv->type))
248                 return BUNDLE_ERROR_INVALID_PARAMETER;
249
250         /* Return values */
251         if (type)
252                 *type = kv->type;
253         if (array_val)
254                 *array_val = kva->array_val;
255         if (len)
256                 *len = kva->len;
257         if (array_element_size)
258                 *array_element_size = kva->array_element_size;
259
260         return BUNDLE_ERROR_NONE;
261 }
262
263 size_t
264 keyval_array_get_encoded_size(keyval_array_t *kva)
265 {
266         size_t sum_array_element_size = 0;
267         int i;
268         for (i = 0; i < kva->len; i++) {
269                 sum_array_element_size += kva->array_element_size[i];
270         }
271         size_t encoded_size
272                 = sizeof(size_t) /* total size */
273                 + sizeof(int)    /* type */
274                 + sizeof(size_t) /* keysize */
275                 + strlen(((keyval_t *)kva)->key) + 1 /* key (+ null byte) */
276                 + sizeof(int)    /* len */
277                 + kva->len * sizeof(size_t)          /* array_element_size */
278                 + sum_array_element_size;
279
280         return encoded_size;
281 }
282
283 size_t
284 keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len)
285 {
286         keyval_t *kv = (keyval_t *)kva;
287         int i;
288
289         /* Calculate memory size for kva */
290         static const size_t sz_type = sizeof(int);
291         static const size_t sz_keysize = sizeof(size_t);
292         size_t sz_key = strlen(kv->key) + 1;
293         static const unsigned int sz_len = sizeof(int);
294         size_t sz_array_element_size = kva->len * sizeof(size_t);
295         size_t sz_array_val = 0;
296         for (i = 0; i < kva->len; i++) {
297                 sz_array_val += kva->array_element_size[i];
298         }
299
300         /* Allocate memory */
301         *byte_len = keyval_array_get_encoded_size(kva);
302         *byte = calloc(1, *byte_len);
303         if (!*byte)
304                 return 0;
305
306         /* Copy data */
307         unsigned char *p = *byte;
308
309         memcpy(p, byte_len, sizeof(size_t)); p += sizeof(size_t);
310         memcpy(p, &(kv->type), sz_type); p += sz_type;
311         memcpy(p, &sz_key, sz_keysize); p += sz_keysize;
312         memcpy(p, kv->key, sz_key); p += sz_key;
313         memcpy(p, &(kva->len), sz_len); p += sz_len;
314         memcpy(p, kva->array_element_size, sz_array_element_size);
315         p += sz_array_element_size;
316         for (i = 0; i < kva->len; i++) {
317                 memcpy(p, kva->array_val[i], kva->array_element_size[i]);
318                 p += kva->array_element_size[i];
319         }
320
321         return *byte_len;
322 }
323
324 size_t
325 keyval_array_decode(void *byte, keyval_array_t **kva)
326 {
327         static const size_t sz_byte_len = sizeof(size_t);
328         static const size_t sz_type = sizeof(int);
329         static const size_t sz_keysize = sizeof(size_t);
330         static const int sz_len = sizeof(unsigned int);
331
332         unsigned char *p = byte;
333
334         /* Get data */
335         size_t byte_len = *((size_t *)p); p += sz_byte_len;
336         int type = *((int *)p); p += sz_type;
337         size_t keysize = *((size_t *)p); p += sz_keysize;
338         char *key = (char *)p; p += keysize;
339         unsigned int len = *((unsigned int *)p); p += sz_len;
340         size_t *array_element_size = (size_t *) p; p += sizeof(size_t) * len;
341         void *array_val = (void *)p;
342
343         *kva = keyval_array_new(NULL, key, type, NULL, len);
344         int i;
345         size_t elem_size = 0;
346         for (i = 0; i < len; i++) {
347                 elem_size += i ? array_element_size[i-1] : 0;
348                 if (keyval_array_set_element(*kva, i,
349                                         (void *)(array_val+elem_size),
350                                         array_element_size[i])) {
351                         keyval_array_free(*kva, 1);
352                         *kva = NULL;
353                         return 0;
354                 }
355         }
356
357         return byte_len;
358 }
359