]> git.proxmox.com Git - mirror_qemu.git/blame - qobject/block-qdict.c
block-qdict: Simplify qdict_flatten_qdict()
[mirror_qemu.git] / qobject / block-qdict.c
CommitLineData
0bcc8e5b
MA
1/*
2 * Special QDict functions used by the block layer
3 *
4 * Copyright (c) 2013-2018 Red Hat, Inc.
5 *
6 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
7 * See the COPYING.LIB file in the top-level directory.
8 */
9
10#include "qemu/osdep.h"
11#include "block/qdict.h"
e5af0da1 12#include "qapi/qmp/qbool.h"
0bcc8e5b 13#include "qapi/qmp/qlist.h"
e5af0da1
MA
14#include "qapi/qmp/qnum.h"
15#include "qapi/qmp/qstring.h"
af91062e 16#include "qapi/qobject-input-visitor.h"
0bcc8e5b
MA
17#include "qemu/cutils.h"
18#include "qapi/error.h"
19
20/**
21 * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, the
22 * value of 'key' in 'src' is copied there (and the refcount increased
23 * accordingly).
24 */
25void qdict_copy_default(QDict *dst, QDict *src, const char *key)
26{
27 QObject *val;
28
29 if (qdict_haskey(dst, key)) {
30 return;
31 }
32
33 val = qdict_get(src, key);
34 if (val) {
35 qdict_put_obj(dst, key, qobject_ref(val));
36 }
37}
38
39/**
40 * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' yet, a
41 * new QString initialised by 'val' is put there.
42 */
43void qdict_set_default_str(QDict *dst, const char *key, const char *val)
44{
45 if (qdict_haskey(dst, key)) {
46 return;
47 }
48
49 qdict_put_str(dst, key, val);
50}
51
52static void qdict_flatten_qdict(QDict *qdict, QDict *target,
53 const char *prefix);
54
55static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix)
56{
57 QObject *value;
58 const QListEntry *entry;
59 char *new_key;
60 int i;
61
62 /* This function is never called with prefix == NULL, i.e., it is always
63 * called from within qdict_flatten_q(list|dict)(). Therefore, it does not
64 * need to remove list entries during the iteration (the whole list will be
65 * deleted eventually anyway from qdict_flatten_qdict()). */
66 assert(prefix);
67
68 entry = qlist_first(qlist);
69
70 for (i = 0; entry; entry = qlist_next(entry), i++) {
71 value = qlist_entry_obj(entry);
72 new_key = g_strdup_printf("%s.%i", prefix, i);
73
74 if (qobject_type(value) == QTYPE_QDICT) {
75 qdict_flatten_qdict(qobject_to(QDict, value), target, new_key);
76 } else if (qobject_type(value) == QTYPE_QLIST) {
77 qdict_flatten_qlist(qobject_to(QList, value), target, new_key);
78 } else {
79 /* All other types are moved to the target unchanged. */
80 qdict_put_obj(target, new_key, qobject_ref(value));
81 }
82
83 g_free(new_key);
84 }
85}
86
87static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
88{
89 QObject *value;
90 const QDictEntry *entry, *next;
91 char *new_key;
0bcc8e5b
MA
92
93 entry = qdict_first(qdict);
94
95 while (entry != NULL) {
0bcc8e5b
MA
96 next = qdict_next(qdict, entry);
97 value = qdict_entry_value(entry);
98 new_key = NULL;
0bcc8e5b
MA
99
100 if (prefix) {
101 new_key = g_strdup_printf("%s.%s", prefix, entry->key);
102 }
103
104 if (qobject_type(value) == QTYPE_QDICT) {
105 /* Entries of QDicts are processed recursively, the QDict object
106 * itself disappears. */
107 qdict_flatten_qdict(qobject_to(QDict, value), target,
108 new_key ? new_key : entry->key);
eb0e0f7d 109 qdict_del(qdict, entry->key);
0bcc8e5b
MA
110 } else if (qobject_type(value) == QTYPE_QLIST) {
111 qdict_flatten_qlist(qobject_to(QList, value), target,
112 new_key ? new_key : entry->key);
eb0e0f7d 113 qdict_del(qdict, entry->key);
0bcc8e5b
MA
114 } else if (prefix) {
115 /* All other objects are moved to the target unchanged. */
116 qdict_put_obj(target, new_key, qobject_ref(value));
0bcc8e5b 117 qdict_del(qdict, entry->key);
0bcc8e5b
MA
118 }
119
eb0e0f7d 120 g_free(new_key);
0bcc8e5b
MA
121 entry = next;
122 }
123}
124
125/**
126 * qdict_flatten(): For each nested QDict with key x, all fields with key y
127 * are moved to this QDict and their key is renamed to "x.y". For each nested
128 * QList with key x, the field at index y is moved to this QDict with the key
129 * "x.y" (i.e., the reverse of what qdict_array_split() does).
130 * This operation is applied recursively for nested QDicts and QLists.
131 */
132void qdict_flatten(QDict *qdict)
133{
134 qdict_flatten_qdict(qdict, qdict, NULL);
135}
136
137/* extract all the src QDict entries starting by start into dst */
138void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
139
140{
141 const QDictEntry *entry, *next;
142 const char *p;
143
144 *dst = qdict_new();
145 entry = qdict_first(src);
146
147 while (entry != NULL) {
148 next = qdict_next(src, entry);
149 if (strstart(entry->key, start, &p)) {
150 qdict_put_obj(*dst, p, qobject_ref(entry->value));
151 qdict_del(src, entry->key);
152 }
153 entry = next;
154 }
155}
156
157static int qdict_count_prefixed_entries(const QDict *src, const char *start)
158{
159 const QDictEntry *entry;
160 int count = 0;
161
162 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
163 if (strstart(entry->key, start, NULL)) {
164 if (count == INT_MAX) {
165 return -ERANGE;
166 }
167 count++;
168 }
169 }
170
171 return count;
172}
173
174/**
175 * qdict_array_split(): This function moves array-like elements of a QDict into
176 * a new QList. Every entry in the original QDict with a key "%u" or one
177 * prefixed "%u.", where %u designates an unsigned integer starting at 0 and
178 * incrementally counting up, will be moved to a new QDict at index %u in the
179 * output QList with the key prefix removed, if that prefix is "%u.". If the
180 * whole key is just "%u", the whole QObject will be moved unchanged without
181 * creating a new QDict. The function terminates when there is no entry in the
182 * QDict with a prefix directly (incrementally) following the last one; it also
183 * returns if there are both entries with "%u" and "%u." for the same index %u.
184 * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66}
185 * (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66})
186 * => [{"a": 42, "b": 23}, {"x": 0}, 66]
187 * and {"4.y": 1, "o.o": 7} (remainder of the old QDict)
188 */
189void qdict_array_split(QDict *src, QList **dst)
190{
191 unsigned i;
192
193 *dst = qlist_new();
194
195 for (i = 0; i < UINT_MAX; i++) {
196 QObject *subqobj;
197 bool is_subqdict;
198 QDict *subqdict;
199 char indexstr[32], prefix[32];
200 size_t snprintf_ret;
201
202 snprintf_ret = snprintf(indexstr, 32, "%u", i);
203 assert(snprintf_ret < 32);
204
205 subqobj = qdict_get(src, indexstr);
206
207 snprintf_ret = snprintf(prefix, 32, "%u.", i);
208 assert(snprintf_ret < 32);
209
210 /* Overflow is the same as positive non-zero results */
211 is_subqdict = qdict_count_prefixed_entries(src, prefix);
212
213 /*
214 * There may be either a single subordinate object (named
215 * "%u") or multiple objects (each with a key prefixed "%u."),
216 * but not both.
217 */
218 if (!subqobj == !is_subqdict) {
219 break;
220 }
221
222 if (is_subqdict) {
223 qdict_extract_subqdict(src, &subqdict, prefix);
224 assert(qdict_size(subqdict) > 0);
225 } else {
226 qobject_ref(subqobj);
227 qdict_del(src, indexstr);
228 }
229
230 qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict));
231 }
232}
233
234/**
235 * qdict_split_flat_key:
236 * @key: the key string to split
237 * @prefix: non-NULL pointer to hold extracted prefix
238 * @suffix: non-NULL pointer to remaining suffix
239 *
240 * Given a flattened key such as 'foo.0.bar', split it into two parts
241 * at the first '.' separator. Allows double dot ('..') to escape the
242 * normal separator.
243 *
244 * e.g.
245 * 'foo.0.bar' -> prefix='foo' and suffix='0.bar'
246 * 'foo..0.bar' -> prefix='foo.0' and suffix='bar'
247 *
248 * The '..' sequence will be unescaped in the returned 'prefix'
249 * string. The 'suffix' string will be left in escaped format, so it
250 * can be fed back into the qdict_split_flat_key() key as the input
251 * later.
252 *
253 * The caller is responsible for freeing the string returned in @prefix
254 * using g_free().
255 */
256static void qdict_split_flat_key(const char *key, char **prefix,
257 const char **suffix)
258{
259 const char *separator;
260 size_t i, j;
261
262 /* Find first '.' separator, but if there is a pair '..'
263 * that acts as an escape, so skip over '..' */
264 separator = NULL;
265 do {
266 if (separator) {
267 separator += 2;
268 } else {
269 separator = key;
270 }
271 separator = strchr(separator, '.');
272 } while (separator && separator[1] == '.');
273
274 if (separator) {
275 *prefix = g_strndup(key, separator - key);
276 *suffix = separator + 1;
277 } else {
278 *prefix = g_strdup(key);
279 *suffix = NULL;
280 }
281
282 /* Unescape the '..' sequence into '.' */
283 for (i = 0, j = 0; (*prefix)[i] != '\0'; i++, j++) {
284 if ((*prefix)[i] == '.') {
285 assert((*prefix)[i + 1] == '.');
286 i++;
287 }
288 (*prefix)[j] = (*prefix)[i];
289 }
290 (*prefix)[j] = '\0';
291}
292
293/**
294 * qdict_is_list:
295 * @maybe_list: dict to check if keys represent list elements.
296 *
297 * Determine whether all keys in @maybe_list are valid list elements.
298 * If @maybe_list is non-zero in length and all the keys look like
299 * valid list indexes, this will return 1. If @maybe_list is zero
300 * length or all keys are non-numeric then it will return 0 to indicate
301 * it is a normal qdict. If there is a mix of numeric and non-numeric
302 * keys, or the list indexes are non-contiguous, an error is reported.
303 *
304 * Returns: 1 if a valid list, 0 if a dict, -1 on error
305 */
306static int qdict_is_list(QDict *maybe_list, Error **errp)
307{
308 const QDictEntry *ent;
309 ssize_t len = 0;
310 ssize_t max = -1;
311 int is_list = -1;
312 int64_t val;
313
314 for (ent = qdict_first(maybe_list); ent != NULL;
315 ent = qdict_next(maybe_list, ent)) {
316
317 if (qemu_strtoi64(ent->key, NULL, 10, &val) == 0) {
318 if (is_list == -1) {
319 is_list = 1;
320 } else if (!is_list) {
321 error_setg(errp,
322 "Cannot mix list and non-list keys");
323 return -1;
324 }
325 len++;
326 if (val > max) {
327 max = val;
328 }
329 } else {
330 if (is_list == -1) {
331 is_list = 0;
332 } else if (is_list) {
333 error_setg(errp,
334 "Cannot mix list and non-list keys");
335 return -1;
336 }
337 }
338 }
339
340 if (is_list == -1) {
341 assert(!qdict_size(maybe_list));
342 is_list = 0;
343 }
344
345 /* NB this isn't a perfect check - e.g. it won't catch
346 * a list containing '1', '+1', '01', '3', but that
347 * does not matter - we've still proved that the
348 * input is a list. It is up the caller to do a
349 * stricter check if desired */
350 if (len != (max + 1)) {
351 error_setg(errp, "List indices are not contiguous, "
352 "saw %zd elements but %zd largest index",
353 len, max);
354 return -1;
355 }
356
357 return is_list;
358}
359
360/**
361 * qdict_crumple:
362 * @src: the original flat dictionary (only scalar values) to crumple
363 *
364 * Takes a flat dictionary whose keys use '.' separator to indicate
365 * nesting, and values are scalars, and crumples it into a nested
366 * structure.
367 *
368 * To include a literal '.' in a key name, it must be escaped as '..'
369 *
370 * For example, an input of:
371 *
372 * { 'foo.0.bar': 'one', 'foo.0.wizz': '1',
373 * 'foo.1.bar': 'two', 'foo.1.wizz': '2' }
374 *
375 * will result in an output of:
376 *
377 * {
378 * 'foo': [
379 * { 'bar': 'one', 'wizz': '1' },
380 * { 'bar': 'two', 'wizz': '2' }
381 * ],
382 * }
383 *
384 * The following scenarios in the input dict will result in an
385 * error being returned:
386 *
387 * - Any values in @src are non-scalar types
388 * - If keys in @src imply that a particular level is both a
389 * list and a dict. e.g., "foo.0.bar" and "foo.eek.bar".
390 * - If keys in @src imply that a particular level is a list,
391 * but the indices are non-contiguous. e.g. "foo.0.bar" and
392 * "foo.2.bar" without any "foo.1.bar" present.
393 * - If keys in @src represent list indexes, but are not in
394 * the "%zu" format. e.g. "foo.+0.bar"
395 *
396 * Returns: either a QDict or QList for the nested data structure, or NULL
397 * on error
398 */
399QObject *qdict_crumple(const QDict *src, Error **errp)
400{
401 const QDictEntry *ent;
402 QDict *two_level, *multi_level = NULL;
403 QObject *dst = NULL, *child;
404 size_t i;
405 char *prefix = NULL;
406 const char *suffix = NULL;
407 int is_list;
408
409 two_level = qdict_new();
410
411 /* Step 1: split our totally flat dict into a two level dict */
412 for (ent = qdict_first(src); ent != NULL; ent = qdict_next(src, ent)) {
413 if (qobject_type(ent->value) == QTYPE_QDICT ||
414 qobject_type(ent->value) == QTYPE_QLIST) {
415 error_setg(errp, "Value %s is not a scalar",
416 ent->key);
417 goto error;
418 }
419
420 qdict_split_flat_key(ent->key, &prefix, &suffix);
421
422 child = qdict_get(two_level, prefix);
423 if (suffix) {
424 QDict *child_dict = qobject_to(QDict, child);
425 if (!child_dict) {
426 if (child) {
427 error_setg(errp, "Key %s prefix is already set as a scalar",
428 prefix);
429 goto error;
430 }
431
432 child_dict = qdict_new();
433 qdict_put_obj(two_level, prefix, QOBJECT(child_dict));
434 }
435
436 qdict_put_obj(child_dict, suffix, qobject_ref(ent->value));
437 } else {
438 if (child) {
439 error_setg(errp, "Key %s prefix is already set as a dict",
440 prefix);
441 goto error;
442 }
443 qdict_put_obj(two_level, prefix, qobject_ref(ent->value));
444 }
445
446 g_free(prefix);
447 prefix = NULL;
448 }
449
450 /* Step 2: optionally process the two level dict recursively
451 * into a multi-level dict */
452 multi_level = qdict_new();
453 for (ent = qdict_first(two_level); ent != NULL;
454 ent = qdict_next(two_level, ent)) {
455 QDict *dict = qobject_to(QDict, ent->value);
456 if (dict) {
457 child = qdict_crumple(dict, errp);
458 if (!child) {
459 goto error;
460 }
461
462 qdict_put_obj(multi_level, ent->key, child);
463 } else {
464 qdict_put_obj(multi_level, ent->key, qobject_ref(ent->value));
465 }
466 }
467 qobject_unref(two_level);
468 two_level = NULL;
469
470 /* Step 3: detect if we need to turn our dict into list */
471 is_list = qdict_is_list(multi_level, errp);
472 if (is_list < 0) {
473 goto error;
474 }
475
476 if (is_list) {
477 dst = QOBJECT(qlist_new());
478
479 for (i = 0; i < qdict_size(multi_level); i++) {
480 char *key = g_strdup_printf("%zu", i);
481
482 child = qdict_get(multi_level, key);
483 g_free(key);
484
485 if (!child) {
486 error_setg(errp, "Missing list index %zu", i);
487 goto error;
488 }
489
490 qlist_append_obj(qobject_to(QList, dst), qobject_ref(child));
491 }
492 qobject_unref(multi_level);
493 multi_level = NULL;
494 } else {
495 dst = QOBJECT(multi_level);
496 }
497
498 return dst;
499
500 error:
501 g_free(prefix);
502 qobject_unref(multi_level);
503 qobject_unref(two_level);
504 qobject_unref(dst);
505 return NULL;
506}
507
e5af0da1
MA
508/**
509 * qdict_crumple_for_keyval_qiv:
510 * @src: the flat dictionary (only scalar values) to crumple
511 * @errp: location to store error
512 *
513 * Like qdict_crumple(), but additionally transforms scalar values so
514 * the result can be passed to qobject_input_visitor_new_keyval().
515 *
516 * The block subsystem uses this function to prepare its flat QDict
517 * with possibly confused scalar types for a visit. It should not be
518 * used for anything else, and it should go away once the block
519 * subsystem has been cleaned up.
520 */
af91062e 521static QObject *qdict_crumple_for_keyval_qiv(QDict *src, Error **errp)
e5af0da1
MA
522{
523 QDict *tmp = NULL;
524 char *buf;
525 const char *s;
526 const QDictEntry *ent;
527 QObject *dst;
528
529 for (ent = qdict_first(src); ent; ent = qdict_next(src, ent)) {
530 buf = NULL;
531 switch (qobject_type(ent->value)) {
532 case QTYPE_QNULL:
533 case QTYPE_QSTRING:
534 continue;
535 case QTYPE_QNUM:
536 s = buf = qnum_to_string(qobject_to(QNum, ent->value));
537 break;
538 case QTYPE_QDICT:
539 case QTYPE_QLIST:
540 /* @src isn't flat; qdict_crumple() will fail */
541 continue;
542 case QTYPE_QBOOL:
543 s = qbool_get_bool(qobject_to(QBool, ent->value))
544 ? "on" : "off";
545 break;
546 default:
547 abort();
548 }
549
550 if (!tmp) {
551 tmp = qdict_clone_shallow(src);
552 }
553 qdict_put(tmp, ent->key, qstring_from_str(s));
554 g_free(buf);
555 }
556
557 dst = qdict_crumple(tmp ?: src, errp);
558 qobject_unref(tmp);
559 return dst;
560}
561
0bcc8e5b
MA
562/**
563 * qdict_array_entries(): Returns the number of direct array entries if the
564 * sub-QDict of src specified by the prefix in subqdict (or src itself for
565 * prefix == "") is valid as an array, i.e. the length of the created list if
566 * the sub-QDict would become empty after calling qdict_array_split() on it. If
567 * the array is not valid, -EINVAL is returned.
568 */
569int qdict_array_entries(QDict *src, const char *subqdict)
570{
571 const QDictEntry *entry;
572 unsigned i;
573 unsigned entries = 0;
574 size_t subqdict_len = strlen(subqdict);
575
576 assert(!subqdict_len || subqdict[subqdict_len - 1] == '.');
577
578 /* qdict_array_split() loops until UINT_MAX, but as we want to return
579 * negative errors, we only have a signed return value here. Any additional
580 * entries will lead to -EINVAL. */
581 for (i = 0; i < INT_MAX; i++) {
582 QObject *subqobj;
583 int subqdict_entries;
584 char *prefix = g_strdup_printf("%s%u.", subqdict, i);
585
586 subqdict_entries = qdict_count_prefixed_entries(src, prefix);
587
588 /* Remove ending "." */
589 prefix[strlen(prefix) - 1] = 0;
590 subqobj = qdict_get(src, prefix);
591
592 g_free(prefix);
593
594 if (subqdict_entries < 0) {
595 return subqdict_entries;
596 }
597
598 /* There may be either a single subordinate object (named "%u") or
599 * multiple objects (each with a key prefixed "%u."), but not both. */
600 if (subqobj && subqdict_entries) {
601 return -EINVAL;
602 } else if (!subqobj && !subqdict_entries) {
603 break;
604 }
605
606 entries += subqdict_entries ? subqdict_entries : 1;
607 }
608
609 /* Consider everything handled that isn't part of the given sub-QDict */
610 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
611 if (!strstart(qdict_entry_key(entry), subqdict, NULL)) {
612 entries++;
613 }
614 }
615
616 /* Anything left in the sub-QDict that wasn't handled? */
617 if (qdict_size(src) != entries) {
618 return -EINVAL;
619 }
620
621 return i;
622}
623
624/**
625 * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all
626 * elements from src to dest.
627 *
628 * If an element from src has a key already present in dest, it will not be
629 * moved unless overwrite is true.
630 *
631 * If overwrite is true, the conflicting values in dest will be discarded and
632 * replaced by the corresponding values from src.
633 *
634 * Therefore, with overwrite being true, the src QDict will always be empty when
635 * this function returns. If overwrite is false, the src QDict will be empty
636 * iff there were no conflicts.
637 */
638void qdict_join(QDict *dest, QDict *src, bool overwrite)
639{
640 const QDictEntry *entry, *next;
641
642 entry = qdict_first(src);
643 while (entry) {
644 next = qdict_next(src, entry);
645
646 if (overwrite || !qdict_haskey(dest, entry->key)) {
647 qdict_put_obj(dest, entry->key, qobject_ref(entry->value));
648 qdict_del(src, entry->key);
649 }
650
651 entry = next;
652 }
653}
654
655/**
656 * qdict_rename_keys(): Rename keys in qdict according to the replacements
657 * specified in the array renames. The array must be terminated by an entry
658 * with from = NULL.
659 *
660 * The renames are performed individually in the order of the array, so entries
661 * may be renamed multiple times and may or may not conflict depending on the
662 * order of the renames array.
663 *
664 * Returns true for success, false in error cases.
665 */
666bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **errp)
667{
668 QObject *qobj;
669
670 while (renames->from) {
671 if (qdict_haskey(qdict, renames->from)) {
672 if (qdict_haskey(qdict, renames->to)) {
673 error_setg(errp, "'%s' and its alias '%s' can't be used at the "
674 "same time", renames->to, renames->from);
675 return false;
676 }
677
678 qobj = qdict_get(qdict, renames->from);
679 qdict_put_obj(qdict, renames->to, qobject_ref(qobj));
680 qdict_del(qdict, renames->from);
681 }
682
683 renames++;
684 }
685 return true;
686}
af91062e
MA
687
688/*
689 * Create a QObject input visitor for flat @qdict with possibly
690 * confused scalar types.
691 *
692 * The block subsystem uses this function to visit its flat QDict with
693 * possibly confused scalar types. It should not be used for anything
694 * else, and it should go away once the block subsystem has been
695 * cleaned up.
696 */
697Visitor *qobject_input_visitor_new_flat_confused(QDict *qdict,
698 Error **errp)
699{
700 QObject *crumpled;
701 Visitor *v;
702
703 crumpled = qdict_crumple_for_keyval_qiv(qdict, errp);
704 if (!crumpled) {
705 return NULL;
706 }
707
708 v = qobject_input_visitor_new_keyval(crumpled);
709 qobject_unref(crumpled);
710 return v;
711}