mirror of
https://github.com/yuzu-emu/unicorn
synced 2024-11-25 21:57:48 +00:00
qmp-input: Refactor when list is advanced
In the QMP input visitor, visiting a list traverses two objects: the QAPI GenericList of the caller (which gets advanced in visit_next_list() regardless of this patch), and the QList input that we are converting to QAPI. For consistency with QDict visits, we want to consume elements from the input QList during the visit_type_FOO() for the list element; that is, we want ALL the code for consuming an input to live in qmp_input_get_object(), rather than having it split according to whether we are visiting a dict or a list. Making qmp_input_get_object() the common point of consumption will make it easier for a later patch to refactor visit_start_list() to cover the GenericList * head of a QAPI list, and in turn will get rid of the 'first' flag (which lived in qmp_input_next_list() pre-patch, and is hoisted to StackObject by this patch). This patch is therefore altering the post-condition use of 'entry', while keeping what gets visited unchanged, from: start_list next_list type_ELT ... next_list type_ELT next_list end_list visits 1st elt last elt entry NULL 1st elt 1st elt last elt last elt NULL gone where type_ELT() returns (entry ? entry : 1st elt) and next_list() steps entry to this usage: start_list next_list type_ELT ... next_list type_ELT next_list end_list visits 1st elt last elt entry 1st elt 1nd elt 2nd elt last elt NULL NULL gone where type_ELT() steps entry and returns the old entry, and next_list() leaves entry alone. Backports commit fcf3cb21783b2dae3358fdbe7001cb2f74e0cedf from qemu
This commit is contained in:
parent
68cf25fafa
commit
5389c1cd5f
1 changed files with 16 additions and 14 deletions
|
@ -28,6 +28,7 @@ typedef struct StackObject
|
||||||
|
|
||||||
GHashTable *h; /* If obj is dict: unvisited keys */
|
GHashTable *h; /* If obj is dict: unvisited keys */
|
||||||
const QListEntry *entry; /* If obj is list: unvisited tail */
|
const QListEntry *entry; /* If obj is list: unvisited tail */
|
||||||
|
bool first; /* If obj is list: next_list() not yet called? */
|
||||||
} StackObject;
|
} StackObject;
|
||||||
|
|
||||||
struct QmpInputVisitor
|
struct QmpInputVisitor
|
||||||
|
@ -79,7 +80,11 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
|
||||||
} else {
|
} else {
|
||||||
assert(qobject_type(qobj) == QTYPE_QLIST);
|
assert(qobject_type(qobj) == QTYPE_QLIST);
|
||||||
assert(!name);
|
assert(!name);
|
||||||
|
assert(!tos->first);
|
||||||
ret = qlist_entry_obj(tos->entry);
|
ret = qlist_entry_obj(tos->entry);
|
||||||
|
if (consume) {
|
||||||
|
tos->entry = qlist_next(tos->entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -103,13 +108,16 @@ static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
|
||||||
}
|
}
|
||||||
|
|
||||||
tos->obj = obj;
|
tos->obj = obj;
|
||||||
tos->entry = NULL;
|
assert(!tos->h);
|
||||||
tos->h = NULL;
|
assert(!tos->entry);
|
||||||
|
|
||||||
if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
|
if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
|
||||||
h = g_hash_table_new(g_str_hash, g_str_equal);
|
h = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
|
qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
|
||||||
tos->h = h;
|
tos->h = h;
|
||||||
|
} else if (qobject_type(obj) == QTYPE_QLIST) {
|
||||||
|
tos->entry = qlist_first(qobject_to_qlist(obj));
|
||||||
|
tos->first = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
qiv->nb_stack++;
|
qiv->nb_stack++;
|
||||||
|
@ -124,10 +132,11 @@ static gboolean always_true(gpointer key, gpointer val, gpointer user_pkey)
|
||||||
|
|
||||||
static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
|
static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
|
||||||
{
|
{
|
||||||
|
StackObject *tos = &qiv->stack[qiv->nb_stack - 1];
|
||||||
assert(qiv->nb_stack > 0);
|
assert(qiv->nb_stack > 0);
|
||||||
|
|
||||||
if (qiv->strict) {
|
if (qiv->strict) {
|
||||||
GHashTable * const top_ht = qiv->stack[qiv->nb_stack - 1].h;
|
GHashTable *const top_ht = tos->h;
|
||||||
if (top_ht) {
|
if (top_ht) {
|
||||||
if (g_hash_table_size(top_ht)) {
|
if (g_hash_table_size(top_ht)) {
|
||||||
const char *key;
|
const char *key;
|
||||||
|
@ -136,6 +145,7 @@ static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
|
||||||
}
|
}
|
||||||
g_hash_table_unref(top_ht);
|
g_hash_table_unref(top_ht);
|
||||||
}
|
}
|
||||||
|
tos->h = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
qiv->nb_stack--;
|
qiv->nb_stack--;
|
||||||
|
@ -207,23 +217,15 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
|
||||||
QmpInputVisitor *qiv = to_qiv(v);
|
QmpInputVisitor *qiv = to_qiv(v);
|
||||||
GenericList *entry;
|
GenericList *entry;
|
||||||
StackObject *so = &qiv->stack[qiv->nb_stack - 1];
|
StackObject *so = &qiv->stack[qiv->nb_stack - 1];
|
||||||
bool first;
|
|
||||||
|
|
||||||
if (so->entry == NULL) {
|
if (!so->entry) {
|
||||||
so->entry = qlist_first(qobject_to_qlist(so->obj));
|
|
||||||
first = true;
|
|
||||||
} else {
|
|
||||||
so->entry = qlist_next(so->entry);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (so->entry == NULL) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = g_malloc0(size);
|
entry = g_malloc0(size);
|
||||||
if (first) {
|
if (so->first) {
|
||||||
*list = entry;
|
*list = entry;
|
||||||
|
so->first = false;
|
||||||
} else {
|
} else {
|
||||||
(*list)->next = entry;
|
(*list)->next = entry;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue