2 * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * Implementation of keyval_array object
27 #include "bundle_log.h"
28 #include "bundle_private.h"
30 #include "keyval_array.h"
31 #include "keyval_type.h"
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
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)
44 int must_free_obj = kva ? 0 : 1;
48 kva = calloc(1, sizeof(keyval_array_t));
49 if (unlikely(kva == NULL)) {
50 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
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);
62 kv->type = kv->type | BUNDLE_TYPE_ARRAY;
65 /* Set array value, if exist */
67 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
69 keyval_array_free(kva, 1);
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);
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);
85 /* If available, copy 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! */
91 if (keyval_array_copy_array((keyval_array_t *)kv,
94 keyval_type_get_measure_size_func(type))
96 keyval_array_free(kva, 1);
102 kv->method = &method;
107 void keyval_array_free(keyval_array_t *kva, int do_free_object)
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]);
120 free(kva->array_val);
123 keyval_free((keyval_t *)kva, 0);
130 /* LCOV_EXCL_START */
131 int keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2)
140 kv1 = (keyval_t *)kva1;
141 kv2 = (keyval_t *)kva2;
143 if (strcmp(kv1->key, kv2->key) != 0)
145 if (kv1->type != kv2->type)
147 if (kva1->len != kva2->len)
150 for (i = 0; i < kva1->len; i++) {
151 if (kva1->array_val[i] == NULL && kva2->array_val[i] == NULL)
153 if (kva1->array_val[i] == NULL || kva2->array_val[i] == NULL)
155 if (memcmp(kva1->array_val[i], kva2->array_val[i],
156 kva1->array_element_size[i]) != 0)
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))
167 keyval_t *kv = (keyval_t *)kva;
168 keyval_type_measure_size_func_t measure_size;
171 /* Get measure_size function of the value type */
172 measure_size = keyval_type_get_measure_size_func(kv->type);
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);
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]);
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;
199 int keyval_array_is_idx_valid(keyval_array_t *kva, int idx)
201 if (kva && kva->len > idx && 0 <= idx)
206 int keyval_array_set_element(keyval_array_t *kva, int idx, void *val, size_t size)
208 keyval_t *kv = (keyval_t *)kva;
212 return BUNDLE_ERROR_INVALID_PARAMETER;
214 /* An element is already exist in the idx! */
215 if (kva->array_val[idx]) {
216 /* val==NULL means 'Free this element!' */
218 free(kva->array_val[idx]);
219 kva->array_val[idx] = NULL;
220 kva->array_element_size[idx] = 0;
223 return BUNDLE_ERROR_INVALID_PARAMETER;
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;
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';
238 kva->array_element_size[idx] = size;
242 return BUNDLE_ERROR_NONE;
245 int keyval_array_get_data(keyval_array_t *kva, int *type, void ***array_val,
246 unsigned int *len, size_t **array_element_size)
251 return BUNDLE_ERROR_INVALID_PARAMETER;
253 kv = (keyval_t *)kva;
254 if (!keyval_type_is_array(kv->type))
255 return BUNDLE_ERROR_INVALID_PARAMETER;
261 *array_val = kva->array_val;
264 if (array_element_size)
265 *array_element_size = kva->array_element_size;
267 return BUNDLE_ERROR_NONE;
270 size_t keyval_array_get_encoded_size(keyval_array_t *kva)
272 size_t sum_array_element_size = 0;
274 size_t encoded_size = 0;
276 encoded_size += sizeof(size_t); /* total size */
277 encoded_size += sizeof(int); /* type */
278 encoded_size += sizeof(size_t); /* key size */
280 if ((encoded_size + strlen(((keyval_t *)kva)->key) + 1) < encoded_size)
283 encoded_size += strlen(((keyval_t *)kva)->key) + 1; /* key */
285 if ((encoded_size + sizeof(int)) < encoded_size)
288 encoded_size += sizeof(int); /* len */
290 if ((encoded_size + (kva->len * sizeof(size_t))) < encoded_size)
293 encoded_size += kva->len * sizeof(size_t); /* array_element_size */
295 for (i = 0; i < kva->len; i++) {
296 if ((sum_array_element_size + kva->array_element_size[i]) < sum_array_element_size)
299 sum_array_element_size += kva->array_element_size[i];
302 if ((encoded_size + sum_array_element_size) < encoded_size)
305 encoded_size += sum_array_element_size;
310 size_t keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len)
312 keyval_t *kv = (keyval_t *)kva;
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);
322 /* Allocate memory */
323 *byte_len = keyval_array_get_encoded_size(kva);
327 *byte = calloc(1, *byte_len);
334 memcpy(p, byte_len, sizeof(size_t));
336 memcpy(p, &(kv->type), sz_type);
338 memcpy(p, &sz_key, sz_keysize);
340 memcpy(p, kv->key, sz_key);
342 memcpy(p, &(kva->len), sz_len);
344 memcpy(p, kva->array_element_size, sz_array_element_size);
345 p += sz_array_element_size;
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];
355 size_t keyval_array_decode(void *byte, keyval_array_t **kva, size_t byte_size)
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;
367 size_t *array_element_size;
370 size_t elem_size = 0;
371 size_t sum_array_element_size = 0;
374 if (byte_size < sz_byte_len)
377 memcpy(&byte_len, p, sz_byte_len);
378 if (byte_size < byte_len)
381 byte_size -= sz_byte_len;
384 if (byte_size < sz_type)
387 memcpy(&type, p, sz_type);
388 byte_size -= sz_type;
391 if (byte_size < sz_keysize)
394 memcpy(&keysize, p, sz_keysize);
395 byte_size -= sz_keysize;
398 if (byte_size < keysize)
402 if (!key || (strnlen(key, keysize) + 1) != keysize)
405 byte_size -= keysize;
408 if (byte_size < sz_len)
411 memcpy(&len, p, sz_len);
415 if ((sizeof(size_t) * len) < len)
418 if (byte_size < (sizeof(size_t) * len))
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)
426 sum_array_element_size += array_element_size[i];
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)
434 p += sizeof(size_t) * len;
435 array_val = (void *)p;
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);