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