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