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