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