1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "qapi/qmp/qnum.h"
15#include "qapi/qmp/qdict.h"
16#include "qapi/qmp/qbool.h"
17#include "qapi/qmp/qlist.h"
18#include "qapi/qmp/qnull.h"
19#include "qapi/qmp/qstring.h"
20#include "qapi/error.h"
21#include "qemu/queue.h"
22#include "qemu-common.h"
23#include "qemu/cutils.h"
24
25
26
27
28
29
30QDict *qdict_new(void)
31{
32 QDict *qdict;
33
34 qdict = g_malloc0(sizeof(*qdict));
35 qobject_init(QOBJECT(qdict), QTYPE_QDICT);
36
37 return qdict;
38}
39
40
41
42
43
44static unsigned int tdb_hash(const char *name)
45{
46 unsigned value;
47 unsigned i;
48
49
50 for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++)
51 value = (value + (((const unsigned char *)name)[i] << (i*5 % 24)));
52
53 return (1103515243 * value + 12345);
54}
55
56
57
58
59static QDictEntry *alloc_entry(const char *key, QObject *value)
60{
61 QDictEntry *entry;
62
63 entry = g_malloc0(sizeof(*entry));
64 entry->key = g_strdup(key);
65 entry->value = value;
66
67 return entry;
68}
69
70
71
72
73
74
75QObject *qdict_entry_value(const QDictEntry *entry)
76{
77 return entry->value;
78}
79
80
81
82
83
84
85
86const char *qdict_entry_key(const QDictEntry *entry)
87{
88 return entry->key;
89}
90
91
92
93
94static QDictEntry *qdict_find(const QDict *qdict,
95 const char *key, unsigned int bucket)
96{
97 QDictEntry *entry;
98
99 QLIST_FOREACH(entry, &qdict->table[bucket], next)
100 if (!strcmp(entry->key, key))
101 return entry;
102
103 return NULL;
104}
105
106
107
108
109
110
111
112
113
114
115
116
117void qdict_put_obj(QDict *qdict, const char *key, QObject *value)
118{
119 unsigned int bucket;
120 QDictEntry *entry;
121
122 bucket = tdb_hash(key) % QDICT_BUCKET_MAX;
123 entry = qdict_find(qdict, key, bucket);
124 if (entry) {
125
126 qobject_decref(entry->value);
127 entry->value = value;
128 } else {
129
130 entry = alloc_entry(key, value);
131 QLIST_INSERT_HEAD(&qdict->table[bucket], entry, next);
132 qdict->size++;
133 }
134}
135
136void qdict_put_int(QDict *qdict, const char *key, int64_t value)
137{
138 qdict_put(qdict, key, qnum_from_int(value));
139}
140
141void qdict_put_bool(QDict *qdict, const char *key, bool value)
142{
143 qdict_put(qdict, key, qbool_from_bool(value));
144}
145
146void qdict_put_str(QDict *qdict, const char *key, const char *value)
147{
148 qdict_put(qdict, key, qstring_from_str(value));
149}
150
151void qdict_put_null(QDict *qdict, const char *key)
152{
153 qdict_put(qdict, key, qnull());
154}
155
156
157
158
159
160
161
162QObject *qdict_get(const QDict *qdict, const char *key)
163{
164 QDictEntry *entry;
165
166 entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX);
167 return (entry == NULL ? NULL : entry->value);
168}
169
170
171
172
173
174
175int qdict_haskey(const QDict *qdict, const char *key)
176{
177 unsigned int bucket = tdb_hash(key) % QDICT_BUCKET_MAX;
178 return (qdict_find(qdict, key, bucket) == NULL ? 0 : 1);
179}
180
181
182
183
184size_t qdict_size(const QDict *qdict)
185{
186 return qdict->size;
187}
188
189
190
191
192
193
194
195
196double qdict_get_double(const QDict *qdict, const char *key)
197{
198 return qnum_get_double(qobject_to(QNum, qdict_get(qdict, key)));
199}
200
201
202
203
204
205
206
207
208
209int64_t qdict_get_int(const QDict *qdict, const char *key)
210{
211 return qnum_get_int(qobject_to(QNum, qdict_get(qdict, key)));
212}
213
214
215
216
217
218
219
220
221
222bool qdict_get_bool(const QDict *qdict, const char *key)
223{
224 return qbool_get_bool(qobject_to(QBool, qdict_get(qdict, key)));
225}
226
227
228
229
230QList *qdict_get_qlist(const QDict *qdict, const char *key)
231{
232 return qobject_to(QList, qdict_get(qdict, key));
233}
234
235
236
237
238QDict *qdict_get_qdict(const QDict *qdict, const char *key)
239{
240 return qobject_to(QDict, qdict_get(qdict, key));
241}
242
243
244
245
246
247
248
249
250
251
252const char *qdict_get_str(const QDict *qdict, const char *key)
253{
254 return qstring_get_str(qobject_to(QString, qdict_get(qdict, key)));
255}
256
257
258
259
260
261
262
263
264int64_t qdict_get_try_int(const QDict *qdict, const char *key,
265 int64_t def_value)
266{
267 QNum *qnum = qobject_to(QNum, qdict_get(qdict, key));
268 int64_t val;
269
270 if (!qnum || !qnum_get_try_int(qnum, &val)) {
271 return def_value;
272 }
273
274 return val;
275}
276
277
278
279
280
281
282
283
284bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
285{
286 QBool *qbool = qobject_to(QBool, qdict_get(qdict, key));
287
288 return qbool ? qbool_get_bool(qbool) : def_value;
289}
290
291
292
293
294
295
296
297
298
299const char *qdict_get_try_str(const QDict *qdict, const char *key)
300{
301 QString *qstr = qobject_to(QString, qdict_get(qdict, key));
302
303 return qstr ? qstring_get_str(qstr) : NULL;
304}
305
306
307
308
309
310
311
312void qdict_iter(const QDict *qdict,
313 void (*iter)(const char *key, QObject *obj, void *opaque),
314 void *opaque)
315{
316 int i;
317 QDictEntry *entry;
318
319 for (i = 0; i < QDICT_BUCKET_MAX; i++) {
320 QLIST_FOREACH(entry, &qdict->table[i], next)
321 iter(entry->key, entry->value, opaque);
322 }
323}
324
325static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket)
326{
327 int i;
328
329 for (i = first_bucket; i < QDICT_BUCKET_MAX; i++) {
330 if (!QLIST_EMPTY(&qdict->table[i])) {
331 return QLIST_FIRST(&qdict->table[i]);
332 }
333 }
334
335 return NULL;
336}
337
338
339
340
341const QDictEntry *qdict_first(const QDict *qdict)
342{
343 return qdict_next_entry(qdict, 0);
344}
345
346
347
348
349const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry)
350{
351 QDictEntry *ret;
352
353 ret = QLIST_NEXT(entry, next);
354 if (!ret) {
355 unsigned int bucket = tdb_hash(entry->key) % QDICT_BUCKET_MAX;
356 ret = qdict_next_entry(qdict, bucket + 1);
357 }
358
359 return ret;
360}
361
362
363
364
365
366QDict *qdict_clone_shallow(const QDict *src)
367{
368 QDict *dest;
369 QDictEntry *entry;
370 int i;
371
372 dest = qdict_new();
373
374 for (i = 0; i < QDICT_BUCKET_MAX; i++) {
375 QLIST_FOREACH(entry, &src->table[i], next) {
376 qobject_incref(entry->value);
377 qdict_put_obj(dest, entry->key, entry->value);
378 }
379 }
380
381 return dest;
382}
383
384
385
386
387static void qentry_destroy(QDictEntry *e)
388{
389 assert(e != NULL);
390 assert(e->key != NULL);
391 assert(e->value != NULL);
392
393 qobject_decref(e->value);
394 g_free(e->key);
395 g_free(e);
396}
397
398
399
400
401
402
403void qdict_del(QDict *qdict, const char *key)
404{
405 QDictEntry *entry;
406
407 entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX);
408 if (entry) {
409 QLIST_REMOVE(entry, next);
410 qentry_destroy(entry);
411 qdict->size--;
412 }
413}
414
415
416
417
418
419
420
421
422bool qdict_is_equal(const QObject *x, const QObject *y)
423{
424 const QDict *dict_x = qobject_to(QDict, x);
425 const QDict *dict_y = qobject_to(QDict, y);
426 const QDictEntry *e;
427
428 if (qdict_size(dict_x) != qdict_size(dict_y)) {
429 return false;
430 }
431
432 for (e = qdict_first(dict_x); e; e = qdict_next(dict_x, e)) {
433 const QObject *obj_x = qdict_entry_value(e);
434 const QObject *obj_y = qdict_get(dict_y, qdict_entry_key(e));
435
436 if (!qobject_is_equal(obj_x, obj_y)) {
437 return false;
438 }
439 }
440
441 return true;
442}
443
444
445
446
447void qdict_destroy_obj(QObject *obj)
448{
449 int i;
450 QDict *qdict;
451
452 assert(obj != NULL);
453 qdict = qobject_to(QDict, obj);
454
455 for (i = 0; i < QDICT_BUCKET_MAX; i++) {
456 QDictEntry *entry = QLIST_FIRST(&qdict->table[i]);
457 while (entry) {
458 QDictEntry *tmp = QLIST_NEXT(entry, next);
459 QLIST_REMOVE(entry, next);
460 qentry_destroy(entry);
461 entry = tmp;
462 }
463 }
464
465 g_free(qdict);
466}
467
468
469
470
471
472
473void qdict_copy_default(QDict *dst, QDict *src, const char *key)
474{
475 QObject *val;
476
477 if (qdict_haskey(dst, key)) {
478 return;
479 }
480
481 val = qdict_get(src, key);
482 if (val) {
483 qobject_incref(val);
484 qdict_put_obj(dst, key, val);
485 }
486}
487
488
489
490
491
492void qdict_set_default_str(QDict *dst, const char *key, const char *val)
493{
494 if (qdict_haskey(dst, key)) {
495 return;
496 }
497
498 qdict_put_str(dst, key, val);
499}
500
501static void qdict_flatten_qdict(QDict *qdict, QDict *target,
502 const char *prefix);
503
504static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix)
505{
506 QObject *value;
507 const QListEntry *entry;
508 char *new_key;
509 int i;
510
511
512
513
514
515 assert(prefix);
516
517 entry = qlist_first(qlist);
518
519 for (i = 0; entry; entry = qlist_next(entry), i++) {
520 value = qlist_entry_obj(entry);
521 new_key = g_strdup_printf("%s.%i", prefix, i);
522
523 if (qobject_type(value) == QTYPE_QDICT) {
524 qdict_flatten_qdict(qobject_to(QDict, value), target, new_key);
525 } else if (qobject_type(value) == QTYPE_QLIST) {
526 qdict_flatten_qlist(qobject_to(QList, value), target, new_key);
527 } else {
528
529 qobject_incref(value);
530 qdict_put_obj(target, new_key, value);
531 }
532
533 g_free(new_key);
534 }
535}
536
537static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
538{
539 QObject *value;
540 const QDictEntry *entry, *next;
541 char *new_key;
542 bool delete;
543
544 entry = qdict_first(qdict);
545
546 while (entry != NULL) {
547
548 next = qdict_next(qdict, entry);
549 value = qdict_entry_value(entry);
550 new_key = NULL;
551 delete = false;
552
553 if (prefix) {
554 new_key = g_strdup_printf("%s.%s", prefix, entry->key);
555 }
556
557 if (qobject_type(value) == QTYPE_QDICT) {
558
559
560 qdict_flatten_qdict(qobject_to(QDict, value), target,
561 new_key ? new_key : entry->key);
562 delete = true;
563 } else if (qobject_type(value) == QTYPE_QLIST) {
564 qdict_flatten_qlist(qobject_to(QList, value), target,
565 new_key ? new_key : entry->key);
566 delete = true;
567 } else if (prefix) {
568
569 qobject_incref(value);
570 qdict_put_obj(target, new_key, value);
571 delete = true;
572 }
573
574 g_free(new_key);
575
576 if (delete) {
577 qdict_del(qdict, entry->key);
578
579
580 entry = qdict_first(qdict);
581 continue;
582 }
583
584 entry = next;
585 }
586}
587
588
589
590
591
592
593
594
595void qdict_flatten(QDict *qdict)
596{
597 qdict_flatten_qdict(qdict, qdict, NULL);
598}
599
600
601void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
602
603{
604 const QDictEntry *entry, *next;
605 const char *p;
606
607 *dst = qdict_new();
608 entry = qdict_first(src);
609
610 while (entry != NULL) {
611 next = qdict_next(src, entry);
612 if (strstart(entry->key, start, &p)) {
613 qobject_incref(entry->value);
614 qdict_put_obj(*dst, p, entry->value);
615 qdict_del(src, entry->key);
616 }
617 entry = next;
618 }
619}
620
621static int qdict_count_prefixed_entries(const QDict *src, const char *start)
622{
623 const QDictEntry *entry;
624 int count = 0;
625
626 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
627 if (strstart(entry->key, start, NULL)) {
628 if (count == INT_MAX) {
629 return -ERANGE;
630 }
631 count++;
632 }
633 }
634
635 return count;
636}
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653void qdict_array_split(QDict *src, QList **dst)
654{
655 unsigned i;
656
657 *dst = qlist_new();
658
659 for (i = 0; i < UINT_MAX; i++) {
660 QObject *subqobj;
661 bool is_subqdict;
662 QDict *subqdict;
663 char indexstr[32], prefix[32];
664 size_t snprintf_ret;
665
666 snprintf_ret = snprintf(indexstr, 32, "%u", i);
667 assert(snprintf_ret < 32);
668
669 subqobj = qdict_get(src, indexstr);
670
671 snprintf_ret = snprintf(prefix, 32, "%u.", i);
672 assert(snprintf_ret < 32);
673
674
675 is_subqdict = qdict_count_prefixed_entries(src, prefix);
676
677
678
679 if (!subqobj == !is_subqdict) {
680 break;
681 }
682
683 if (is_subqdict) {
684 qdict_extract_subqdict(src, &subqdict, prefix);
685 assert(qdict_size(subqdict) > 0);
686 } else {
687 qobject_incref(subqobj);
688 qdict_del(src, indexstr);
689 }
690
691 qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict));
692 }
693}
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717static void qdict_split_flat_key(const char *key, char **prefix,
718 const char **suffix)
719{
720 const char *separator;
721 size_t i, j;
722
723
724
725 separator = NULL;
726 do {
727 if (separator) {
728 separator += 2;
729 } else {
730 separator = key;
731 }
732 separator = strchr(separator, '.');
733 } while (separator && separator[1] == '.');
734
735 if (separator) {
736 *prefix = g_strndup(key, separator - key);
737 *suffix = separator + 1;
738 } else {
739 *prefix = g_strdup(key);
740 *suffix = NULL;
741 }
742
743
744 for (i = 0, j = 0; (*prefix)[i] != '\0'; i++, j++) {
745 if ((*prefix)[i] == '.') {
746 assert((*prefix)[i + 1] == '.');
747 i++;
748 }
749 (*prefix)[j] = (*prefix)[i];
750 }
751 (*prefix)[j] = '\0';
752}
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767static int qdict_is_list(QDict *maybe_list, Error **errp)
768{
769 const QDictEntry *ent;
770 ssize_t len = 0;
771 ssize_t max = -1;
772 int is_list = -1;
773 int64_t val;
774
775 for (ent = qdict_first(maybe_list); ent != NULL;
776 ent = qdict_next(maybe_list, ent)) {
777
778 if (qemu_strtoi64(ent->key, NULL, 10, &val) == 0) {
779 if (is_list == -1) {
780 is_list = 1;
781 } else if (!is_list) {
782 error_setg(errp,
783 "Cannot mix list and non-list keys");
784 return -1;
785 }
786 len++;
787 if (val > max) {
788 max = val;
789 }
790 } else {
791 if (is_list == -1) {
792 is_list = 0;
793 } else if (is_list) {
794 error_setg(errp,
795 "Cannot mix list and non-list keys");
796 return -1;
797 }
798 }
799 }
800
801 if (is_list == -1) {
802 assert(!qdict_size(maybe_list));
803 is_list = 0;
804 }
805
806
807
808
809
810
811 if (len != (max + 1)) {
812 error_setg(errp, "List indices are not contiguous, "
813 "saw %zd elements but %zd largest index",
814 len, max);
815 return -1;
816 }
817
818 return is_list;
819}
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860QObject *qdict_crumple(const QDict *src, Error **errp)
861{
862 const QDictEntry *ent;
863 QDict *two_level, *multi_level = NULL;
864 QObject *dst = NULL, *child;
865 size_t i;
866 char *prefix = NULL;
867 const char *suffix = NULL;
868 int is_list;
869
870 two_level = qdict_new();
871
872
873 for (ent = qdict_first(src); ent != NULL; ent = qdict_next(src, ent)) {
874 if (qobject_type(ent->value) == QTYPE_QDICT ||
875 qobject_type(ent->value) == QTYPE_QLIST) {
876 error_setg(errp, "Value %s is not a scalar",
877 ent->key);
878 goto error;
879 }
880
881 qdict_split_flat_key(ent->key, &prefix, &suffix);
882
883 child = qdict_get(two_level, prefix);
884 if (suffix) {
885 QDict *child_dict = qobject_to(QDict, child);
886 if (!child_dict) {
887 if (child) {
888 error_setg(errp, "Key %s prefix is already set as a scalar",
889 prefix);
890 goto error;
891 }
892
893 child_dict = qdict_new();
894 qdict_put_obj(two_level, prefix, QOBJECT(child_dict));
895 }
896
897 qobject_incref(ent->value);
898 qdict_put_obj(child_dict, suffix, ent->value);
899 } else {
900 if (child) {
901 error_setg(errp, "Key %s prefix is already set as a dict",
902 prefix);
903 goto error;
904 }
905 qobject_incref(ent->value);
906 qdict_put_obj(two_level, prefix, ent->value);
907 }
908
909 g_free(prefix);
910 prefix = NULL;
911 }
912
913
914
915 multi_level = qdict_new();
916 for (ent = qdict_first(two_level); ent != NULL;
917 ent = qdict_next(two_level, ent)) {
918 QDict *dict = qobject_to(QDict, ent->value);
919 if (dict) {
920 child = qdict_crumple(dict, errp);
921 if (!child) {
922 goto error;
923 }
924
925 qdict_put_obj(multi_level, ent->key, child);
926 } else {
927 qobject_incref(ent->value);
928 qdict_put_obj(multi_level, ent->key, ent->value);
929 }
930 }
931 QDECREF(two_level);
932 two_level = NULL;
933
934
935 is_list = qdict_is_list(multi_level, errp);
936 if (is_list < 0) {
937 goto error;
938 }
939
940 if (is_list) {
941 dst = QOBJECT(qlist_new());
942
943 for (i = 0; i < qdict_size(multi_level); i++) {
944 char *key = g_strdup_printf("%zu", i);
945
946 child = qdict_get(multi_level, key);
947 g_free(key);
948
949 if (!child) {
950 error_setg(errp, "Missing list index %zu", i);
951 goto error;
952 }
953
954 qobject_incref(child);
955 qlist_append_obj(qobject_to(QList, dst), child);
956 }
957 QDECREF(multi_level);
958 multi_level = NULL;
959 } else {
960 dst = QOBJECT(multi_level);
961 }
962
963 return dst;
964
965 error:
966 g_free(prefix);
967 QDECREF(multi_level);
968 QDECREF(two_level);
969 qobject_decref(dst);
970 return NULL;
971}
972
973
974
975
976
977
978
979
980int qdict_array_entries(QDict *src, const char *subqdict)
981{
982 const QDictEntry *entry;
983 unsigned i;
984 unsigned entries = 0;
985 size_t subqdict_len = strlen(subqdict);
986
987 assert(!subqdict_len || subqdict[subqdict_len - 1] == '.');
988
989
990
991
992 for (i = 0; i < INT_MAX; i++) {
993 QObject *subqobj;
994 int subqdict_entries;
995 char *prefix = g_strdup_printf("%s%u.", subqdict, i);
996
997 subqdict_entries = qdict_count_prefixed_entries(src, prefix);
998
999
1000 prefix[strlen(prefix) - 1] = 0;
1001 subqobj = qdict_get(src, prefix);
1002
1003 g_free(prefix);
1004
1005 if (subqdict_entries < 0) {
1006 return subqdict_entries;
1007 }
1008
1009
1010
1011 if (subqobj && subqdict_entries) {
1012 return -EINVAL;
1013 } else if (!subqobj && !subqdict_entries) {
1014 break;
1015 }
1016
1017 entries += subqdict_entries ? subqdict_entries : 1;
1018 }
1019
1020
1021 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
1022 if (!strstart(qdict_entry_key(entry), subqdict, NULL)) {
1023 entries++;
1024 }
1025 }
1026
1027
1028 if (qdict_size(src) != entries) {
1029 return -EINVAL;
1030 }
1031
1032 return i;
1033}
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049void qdict_join(QDict *dest, QDict *src, bool overwrite)
1050{
1051 const QDictEntry *entry, *next;
1052
1053 entry = qdict_first(src);
1054 while (entry) {
1055 next = qdict_next(src, entry);
1056
1057 if (overwrite || !qdict_haskey(dest, entry->key)) {
1058 qobject_incref(entry->value);
1059 qdict_put_obj(dest, entry->key, entry->value);
1060 qdict_del(src, entry->key);
1061 }
1062
1063 entry = next;
1064 }
1065}
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **errp)
1079{
1080 QObject *qobj;
1081
1082 while (renames->from) {
1083 if (qdict_haskey(qdict, renames->from)) {
1084 if (qdict_haskey(qdict, renames->to)) {
1085 error_setg(errp, "'%s' and its alias '%s' can't be used at the "
1086 "same time", renames->to, renames->from);
1087 return false;
1088 }
1089
1090 qobj = qdict_get(qdict, renames->from);
1091 qobject_incref(qobj);
1092 qdict_put_obj(qdict, renames->to, qobj);
1093 qdict_del(qdict, renames->from);
1094 }
1095
1096 renames++;
1097 }
1098 return true;
1099}
1100