File: | build-analysis/../src/lib/xmmstypes/xmmsv_dict.c |
Warning: | line 715, column 7 Function call argument is an uninitialized value |
1 | /* XMMS2 - X Music Multiplexer System | |||
2 | * Copyright (C) 2003-2017 XMMS2 Team | |||
3 | * | |||
4 | * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!! | |||
5 | * | |||
6 | * This library is free software; you can redistribute it and/or | |||
7 | * modify it under the terms of the GNU Lesser General Public | |||
8 | * License as published by the Free Software Foundation; either | |||
9 | * version 2.1 of the License, or (at your option) any later version. | |||
10 | * | |||
11 | * This library is distributed in the hope that it will be useful, | |||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
14 | * Lesser General Public License for more details. | |||
15 | */ | |||
16 | ||||
17 | #include <stdlib.h> | |||
18 | #include <string.h> | |||
19 | ||||
20 | #include <xmmscpriv/xmmsv.h> | |||
21 | #include <xmmscpriv/xmms_list.h> | |||
22 | ||||
23 | typedef struct xmmsv_dict_data_St { | |||
24 | uint32_t hash; | |||
25 | char *str; | |||
26 | xmmsv_t *value; | |||
27 | } xmmsv_dict_data_t; | |||
28 | ||||
29 | struct xmmsv_dict_internal_St { | |||
30 | int elems; | |||
31 | int size; | |||
32 | xmmsv_dict_data_t *data; | |||
33 | ||||
34 | x_list_t *iterators; | |||
35 | }; | |||
36 | ||||
37 | struct xmmsv_dict_iter_St { | |||
38 | int pos; | |||
39 | xmmsv_dict_internal_t *parent; | |||
40 | }; | |||
41 | ||||
42 | static void _xmmsv_dict_iter_free (xmmsv_dict_iter_t *it); | |||
43 | ||||
44 | #define HASH_MASK(table)((1 << (table)->size) - 1) ((1 << (table)->size) - 1) | |||
45 | #define HASH_FILL_LIM7 7 | |||
46 | #define DELETED_STR((char*)-1) ((char*)-1) | |||
47 | #define DICT_INIT_DATA(s){.hash = _xmmsv_dict_hash (s, strlen (s)), .str = (char*)s} {.hash = _xmmsv_dict_hash (s, strlen (s)), .str = (char*)s} | |||
48 | #define START_SIZE2 2 | |||
49 | ||||
50 | /* MurmurHash2, by Austin Appleby */ | |||
51 | static uint32_t | |||
52 | _xmmsv_dict_hash (const void *key, int len) | |||
53 | { | |||
54 | /* 'm' and 'r' are mixing constants generated offline. | |||
55 | * They're not really 'magic', they just happen to work well. | |||
56 | */ | |||
57 | const uint32_t seed = 0x12345678; | |||
58 | const uint32_t m = 0x5bd1e995; | |||
59 | const int r = 24; | |||
60 | ||||
61 | /* Initialize the hash to a 'random' value */ | |||
62 | uint32_t h = seed ^ len; | |||
63 | ||||
64 | /* Mix 4 bytes at a time into the hash */ | |||
65 | const unsigned char * data = (const unsigned char *)key; | |||
66 | ||||
67 | while (len >= 4) | |||
68 | { | |||
69 | uint32_t k = data [0] | |||
70 | | data [1] << 8 | |||
71 | | data [2] << 16 | |||
72 | | data [3] << 24; | |||
73 | ||||
74 | k *= m; | |||
75 | k ^= k >> r; | |||
76 | k *= m; | |||
77 | ||||
78 | h *= m; | |||
79 | h ^= k; | |||
80 | ||||
81 | data += 4; | |||
82 | len -= 4; | |||
83 | } | |||
84 | ||||
85 | /* Handle the last few bytes of the input array */ | |||
86 | switch (len) | |||
87 | { | |||
88 | case 3: h ^= data[2] << 16; | |||
89 | case 2: h ^= data[1] << 8; | |||
90 | case 1: h ^= data[0]; | |||
91 | h *= m; | |||
92 | }; | |||
93 | ||||
94 | /* Do a few final mixes of the hash to ensure the last few | |||
95 | * bytes are well-incorporated. | |||
96 | */ | |||
97 | h ^= h >> 13; | |||
98 | h *= m; | |||
99 | h ^= h >> 15; | |||
100 | ||||
101 | return h; | |||
102 | } | |||
103 | ||||
104 | /* Searches the hash table for an entry matching the hash and string in data. | |||
105 | * It will save the found position in pos. | |||
106 | * If a deleted position was found before the key, it will be saved in deleted | |||
107 | * Returns 1 if the entry was found, 0 otherwise | |||
108 | */ | |||
109 | static int | |||
110 | _xmmsv_dict_search (xmmsv_dict_internal_t *dict, xmmsv_dict_data_t data, | |||
111 | int *pos, int *deleted) | |||
112 | { | |||
113 | int bucket = data.hash & HASH_MASK (dict)((1 << (dict)->size) - 1); | |||
114 | int stop = bucket; | |||
115 | int size = 1 << dict->size; | |||
116 | ||||
117 | *deleted = -1; | |||
118 | ||||
119 | while (dict->data[bucket].str != NULL((void*)0)) { | |||
120 | /* If this is a free entry we save it in the free pointer */ | |||
121 | if (dict->data[bucket].str == DELETED_STR((char*)-1)) { | |||
122 | if (*deleted == -1) { | |||
123 | *deleted = bucket; | |||
124 | } | |||
125 | /* If we found the entry we save it in the pos pointer */ | |||
126 | } else if (dict->data[bucket].hash == data.hash | |||
127 | && strcmp (dict->data[bucket].str, data.str) == 0) { | |||
128 | *pos = bucket; | |||
129 | return 1; | |||
130 | } | |||
131 | ||||
132 | /* If we hit the end we roll around */ | |||
133 | if (++bucket >= size) | |||
134 | bucket = 0; | |||
135 | /* If we have checked the whole table we exit */ | |||
136 | if (bucket == stop) | |||
137 | break; | |||
138 | } | |||
139 | ||||
140 | /* Save the position to the first free entry | |||
141 | * (or the start bucket if we made it the whole way around | |||
142 | * without finding the entry and without finding any empty | |||
143 | * entries, but in that case free is set, since there have to | |||
144 | * be atleast 1 deleted or empty entry in the table) | |||
145 | */ | |||
146 | *pos = bucket; | |||
147 | return 0; | |||
148 | } | |||
149 | ||||
150 | /* Inserts data into the hash table */ | |||
151 | static void | |||
152 | _xmmsv_dict_insert (xmmsv_dict_internal_t *dict, xmmsv_dict_data_t data, int alloc) | |||
153 | { | |||
154 | int pos, deleted; | |||
155 | ||||
156 | if (_xmmsv_dict_search (dict, data, &pos, &deleted)) { | |||
157 | /* If the key already exists we change the data*/ | |||
158 | xmmsv_unref (dict->data[pos].value); | |||
159 | dict->data[pos].value = data.value; | |||
160 | } else { | |||
161 | /* Otherwise we insert a new entry */ | |||
162 | if (alloc) | |||
163 | data.str = strdup (data.str); | |||
164 | dict->elems++; | |||
165 | /* If we found a deleted entry before an empty one we use the free entry */ | |||
166 | if (deleted != -1) { | |||
167 | dict->data[deleted] = data; | |||
168 | } else { | |||
169 | dict->data[pos] = data; | |||
170 | } | |||
171 | } | |||
172 | } | |||
173 | ||||
174 | /* Remove an entry at the given position | |||
175 | */ | |||
176 | static void | |||
177 | _xmmsv_dict_remove (xmmsv_dict_internal_t *dict, int pos) | |||
178 | { | |||
179 | free ((void*)dict->data[pos].str); | |||
180 | dict->data[pos].str = DELETED_STR((char*)-1); | |||
181 | xmmsv_unref (dict->data[pos].value); | |||
182 | dict->data[pos].value = NULL((void*)0); | |||
183 | dict->elems--; | |||
184 | } | |||
185 | ||||
186 | /* Resizes the hash table by creating a new data table | |||
187 | * twice the size of the old one | |||
188 | */ | |||
189 | static void | |||
190 | _xmmsv_dict_resize (xmmsv_dict_internal_t *dict) | |||
191 | { | |||
192 | int i; | |||
193 | xmmsv_dict_data_t *old_data; | |||
194 | ||||
195 | /* Double the table size */ | |||
196 | dict->size++; | |||
197 | dict->elems = 0; | |||
198 | old_data = dict->data; | |||
199 | dict->data = x_new0 (xmmsv_dict_data_t, 1 << dict->size)calloc (1, sizeof (xmmsv_dict_data_t) * (1 << dict-> size)); | |||
200 | ||||
201 | /* Insert all the entries in the old table into the new one */ | |||
202 | for (i = 0; i < (1 << (dict->size - 1)); i++) { | |||
203 | if (old_data[i].str != NULL((void*)0)) { | |||
204 | _xmmsv_dict_insert (dict, old_data[i], 0); | |||
205 | } | |||
206 | } | |||
207 | ||||
208 | free (old_data); | |||
209 | } | |||
210 | ||||
211 | static xmmsv_dict_internal_t * | |||
212 | _xmmsv_dict_new (void) | |||
213 | { | |||
214 | xmmsv_dict_internal_t *dict; | |||
215 | ||||
216 | dict = x_new0 (xmmsv_dict_internal_t, 1)calloc (1, sizeof (xmmsv_dict_internal_t) * (1)); | |||
217 | if (!dict) { | |||
218 | x_oom ()xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL, "Out of memory in %s at %s:%d" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 218); | |||
219 | return NULL((void*)0); | |||
220 | } | |||
221 | ||||
222 | dict->size = 2; | |||
223 | dict->data = x_new0 (xmmsv_dict_data_t, (1 << dict->size))calloc (1, sizeof (xmmsv_dict_data_t) * ((1 << dict-> size))); | |||
224 | ||||
225 | if (!dict->data) { | |||
226 | x_oom ()xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL, "Out of memory in %s at %s:%d" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 226); | |||
227 | free (dict); | |||
228 | return NULL((void*)0); | |||
229 | } | |||
230 | ||||
231 | return dict; | |||
232 | } | |||
233 | ||||
234 | void | |||
235 | _xmmsv_dict_free (xmmsv_dict_internal_t *dict) | |||
236 | { | |||
237 | xmmsv_dict_iter_t *it; | |||
238 | int i; | |||
239 | ||||
240 | /* free iterators */ | |||
241 | while (dict->iterators) { | |||
242 | it = (xmmsv_dict_iter_t *) dict->iterators->data; | |||
243 | _xmmsv_dict_iter_free (it); | |||
244 | } | |||
245 | ||||
246 | for (i = (1 << dict->size) - 1; i >= 0; i--) { | |||
247 | if (dict->data[i].str != NULL((void*)0)) { | |||
248 | if (dict->data[i].str != DELETED_STR((char*)-1)) { | |||
249 | free (dict->data[i].str); | |||
250 | xmmsv_unref (dict->data[i].value); | |||
251 | } | |||
252 | dict->data[i].str = NULL((void*)0); | |||
253 | } | |||
254 | } | |||
255 | free (dict->data); | |||
256 | free (dict); | |||
257 | } | |||
258 | ||||
259 | /** | |||
260 | * Allocates a new dict #xmmsv_t. | |||
261 | * @return The new #xmmsv_t. Must be unreferenced with | |||
262 | * #xmmsv_unref. | |||
263 | */ | |||
264 | xmmsv_t * | |||
265 | xmmsv_new_dict (void) | |||
266 | { | |||
267 | xmmsv_t *val = _xmmsv_new (XMMSV_TYPE_DICT); | |||
268 | ||||
269 | if (val) { | |||
270 | val->value.dict = _xmmsv_dict_new (); | |||
271 | } | |||
272 | ||||
273 | return val; | |||
274 | } | |||
275 | ||||
276 | int | |||
277 | xmmsv_dict_has_key (xmmsv_t *dictv, const char *key) | |||
278 | { | |||
279 | return xmmsv_dict_get (dictv, key, NULL((void*)0)); | |||
280 | } | |||
281 | ||||
282 | /** | |||
283 | * Get a #XMMSV_TYPE_LIST of all the keys. | |||
284 | * | |||
285 | * @param val A xmmsv_t containing a dict. | |||
286 | * @param keys Pointer that will own the reference | |||
287 | * to the new list containing the dict keys. | |||
288 | * @return 1 upon success otherwise 0 | |||
289 | */ | |||
290 | int xmmsv_dict_keys (xmmsv_t *dictv, xmmsv_t **keys) | |||
291 | { | |||
292 | xmmsv_dict_iter_t *it; | |||
293 | const char *key; | |||
294 | ||||
295 | x_return_val_if_fail (keys, 0)if (!(keys)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "keys", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 295); return (0); }; | |||
296 | x_return_val_if_fail (xmmsv_get_dict_iter (dictv, &it), 0)if (!(xmmsv_get_dict_iter (dictv, &it))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_get_dict_iter (dictv, &it)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 296); return (0); }; | |||
297 | ||||
298 | *keys = xmmsv_new_list (); | |||
299 | xmmsv_list_restrict_type (*keys, XMMSV_TYPE_STRING); | |||
300 | while (xmmsv_dict_iter_pair (it, &key, NULL((void*)0))) { | |||
301 | xmmsv_list_append_string (*keys, key); | |||
302 | xmmsv_dict_iter_next (it); | |||
303 | } | |||
304 | ||||
305 | xmmsv_dict_iter_explicit_destroy (it); | |||
306 | ||||
307 | return 1; | |||
308 | } | |||
309 | ||||
310 | /** | |||
311 | * Get a #XMMSV_TYPE_LIST of all the values. | |||
312 | * | |||
313 | * @param val A xmmsv_t containing a dict. | |||
314 | * @param keys Pointer that will own the reference | |||
315 | * to the new list containing the dict values. | |||
316 | * @return 1 upon success otherwise 0 | |||
317 | */ | |||
318 | int xmmsv_dict_values (xmmsv_t *dictv, xmmsv_t **values) | |||
319 | { | |||
320 | xmmsv_dict_iter_t *it; | |||
321 | xmmsv_t *value; | |||
322 | ||||
323 | x_return_val_if_fail (values, 0)if (!(values)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "values", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 323); return (0); }; | |||
324 | x_return_val_if_fail (xmmsv_get_dict_iter (dictv, &it), 0)if (!(xmmsv_get_dict_iter (dictv, &it))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_get_dict_iter (dictv, &it)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 324); return (0); }; | |||
325 | ||||
326 | *values = xmmsv_new_list (); | |||
327 | while (xmmsv_dict_iter_pair (it, NULL((void*)0), &value)) { | |||
328 | xmmsv_list_append (*values, value); | |||
329 | xmmsv_dict_iter_next (it); | |||
330 | } | |||
331 | ||||
332 | xmmsv_dict_iter_explicit_destroy (it); | |||
333 | ||||
334 | return 1; | |||
335 | } | |||
336 | ||||
337 | /** | |||
338 | * Gets the type of a dict entry. | |||
339 | * | |||
340 | * @param val A xmmsv_t containing a dict. | |||
341 | * @param key The key in the dict. | |||
342 | * @return The type of the entry or #XMMSV_TYPE_NONE if something goes wrong. | |||
343 | */ | |||
344 | xmmsv_type_t | |||
345 | xmmsv_dict_entry_get_type (xmmsv_t *val, const char *key) | |||
346 | { | |||
347 | xmmsv_t *v; | |||
348 | ||||
349 | if (!xmmsv_dict_get (val, key, &v)) { | |||
350 | return XMMSV_TYPE_NONE; | |||
351 | } | |||
352 | ||||
353 | return xmmsv_get_type (v); | |||
354 | } | |||
355 | ||||
356 | /** | |||
357 | * Get the element corresponding to the given key in the dict #xmmsv_t | |||
358 | * (if it exists). This function does not increase the refcount of | |||
359 | * the element, the reference is still owned by the dict. | |||
360 | * | |||
361 | * @param dictv A #xmmsv_t containing a dict. | |||
362 | * @param key The key in the dict. | |||
363 | * @param val Pointer set to a borrowed reference to the element | |||
364 | * corresponding to the given key in the dict. | |||
365 | * @return 1 upon success otherwise 0 | |||
366 | */ | |||
367 | int | |||
368 | xmmsv_dict_get (xmmsv_t *dictv, const char *key, xmmsv_t **val) | |||
369 | { | |||
370 | xmmsv_dict_internal_t *dict; | |||
371 | int ret = 0; | |||
372 | int pos, deleted; | |||
373 | ||||
374 | x_return_val_if_fail (key, 0)if (!(key)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "key", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 374); return (0); }; | |||
375 | x_return_val_if_fail (dictv, 0)if (!(dictv)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "dictv", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 375); return (0); }; | |||
376 | x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0)if (!(xmmsv_is_type (dictv, XMMSV_TYPE_DICT))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_is_type (dictv, XMMSV_TYPE_DICT)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 376); return (0); }; | |||
377 | ||||
378 | xmmsv_dict_data_t data = DICT_INIT_DATA (key){.hash = _xmmsv_dict_hash (key, strlen (key)), .str = (char*) key}; | |||
379 | dict = dictv->value.dict; | |||
380 | ||||
381 | if (_xmmsv_dict_search (dict, data, &pos, &deleted)) { | |||
382 | /* If there was a deleted entry before the one we found | |||
383 | * we can optimize a little by moving the entry to the | |||
384 | * deleted slot (and thus closer to the actual bucket it | |||
385 | * belongs to) | |||
386 | */ | |||
387 | if (deleted != -1) { | |||
388 | dict->data[deleted] = dict->data[pos]; | |||
389 | dict->data[pos].str = DELETED_STR((char*)-1); | |||
390 | } | |||
391 | if (val != NULL((void*)0)) { | |||
392 | *val = dict->data[pos].value; | |||
393 | } | |||
394 | ret = 1; | |||
395 | } | |||
396 | ||||
397 | return ret; | |||
398 | } | |||
399 | ||||
400 | /** | |||
401 | * Insert an element under the given key in the dict #xmmsv_t. If the | |||
402 | * key already referenced an element, that element is unref'd and | |||
403 | * replaced by the new one. | |||
404 | * | |||
405 | * @param dictv A #xmmsv_t containing a dict. | |||
406 | * @param key The key in the dict. | |||
407 | * @param val The new element to insert in the dict. | |||
408 | * @return 1 upon success otherwise 0 | |||
409 | */ | |||
410 | int | |||
411 | xmmsv_dict_set (xmmsv_t *dictv, const char *key, xmmsv_t *val) | |||
412 | { | |||
413 | xmmsv_dict_internal_t *dict; | |||
414 | int ret = 1; | |||
415 | ||||
416 | x_return_val_if_fail (key, 0)if (!(key)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "key", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 416); return (0); }; | |||
417 | x_return_val_if_fail (val, 0)if (!(val)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "val", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 417); return (0); }; | |||
418 | x_return_val_if_fail (dictv, 0)if (!(dictv)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "dictv", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 418); return (0); }; | |||
419 | x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0)if (!(xmmsv_is_type (dictv, XMMSV_TYPE_DICT))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_is_type (dictv, XMMSV_TYPE_DICT)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 419); return (0); }; | |||
420 | ||||
421 | xmmsv_dict_data_t data = DICT_INIT_DATA (key){.hash = _xmmsv_dict_hash (key, strlen (key)), .str = (char*) key}; | |||
422 | data.value = xmmsv_ref (val); | |||
423 | dict = dictv->value.dict; | |||
424 | ||||
425 | /* Resize if fill is too high */ | |||
426 | if (((dict->elems * 10) >> dict->size) > HASH_FILL_LIM7) { | |||
427 | _xmmsv_dict_resize (dict); | |||
428 | } | |||
429 | ||||
430 | _xmmsv_dict_insert (dict, data, 1); | |||
431 | ||||
432 | return ret; | |||
433 | } | |||
434 | ||||
435 | /** | |||
436 | * Remove the element corresponding to a given key in the dict | |||
437 | * #xmmsv_t (if it exists). | |||
438 | * | |||
439 | * @param dictv A #xmmsv_t containing a dict. | |||
440 | * @param key The key in the dict. | |||
441 | * @return 1 upon success otherwise 0 | |||
442 | */ | |||
443 | int | |||
444 | xmmsv_dict_remove (xmmsv_t *dictv, const char *key) | |||
445 | { | |||
446 | xmmsv_dict_internal_t *dict; | |||
447 | int pos, deleted; | |||
448 | int ret = 0; | |||
449 | ||||
450 | x_return_val_if_fail (key, 0)if (!(key)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "key", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 450); return (0); }; | |||
451 | x_return_val_if_fail (dictv, 0)if (!(dictv)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "dictv", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 451); return (0); }; | |||
452 | x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0)if (!(xmmsv_is_type (dictv, XMMSV_TYPE_DICT))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_is_type (dictv, XMMSV_TYPE_DICT)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 452); return (0); }; | |||
453 | ||||
454 | xmmsv_dict_data_t data = DICT_INIT_DATA (key){.hash = _xmmsv_dict_hash (key, strlen (key)), .str = (char*) key}; | |||
455 | dict = dictv->value.dict; | |||
456 | ||||
457 | /* If we find the entry we free the string and mark it as deleted */ | |||
458 | if (_xmmsv_dict_search (dict, data, &pos, &deleted)) { | |||
459 | _xmmsv_dict_remove (dict, pos); | |||
460 | ret = 1; | |||
461 | } | |||
462 | ||||
463 | return ret; | |||
464 | } | |||
465 | ||||
466 | /** | |||
467 | * Empty the dict of all its elements. | |||
468 | * | |||
469 | * @param dictv A #xmmsv_t containing a dict. | |||
470 | * @return 1 upon success otherwise 0 | |||
471 | */ | |||
472 | int | |||
473 | xmmsv_dict_clear (xmmsv_t *dictv) | |||
474 | { | |||
475 | int i; | |||
476 | xmmsv_dict_internal_t *dict; | |||
477 | ||||
478 | x_return_val_if_fail (dictv, 0)if (!(dictv)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "dictv", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 478); return (0); }; | |||
479 | x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0)if (!(xmmsv_is_type (dictv, XMMSV_TYPE_DICT))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_is_type (dictv, XMMSV_TYPE_DICT)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 479); return (0); }; | |||
480 | ||||
481 | dict = dictv->value.dict; | |||
482 | ||||
483 | for (i = (1 << dict->size) - 1; i >= 0; i--) { | |||
484 | if (dict->data[i].str != NULL((void*)0)) { | |||
485 | if (dict->data[i].str != DELETED_STR((char*)-1)) { | |||
486 | free (dict->data[i].str); | |||
487 | xmmsv_unref (dict->data[i].value); | |||
488 | } | |||
489 | dict->data[i].str = NULL((void*)0); | |||
490 | } | |||
491 | } | |||
492 | ||||
493 | return 1; | |||
494 | } | |||
495 | ||||
496 | /** | |||
497 | * Apply a function to each key-element pair in the list. No | |||
498 | * particular order is assumed. | |||
499 | * | |||
500 | * @param dictv A #xmmsv_t containing a dict. | |||
501 | * @param function The function to apply to each key-element pair. | |||
502 | * @param user_data User data passed to the foreach function. | |||
503 | * @return 1 upon success otherwise 0 | |||
504 | */ | |||
505 | int | |||
506 | xmmsv_dict_foreach (xmmsv_t *dictv, xmmsv_dict_foreach_func func, | |||
507 | void *user_data) | |||
508 | { | |||
509 | xmmsv_dict_iter_t *it; | |||
510 | const char *key; | |||
511 | xmmsv_t *v; | |||
512 | ||||
513 | x_return_val_if_fail (dictv, 0)if (!(dictv)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "dictv", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 513); return (0); }; | |||
514 | x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0)if (!(xmmsv_is_type (dictv, XMMSV_TYPE_DICT))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_is_type (dictv, XMMSV_TYPE_DICT)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 514); return (0); }; | |||
515 | x_return_val_if_fail (xmmsv_get_dict_iter (dictv, &it), 0)if (!(xmmsv_get_dict_iter (dictv, &it))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_get_dict_iter (dictv, &it)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 515); return (0); }; | |||
516 | ||||
517 | while (xmmsv_dict_iter_pair (it, &key, &v)) { | |||
518 | func (key, v, user_data); | |||
519 | xmmsv_dict_iter_next (it); | |||
520 | } | |||
521 | ||||
522 | _xmmsv_dict_iter_free (it); | |||
523 | ||||
524 | return 1; | |||
525 | } | |||
526 | ||||
527 | /** | |||
528 | * Return the size of the dict. | |||
529 | * | |||
530 | * @param dictv The #xmmsv_t containing the dict. | |||
531 | * @return The size of the dict, or -1 if dict is invalid. | |||
532 | */ | |||
533 | int | |||
534 | xmmsv_dict_get_size (xmmsv_t *dictv) | |||
535 | { | |||
536 | x_return_val_if_fail (dictv, -1)if (!(dictv)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "dictv", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 536); return (-1); }; | |||
537 | x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), -1)if (!(xmmsv_is_type (dictv, XMMSV_TYPE_DICT))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_is_type (dictv, XMMSV_TYPE_DICT)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 537); return (-1); }; | |||
538 | ||||
539 | return dictv->value.dict->elems; | |||
540 | } | |||
541 | ||||
542 | static xmmsv_dict_iter_t * | |||
543 | _xmmsv_dict_iter_new (xmmsv_dict_internal_t *d) | |||
544 | { | |||
545 | xmmsv_dict_iter_t *it; | |||
546 | ||||
547 | it = x_new0 (xmmsv_dict_iter_t, 1)calloc (1, sizeof (xmmsv_dict_iter_t) * (1)); | |||
548 | if (!it) { | |||
549 | x_oom ()xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL, "Out of memory in %s at %s:%d" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 549); | |||
550 | return NULL((void*)0); | |||
551 | } | |||
552 | ||||
553 | it->parent = d; | |||
554 | xmmsv_dict_iter_first (it); | |||
555 | ||||
556 | /* register iterator into parent */ | |||
557 | d->iterators = x_list_prepend (d->iterators, it); | |||
558 | ||||
559 | return it; | |||
560 | } | |||
561 | ||||
562 | static void | |||
563 | _xmmsv_dict_iter_free (xmmsv_dict_iter_t *it) | |||
564 | { | |||
565 | /* unref iterator from dict and free it */ | |||
566 | it->parent->iterators = x_list_remove (it->parent->iterators, it); | |||
567 | free (it); | |||
568 | } | |||
569 | ||||
570 | /** | |||
571 | * Retrieves a dict iterator from a dict #xmmsv_t. | |||
572 | * | |||
573 | * @param val a #xmmsv_t containing a dict. | |||
574 | * @param it An #xmmsv_dict_iter_t that can be used to access the dict | |||
575 | * data. The iterator will be freed when the value is freed. | |||
576 | * @return 1 upon success otherwise 0 | |||
577 | */ | |||
578 | int | |||
579 | xmmsv_get_dict_iter (const xmmsv_t *val, xmmsv_dict_iter_t **it) | |||
580 | { | |||
581 | xmmsv_dict_iter_t *new_it; | |||
582 | ||||
583 | if (!val || val->type != XMMSV_TYPE_DICT) { | |||
584 | *it = NULL((void*)0); | |||
585 | return 0; | |||
586 | } | |||
587 | ||||
588 | new_it = _xmmsv_dict_iter_new (val->value.dict); | |||
589 | if (!new_it) { | |||
590 | *it = NULL((void*)0); | |||
591 | return 0; | |||
592 | } | |||
593 | ||||
594 | *it = new_it; | |||
595 | ||||
596 | return 1; | |||
597 | } | |||
598 | ||||
599 | /** | |||
600 | * Explicitly free dict iterator. | |||
601 | * | |||
602 | * Immediately frees any resources used by this iterator. The iterator | |||
603 | * is freed automatically when the dict is freed, but this function is | |||
604 | * useful when the dict can be long lived. | |||
605 | * | |||
606 | * @param it iterator to free | |||
607 | * | |||
608 | */ | |||
609 | void | |||
610 | xmmsv_dict_iter_explicit_destroy (xmmsv_dict_iter_t *it) | |||
611 | { | |||
612 | _xmmsv_dict_iter_free (it); | |||
613 | } | |||
614 | ||||
615 | /** | |||
616 | * Get the key-element pair currently pointed at by the iterator. This | |||
617 | * function does not increase the refcount of the element, the | |||
618 | * reference is still owned by the dict. | |||
619 | * | |||
620 | * @param it A #xmmsv_dict_iter_t. | |||
621 | * @param key Pointer set to the key pointed at by the iterator. | |||
622 | * @param val Pointer set to a borrowed reference to the element | |||
623 | * pointed at by the iterator. | |||
624 | * @return 1 upon success otherwise 0 | |||
625 | */ | |||
626 | int | |||
627 | xmmsv_dict_iter_pair (xmmsv_dict_iter_t *it, const char **key, | |||
628 | xmmsv_t **val) | |||
629 | { | |||
630 | if (!xmmsv_dict_iter_valid (it)) { | |||
631 | return 0; | |||
632 | } | |||
633 | ||||
634 | if (key) { | |||
635 | *key = it->parent->data[it->pos].str; | |||
636 | } | |||
637 | ||||
638 | if (val) { | |||
639 | *val = it->parent->data[it->pos].value; | |||
640 | } | |||
641 | ||||
642 | return 1; | |||
643 | } | |||
644 | ||||
645 | /** | |||
646 | * Check whether the iterator is valid and points to a valid pair. | |||
647 | * | |||
648 | * @param it A #xmmsv_dict_iter_t. | |||
649 | * @return 1 if the iterator is valid, 0 otherwise | |||
650 | */ | |||
651 | int | |||
652 | xmmsv_dict_iter_valid (xmmsv_dict_iter_t *it) | |||
653 | { | |||
654 | return it && (it->pos < (1 << it->parent->size)) | |||
655 | && it->parent->data[it->pos].str != NULL((void*)0) | |||
656 | && it->parent->data[it->pos].str != DELETED_STR((char*)-1); | |||
657 | } | |||
658 | ||||
659 | /** | |||
660 | * Rewind the iterator to the start of the dict. | |||
661 | * | |||
662 | * @param it A #xmmsv_dict_iter_t. | |||
663 | * @return 1 upon success otherwise 0 | |||
664 | */ | |||
665 | void | |||
666 | xmmsv_dict_iter_first (xmmsv_dict_iter_t *it) | |||
667 | { | |||
668 | x_return_if_fail (it)if (!(it)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "it", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 668); return; }; | |||
669 | xmmsv_dict_internal_t *d = it->parent; | |||
670 | ||||
671 | for (it->pos = 0 | |||
672 | ; it->pos < (1 << d->size) && (d->data[it->pos].str == NULL((void*)0) || d->data[it->pos].str == DELETED_STR((char*)-1)) | |||
673 | ; it->pos++); | |||
674 | } | |||
675 | ||||
676 | /** | |||
677 | * Advance the iterator to the next pair in the dict. | |||
678 | * | |||
679 | * @param it A #xmmsv_dict_iter_t. | |||
680 | * @return 1 upon success otherwise 0 | |||
681 | */ | |||
682 | void | |||
683 | xmmsv_dict_iter_next (xmmsv_dict_iter_t *it) | |||
684 | { | |||
685 | x_return_if_fail (it)if (!(it)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "it", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 685); return; }; | |||
686 | xmmsv_dict_internal_t *d = it->parent; | |||
687 | ||||
688 | for (it->pos++ | |||
689 | ; it->pos < (1 << d->size) && (d->data[it->pos].str == NULL((void*)0) || d->data[it->pos].str == DELETED_STR((char*)-1)) | |||
690 | ; it->pos++); | |||
691 | } | |||
692 | ||||
693 | /** | |||
694 | * Move the iterator to the pair with the given key (if it exists) | |||
695 | * or move it to the position where the key would have to be | |||
696 | * put (if it doesn't exist yet). | |||
697 | * | |||
698 | * @param it A #xmmsv_dict_iter_t. | |||
699 | * @param key The key to seek for. | |||
700 | * @return 1 upon success otherwise 0 | |||
701 | */ | |||
702 | int | |||
703 | xmmsv_dict_iter_find (xmmsv_dict_iter_t *it, const char *key) | |||
704 | { | |||
705 | x_return_val_if_fail (xmmsv_dict_iter_valid (it), 0)if (!(xmmsv_dict_iter_valid (it))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_dict_iter_valid (it)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 705); return (0); }; | |||
706 | ||||
707 | xmmsv_dict_iter_first (it); | |||
708 | ||||
709 | for (xmmsv_dict_iter_first (it) | |||
| ||||
710 | ; xmmsv_dict_iter_valid (it) | |||
711 | ; xmmsv_dict_iter_next (it)) { | |||
712 | const char *s; | |||
713 | ||||
714 | xmmsv_dict_iter_pair (it, &s, NULL((void*)0)); | |||
715 | if (strcmp (s, key) == 0) | |||
| ||||
716 | return 1; | |||
717 | } | |||
718 | ||||
719 | return 0; | |||
720 | } | |||
721 | ||||
722 | /** | |||
723 | * Replace the element of the pair currently pointed to by the | |||
724 | * iterator. | |||
725 | * | |||
726 | * @param it A #xmmsv_dict_iter_t. | |||
727 | * @param val The element to set in the pair. | |||
728 | * @return 1 upon success otherwise 0 | |||
729 | */ | |||
730 | int | |||
731 | xmmsv_dict_iter_set (xmmsv_dict_iter_t *it, xmmsv_t *val) | |||
732 | { | |||
733 | x_return_val_if_fail (xmmsv_dict_iter_valid (it), 0)if (!(xmmsv_dict_iter_valid (it))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_dict_iter_valid (it)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 733); return (0); }; | |||
734 | x_return_val_if_fail (val, 0)if (!(val)) { xmmsc_log ("xmmsc/xmmstypes", XMMS_LOG_LEVEL_FAIL , "Check '%s' failed in %s at %s:%d", "val", __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c" , 734); return (0); }; | |||
735 | ||||
736 | /* In case old value is new value, ref first. */ | |||
737 | xmmsv_ref (val); | |||
738 | xmmsv_unref (it->parent->data[it->pos].value); | |||
739 | it->parent->data[it->pos].value = val; | |||
740 | ||||
741 | return 1; | |||
742 | } | |||
743 | ||||
744 | /** | |||
745 | * Remove the pair in the dict pointed at by the iterator. | |||
746 | * | |||
747 | * @param it A #xmmsv_dict_iter_t. | |||
748 | * @return 1 upon success otherwise 0 | |||
749 | */ | |||
750 | int | |||
751 | xmmsv_dict_iter_remove (xmmsv_dict_iter_t *it) | |||
752 | { | |||
753 | x_return_val_if_fail (xmmsv_dict_iter_valid (it), 0)if (!(xmmsv_dict_iter_valid (it))) { xmmsc_log ("xmmsc/xmmstypes" , XMMS_LOG_LEVEL_FAIL, "Check '%s' failed in %s at %s:%d", "xmmsv_dict_iter_valid (it)" , __FUNCTION__, "../src/lib/xmmstypes/xmmsv_dict.c", 753); return (0); }; | |||
754 | ||||
755 | _xmmsv_dict_remove (it->parent, it->pos); | |||
756 | xmmsv_dict_iter_next (it); | |||
757 | ||||
758 | return 1; | |||
759 | } | |||
760 | ||||
761 | /* macro-magically define dict extractors */ | |||
762 | #define GEN_DICT_EXTRACTOR_FUNC(typename, type)int xmmsv_dict_entry_get_typename (xmmsv_t *val, const char * key, type *r) { xmmsv_t *v; if (!xmmsv_dict_get (val, key, & v)) { return 0; } return xmmsv_get_typename (v, r); } \ | |||
763 | int \ | |||
764 | xmmsv_dict_entry_get_##typename (xmmsv_t *val, const char *key, \ | |||
765 | type *r) \ | |||
766 | { \ | |||
767 | xmmsv_t *v; \ | |||
768 | if (!xmmsv_dict_get (val, key, &v)) { \ | |||
769 | return 0; \ | |||
770 | } \ | |||
771 | return xmmsv_get_##typename (v, r); \ | |||
772 | } | |||
773 | ||||
774 | GEN_DICT_EXTRACTOR_FUNC (string, const char *)int xmmsv_dict_entry_get_string (xmmsv_t *val, const char *key , const char * *r) { xmmsv_t *v; if (!xmmsv_dict_get (val, key , &v)) { return 0; } return xmmsv_get_string (v, r); } | |||
775 | GEN_DICT_EXTRACTOR_FUNC (int32, int32_t)int xmmsv_dict_entry_get_int32 (xmmsv_t *val, const char *key , int32_t *r) { xmmsv_t *v; if (!xmmsv_dict_get (val, key, & v)) { return 0; } return xmmsv_get_int32 (v, r); } | |||
776 | GEN_DICT_EXTRACTOR_FUNC (int64, int64_t)int xmmsv_dict_entry_get_int64 (xmmsv_t *val, const char *key , int64_t *r) { xmmsv_t *v; if (!xmmsv_dict_get (val, key, & v)) { return 0; } return xmmsv_get_int64 (v, r); } | |||
777 | GEN_DICT_EXTRACTOR_FUNC (float, float)int xmmsv_dict_entry_get_float (xmmsv_t *val, const char *key , float *r) { xmmsv_t *v; if (!xmmsv_dict_get (val, key, & v)) { return 0; } return xmmsv_get_float (v, r); } | |||
778 | ||||
779 | int | |||
780 | xmmsv_dict_entry_get_coll (xmmsv_t *val, const char *key, xmmsv_t **r) | |||
781 | { | |||
782 | return xmmsv_dict_get (val, key, r); | |||
783 | } | |||
784 | ||||
785 | /* macro-magically define dict set functions */ | |||
786 | #define GEN_DICT_SET_FUNC(typename, type)int xmmsv_dict_set_typename (xmmsv_t *dict, const char *key, type elem) { int ret; xmmsv_t *v; v = xmmsv_new_typename (elem); ret = xmmsv_dict_set (dict, key, v); xmmsv_unref (v); return ret ; } \ | |||
787 | int \ | |||
788 | xmmsv_dict_set_##typename (xmmsv_t *dict, const char *key, type elem) \ | |||
789 | { \ | |||
790 | int ret; \ | |||
791 | xmmsv_t *v; \ | |||
792 | \ | |||
793 | v = xmmsv_new_##typename (elem); \ | |||
794 | ret = xmmsv_dict_set (dict, key, v); \ | |||
795 | xmmsv_unref (v); \ | |||
796 | \ | |||
797 | return ret; \ | |||
798 | } | |||
799 | ||||
800 | GEN_DICT_SET_FUNC (string, const char *)int xmmsv_dict_set_string (xmmsv_t *dict, const char *key, const char * elem) { int ret; xmmsv_t *v; v = xmmsv_new_string (elem ); ret = xmmsv_dict_set (dict, key, v); xmmsv_unref (v); return ret; } | |||
801 | GEN_DICT_SET_FUNC (int, int64_t)int xmmsv_dict_set_int (xmmsv_t *dict, const char *key, int64_t elem) { int ret; xmmsv_t *v; v = xmmsv_new_int (elem); ret = xmmsv_dict_set (dict, key, v); xmmsv_unref (v); return ret; } | |||
802 | GEN_DICT_SET_FUNC (float, float)int xmmsv_dict_set_float (xmmsv_t *dict, const char *key, float elem) { int ret; xmmsv_t *v; v = xmmsv_new_float (elem); ret = xmmsv_dict_set (dict, key, v); xmmsv_unref (v); return ret ; } | |||
803 | ||||
804 | int | |||
805 | xmmsv_dict_set_coll (xmmsv_t *dict, const char *key, xmmsv_t *elem) | |||
806 | { | |||
807 | return xmmsv_dict_set (dict, key, elem); | |||
808 | } | |||
809 | ||||
810 | /* macro-magically define dict_iter extractors */ | |||
811 | #define GEN_DICT_ITER_EXTRACTOR_FUNC(typename, type)int xmmsv_dict_iter_pair_typename (xmmsv_dict_iter_t *it, const char **key, type *r) { xmmsv_t *v; if (!xmmsv_dict_iter_pair (it, key, &v)) { return 0; } if (r) { return xmmsv_get_typename (v, r); } else { return 1; } } \ | |||
812 | int \ | |||
813 | xmmsv_dict_iter_pair_##typename (xmmsv_dict_iter_t *it, \ | |||
814 | const char **key, \ | |||
815 | type *r) \ | |||
816 | { \ | |||
817 | xmmsv_t *v; \ | |||
818 | if (!xmmsv_dict_iter_pair (it, key, &v)) { \ | |||
819 | return 0; \ | |||
820 | } \ | |||
821 | if (r) { \ | |||
822 | return xmmsv_get_##typename (v, r); \ | |||
823 | } else { \ | |||
824 | return 1; \ | |||
825 | } \ | |||
826 | } | |||
827 | ||||
828 | GEN_DICT_ITER_EXTRACTOR_FUNC (string, const char *)int xmmsv_dict_iter_pair_string (xmmsv_dict_iter_t *it, const char **key, const char * *r) { xmmsv_t *v; if (!xmmsv_dict_iter_pair (it, key, &v)) { return 0; } if (r) { return xmmsv_get_string (v, r); } else { return 1; } } | |||
829 | GEN_DICT_ITER_EXTRACTOR_FUNC (int32, int32_t)int xmmsv_dict_iter_pair_int32 (xmmsv_dict_iter_t *it, const char **key, int32_t *r) { xmmsv_t *v; if (!xmmsv_dict_iter_pair ( it, key, &v)) { return 0; } if (r) { return xmmsv_get_int32 (v, r); } else { return 1; } } | |||
830 | GEN_DICT_ITER_EXTRACTOR_FUNC (int64, int64_t)int xmmsv_dict_iter_pair_int64 (xmmsv_dict_iter_t *it, const char **key, int64_t *r) { xmmsv_t *v; if (!xmmsv_dict_iter_pair ( it, key, &v)) { return 0; } if (r) { return xmmsv_get_int64 (v, r); } else { return 1; } } | |||
831 | GEN_DICT_ITER_EXTRACTOR_FUNC (float, float)int xmmsv_dict_iter_pair_float (xmmsv_dict_iter_t *it, const char **key, float *r) { xmmsv_t *v; if (!xmmsv_dict_iter_pair (it , key, &v)) { return 0; } if (r) { return xmmsv_get_float (v, r); } else { return 1; } } | |||
832 | ||||
833 | int | |||
834 | xmmsv_dict_iter_pair_coll (xmmsv_dict_iter_t *it, const char **key, xmmsv_t **r) | |||
835 | { | |||
836 | return xmmsv_dict_iter_pair (it, key, r); | |||
837 | } | |||
838 | ||||
839 | /* macro-magically define dict_iter set functions */ | |||
840 | #define GEN_DICT_ITER_SET_FUNC(typename, type)int xmmsv_dict_iter_set_typename (xmmsv_dict_iter_t *it, type elem) { int ret; xmmsv_t *v; v = xmmsv_new_typename (elem); ret = xmmsv_dict_iter_set (it, v); xmmsv_unref (v); return ret; } \ | |||
841 | int \ | |||
842 | xmmsv_dict_iter_set_##typename (xmmsv_dict_iter_t *it, type elem) \ | |||
843 | { \ | |||
844 | int ret; \ | |||
845 | xmmsv_t *v; \ | |||
846 | \ | |||
847 | v = xmmsv_new_##typename (elem); \ | |||
848 | ret = xmmsv_dict_iter_set (it, v); \ | |||
849 | xmmsv_unref (v); \ | |||
850 | \ | |||
851 | return ret; \ | |||
852 | } | |||
853 | ||||
854 | GEN_DICT_ITER_SET_FUNC (string, const char *)int xmmsv_dict_iter_set_string (xmmsv_dict_iter_t *it, const char * elem) { int ret; xmmsv_t *v; v = xmmsv_new_string (elem); ret = xmmsv_dict_iter_set (it, v); xmmsv_unref (v); return ret; } | |||
855 | GEN_DICT_ITER_SET_FUNC (int, int64_t)int xmmsv_dict_iter_set_int (xmmsv_dict_iter_t *it, int64_t elem ) { int ret; xmmsv_t *v; v = xmmsv_new_int (elem); ret = xmmsv_dict_iter_set (it, v); xmmsv_unref (v); return ret; } | |||
856 | GEN_DICT_ITER_SET_FUNC (float, float)int xmmsv_dict_iter_set_float (xmmsv_dict_iter_t *it, float elem ) { int ret; xmmsv_t *v; v = xmmsv_new_float (elem); ret = xmmsv_dict_iter_set (it, v); xmmsv_unref (v); return ret; } | |||
857 | ||||
858 | int | |||
859 | xmmsv_dict_iter_set_coll (xmmsv_dict_iter_t *it, xmmsv_t *elem) | |||
860 | { | |||
861 | return xmmsv_dict_iter_set (it, elem); | |||
862 | } |