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