4ca41bd51e454eb8f00f3ca436db9e3b1a6c7a14
[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, 1);
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 int keyval_compare(keyval_t *kv1, keyval_t *kv2)
121 {
122         if (!kv1 || !kv2)
123                 return -1;
124
125         if (strcmp(kv1->key, kv2->key) != 0)
126                 return 1;
127         if (kv1->type != kv2->type)
128                 return 1;
129         if (kv1->size != kv2->size)
130                 return 1;
131
132         if (kv1->val == NULL && kv2->val == NULL)
133                 return 0;
134         if (kv1->val == NULL || kv2->val == NULL)
135                 return 1;
136         if (memcmp(kv1->val, kv2->val, kv1->size) != 0)
137                 return 1;
138
139         return 0;
140 }
141
142 size_t keyval_get_encoded_size(keyval_t *kv)
143 {
144         size_t encoded_size;
145
146         if (!kv)
147                 return 0;
148
149         encoded_size = sizeof(size_t)   /* total size */
150                 + sizeof(int)           /* type */
151                 + sizeof(size_t)        /* key size */
152                 + strlen(kv->key) + 1   /* key (+ null byte) */
153                 + sizeof(size_t)        /* size */
154                 + kv->size;             /* val */
155
156         return encoded_size;
157 }
158
159 /**
160  * encode a keyval to byte
161  *
162  * @pre                 kv must be valid.
163  * @post                byte must be freed.
164  * @param[in]   kv
165  * @param[out]  byte
166  * @param[out]  byte_len
167  * @return byte_len
168  */
169 size_t keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len)
170 {
171         static const size_t sz_type = sizeof(int);
172         static const size_t sz_keysize = sizeof(size_t);
173         size_t sz_key = strlen(kv->key) + 1;
174         static const size_t sz_size = sizeof(size_t);
175         size_t sz_val = kv->size;
176         unsigned char *p;
177
178         *byte_len = keyval_get_encoded_size(kv);
179
180         *byte = calloc(1, *byte_len);
181         if (!*byte)
182                 return 0;
183
184         p = *byte;
185
186         memcpy(p, byte_len, sizeof(size_t));
187         p += sizeof(size_t);
188         memcpy(p, &(kv->type), sz_type);
189         p += sz_type;
190         memcpy(p, &sz_key, sz_keysize);
191         p += sz_keysize;
192         memcpy(p, kv->key, sz_key);
193         p += sz_key;
194         memcpy(p, &(kv->size), sz_size);
195         p += sz_size;
196         memcpy(p, kv->val, sz_val);
197         p += sz_val;
198
199         return *byte_len;
200 }
201
202 /**
203  * decode a byte stream to a keyval
204  *
205  * @param[in]     byte  byte stream.
206  * @param[in|out] kv    keyval.
207  *                  If kv is NULL, new keyval_t object comes.
208  *                  If kv is not NULL, given kv is used. (No new kv is created.)
209  * @return        Number of bytes read from byte.
210  */
211 size_t keyval_decode(unsigned char *byte, keyval_t **kv)
212 {
213         static const size_t sz_byte_len = sizeof(size_t);
214         static const size_t sz_type = sizeof(int);
215         static const size_t sz_keysize = sizeof(size_t);
216         static const size_t sz_size = sizeof(size_t);
217         size_t byte_len;
218         int type;
219         size_t keysize;
220         char *key;
221         size_t size;
222         void *val;
223         unsigned char *p = byte;
224
225         byte_len = *((size_t *)p);
226         p += sz_byte_len;
227         type = *((int *)p);
228         p += sz_type;
229         keysize = *((size_t *)p);
230         p += sz_keysize;
231         key = (char *)p;
232         p += keysize;
233         size = *((size_t *)p);
234         p += sz_size;
235         val = (void *)p;
236         p += size;
237
238         if (kv)
239                 *kv = keyval_new(*kv, key, type, val, size);
240
241         return byte_len;
242 }
243
244 int keyval_get_type_from_encoded_byte(unsigned char *byte)
245 {
246         static const size_t sz_byte_len = sizeof(size_t);
247         unsigned char *p = byte;
248         int type;
249
250          p += sz_byte_len;
251         type = *((int *)p);
252
253         return type;
254 }