qdict: Extract non-QDicts in qdict_array_split()
Currently, qdict_array_split() only splits off entries with a key prefix of "%u.", packing them into a new QDict. This patch makes it support entries with the plain key "%u" as well, directly putting them into the new QList without creating a QDict. If there is both an entry with a key of "%u" and other entries with keys prefixed "%u." (for the same index), the function simply terminates. To do this, this patch also adds a static function which tests whether a given QDict contains any keys with the given prefix. This is used to test whether entries with a key prefixed "%u." do exist in the source QDict without modifying it. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
ae39c4b201
commit
bae3f92a01
@ -597,18 +597,33 @@ void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool qdict_has_prefixed_entries(const QDict *src, const char *start)
|
||||||
|
{
|
||||||
|
const QDictEntry *entry;
|
||||||
|
|
||||||
|
for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
|
||||||
|
if (strstart(entry->key, start, NULL)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qdict_array_split(): This function moves array-like elements of a QDict into
|
* qdict_array_split(): This function moves array-like elements of a QDict into
|
||||||
* a new QList of QDicts. Every entry in the original QDict with a key prefixed
|
* a new QList. Every entry in the original QDict with a key "%u" or one
|
||||||
* "%u.", where %u designates an unsigned integer starting at 0 and
|
* prefixed "%u.", where %u designates an unsigned integer starting at 0 and
|
||||||
* incrementally counting up, will be moved to a new QDict at index %u in the
|
* incrementally counting up, will be moved to a new QDict at index %u in the
|
||||||
* output QList with the key prefix removed. The function terminates when there
|
* output QList with the key prefix removed, if that prefix is "%u.". If the
|
||||||
* is no entry in the QDict with a prefix directly (incrementally) following the
|
* whole key is just "%u", the whole QObject will be moved unchanged without
|
||||||
* last one.
|
* creating a new QDict. The function terminates when there is no entry in the
|
||||||
* Example: {"0.a": 42, "0.b": 23, "1.x": 0, "3.y": 1, "o.o": 7}
|
* QDict with a prefix directly (incrementally) following the last one; it also
|
||||||
* (or {"1.x": 0, "3.y": 1, "0.a": 42, "o.o": 7, "0.b": 23})
|
* returns if there are both entries with "%u" and "%u." for the same index %u.
|
||||||
* => [{"a": 42, "b": 23}, {"x": 0}]
|
* Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66}
|
||||||
* and {"3.y": 1, "o.o": 7} (remainder of the old QDict)
|
* (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66})
|
||||||
|
* => [{"a": 42, "b": 23}, {"x": 0}, 66]
|
||||||
|
* and {"4.y": 1, "o.o": 7} (remainder of the old QDict)
|
||||||
*/
|
*/
|
||||||
void qdict_array_split(QDict *src, QList **dst)
|
void qdict_array_split(QDict *src, QList **dst)
|
||||||
{
|
{
|
||||||
@ -617,19 +632,36 @@ void qdict_array_split(QDict *src, QList **dst)
|
|||||||
*dst = qlist_new();
|
*dst = qlist_new();
|
||||||
|
|
||||||
for (i = 0; i < UINT_MAX; i++) {
|
for (i = 0; i < UINT_MAX; i++) {
|
||||||
|
QObject *subqobj;
|
||||||
|
bool is_subqdict;
|
||||||
QDict *subqdict;
|
QDict *subqdict;
|
||||||
char prefix[32];
|
char indexstr[32], prefix[32];
|
||||||
size_t snprintf_ret;
|
size_t snprintf_ret;
|
||||||
|
|
||||||
|
snprintf_ret = snprintf(indexstr, 32, "%u", i);
|
||||||
|
assert(snprintf_ret < 32);
|
||||||
|
|
||||||
|
subqobj = qdict_get(src, indexstr);
|
||||||
|
|
||||||
snprintf_ret = snprintf(prefix, 32, "%u.", i);
|
snprintf_ret = snprintf(prefix, 32, "%u.", i);
|
||||||
assert(snprintf_ret < 32);
|
assert(snprintf_ret < 32);
|
||||||
|
|
||||||
qdict_extract_subqdict(src, &subqdict, prefix);
|
is_subqdict = qdict_has_prefixed_entries(src, prefix);
|
||||||
if (!qdict_size(subqdict)) {
|
|
||||||
QDECREF(subqdict);
|
// There may be either a single subordinate object (named "%u") or
|
||||||
|
// multiple objects (each with a key prefixed "%u."), but not both.
|
||||||
|
if (!subqobj == !is_subqdict) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
qlist_append_obj(*dst, QOBJECT(subqdict));
|
if (is_subqdict) {
|
||||||
|
qdict_extract_subqdict(src, &subqdict, prefix);
|
||||||
|
assert(qdict_size(subqdict) > 0);
|
||||||
|
} else {
|
||||||
|
qobject_incref(subqobj);
|
||||||
|
qdict_del(src, indexstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user