]>
Commit | Line | Data |
---|---|---|
fb08dde0 | 1 | /* |
41836a9f | 2 | * QDict Module |
fb08dde0 LC |
3 | * |
4 | * Copyright (C) 2009 Red Hat Inc. | |
5 | * | |
6 | * Authors: | |
7 | * Luiz Capitulino <lcapitulino@redhat.com> | |
8 | * | |
41836a9f LC |
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. | |
fb08dde0 LC |
11 | */ |
12 | ||
f2ad72b3 | 13 | #include "qemu/osdep.h" |
609f45ea | 14 | #include "block/qdict.h" |
01b2ffce | 15 | #include "qapi/qmp/qnum.h" |
7b1b5d19 PB |
16 | #include "qapi/qmp/qdict.h" |
17 | #include "qapi/qmp/qbool.h" | |
47e6b297 | 18 | #include "qapi/qmp/qlist.h" |
15280c36 | 19 | #include "qapi/qmp/qnull.h" |
7b1b5d19 | 20 | #include "qapi/qmp/qstring.h" |
603476c2 | 21 | #include "qapi/error.h" |
1de7afc9 | 22 | #include "qemu/queue.h" |
fb08dde0 | 23 | #include "qemu-common.h" |
f348b6d1 | 24 | #include "qemu/cutils.h" |
fb08dde0 | 25 | |
fb08dde0 LC |
26 | /** |
27 | * qdict_new(): Create a new QDict | |
28 | * | |
29 | * Return strong reference. | |
30 | */ | |
31 | QDict *qdict_new(void) | |
32 | { | |
33 | QDict *qdict; | |
34 | ||
7267c094 | 35 | qdict = g_malloc0(sizeof(*qdict)); |
55e1819c | 36 | qobject_init(QOBJECT(qdict), QTYPE_QDICT); |
fb08dde0 LC |
37 | |
38 | return qdict; | |
39 | } | |
40 | ||
fb08dde0 LC |
41 | /** |
42 | * tdb_hash(): based on the hash agorithm from gdbm, via tdb | |
43 | * (from module-init-tools) | |
44 | */ | |
45 | static unsigned int tdb_hash(const char *name) | |
46 | { | |
47 | unsigned value; /* Used to compute the hash value. */ | |
48 | unsigned i; /* Used to cycle through random values. */ | |
49 | ||
50 | /* Set the initial value from the key size. */ | |
51 | for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) | |
52 | value = (value + (((const unsigned char *)name)[i] << (i*5 % 24))); | |
53 | ||
54 | return (1103515243 * value + 12345); | |
55 | } | |
56 | ||
57 | /** | |
58 | * alloc_entry(): allocate a new QDictEntry | |
59 | */ | |
60 | static QDictEntry *alloc_entry(const char *key, QObject *value) | |
61 | { | |
62 | QDictEntry *entry; | |
63 | ||
7267c094 AL |
64 | entry = g_malloc0(sizeof(*entry)); |
65 | entry->key = g_strdup(key); | |
fb08dde0 LC |
66 | entry->value = value; |
67 | ||
68 | return entry; | |
69 | } | |
70 | ||
0d078b2a LC |
71 | /** |
72 | * qdict_entry_value(): Return qdict entry value | |
73 | * | |
74 | * Return weak reference. | |
75 | */ | |
76 | QObject *qdict_entry_value(const QDictEntry *entry) | |
77 | { | |
78 | return entry->value; | |
79 | } | |
80 | ||
81 | /** | |
82 | * qdict_entry_key(): Return qdict entry key | |
83 | * | |
84 | * Return a *pointer* to the string, it has to be duplicated before being | |
85 | * stored. | |
86 | */ | |
87 | const char *qdict_entry_key(const QDictEntry *entry) | |
88 | { | |
89 | return entry->key; | |
90 | } | |
91 | ||
fb08dde0 LC |
92 | /** |
93 | * qdict_find(): List lookup function | |
94 | */ | |
95 | static QDictEntry *qdict_find(const QDict *qdict, | |
c8bc3cd7 | 96 | const char *key, unsigned int bucket) |
fb08dde0 LC |
97 | { |
98 | QDictEntry *entry; | |
99 | ||
c8bc3cd7 | 100 | QLIST_FOREACH(entry, &qdict->table[bucket], next) |
fb08dde0 LC |
101 | if (!strcmp(entry->key, key)) |
102 | return entry; | |
103 | ||
104 | return NULL; | |
105 | } | |
106 | ||
107 | /** | |
108 | * qdict_put_obj(): Put a new QObject into the dictionary | |
109 | * | |
110 | * Insert the pair 'key:value' into 'qdict', if 'key' already exists | |
111 | * its 'value' will be replaced. | |
112 | * | |
113 | * This is done by freeing the reference to the stored QObject and | |
114 | * storing the new one in the same entry. | |
115 | * | |
116 | * NOTE: ownership of 'value' is transferred to the QDict | |
117 | */ | |
118 | void qdict_put_obj(QDict *qdict, const char *key, QObject *value) | |
119 | { | |
c8bc3cd7 | 120 | unsigned int bucket; |
fb08dde0 LC |
121 | QDictEntry *entry; |
122 | ||
c8bc3cd7 LC |
123 | bucket = tdb_hash(key) % QDICT_BUCKET_MAX; |
124 | entry = qdict_find(qdict, key, bucket); | |
fb08dde0 LC |
125 | if (entry) { |
126 | /* replace key's value */ | |
cb3e7f08 | 127 | qobject_unref(entry->value); |
fb08dde0 LC |
128 | entry->value = value; |
129 | } else { | |
130 | /* allocate a new entry */ | |
131 | entry = alloc_entry(key, value); | |
c8bc3cd7 | 132 | QLIST_INSERT_HEAD(&qdict->table[bucket], entry, next); |
29ec3156 | 133 | qdict->size++; |
fb08dde0 | 134 | } |
fb08dde0 LC |
135 | } |
136 | ||
15280c36 MA |
137 | void qdict_put_int(QDict *qdict, const char *key, int64_t value) |
138 | { | |
139 | qdict_put(qdict, key, qnum_from_int(value)); | |
140 | } | |
141 | ||
142 | void qdict_put_bool(QDict *qdict, const char *key, bool value) | |
143 | { | |
144 | qdict_put(qdict, key, qbool_from_bool(value)); | |
145 | } | |
146 | ||
147 | void qdict_put_str(QDict *qdict, const char *key, const char *value) | |
148 | { | |
149 | qdict_put(qdict, key, qstring_from_str(value)); | |
150 | } | |
151 | ||
152 | void qdict_put_null(QDict *qdict, const char *key) | |
153 | { | |
154 | qdict_put(qdict, key, qnull()); | |
155 | } | |
156 | ||
fb08dde0 LC |
157 | /** |
158 | * qdict_get(): Lookup for a given 'key' | |
159 | * | |
160 | * Return a weak reference to the QObject associated with 'key' if | |
161 | * 'key' is present in the dictionary, NULL otherwise. | |
162 | */ | |
163 | QObject *qdict_get(const QDict *qdict, const char *key) | |
164 | { | |
165 | QDictEntry *entry; | |
166 | ||
c8bc3cd7 | 167 | entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX); |
fb08dde0 LC |
168 | return (entry == NULL ? NULL : entry->value); |
169 | } | |
170 | ||
171 | /** | |
172 | * qdict_haskey(): Check if 'key' exists | |
173 | * | |
174 | * Return 1 if 'key' exists in the dict, 0 otherwise | |
175 | */ | |
176 | int qdict_haskey(const QDict *qdict, const char *key) | |
177 | { | |
c8bc3cd7 LC |
178 | unsigned int bucket = tdb_hash(key) % QDICT_BUCKET_MAX; |
179 | return (qdict_find(qdict, key, bucket) == NULL ? 0 : 1); | |
fb08dde0 LC |
180 | } |
181 | ||
182 | /** | |
183 | * qdict_size(): Return the size of the dictionary | |
184 | */ | |
185 | size_t qdict_size(const QDict *qdict) | |
186 | { | |
187 | return qdict->size; | |
188 | } | |
189 | ||
acc3b033 MA |
190 | /** |
191 | * qdict_get_double(): Get an number mapped by 'key' | |
192 | * | |
01b2ffce | 193 | * This function assumes that 'key' exists and it stores a QNum. |
acc3b033 MA |
194 | * |
195 | * Return number mapped by 'key'. | |
196 | */ | |
197 | double qdict_get_double(const QDict *qdict, const char *key) | |
198 | { | |
7dc847eb | 199 | return qnum_get_double(qobject_to(QNum, qdict_get(qdict, key))); |
acc3b033 MA |
200 | } |
201 | ||
fb08dde0 LC |
202 | /** |
203 | * qdict_get_int(): Get an integer mapped by 'key' | |
204 | * | |
205 | * This function assumes that 'key' exists and it stores a | |
01b2ffce | 206 | * QNum representable as int. |
fb08dde0 LC |
207 | * |
208 | * Return integer mapped by 'key'. | |
209 | */ | |
210 | int64_t qdict_get_int(const QDict *qdict, const char *key) | |
211 | { | |
7dc847eb | 212 | return qnum_get_int(qobject_to(QNum, qdict_get(qdict, key))); |
fb08dde0 LC |
213 | } |
214 | ||
cd4dde36 LC |
215 | /** |
216 | * qdict_get_bool(): Get a bool mapped by 'key' | |
217 | * | |
218 | * This function assumes that 'key' exists and it stores a | |
219 | * QBool object. | |
220 | * | |
221 | * Return bool mapped by 'key'. | |
222 | */ | |
34acbc95 | 223 | bool qdict_get_bool(const QDict *qdict, const char *key) |
cd4dde36 | 224 | { |
7dc847eb | 225 | return qbool_get_bool(qobject_to(QBool, qdict_get(qdict, key))); |
cd4dde36 LC |
226 | } |
227 | ||
f2e17508 | 228 | /** |
b25f23e7 | 229 | * qdict_get_qlist(): If @qdict maps @key to a QList, return it, else NULL. |
f2e17508 LC |
230 | */ |
231 | QList *qdict_get_qlist(const QDict *qdict, const char *key) | |
232 | { | |
7dc847eb | 233 | return qobject_to(QList, qdict_get(qdict, key)); |
f2e17508 LC |
234 | } |
235 | ||
df10ce6a | 236 | /** |
b25f23e7 | 237 | * qdict_get_qdict(): If @qdict maps @key to a QDict, return it, else NULL. |
df10ce6a LC |
238 | */ |
239 | QDict *qdict_get_qdict(const QDict *qdict, const char *key) | |
240 | { | |
7dc847eb | 241 | return qobject_to(QDict, qdict_get(qdict, key)); |
df10ce6a LC |
242 | } |
243 | ||
fb08dde0 LC |
244 | /** |
245 | * qdict_get_str(): Get a pointer to the stored string mapped | |
246 | * by 'key' | |
247 | * | |
248 | * This function assumes that 'key' exists and it stores a | |
249 | * QString object. | |
250 | * | |
251 | * Return pointer to the string mapped by 'key'. | |
252 | */ | |
253 | const char *qdict_get_str(const QDict *qdict, const char *key) | |
254 | { | |
7dc847eb | 255 | return qstring_get_str(qobject_to(QString, qdict_get(qdict, key))); |
fb08dde0 LC |
256 | } |
257 | ||
258 | /** | |
259 | * qdict_get_try_int(): Try to get integer mapped by 'key' | |
260 | * | |
01b2ffce MAL |
261 | * Return integer mapped by 'key', if it is not present in the |
262 | * dictionary or if the stored object is not a QNum representing an | |
263 | * integer, 'def_value' will be returned. | |
fb08dde0 LC |
264 | */ |
265 | int64_t qdict_get_try_int(const QDict *qdict, const char *key, | |
83aba69e | 266 | int64_t def_value) |
fb08dde0 | 267 | { |
7dc847eb | 268 | QNum *qnum = qobject_to(QNum, qdict_get(qdict, key)); |
01b2ffce MAL |
269 | int64_t val; |
270 | ||
271 | if (!qnum || !qnum_get_try_int(qnum, &val)) { | |
272 | return def_value; | |
273 | } | |
fb08dde0 | 274 | |
01b2ffce | 275 | return val; |
fb08dde0 LC |
276 | } |
277 | ||
35006ac8 LC |
278 | /** |
279 | * qdict_get_try_bool(): Try to get a bool mapped by 'key' | |
280 | * | |
281 | * Return bool mapped by 'key', if it is not present in the | |
282 | * dictionary or if the stored object is not of QBool type | |
283 | * 'def_value' will be returned. | |
284 | */ | |
34acbc95 | 285 | bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value) |
35006ac8 | 286 | { |
7dc847eb | 287 | QBool *qbool = qobject_to(QBool, qdict_get(qdict, key)); |
35006ac8 | 288 | |
14b61600 | 289 | return qbool ? qbool_get_bool(qbool) : def_value; |
35006ac8 LC |
290 | } |
291 | ||
fb08dde0 LC |
292 | /** |
293 | * qdict_get_try_str(): Try to get a pointer to the stored string | |
294 | * mapped by 'key' | |
295 | * | |
296 | * Return a pointer to the string mapped by 'key', if it is not present | |
297 | * in the dictionary or if the stored object is not of QString type | |
298 | * NULL will be returned. | |
299 | */ | |
300 | const char *qdict_get_try_str(const QDict *qdict, const char *key) | |
301 | { | |
7dc847eb | 302 | QString *qstr = qobject_to(QString, qdict_get(qdict, key)); |
fb08dde0 | 303 | |
7f027843 | 304 | return qstr ? qstring_get_str(qstr) : NULL; |
fb08dde0 LC |
305 | } |
306 | ||
21f800d3 LC |
307 | /** |
308 | * qdict_iter(): Iterate over all the dictionary's stored values. | |
309 | * | |
310 | * This function allows the user to provide an iterator, which will be | |
311 | * called for each stored value in the dictionary. | |
312 | */ | |
313 | void qdict_iter(const QDict *qdict, | |
314 | void (*iter)(const char *key, QObject *obj, void *opaque), | |
315 | void *opaque) | |
316 | { | |
317 | int i; | |
318 | QDictEntry *entry; | |
319 | ||
c8bc3cd7 | 320 | for (i = 0; i < QDICT_BUCKET_MAX; i++) { |
21f800d3 LC |
321 | QLIST_FOREACH(entry, &qdict->table[i], next) |
322 | iter(entry->key, entry->value, opaque); | |
323 | } | |
324 | } | |
325 | ||
f2b07f35 LC |
326 | static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket) |
327 | { | |
328 | int i; | |
329 | ||
330 | for (i = first_bucket; i < QDICT_BUCKET_MAX; i++) { | |
331 | if (!QLIST_EMPTY(&qdict->table[i])) { | |
332 | return QLIST_FIRST(&qdict->table[i]); | |
333 | } | |
334 | } | |
335 | ||
336 | return NULL; | |
337 | } | |
338 | ||
339 | /** | |
340 | * qdict_first(): Return first qdict entry for iteration. | |
341 | */ | |
342 | const QDictEntry *qdict_first(const QDict *qdict) | |
343 | { | |
344 | return qdict_next_entry(qdict, 0); | |
345 | } | |
346 | ||
347 | /** | |
348 | * qdict_next(): Return next qdict entry in an iteration. | |
349 | */ | |
350 | const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry) | |
351 | { | |
352 | QDictEntry *ret; | |
353 | ||
354 | ret = QLIST_NEXT(entry, next); | |
355 | if (!ret) { | |
356 | unsigned int bucket = tdb_hash(entry->key) % QDICT_BUCKET_MAX; | |
357 | ret = qdict_next_entry(qdict, bucket + 1); | |
358 | } | |
359 | ||
360 | return ret; | |
361 | } | |
362 | ||
b382bc9a KW |
363 | /** |
364 | * qdict_clone_shallow(): Clones a given QDict. Its entries are not copied, but | |
365 | * another reference is added. | |
366 | */ | |
367 | QDict *qdict_clone_shallow(const QDict *src) | |
368 | { | |
369 | QDict *dest; | |
370 | QDictEntry *entry; | |
371 | int i; | |
372 | ||
373 | dest = qdict_new(); | |
374 | ||
375 | for (i = 0; i < QDICT_BUCKET_MAX; i++) { | |
376 | QLIST_FOREACH(entry, &src->table[i], next) { | |
f5a74a5a | 377 | qdict_put_obj(dest, entry->key, qobject_ref(entry->value)); |
b382bc9a KW |
378 | } |
379 | } | |
380 | ||
381 | return dest; | |
382 | } | |
383 | ||
fb08dde0 LC |
384 | /** |
385 | * qentry_destroy(): Free all the memory allocated by a QDictEntry | |
386 | */ | |
387 | static void qentry_destroy(QDictEntry *e) | |
388 | { | |
389 | assert(e != NULL); | |
390 | assert(e->key != NULL); | |
391 | assert(e->value != NULL); | |
392 | ||
cb3e7f08 | 393 | qobject_unref(e->value); |
7267c094 AL |
394 | g_free(e->key); |
395 | g_free(e); | |
fb08dde0 LC |
396 | } |
397 | ||
398 | /** | |
399 | * qdict_del(): Delete a 'key:value' pair from the dictionary | |
400 | * | |
401 | * This will destroy all data allocated by this entry. | |
402 | */ | |
403 | void qdict_del(QDict *qdict, const char *key) | |
404 | { | |
405 | QDictEntry *entry; | |
406 | ||
c8bc3cd7 | 407 | entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX); |
fb08dde0 | 408 | if (entry) { |
72cf2d4f | 409 | QLIST_REMOVE(entry, next); |
fb08dde0 LC |
410 | qentry_destroy(entry); |
411 | qdict->size--; | |
412 | } | |
413 | } | |
414 | ||
b38dd678 HR |
415 | /** |
416 | * qdict_is_equal(): Test whether the two QDicts are equal | |
417 | * | |
418 | * Here, equality means whether they contain the same keys and whether | |
419 | * the respective values are in turn equal (i.e. invoking | |
420 | * qobject_is_equal() on them yields true). | |
421 | */ | |
422 | bool qdict_is_equal(const QObject *x, const QObject *y) | |
423 | { | |
7dc847eb HR |
424 | const QDict *dict_x = qobject_to(QDict, x); |
425 | const QDict *dict_y = qobject_to(QDict, y); | |
b38dd678 HR |
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 | ||
fb08dde0 LC |
444 | /** |
445 | * qdict_destroy_obj(): Free all the memory allocated by a QDict | |
446 | */ | |
55e1819c | 447 | void qdict_destroy_obj(QObject *obj) |
fb08dde0 LC |
448 | { |
449 | int i; | |
450 | QDict *qdict; | |
451 | ||
452 | assert(obj != NULL); | |
7dc847eb | 453 | qdict = qobject_to(QDict, obj); |
fb08dde0 | 454 | |
c8bc3cd7 | 455 | for (i = 0; i < QDICT_BUCKET_MAX; i++) { |
72cf2d4f | 456 | QDictEntry *entry = QLIST_FIRST(&qdict->table[i]); |
fb08dde0 | 457 | while (entry) { |
72cf2d4f BS |
458 | QDictEntry *tmp = QLIST_NEXT(entry, next); |
459 | QLIST_REMOVE(entry, next); | |
fb08dde0 LC |
460 | qentry_destroy(entry); |
461 | entry = tmp; | |
462 | } | |
463 | } | |
464 | ||
7267c094 | 465 | g_free(qdict); |
fb08dde0 | 466 | } |
f660dc6a | 467 | |
7990d2c9 KW |
468 | /** |
469 | * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, the | |
470 | * value of 'key' in 'src' is copied there (and the refcount increased | |
471 | * accordingly). | |
472 | */ | |
473 | void 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) { | |
f5a74a5a | 483 | qdict_put_obj(dst, key, qobject_ref(val)); |
7990d2c9 KW |
484 | } |
485 | } | |
486 | ||
487 | /** | |
488 | * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' yet, a | |
489 | * new QString initialised by 'val' is put there. | |
490 | */ | |
491 | void qdict_set_default_str(QDict *dst, const char *key, const char *val) | |
492 | { | |
493 | if (qdict_haskey(dst, key)) { | |
494 | return; | |
495 | } | |
496 | ||
46f5ac20 | 497 | qdict_put_str(dst, key, val); |
7990d2c9 KW |
498 | } |
499 | ||
9f23fc0c HR |
500 | static void qdict_flatten_qdict(QDict *qdict, QDict *target, |
501 | const char *prefix); | |
502 | ||
503 | static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix) | |
504 | { | |
505 | QObject *value; | |
506 | const QListEntry *entry; | |
507 | char *new_key; | |
508 | int i; | |
509 | ||
510 | /* This function is never called with prefix == NULL, i.e., it is always | |
511 | * called from within qdict_flatten_q(list|dict)(). Therefore, it does not | |
512 | * need to remove list entries during the iteration (the whole list will be | |
513 | * deleted eventually anyway from qdict_flatten_qdict()). */ | |
514 | assert(prefix); | |
515 | ||
516 | entry = qlist_first(qlist); | |
517 | ||
518 | for (i = 0; entry; entry = qlist_next(entry), i++) { | |
519 | value = qlist_entry_obj(entry); | |
520 | new_key = g_strdup_printf("%s.%i", prefix, i); | |
521 | ||
522 | if (qobject_type(value) == QTYPE_QDICT) { | |
7dc847eb | 523 | qdict_flatten_qdict(qobject_to(QDict, value), target, new_key); |
9f23fc0c | 524 | } else if (qobject_type(value) == QTYPE_QLIST) { |
7dc847eb | 525 | qdict_flatten_qlist(qobject_to(QList, value), target, new_key); |
9f23fc0c HR |
526 | } else { |
527 | /* All other types are moved to the target unchanged. */ | |
f5a74a5a | 528 | qdict_put_obj(target, new_key, qobject_ref(value)); |
9f23fc0c HR |
529 | } |
530 | ||
531 | g_free(new_key); | |
532 | } | |
533 | } | |
534 | ||
535 | static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix) | |
f660dc6a KW |
536 | { |
537 | QObject *value; | |
538 | const QDictEntry *entry, *next; | |
6273d113 | 539 | char *new_key; |
f660dc6a KW |
540 | bool delete; |
541 | ||
542 | entry = qdict_first(qdict); | |
543 | ||
544 | while (entry != NULL) { | |
545 | ||
546 | next = qdict_next(qdict, entry); | |
547 | value = qdict_entry_value(entry); | |
548 | new_key = NULL; | |
549 | delete = false; | |
550 | ||
551 | if (prefix) { | |
f660dc6a | 552 | new_key = g_strdup_printf("%s.%s", prefix, entry->key); |
f660dc6a KW |
553 | } |
554 | ||
555 | if (qobject_type(value) == QTYPE_QDICT) { | |
4d5977ea KW |
556 | /* Entries of QDicts are processed recursively, the QDict object |
557 | * itself disappears. */ | |
7dc847eb | 558 | qdict_flatten_qdict(qobject_to(QDict, value), target, |
9f23fc0c HR |
559 | new_key ? new_key : entry->key); |
560 | delete = true; | |
561 | } else if (qobject_type(value) == QTYPE_QLIST) { | |
7dc847eb | 562 | qdict_flatten_qlist(qobject_to(QList, value), target, |
9f23fc0c | 563 | new_key ? new_key : entry->key); |
f660dc6a | 564 | delete = true; |
4d5977ea KW |
565 | } else if (prefix) { |
566 | /* All other objects are moved to the target unchanged. */ | |
f5a74a5a | 567 | qdict_put_obj(target, new_key, qobject_ref(value)); |
4d5977ea | 568 | delete = true; |
f660dc6a KW |
569 | } |
570 | ||
6273d113 KW |
571 | g_free(new_key); |
572 | ||
f660dc6a KW |
573 | if (delete) { |
574 | qdict_del(qdict, entry->key); | |
575 | ||
576 | /* Restart loop after modifying the iterated QDict */ | |
577 | entry = qdict_first(qdict); | |
578 | continue; | |
579 | } | |
580 | ||
581 | entry = next; | |
582 | } | |
583 | } | |
584 | ||
585 | /** | |
586 | * qdict_flatten(): For each nested QDict with key x, all fields with key y | |
9f23fc0c HR |
587 | * are moved to this QDict and their key is renamed to "x.y". For each nested |
588 | * QList with key x, the field at index y is moved to this QDict with the key | |
589 | * "x.y" (i.e., the reverse of what qdict_array_split() does). | |
590 | * This operation is applied recursively for nested QDicts and QLists. | |
f660dc6a KW |
591 | */ |
592 | void qdict_flatten(QDict *qdict) | |
593 | { | |
9f23fc0c | 594 | qdict_flatten_qdict(qdict, qdict, NULL); |
f660dc6a | 595 | } |
5726d872 BC |
596 | |
597 | /* extract all the src QDict entries starting by start into dst */ | |
598 | void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start) | |
599 | ||
600 | { | |
601 | const QDictEntry *entry, *next; | |
602 | const char *p; | |
603 | ||
604 | *dst = qdict_new(); | |
605 | entry = qdict_first(src); | |
606 | ||
607 | while (entry != NULL) { | |
608 | next = qdict_next(src, entry); | |
609 | if (strstart(entry->key, start, &p)) { | |
f5a74a5a | 610 | qdict_put_obj(*dst, p, qobject_ref(entry->value)); |
5726d872 BC |
611 | qdict_del(src, entry->key); |
612 | } | |
613 | entry = next; | |
614 | } | |
615 | } | |
05a8c222 | 616 | |
bd50530a | 617 | static int qdict_count_prefixed_entries(const QDict *src, const char *start) |
bae3f92a HR |
618 | { |
619 | const QDictEntry *entry; | |
bd50530a | 620 | int count = 0; |
bae3f92a HR |
621 | |
622 | for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) { | |
623 | if (strstart(entry->key, start, NULL)) { | |
bd50530a KW |
624 | if (count == INT_MAX) { |
625 | return -ERANGE; | |
626 | } | |
627 | count++; | |
bae3f92a HR |
628 | } |
629 | } | |
630 | ||
bd50530a | 631 | return count; |
bae3f92a HR |
632 | } |
633 | ||
05a8c222 HR |
634 | /** |
635 | * qdict_array_split(): This function moves array-like elements of a QDict into | |
bae3f92a HR |
636 | * a new QList. Every entry in the original QDict with a key "%u" or one |
637 | * prefixed "%u.", where %u designates an unsigned integer starting at 0 and | |
05a8c222 | 638 | * incrementally counting up, will be moved to a new QDict at index %u in the |
bae3f92a HR |
639 | * output QList with the key prefix removed, if that prefix is "%u.". If the |
640 | * whole key is just "%u", the whole QObject will be moved unchanged without | |
641 | * creating a new QDict. The function terminates when there is no entry in the | |
642 | * QDict with a prefix directly (incrementally) following the last one; it also | |
643 | * returns if there are both entries with "%u" and "%u." for the same index %u. | |
644 | * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66} | |
645 | * (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66}) | |
646 | * => [{"a": 42, "b": 23}, {"x": 0}, 66] | |
647 | * and {"4.y": 1, "o.o": 7} (remainder of the old QDict) | |
05a8c222 HR |
648 | */ |
649 | void qdict_array_split(QDict *src, QList **dst) | |
650 | { | |
651 | unsigned i; | |
652 | ||
653 | *dst = qlist_new(); | |
654 | ||
655 | for (i = 0; i < UINT_MAX; i++) { | |
bae3f92a HR |
656 | QObject *subqobj; |
657 | bool is_subqdict; | |
05a8c222 | 658 | QDict *subqdict; |
bae3f92a | 659 | char indexstr[32], prefix[32]; |
05a8c222 HR |
660 | size_t snprintf_ret; |
661 | ||
bae3f92a HR |
662 | snprintf_ret = snprintf(indexstr, 32, "%u", i); |
663 | assert(snprintf_ret < 32); | |
664 | ||
665 | subqobj = qdict_get(src, indexstr); | |
666 | ||
05a8c222 HR |
667 | snprintf_ret = snprintf(prefix, 32, "%u.", i); |
668 | assert(snprintf_ret < 32); | |
669 | ||
bd50530a KW |
670 | /* Overflow is the same as positive non-zero results */ |
671 | is_subqdict = qdict_count_prefixed_entries(src, prefix); | |
bae3f92a HR |
672 | |
673 | // There may be either a single subordinate object (named "%u") or | |
674 | // multiple objects (each with a key prefixed "%u."), but not both. | |
675 | if (!subqobj == !is_subqdict) { | |
05a8c222 HR |
676 | break; |
677 | } | |
678 | ||
bae3f92a HR |
679 | if (is_subqdict) { |
680 | qdict_extract_subqdict(src, &subqdict, prefix); | |
681 | assert(qdict_size(subqdict) > 0); | |
682 | } else { | |
cb3e7f08 | 683 | qobject_ref(subqobj); |
bae3f92a HR |
684 | qdict_del(src, indexstr); |
685 | } | |
686 | ||
687 | qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict)); | |
05a8c222 HR |
688 | } |
689 | } | |
9c526812 | 690 | |
603476c2 DB |
691 | /** |
692 | * qdict_split_flat_key: | |
693 | * @key: the key string to split | |
694 | * @prefix: non-NULL pointer to hold extracted prefix | |
695 | * @suffix: non-NULL pointer to remaining suffix | |
696 | * | |
697 | * Given a flattened key such as 'foo.0.bar', split it into two parts | |
698 | * at the first '.' separator. Allows double dot ('..') to escape the | |
699 | * normal separator. | |
700 | * | |
701 | * e.g. | |
702 | * 'foo.0.bar' -> prefix='foo' and suffix='0.bar' | |
703 | * 'foo..0.bar' -> prefix='foo.0' and suffix='bar' | |
704 | * | |
705 | * The '..' sequence will be unescaped in the returned 'prefix' | |
706 | * string. The 'suffix' string will be left in escaped format, so it | |
707 | * can be fed back into the qdict_split_flat_key() key as the input | |
708 | * later. | |
709 | * | |
710 | * The caller is responsible for freeing the string returned in @prefix | |
711 | * using g_free(). | |
712 | */ | |
713 | static void qdict_split_flat_key(const char *key, char **prefix, | |
714 | const char **suffix) | |
715 | { | |
716 | const char *separator; | |
717 | size_t i, j; | |
718 | ||
719 | /* Find first '.' separator, but if there is a pair '..' | |
720 | * that acts as an escape, so skip over '..' */ | |
721 | separator = NULL; | |
722 | do { | |
723 | if (separator) { | |
724 | separator += 2; | |
725 | } else { | |
726 | separator = key; | |
727 | } | |
728 | separator = strchr(separator, '.'); | |
729 | } while (separator && separator[1] == '.'); | |
730 | ||
731 | if (separator) { | |
732 | *prefix = g_strndup(key, separator - key); | |
733 | *suffix = separator + 1; | |
734 | } else { | |
735 | *prefix = g_strdup(key); | |
736 | *suffix = NULL; | |
737 | } | |
738 | ||
739 | /* Unescape the '..' sequence into '.' */ | |
740 | for (i = 0, j = 0; (*prefix)[i] != '\0'; i++, j++) { | |
741 | if ((*prefix)[i] == '.') { | |
742 | assert((*prefix)[i + 1] == '.'); | |
743 | i++; | |
744 | } | |
745 | (*prefix)[j] = (*prefix)[i]; | |
746 | } | |
747 | (*prefix)[j] = '\0'; | |
748 | } | |
749 | ||
750 | /** | |
751 | * qdict_is_list: | |
752 | * @maybe_list: dict to check if keys represent list elements. | |
753 | * | |
754 | * Determine whether all keys in @maybe_list are valid list elements. | |
755 | * If @maybe_list is non-zero in length and all the keys look like | |
756 | * valid list indexes, this will return 1. If @maybe_list is zero | |
757 | * length or all keys are non-numeric then it will return 0 to indicate | |
758 | * it is a normal qdict. If there is a mix of numeric and non-numeric | |
759 | * keys, or the list indexes are non-contiguous, an error is reported. | |
760 | * | |
761 | * Returns: 1 if a valid list, 0 if a dict, -1 on error | |
762 | */ | |
763 | static int qdict_is_list(QDict *maybe_list, Error **errp) | |
764 | { | |
765 | const QDictEntry *ent; | |
766 | ssize_t len = 0; | |
767 | ssize_t max = -1; | |
768 | int is_list = -1; | |
769 | int64_t val; | |
770 | ||
771 | for (ent = qdict_first(maybe_list); ent != NULL; | |
772 | ent = qdict_next(maybe_list, ent)) { | |
773 | ||
b30d1886 | 774 | if (qemu_strtoi64(ent->key, NULL, 10, &val) == 0) { |
603476c2 DB |
775 | if (is_list == -1) { |
776 | is_list = 1; | |
777 | } else if (!is_list) { | |
778 | error_setg(errp, | |
779 | "Cannot mix list and non-list keys"); | |
780 | return -1; | |
781 | } | |
782 | len++; | |
783 | if (val > max) { | |
784 | max = val; | |
785 | } | |
786 | } else { | |
787 | if (is_list == -1) { | |
788 | is_list = 0; | |
789 | } else if (is_list) { | |
790 | error_setg(errp, | |
791 | "Cannot mix list and non-list keys"); | |
792 | return -1; | |
793 | } | |
794 | } | |
795 | } | |
796 | ||
797 | if (is_list == -1) { | |
798 | assert(!qdict_size(maybe_list)); | |
799 | is_list = 0; | |
800 | } | |
801 | ||
802 | /* NB this isn't a perfect check - e.g. it won't catch | |
803 | * a list containing '1', '+1', '01', '3', but that | |
804 | * does not matter - we've still proved that the | |
805 | * input is a list. It is up the caller to do a | |
806 | * stricter check if desired */ | |
807 | if (len != (max + 1)) { | |
808 | error_setg(errp, "List indices are not contiguous, " | |
809 | "saw %zd elements but %zd largest index", | |
810 | len, max); | |
811 | return -1; | |
812 | } | |
813 | ||
814 | return is_list; | |
815 | } | |
816 | ||
817 | /** | |
818 | * qdict_crumple: | |
819 | * @src: the original flat dictionary (only scalar values) to crumple | |
820 | * | |
821 | * Takes a flat dictionary whose keys use '.' separator to indicate | |
822 | * nesting, and values are scalars, and crumples it into a nested | |
823 | * structure. | |
824 | * | |
825 | * To include a literal '.' in a key name, it must be escaped as '..' | |
826 | * | |
827 | * For example, an input of: | |
828 | * | |
829 | * { 'foo.0.bar': 'one', 'foo.0.wizz': '1', | |
830 | * 'foo.1.bar': 'two', 'foo.1.wizz': '2' } | |
831 | * | |
832 | * will result in an output of: | |
833 | * | |
834 | * { | |
835 | * 'foo': [ | |
836 | * { 'bar': 'one', 'wizz': '1' }, | |
837 | * { 'bar': 'two', 'wizz': '2' } | |
838 | * ], | |
839 | * } | |
840 | * | |
841 | * The following scenarios in the input dict will result in an | |
842 | * error being returned: | |
843 | * | |
844 | * - Any values in @src are non-scalar types | |
845 | * - If keys in @src imply that a particular level is both a | |
846 | * list and a dict. e.g., "foo.0.bar" and "foo.eek.bar". | |
847 | * - If keys in @src imply that a particular level is a list, | |
848 | * but the indices are non-contiguous. e.g. "foo.0.bar" and | |
849 | * "foo.2.bar" without any "foo.1.bar" present. | |
850 | * - If keys in @src represent list indexes, but are not in | |
851 | * the "%zu" format. e.g. "foo.+0.bar" | |
852 | * | |
853 | * Returns: either a QDict or QList for the nested data structure, or NULL | |
854 | * on error | |
855 | */ | |
856 | QObject *qdict_crumple(const QDict *src, Error **errp) | |
857 | { | |
858 | const QDictEntry *ent; | |
859 | QDict *two_level, *multi_level = NULL; | |
860 | QObject *dst = NULL, *child; | |
861 | size_t i; | |
862 | char *prefix = NULL; | |
863 | const char *suffix = NULL; | |
864 | int is_list; | |
865 | ||
866 | two_level = qdict_new(); | |
867 | ||
868 | /* Step 1: split our totally flat dict into a two level dict */ | |
869 | for (ent = qdict_first(src); ent != NULL; ent = qdict_next(src, ent)) { | |
870 | if (qobject_type(ent->value) == QTYPE_QDICT || | |
871 | qobject_type(ent->value) == QTYPE_QLIST) { | |
872 | error_setg(errp, "Value %s is not a scalar", | |
873 | ent->key); | |
874 | goto error; | |
875 | } | |
876 | ||
877 | qdict_split_flat_key(ent->key, &prefix, &suffix); | |
878 | ||
879 | child = qdict_get(two_level, prefix); | |
880 | if (suffix) { | |
532fb532 HR |
881 | QDict *child_dict = qobject_to(QDict, child); |
882 | if (!child_dict) { | |
883 | if (child) { | |
603476c2 DB |
884 | error_setg(errp, "Key %s prefix is already set as a scalar", |
885 | prefix); | |
886 | goto error; | |
887 | } | |
532fb532 HR |
888 | |
889 | child_dict = qdict_new(); | |
890 | qdict_put_obj(two_level, prefix, QOBJECT(child_dict)); | |
603476c2 | 891 | } |
532fb532 | 892 | |
f5a74a5a | 893 | qdict_put_obj(child_dict, suffix, qobject_ref(ent->value)); |
603476c2 DB |
894 | } else { |
895 | if (child) { | |
896 | error_setg(errp, "Key %s prefix is already set as a dict", | |
897 | prefix); | |
898 | goto error; | |
899 | } | |
f5a74a5a | 900 | qdict_put_obj(two_level, prefix, qobject_ref(ent->value)); |
603476c2 DB |
901 | } |
902 | ||
903 | g_free(prefix); | |
904 | prefix = NULL; | |
905 | } | |
906 | ||
907 | /* Step 2: optionally process the two level dict recursively | |
908 | * into a multi-level dict */ | |
909 | multi_level = qdict_new(); | |
910 | for (ent = qdict_first(two_level); ent != NULL; | |
911 | ent = qdict_next(two_level, ent)) { | |
532fb532 HR |
912 | QDict *dict = qobject_to(QDict, ent->value); |
913 | if (dict) { | |
914 | child = qdict_crumple(dict, errp); | |
603476c2 DB |
915 | if (!child) { |
916 | goto error; | |
917 | } | |
918 | ||
919 | qdict_put_obj(multi_level, ent->key, child); | |
920 | } else { | |
f5a74a5a | 921 | qdict_put_obj(multi_level, ent->key, qobject_ref(ent->value)); |
603476c2 DB |
922 | } |
923 | } | |
cb3e7f08 | 924 | qobject_unref(two_level); |
603476c2 DB |
925 | two_level = NULL; |
926 | ||
927 | /* Step 3: detect if we need to turn our dict into list */ | |
928 | is_list = qdict_is_list(multi_level, errp); | |
929 | if (is_list < 0) { | |
930 | goto error; | |
931 | } | |
932 | ||
933 | if (is_list) { | |
934 | dst = QOBJECT(qlist_new()); | |
935 | ||
936 | for (i = 0; i < qdict_size(multi_level); i++) { | |
937 | char *key = g_strdup_printf("%zu", i); | |
938 | ||
939 | child = qdict_get(multi_level, key); | |
940 | g_free(key); | |
941 | ||
942 | if (!child) { | |
943 | error_setg(errp, "Missing list index %zu", i); | |
944 | goto error; | |
945 | } | |
946 | ||
f5a74a5a | 947 | qlist_append_obj(qobject_to(QList, dst), qobject_ref(child)); |
603476c2 | 948 | } |
cb3e7f08 | 949 | qobject_unref(multi_level); |
603476c2 DB |
950 | multi_level = NULL; |
951 | } else { | |
952 | dst = QOBJECT(multi_level); | |
953 | } | |
954 | ||
955 | return dst; | |
956 | ||
957 | error: | |
958 | g_free(prefix); | |
cb3e7f08 MAL |
959 | qobject_unref(multi_level); |
960 | qobject_unref(two_level); | |
961 | qobject_unref(dst); | |
603476c2 DB |
962 | return NULL; |
963 | } | |
964 | ||
bd50530a KW |
965 | /** |
966 | * qdict_array_entries(): Returns the number of direct array entries if the | |
967 | * sub-QDict of src specified by the prefix in subqdict (or src itself for | |
968 | * prefix == "") is valid as an array, i.e. the length of the created list if | |
969 | * the sub-QDict would become empty after calling qdict_array_split() on it. If | |
970 | * the array is not valid, -EINVAL is returned. | |
971 | */ | |
972 | int qdict_array_entries(QDict *src, const char *subqdict) | |
973 | { | |
974 | const QDictEntry *entry; | |
975 | unsigned i; | |
976 | unsigned entries = 0; | |
977 | size_t subqdict_len = strlen(subqdict); | |
978 | ||
979 | assert(!subqdict_len || subqdict[subqdict_len - 1] == '.'); | |
980 | ||
981 | /* qdict_array_split() loops until UINT_MAX, but as we want to return | |
982 | * negative errors, we only have a signed return value here. Any additional | |
983 | * entries will lead to -EINVAL. */ | |
984 | for (i = 0; i < INT_MAX; i++) { | |
985 | QObject *subqobj; | |
986 | int subqdict_entries; | |
de4905f4 | 987 | char *prefix = g_strdup_printf("%s%u.", subqdict, i); |
bd50530a | 988 | |
de4905f4 | 989 | subqdict_entries = qdict_count_prefixed_entries(src, prefix); |
bd50530a | 990 | |
de4905f4 PX |
991 | /* Remove ending "." */ |
992 | prefix[strlen(prefix) - 1] = 0; | |
993 | subqobj = qdict_get(src, prefix); | |
bd50530a | 994 | |
de4905f4 | 995 | g_free(prefix); |
bd50530a | 996 | |
bd50530a KW |
997 | if (subqdict_entries < 0) { |
998 | return subqdict_entries; | |
999 | } | |
1000 | ||
1001 | /* There may be either a single subordinate object (named "%u") or | |
1002 | * multiple objects (each with a key prefixed "%u."), but not both. */ | |
1003 | if (subqobj && subqdict_entries) { | |
1004 | return -EINVAL; | |
1005 | } else if (!subqobj && !subqdict_entries) { | |
1006 | break; | |
1007 | } | |
1008 | ||
1009 | entries += subqdict_entries ? subqdict_entries : 1; | |
1010 | } | |
1011 | ||
1012 | /* Consider everything handled that isn't part of the given sub-QDict */ | |
1013 | for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) { | |
1014 | if (!strstart(qdict_entry_key(entry), subqdict, NULL)) { | |
1015 | entries++; | |
1016 | } | |
1017 | } | |
1018 | ||
1019 | /* Anything left in the sub-QDict that wasn't handled? */ | |
1020 | if (qdict_size(src) != entries) { | |
1021 | return -EINVAL; | |
1022 | } | |
1023 | ||
1024 | return i; | |
1025 | } | |
1026 | ||
9c526812 HR |
1027 | /** |
1028 | * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all | |
1029 | * elements from src to dest. | |
1030 | * | |
1031 | * If an element from src has a key already present in dest, it will not be | |
1032 | * moved unless overwrite is true. | |
1033 | * | |
1034 | * If overwrite is true, the conflicting values in dest will be discarded and | |
1035 | * replaced by the corresponding values from src. | |
1036 | * | |
1037 | * Therefore, with overwrite being true, the src QDict will always be empty when | |
1038 | * this function returns. If overwrite is false, the src QDict will be empty | |
1039 | * iff there were no conflicts. | |
1040 | */ | |
1041 | void qdict_join(QDict *dest, QDict *src, bool overwrite) | |
1042 | { | |
1043 | const QDictEntry *entry, *next; | |
1044 | ||
1045 | entry = qdict_first(src); | |
1046 | while (entry) { | |
1047 | next = qdict_next(src, entry); | |
1048 | ||
1049 | if (overwrite || !qdict_haskey(dest, entry->key)) { | |
f5a74a5a | 1050 | qdict_put_obj(dest, entry->key, qobject_ref(entry->value)); |
9c526812 HR |
1051 | qdict_del(src, entry->key); |
1052 | } | |
1053 | ||
1054 | entry = next; | |
1055 | } | |
1056 | } | |
bcebf102 KW |
1057 | |
1058 | /** | |
1059 | * qdict_rename_keys(): Rename keys in qdict according to the replacements | |
1060 | * specified in the array renames. The array must be terminated by an entry | |
1061 | * with from = NULL. | |
1062 | * | |
1063 | * The renames are performed individually in the order of the array, so entries | |
1064 | * may be renamed multiple times and may or may not conflict depending on the | |
1065 | * order of the renames array. | |
1066 | * | |
1067 | * Returns true for success, false in error cases. | |
1068 | */ | |
1069 | bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **errp) | |
1070 | { | |
1071 | QObject *qobj; | |
1072 | ||
1073 | while (renames->from) { | |
1074 | if (qdict_haskey(qdict, renames->from)) { | |
1075 | if (qdict_haskey(qdict, renames->to)) { | |
1076 | error_setg(errp, "'%s' and its alias '%s' can't be used at the " | |
1077 | "same time", renames->to, renames->from); | |
1078 | return false; | |
1079 | } | |
1080 | ||
1081 | qobj = qdict_get(qdict, renames->from); | |
f5a74a5a | 1082 | qdict_put_obj(qdict, renames->to, qobject_ref(qobj)); |
bcebf102 KW |
1083 | qdict_del(qdict, renames->from); |
1084 | } | |
1085 | ||
1086 | renames++; | |
1087 | } | |
1088 | return true; | |
1089 | } |