| 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 | } |