Update source from tizen 2.3
[platform/core/base/bundle.git] / src / keyval.c
1 /*
2  * bundle
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23
24 /**
25  * keyval.c
26  * Implementation of keyval object
27  */
28
29 #include "keyval_type.h"
30 #include "keyval.h"
31 #include "bundle_log.h"
32 #include "bundle.h"
33 #include <stdlib.h>
34
35 static keyval_method_collection_t method = {
36         keyval_free,
37         keyval_compare,
38         keyval_get_encoded_size,
39         keyval_encode,
40         keyval_decode
41 };
42
43 keyval_t *
44 keyval_new(keyval_t *kv, const char *key, const int type, const void *val,
45                 const size_t size)
46 {
47         int must_free_obj;
48         must_free_obj = kv ? 0 : 1;
49
50         if (!kv) {
51                 kv = calloc(1, sizeof(keyval_t));
52                 if (!kv) {
53                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
54                         return NULL;
55                 }
56         }
57
58         if (kv->key) {
59                 keyval_free(kv, must_free_obj);
60                 return NULL;
61         }
62         kv->key = strdup(key);
63         if (!kv->key) {
64                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
65                 keyval_free(kv, must_free_obj);
66                 return NULL;
67         }
68
69         kv->type = type;
70         kv->size = size;
71
72         if (size) {
73                 kv->val = calloc(1, size);
74                 if (!kv->val) {
75                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
76                         keyval_free(kv, 1);
77                         return NULL;
78                 }
79                 if (val)
80                         memcpy(kv->val, val, size);
81         }
82
83         kv->method = &method;
84
85         return kv;
86 }
87
88 void
89 keyval_free(keyval_t *kv, int do_free_object)
90 {
91         if (NULL == kv)
92                 return;
93
94         if (kv->key) {
95                 free(kv->key);
96                 kv->key = NULL;
97         }
98
99         if (NULL != kv->val) {
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
111 keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size)
112 {
113         if (!kv)
114                 return BUNDLE_ERROR_INVALID_PARAMETER;
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 int
129 keyval_compare(keyval_t *kv1, keyval_t *kv2)
130 {
131         if (!kv1 || !kv2)
132                 return -1;
133
134         if (0 != strcmp(kv1->key, kv2->key))
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 (0 != memcmp(kv1->val, kv2->val, kv1->size))
146                 return 1;
147
148         return 0;
149 }
150
151 size_t
152 keyval_get_encoded_size(keyval_t *kv)
153 {
154         if (!kv)
155                 return 0;
156
157         size_t encoded_size
158                 = sizeof(size_t)        /* total size */
159                 + sizeof(int)           /* type */
160                 + sizeof(size_t)        /* key size */
161                 + strlen(kv->key) + 1   /* key (+ null byte) */
162                 + sizeof(size_t)        /* size */
163                 + kv->size;             /* val */
164
165         return encoded_size;
166 }
167
168 /**
169  * encode a keyval to byte
170  *
171  * @pre                 kv must be valid.
172  * @post                byte must be freed.
173  * @param[in]   kv
174  * @param[out]  byte
175  * @param[out]  byte_len
176  * @return byte_len
177  */
178 size_t
179 keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len)
180 {
181         static const size_t sz_type = sizeof(int);
182         static const size_t sz_keysize = sizeof(size_t);
183         size_t sz_key = strlen(kv->key) + 1;
184         static const size_t sz_size = sizeof(size_t);
185         size_t sz_val = kv->size;
186
187         *byte_len = keyval_get_encoded_size(kv);
188
189         *byte = calloc(1, *byte_len);
190         if (!*byte)
191                 return 0;
192
193         unsigned char *p = *byte;
194
195         memcpy(p, byte_len, sizeof(size_t)); p += sizeof(size_t);
196         memcpy(p, &(kv->type), sz_type); p += sz_type;
197         memcpy(p, &sz_key, sz_keysize); p += sz_keysize;
198         memcpy(p, kv->key, sz_key); p += sz_key;
199         memcpy(p, &(kv->size), sz_size); p += sz_size;
200         memcpy(p, kv->val, sz_val); 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
215 keyval_decode(unsigned char *byte, keyval_t **kv)
216 {
217         static const size_t sz_byte_len = sizeof(size_t);
218         static const size_t sz_type = sizeof(int);
219         static const size_t sz_keysize = sizeof(size_t);
220         static const size_t sz_size = sizeof(size_t);
221
222         unsigned char *p = byte;
223
224         size_t byte_len = *((size_t *)p); p += sz_byte_len;
225         int type = *((int *)p); p += sz_type;
226         size_t keysize = *((size_t *)p); p += sz_keysize;
227         char *key = (char *)p; p += keysize;
228         size_t size = *((size_t *)p); p += sz_size;
229         void *val = (void *)p; p += size;
230
231         if (kv)
232                 *kv = keyval_new(*kv, key, type, val, size);
233
234         return byte_len;
235 }
236
237
238 int
239 keyval_get_type_from_encoded_byte(unsigned char *byte)
240 {
241         static const size_t sz_byte_len = sizeof(size_t);
242
243         unsigned char *p = byte;
244          p += sz_byte_len;
245         int type = *((int *)p);
246         return type;
247 }
248