Update doxygen
[platform/core/base/bundle.git] / src / keyval.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.c
19  * Implementation of keyval object
20  */
21
22 #define _GNU_SOURCE
23 #include <stdlib.h>
24
25 #include "keyval_type.h"
26 #include "keyval.h"
27 #include "bundle_log.h"
28 #include "bundle.h"
29
30 static keyval_method_collection_t method = {
31         keyval_free,
32         keyval_compare,
33         keyval_get_encoded_size,
34         keyval_encode,
35         keyval_decode
36 };
37
38 keyval_t *keyval_new(keyval_t *kv, const char *key,
39                 const int type, const void *val, const size_t size)
40 {
41         int must_free_obj = kv ? 0 : 1;
42         char *str;
43
44         if (!kv) {
45                 kv = calloc(1, sizeof(keyval_t));
46                 if (!kv) {
47                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
48                         return NULL;
49                 }
50         }
51
52         if (kv->key) {
53                 keyval_free(kv, must_free_obj);
54                 return NULL;
55         }
56
57         kv->key = strdup(key);
58         if (!kv->key) {
59                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
60                 keyval_free(kv, must_free_obj);
61                 return NULL;
62         }
63
64         kv->type = type;
65         kv->size = size;
66
67         if (size) {
68                 kv->val = calloc(1, size);
69                 if (!kv->val) {
70                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
71                         keyval_free(kv, must_free_obj);
72                         return NULL;
73                 }
74                 if (val) {
75                         memcpy(kv->val, val, size);
76                         if (type == BUNDLE_TYPE_STR) {
77                                 str = (char *)kv->val;
78                                 if (str[size - 1] != '\0')
79                                         str[size - 1] = '\0';
80                         }
81                 }
82         }
83
84         kv->method = &method;
85
86         return kv;
87 }
88
89 void keyval_free(keyval_t *kv, int do_free_object)
90 {
91         if (kv == NULL)
92                 return;
93
94         if (kv->key) {
95                 free(kv->key);
96                 kv->key = NULL;
97         }
98
99         if (kv->val != NULL) {
100                 free(kv->val);
101                 kv->val = NULL;
102         }
103
104         if (do_free_object)
105                 free(kv);
106
107         return;
108 }
109
110 int keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size)
111 {
112         if (!kv)
113                 return BUNDLE_ERROR_INVALID_PARAMETER;
114
115         if (keyval_type_is_array(kv->type))
116                 return BUNDLE_ERROR_INVALID_PARAMETER;
117
118         if (type)
119                 *type = kv->type;
120         if (val)
121                 *val = kv->val;
122         if (size)
123                 *size = kv->size;
124
125         return 0;
126 }
127
128 /* LCOV_EXCL_START */
129 int keyval_compare(keyval_t *kv1, keyval_t *kv2)
130 {
131         if (!kv1 || !kv2)
132                 return -1;
133
134         if (strcmp(kv1->key, kv2->key) != 0)
135                 return 1;
136         if (kv1->type != kv2->type)
137                 return 1;
138         if (kv1->size != kv2->size)
139                 return 1;
140
141         if (kv1->val == NULL && kv2->val == NULL)
142                 return 0;
143         if (kv1->val == NULL || kv2->val == NULL)
144                 return 1;
145         if (memcmp(kv1->val, kv2->val, kv1->size) != 0)
146                 return 1;
147
148         return 0;
149 }
150 /* LCOV_EXCL_STOP */
151
152 size_t keyval_get_encoded_size(keyval_t *kv)
153 {
154         size_t encoded_size = 0;
155
156         if (!kv)
157                 return 0;
158
159         encoded_size += sizeof(size_t); /* total size */
160         encoded_size += sizeof(int); /* type */
161         encoded_size += sizeof(size_t); /* key size */
162
163         if ((encoded_size + strlen(kv->key) + 1) < encoded_size)
164                 return 0;
165
166         encoded_size += strlen(kv->key) + 1; /* key */
167
168         if ((encoded_size + sizeof(size_t)) < encoded_size)
169                 return 0;
170
171         encoded_size += sizeof(size_t); /* size */
172
173         if ((encoded_size + kv->size) < encoded_size)
174                 return 0;
175
176         encoded_size += kv->size; /* val */
177
178         return encoded_size;
179 }
180
181 /**
182  * encode a keyval to byte
183  *
184  * @pre                 kv must be valid.
185  * @post                byte must be freed.
186  * @param[in]   kv
187  * @param[out]  byte
188  * @param[out]  byte_len
189  * @return byte_len
190  */
191 size_t keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len)
192 {
193         static const size_t sz_type = sizeof(int);
194         static const size_t sz_keysize = sizeof(size_t);
195         size_t sz_key = strlen(kv->key) + 1;
196         static const size_t sz_size = sizeof(size_t);
197         size_t sz_val = kv->size;
198         unsigned char *p;
199
200         *byte_len = keyval_get_encoded_size(kv);
201         if (*byte_len == 0)
202                 return 0;
203
204         *byte = calloc(1, *byte_len);
205         if (!*byte)
206                 return 0;
207
208         p = *byte;
209
210         memcpy(p, byte_len, sizeof(size_t));
211         p += sizeof(size_t);
212         memcpy(p, &(kv->type), sz_type);
213         p += sz_type;
214         memcpy(p, &sz_key, sz_keysize);
215         p += sz_keysize;
216         memcpy(p, kv->key, sz_key);
217         p += sz_key;
218         memcpy(p, &(kv->size), sz_size);
219         p += sz_size;
220         memcpy(p, kv->val, sz_val);
221         p += sz_val;
222
223         return *byte_len;
224 }
225
226 /**
227  * decode a byte stream to a keyval
228  *
229  * @param[in]     byte  byte stream.
230  * @param[in|out] kv    keyval.
231  *                  If kv is NULL, new keyval_t object comes.
232  *                  If kv is not NULL, given kv is used. (No new kv is created.)
233  * @return        Number of bytes read from byte.
234  */
235 size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size)
236 {
237         static const size_t sz_byte_len = sizeof(size_t);
238         static const size_t sz_type = sizeof(int);
239         static const size_t sz_keysize = sizeof(size_t);
240         static const size_t sz_size = sizeof(size_t);
241         size_t byte_len;
242         int type;
243         size_t keysize;
244         char *key;
245         size_t size;
246         void *val;
247         unsigned char *p = byte;
248         size_t encoded_size;
249
250         if (byte_size < sz_byte_len)
251                 return 0;
252
253         memcpy(&byte_len, p, sz_byte_len);
254         if (byte_size < byte_len)
255                 return 0;
256
257         byte_size -= sz_byte_len;
258         p += sz_byte_len;
259
260         if (byte_size < sz_type)
261                 return 0;
262
263         memcpy(&type, p, sz_type);
264
265         byte_size -= sz_type;
266         p += sz_type;
267
268         if (byte_size < sz_keysize)
269                 return 0;
270
271         memcpy(&keysize, p, sz_keysize);
272
273         byte_size -= sz_keysize;
274         p += sz_keysize;
275
276         if (byte_size < keysize)
277                 return 0;
278
279         key = (char *)p;
280         if (!key || (strnlen(key, keysize) + 1) != keysize)
281                 return 0;
282
283         byte_size -= keysize;
284         p += keysize;
285
286         if (byte_size < sz_size)
287                 return 0;
288
289         memcpy(&size, p, sz_size);
290
291         encoded_size = sz_byte_len + sz_type + sz_keysize + keysize +
292                 sz_size + size;
293         if (encoded_size != byte_len)
294                 return 0;
295
296         p += sz_size;
297         val = (void *)p;
298
299         if (kv)
300                 *kv = keyval_new(*kv, key, type, val, size);
301
302         return byte_len;
303 }
304
305 int keyval_get_type_from_encoded_byte(unsigned char *byte)
306 {
307         static const size_t sz_byte_len = sizeof(size_t);
308         unsigned char *p = byte;
309         int type;
310
311         p += sz_byte_len;
312         memcpy(&type, p, sizeof(int));
313
314         return type;
315 }