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