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
25 #include "keyval_array.h"
27 #include "keyval_type.h"
29 #include "bundle_log.h"
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
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)
42 int must_free_obj = kva ? 0 : 1;
46 kva = calloc(1, sizeof(keyval_array_t));
47 if (unlikely(kva == NULL)) {
48 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
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);
60 kv->type = kv->type | BUNDLE_TYPE_ARRAY;
63 /* Set array value, if exist */
65 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
67 keyval_array_free(kva, 1);
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);
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);
83 /* If available, copy 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! */
89 if (keyval_array_copy_array((keyval_array_t *)kv,
92 keyval_type_get_measure_size_func(type))
94 keyval_array_free(kva, 1);
100 kv->method = &method;
105 void keyval_array_free(keyval_array_t *kva, int do_free_object)
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]);
118 free(kva->array_val);
121 keyval_free((keyval_t *)kva, 0);
128 /* LCOV_EXCL_START */
129 int keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2)
138 kv1 = (keyval_t *)kva1;
139 kv2 = (keyval_t *)kva2;
141 if (strcmp(kv1->key, kv2->key) != 0)
143 if (kv1->type != kv2->type)
145 if (kva1->len != kva2->len)
148 for (i = 0; i < kva1->len; i++) {
149 if (kva1->array_val[i] == NULL && kva2->array_val[i] == NULL)
151 if (kva1->array_val[i] == NULL || kva2->array_val[i] == NULL)
153 if (memcmp(kva1->array_val[i], kva2->array_val[i],
154 kva1->array_element_size[i]) != 0)
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))
165 keyval_t *kv = (keyval_t *)kva;
166 keyval_type_measure_size_func_t measure_size;
169 /* Get measure_size function of the value type */
170 measure_size = keyval_type_get_measure_size_func(kv->type);
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);
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]);
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;
197 int keyval_array_is_idx_valid(keyval_array_t *kva, int idx)
199 if (kva && kva->len > idx && 0 <= idx)
204 int keyval_array_set_element(keyval_array_t *kva, int idx, void *val, size_t size)
206 /* An element is already exist in the idx! */
207 if (kva->array_val[idx]) {
208 /* val==NULL means 'Free this element!' */
210 free(kva->array_val[idx]);
211 kva->array_val[idx] = NULL;
212 kva->array_element_size[idx] = 0;
215 return BUNDLE_ERROR_INVALID_PARAMETER;
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;
223 memcpy(kva->array_val[idx], val, size);
224 kva->array_element_size[idx] = size;
228 return BUNDLE_ERROR_NONE;
231 int keyval_array_get_data(keyval_array_t *kva, int *type, void ***array_val,
232 unsigned int *len, size_t **array_element_size)
237 return BUNDLE_ERROR_INVALID_PARAMETER;
239 kv = (keyval_t *)kva;
240 if (!keyval_type_is_array(kv->type))
241 return BUNDLE_ERROR_INVALID_PARAMETER;
247 *array_val = kva->array_val;
250 if (array_element_size)
251 *array_element_size = kva->array_element_size;
253 return BUNDLE_ERROR_NONE;
256 size_t keyval_array_get_encoded_size(keyval_array_t *kva)
258 size_t sum_array_element_size = 0;
262 for (i = 0; i < kva->len; i++)
263 sum_array_element_size += kva->array_element_size[i];
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;
276 size_t keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len)
278 keyval_t *kv = (keyval_t *)kva;
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;
289 for (i = 0; i < kva->len; i++)
290 sz_array_val += kva->array_element_size[i];
292 /* Allocate memory */
293 *byte_len = keyval_array_get_encoded_size(kva);
294 *byte = calloc(1, *byte_len);
301 memcpy(p, byte_len, sizeof(size_t));
303 memcpy(p, &(kv->type), sz_type);
305 memcpy(p, &sz_key, sz_keysize);
307 memcpy(p, kv->key, sz_key);
309 memcpy(p, &(kva->len), sz_len);
311 memcpy(p, kva->array_element_size, sz_array_element_size);
312 p += sz_array_element_size;
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];
322 size_t keyval_array_decode(void *byte, keyval_array_t **kva, size_t byte_size)
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;
334 size_t *array_element_size;
337 size_t elem_size = 0;
340 byte_len = *((size_t *)p);
342 if (byte_size < sz_byte_len)
345 byte_size -= sz_byte_len;
349 if (byte_size < sz_type)
352 byte_size -= sz_type;
354 keysize = *((size_t *)p);
356 if (byte_size < sz_keysize)
359 byte_size -= sz_keysize;
363 if (byte_size < keysize)
366 byte_size -= keysize;
368 len = *((unsigned int *)p);
370 if (byte_size < sz_len)
375 array_element_size = (size_t *)p;
377 if (byte_size < (sizeof(size_t) * len))
380 p += sizeof(size_t) * len;
381 array_val = (void *)p;
383 *kva = keyval_array_new(NULL, key, type, NULL, len);
384 for (i = 0; i < len; i++) {
385 elem_size += i ? array_element_size[i - 1] : 0;
386 if (keyval_array_set_element(*kva, i,
387 (void *)(array_val + elem_size),
388 array_element_size[i])) {
389 keyval_array_free(*kva, 1);