1 /* 2 * QDict Module 3 * 4 * Copyright (C) 2009 Red Hat Inc. 5 * 6 * Authors: 7 * Luiz Capitulino <lcapitulino@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 10 * See the COPYING.LIB file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "qapi/qmp/qint.h" 15 #include "qapi/qmp/qfloat.h" 16 #include "qapi/qmp/qdict.h" 17 #include "qapi/qmp/qbool.h" 18 #include "qapi/qmp/qstring.h" 19 #include "qapi/qmp/qobject.h" 20 #include "qemu/queue.h" 21 #include "qemu-common.h" 22 #include "qemu/cutils.h" 23 24 /** 25 * qdict_new(): Create a new QDict 26 * 27 * Return strong reference. 28 */ 29 QDict *qdict_new(void) 30 { 31 QDict *qdict; 32 33 qdict = g_malloc0(sizeof(*qdict)); 34 qobject_init(QOBJECT(qdict), QTYPE_QDICT); 35 36 return qdict; 37 } 38 39 /** 40 * qobject_to_qdict(): Convert a QObject into a QDict 41 */ 42 QDict *qobject_to_qdict(const QObject *obj) 43 { 44 if (!obj || qobject_type(obj) != QTYPE_QDICT) { 45 return NULL; 46 } 47 return container_of(obj, QDict, base); 48 } 49 50 /** 51 * tdb_hash(): based on the hash agorithm from gdbm, via tdb 52 * (from module-init-tools) 53 */ 54 static unsigned int tdb_hash(const char *name) 55 { 56 unsigned value; /* Used to compute the hash value. */ 57 unsigned i; /* Used to cycle through random values. */ 58 59 /* Set the initial value from the key size. */ 60 for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) 61 value = (value + (((const unsigned char *)name)[i] << (i*5 % 24))); 62 63 return (1103515243 * value + 12345); 64 } 65 66 /** 67 * alloc_entry(): allocate a new QDictEntry 68 */ 69 static QDictEntry *alloc_entry(const char *key, QObject *value) 70 { 71 QDictEntry *entry; 72 73 entry = g_malloc0(sizeof(*entry)); 74 entry->key = g_strdup(key); 75 entry->value = value; 76 77 return entry; 78 } 79 80 /** 81 * qdict_entry_value(): Return qdict entry value 82 * 83 * Return weak reference. 84 */ 85 QObject *qdict_entry_value(const QDictEntry *entry) 86 { 87 return entry->value; 88 } 89 90 /** 91 * qdict_entry_key(): Return qdict entry key 92 * 93 * Return a *pointer* to the string, it has to be duplicated before being 94 * stored. 95 */ 96 const char *qdict_entry_key(const QDictEntry *entry) 97 { 98 return entry->key; 99 } 100 101 /** 102 * qdict_find(): List lookup function 103 */ 104 static QDictEntry *qdict_find(const QDict *qdict, 105 const char *key, unsigned int bucket) 106 { 107 QDictEntry *entry; 108 109 QLIST_FOREACH(entry, &qdict->table[bucket], next) 110 if (!strcmp(entry->key, key)) 111 return entry; 112 113 return NULL; 114 } 115 116 /** 117 * qdict_put_obj(): Put a new QObject into the dictionary 118 * 119 * Insert the pair 'key:value' into 'qdict', if 'key' already exists 120 * its 'value' will be replaced. 121 * 122 * This is done by freeing the reference to the stored QObject and 123 * storing the new one in the same entry. 124 * 125 * NOTE: ownership of 'value' is transferred to the QDict 126 */ 127 void qdict_put_obj(QDict *qdict, const char *key, QObject *value) 128 { 129 unsigned int bucket; 130 QDictEntry *entry; 131 132 bucket = tdb_hash(key) % QDICT_BUCKET_MAX; 133 entry = qdict_find(qdict, key, bucket); 134 if (entry) { 135 /* replace key's value */ 136 qobject_decref(entry->value); 137 entry->value = value; 138 } else { 139 /* allocate a new entry */ 140 entry = alloc_entry(key, value); 141 QLIST_INSERT_HEAD(&qdict->table[bucket], entry, next); 142 qdict->size++; 143 } 144 } 145 146 /** 147 * qdict_get(): Lookup for a given 'key' 148 * 149 * Return a weak reference to the QObject associated with 'key' if 150 * 'key' is present in the dictionary, NULL otherwise. 151 */ 152 QObject *qdict_get(const QDict *qdict, const char *key) 153 { 154 QDictEntry *entry; 155 156 entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX); 157 return (entry == NULL ? NULL : entry->value); 158 } 159 160 /** 161 * qdict_haskey(): Check if 'key' exists 162 * 163 * Return 1 if 'key' exists in the dict, 0 otherwise 164 */ 165 int qdict_haskey(const QDict *qdict, const char *key) 166 { 167 unsigned int bucket = tdb_hash(key) % QDICT_BUCKET_MAX; 168 return (qdict_find(qdict, key, bucket) == NULL ? 0 : 1); 169 } 170 171 /** 172 * qdict_size(): Return the size of the dictionary 173 */ 174 size_t qdict_size(const QDict *qdict) 175 { 176 return qdict->size; 177 } 178 179 /** 180 * qdict_get_obj(): Get a QObject of a specific type 181 */ 182 static QObject *qdict_get_obj(const QDict *qdict, const char *key, QType type) 183 { 184 QObject *obj; 185 186 obj = qdict_get(qdict, key); 187 assert(obj != NULL); 188 assert(qobject_type(obj) == type); 189 190 return obj; 191 } 192 193 /** 194 * qdict_get_double(): Get an number mapped by 'key' 195 * 196 * This function assumes that 'key' exists and it stores a 197 * QFloat or QInt object. 198 * 199 * Return number mapped by 'key'. 200 */ 201 double qdict_get_double(const QDict *qdict, const char *key) 202 { 203 QObject *obj = qdict_get(qdict, key); 204 205 assert(obj); 206 switch (qobject_type(obj)) { 207 case QTYPE_QFLOAT: 208 return qfloat_get_double(qobject_to_qfloat(obj)); 209 case QTYPE_QINT: 210 return qint_get_int(qobject_to_qint(obj)); 211 default: 212 abort(); 213 } 214 } 215 216 /** 217 * qdict_get_int(): Get an integer mapped by 'key' 218 * 219 * This function assumes that 'key' exists and it stores a 220 * QInt object. 221 * 222 * Return integer mapped by 'key'. 223 */ 224 int64_t qdict_get_int(const QDict *qdict, const char *key) 225 { 226 return qint_get_int(qobject_to_qint(qdict_get(qdict, key))); 227 } 228 229 /** 230 * qdict_get_bool(): Get a bool mapped by 'key' 231 * 232 * This function assumes that 'key' exists and it stores a 233 * QBool object. 234 * 235 * Return bool mapped by 'key'. 236 */ 237 bool qdict_get_bool(const QDict *qdict, const char *key) 238 { 239 return qbool_get_bool(qobject_to_qbool(qdict_get(qdict, key))); 240 } 241 242 /** 243 * qdict_get_qlist(): Get the QList mapped by 'key' 244 * 245 * This function assumes that 'key' exists and it stores a 246 * QList object. 247 * 248 * Return QList mapped by 'key'. 249 */ 250 QList *qdict_get_qlist(const QDict *qdict, const char *key) 251 { 252 return qobject_to_qlist(qdict_get_obj(qdict, key, QTYPE_QLIST)); 253 } 254 255 /** 256 * qdict_get_qdict(): Get the QDict mapped by 'key' 257 * 258 * This function assumes that 'key' exists and it stores a 259 * QDict object. 260 * 261 * Return QDict mapped by 'key'. 262 */ 263 QDict *qdict_get_qdict(const QDict *qdict, const char *key) 264 { 265 return qobject_to_qdict(qdict_get(qdict, key)); 266 } 267 268 /** 269 * qdict_get_str(): Get a pointer to the stored string mapped 270 * by 'key' 271 * 272 * This function assumes that 'key' exists and it stores a 273 * QString object. 274 * 275 * Return pointer to the string mapped by 'key'. 276 */ 277 const char *qdict_get_str(const QDict *qdict, const char *key) 278 { 279 return qstring_get_str(qobject_to_qstring(qdict_get(qdict, key))); 280 } 281 282 /** 283 * qdict_get_try_int(): Try to get integer mapped by 'key' 284 * 285 * Return integer mapped by 'key', if it is not present in 286 * the dictionary or if the stored object is not of QInt type 287 * 'def_value' will be returned. 288 */ 289 int64_t qdict_get_try_int(const QDict *qdict, const char *key, 290 int64_t def_value) 291 { 292 QInt *qint = qobject_to_qint(qdict_get(qdict, key)); 293 294 return qint ? qint_get_int(qint) : def_value; 295 } 296 297 /** 298 * qdict_get_try_bool(): Try to get a bool mapped by 'key' 299 * 300 * Return bool mapped by 'key', if it is not present in the 301 * dictionary or if the stored object is not of QBool type 302 * 'def_value' will be returned. 303 */ 304 bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value) 305 { 306 QBool *qbool = qobject_to_qbool(qdict_get(qdict, key)); 307 308 return qbool ? qbool_get_bool(qbool) : def_value; 309 } 310 311 /** 312 * qdict_get_try_str(): Try to get a pointer to the stored string 313 * mapped by 'key' 314 * 315 * Return a pointer to the string mapped by 'key', if it is not present 316 * in the dictionary or if the stored object is not of QString type 317 * NULL will be returned. 318 */ 319 const char *qdict_get_try_str(const QDict *qdict, const char *key) 320 { 321 QString *qstr = qobject_to_qstring(qdict_get(qdict, key)); 322 323 return qstr ? qstring_get_str(qstr) : NULL; 324 } 325 326 /** 327 * qdict_iter(): Iterate over all the dictionary's stored values. 328 * 329 * This function allows the user to provide an iterator, which will be 330 * called for each stored value in the dictionary. 331 */ 332 void qdict_iter(const QDict *qdict, 333 void (*iter)(const char *key, QObject *obj, void *opaque), 334 void *opaque) 335 { 336 int i; 337 QDictEntry *entry; 338 339 for (i = 0; i < QDICT_BUCKET_MAX; i++) { 340 QLIST_FOREACH(entry, &qdict->table[i], next) 341 iter(entry->key, entry->value, opaque); 342 } 343 } 344 345 static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket) 346 { 347 int i; 348 349 for (i = first_bucket; i < QDICT_BUCKET_MAX; i++) { 350 if (!QLIST_EMPTY(&qdict->table[i])) { 351 return QLIST_FIRST(&qdict->table[i]); 352 } 353 } 354 355 return NULL; 356 } 357 358 /** 359 * qdict_first(): Return first qdict entry for iteration. 360 */ 361 const QDictEntry *qdict_first(const QDict *qdict) 362 { 363 return qdict_next_entry(qdict, 0); 364 } 365 366 /** 367 * qdict_next(): Return next qdict entry in an iteration. 368 */ 369 const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry) 370 { 371 QDictEntry *ret; 372 373 ret = QLIST_NEXT(entry, next); 374 if (!ret) { 375 unsigned int bucket = tdb_hash(entry->key) % QDICT_BUCKET_MAX; 376 ret = qdict_next_entry(qdict, bucket + 1); 377 } 378 379 return ret; 380 } 381 382 /** 383 * qdict_clone_shallow(): Clones a given QDict. Its entries are not copied, but 384 * another reference is added. 385 */ 386 QDict *qdict_clone_shallow(const QDict *src) 387 { 388 QDict *dest; 389 QDictEntry *entry; 390 int i; 391 392 dest = qdict_new(); 393 394 for (i = 0; i < QDICT_BUCKET_MAX; i++) { 395 QLIST_FOREACH(entry, &src->table[i], next) { 396 qobject_incref(entry->value); 397 qdict_put_obj(dest, entry->key, entry->value); 398 } 399 } 400 401 return dest; 402 } 403 404 /** 405 * qentry_destroy(): Free all the memory allocated by a QDictEntry 406 */ 407 static void qentry_destroy(QDictEntry *e) 408 { 409 assert(e != NULL); 410 assert(e->key != NULL); 411 assert(e->value != NULL); 412 413 qobject_decref(e->value); 414 g_free(e->key); 415 g_free(e); 416 } 417 418 /** 419 * qdict_del(): Delete a 'key:value' pair from the dictionary 420 * 421 * This will destroy all data allocated by this entry. 422 */ 423 void qdict_del(QDict *qdict, const char *key) 424 { 425 QDictEntry *entry; 426 427 entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX); 428 if (entry) { 429 QLIST_REMOVE(entry, next); 430 qentry_destroy(entry); 431 qdict->size--; 432 } 433 } 434 435 /** 436 * qdict_destroy_obj(): Free all the memory allocated by a QDict 437 */ 438 void qdict_destroy_obj(QObject *obj) 439 { 440 int i; 441 QDict *qdict; 442 443 assert(obj != NULL); 444 qdict = qobject_to_qdict(obj); 445 446 for (i = 0; i < QDICT_BUCKET_MAX; i++) { 447 QDictEntry *entry = QLIST_FIRST(&qdict->table[i]); 448 while (entry) { 449 QDictEntry *tmp = QLIST_NEXT(entry, next); 450 QLIST_REMOVE(entry, next); 451 qentry_destroy(entry); 452 entry = tmp; 453 } 454 } 455 456 g_free(qdict); 457 } 458 459 /** 460 * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, the 461 * value of 'key' in 'src' is copied there (and the refcount increased 462 * accordingly). 463 */ 464 void qdict_copy_default(QDict *dst, QDict *src, const char *key) 465 { 466 QObject *val; 467 468 if (qdict_haskey(dst, key)) { 469 return; 470 } 471 472 val = qdict_get(src, key); 473 if (val) { 474 qobject_incref(val); 475 qdict_put_obj(dst, key, val); 476 } 477 } 478 479 /** 480 * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' yet, a 481 * new QString initialised by 'val' is put there. 482 */ 483 void qdict_set_default_str(QDict *dst, const char *key, const char *val) 484 { 485 if (qdict_haskey(dst, key)) { 486 return; 487 } 488 489 qdict_put(dst, key, qstring_from_str(val)); 490 } 491 492 static void qdict_flatten_qdict(QDict *qdict, QDict *target, 493 const char *prefix); 494 495 static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix) 496 { 497 QObject *value; 498 const QListEntry *entry; 499 char *new_key; 500 int i; 501 502 /* This function is never called with prefix == NULL, i.e., it is always 503 * called from within qdict_flatten_q(list|dict)(). Therefore, it does not 504 * need to remove list entries during the iteration (the whole list will be 505 * deleted eventually anyway from qdict_flatten_qdict()). */ 506 assert(prefix); 507 508 entry = qlist_first(qlist); 509 510 for (i = 0; entry; entry = qlist_next(entry), i++) { 511 value = qlist_entry_obj(entry); 512 new_key = g_strdup_printf("%s.%i", prefix, i); 513 514 if (qobject_type(value) == QTYPE_QDICT) { 515 qdict_flatten_qdict(qobject_to_qdict(value), target, new_key); 516 } else if (qobject_type(value) == QTYPE_QLIST) { 517 qdict_flatten_qlist(qobject_to_qlist(value), target, new_key); 518 } else { 519 /* All other types are moved to the target unchanged. */ 520 qobject_incref(value); 521 qdict_put_obj(target, new_key, value); 522 } 523 524 g_free(new_key); 525 } 526 } 527 528 static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix) 529 { 530 QObject *value; 531 const QDictEntry *entry, *next; 532 char *new_key; 533 bool delete; 534 535 entry = qdict_first(qdict); 536 537 while (entry != NULL) { 538 539 next = qdict_next(qdict, entry); 540 value = qdict_entry_value(entry); 541 new_key = NULL; 542 delete = false; 543 544 if (prefix) { 545 new_key = g_strdup_printf("%s.%s", prefix, entry->key); 546 } 547 548 if (qobject_type(value) == QTYPE_QDICT) { 549 /* Entries of QDicts are processed recursively, the QDict object 550 * itself disappears. */ 551 qdict_flatten_qdict(qobject_to_qdict(value), target, 552 new_key ? new_key : entry->key); 553 delete = true; 554 } else if (qobject_type(value) == QTYPE_QLIST) { 555 qdict_flatten_qlist(qobject_to_qlist(value), target, 556 new_key ? new_key : entry->key); 557 delete = true; 558 } else if (prefix) { 559 /* All other objects are moved to the target unchanged. */ 560 qobject_incref(value); 561 qdict_put_obj(target, new_key, value); 562 delete = true; 563 } 564 565 g_free(new_key); 566 567 if (delete) { 568 qdict_del(qdict, entry->key); 569 570 /* Restart loop after modifying the iterated QDict */ 571 entry = qdict_first(qdict); 572 continue; 573 } 574 575 entry = next; 576 } 577 } 578 579 /** 580 * qdict_flatten(): For each nested QDict with key x, all fields with key y 581 * are moved to this QDict and their key is renamed to "x.y". For each nested 582 * QList with key x, the field at index y is moved to this QDict with the key 583 * "x.y" (i.e., the reverse of what qdict_array_split() does). 584 * This operation is applied recursively for nested QDicts and QLists. 585 */ 586 void qdict_flatten(QDict *qdict) 587 { 588 qdict_flatten_qdict(qdict, qdict, NULL); 589 } 590 591 /* extract all the src QDict entries starting by start into dst */ 592 void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start) 593 594 { 595 const QDictEntry *entry, *next; 596 const char *p; 597 598 *dst = qdict_new(); 599 entry = qdict_first(src); 600 601 while (entry != NULL) { 602 next = qdict_next(src, entry); 603 if (strstart(entry->key, start, &p)) { 604 qobject_incref(entry->value); 605 qdict_put_obj(*dst, p, entry->value); 606 qdict_del(src, entry->key); 607 } 608 entry = next; 609 } 610 } 611 612 static int qdict_count_prefixed_entries(const QDict *src, const char *start) 613 { 614 const QDictEntry *entry; 615 int count = 0; 616 617 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) { 618 if (strstart(entry->key, start, NULL)) { 619 if (count == INT_MAX) { 620 return -ERANGE; 621 } 622 count++; 623 } 624 } 625 626 return count; 627 } 628 629 /** 630 * qdict_array_split(): This function moves array-like elements of a QDict into 631 * a new QList. Every entry in the original QDict with a key "%u" or one 632 * prefixed "%u.", where %u designates an unsigned integer starting at 0 and 633 * incrementally counting up, will be moved to a new QDict at index %u in the 634 * output QList with the key prefix removed, if that prefix is "%u.". If the 635 * whole key is just "%u", the whole QObject will be moved unchanged without 636 * creating a new QDict. The function terminates when there is no entry in the 637 * QDict with a prefix directly (incrementally) following the last one; it also 638 * returns if there are both entries with "%u" and "%u." for the same index %u. 639 * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66} 640 * (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66}) 641 * => [{"a": 42, "b": 23}, {"x": 0}, 66] 642 * and {"4.y": 1, "o.o": 7} (remainder of the old QDict) 643 */ 644 void qdict_array_split(QDict *src, QList **dst) 645 { 646 unsigned i; 647 648 *dst = qlist_new(); 649 650 for (i = 0; i < UINT_MAX; i++) { 651 QObject *subqobj; 652 bool is_subqdict; 653 QDict *subqdict; 654 char indexstr[32], prefix[32]; 655 size_t snprintf_ret; 656 657 snprintf_ret = snprintf(indexstr, 32, "%u", i); 658 assert(snprintf_ret < 32); 659 660 subqobj = qdict_get(src, indexstr); 661 662 snprintf_ret = snprintf(prefix, 32, "%u.", i); 663 assert(snprintf_ret < 32); 664 665 /* Overflow is the same as positive non-zero results */ 666 is_subqdict = qdict_count_prefixed_entries(src, prefix); 667 668 // There may be either a single subordinate object (named "%u") or 669 // multiple objects (each with a key prefixed "%u."), but not both. 670 if (!subqobj == !is_subqdict) { 671 break; 672 } 673 674 if (is_subqdict) { 675 qdict_extract_subqdict(src, &subqdict, prefix); 676 assert(qdict_size(subqdict) > 0); 677 } else { 678 qobject_incref(subqobj); 679 qdict_del(src, indexstr); 680 } 681 682 qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict)); 683 } 684 } 685 686 /** 687 * qdict_array_entries(): Returns the number of direct array entries if the 688 * sub-QDict of src specified by the prefix in subqdict (or src itself for 689 * prefix == "") is valid as an array, i.e. the length of the created list if 690 * the sub-QDict would become empty after calling qdict_array_split() on it. If 691 * the array is not valid, -EINVAL is returned. 692 */ 693 int qdict_array_entries(QDict *src, const char *subqdict) 694 { 695 const QDictEntry *entry; 696 unsigned i; 697 unsigned entries = 0; 698 size_t subqdict_len = strlen(subqdict); 699 700 assert(!subqdict_len || subqdict[subqdict_len - 1] == '.'); 701 702 /* qdict_array_split() loops until UINT_MAX, but as we want to return 703 * negative errors, we only have a signed return value here. Any additional 704 * entries will lead to -EINVAL. */ 705 for (i = 0; i < INT_MAX; i++) { 706 QObject *subqobj; 707 int subqdict_entries; 708 size_t slen = 32 + subqdict_len; 709 char indexstr[slen], prefix[slen]; 710 size_t snprintf_ret; 711 712 snprintf_ret = snprintf(indexstr, slen, "%s%u", subqdict, i); 713 assert(snprintf_ret < slen); 714 715 subqobj = qdict_get(src, indexstr); 716 717 snprintf_ret = snprintf(prefix, slen, "%s%u.", subqdict, i); 718 assert(snprintf_ret < slen); 719 720 subqdict_entries = qdict_count_prefixed_entries(src, prefix); 721 if (subqdict_entries < 0) { 722 return subqdict_entries; 723 } 724 725 /* There may be either a single subordinate object (named "%u") or 726 * multiple objects (each with a key prefixed "%u."), but not both. */ 727 if (subqobj && subqdict_entries) { 728 return -EINVAL; 729 } else if (!subqobj && !subqdict_entries) { 730 break; 731 } 732 733 entries += subqdict_entries ? subqdict_entries : 1; 734 } 735 736 /* Consider everything handled that isn't part of the given sub-QDict */ 737 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) { 738 if (!strstart(qdict_entry_key(entry), subqdict, NULL)) { 739 entries++; 740 } 741 } 742 743 /* Anything left in the sub-QDict that wasn't handled? */ 744 if (qdict_size(src) != entries) { 745 return -EINVAL; 746 } 747 748 return i; 749 } 750 751 /** 752 * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all 753 * elements from src to dest. 754 * 755 * If an element from src has a key already present in dest, it will not be 756 * moved unless overwrite is true. 757 * 758 * If overwrite is true, the conflicting values in dest will be discarded and 759 * replaced by the corresponding values from src. 760 * 761 * Therefore, with overwrite being true, the src QDict will always be empty when 762 * this function returns. If overwrite is false, the src QDict will be empty 763 * iff there were no conflicts. 764 */ 765 void qdict_join(QDict *dest, QDict *src, bool overwrite) 766 { 767 const QDictEntry *entry, *next; 768 769 entry = qdict_first(src); 770 while (entry) { 771 next = qdict_next(src, entry); 772 773 if (overwrite || !qdict_haskey(dest, entry->key)) { 774 qobject_incref(entry->value); 775 qdict_put_obj(dest, entry->key, entry->value); 776 qdict_del(src, entry->key); 777 } 778 779 entry = next; 780 } 781 } 782