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