typedef struct StackObject
{
QObject *obj; /* Object being visited */
+ void *qapi; /* sanity check that caller uses same pointer */
GHashTable *h; /* If obj is dict: unvisited keys */
const QListEntry *entry; /* If obj is list: unvisited tail */
+
+ QSLIST_ENTRY(StackObject) node;
} StackObject;
struct QmpInputVisitor
/* Stack of objects being visited (all entries will be either
* QDict or QList). */
- StackObject stack[QIV_STACK_SIZE];
- int nb_stack;
+ QSLIST_HEAD(, StackObject) stack;
/* True to reject parse in visit_end_struct() if unvisited keys remain. */
bool strict;
QObject *qobj;
QObject *ret;
- if (!qiv->nb_stack) {
+ if (QSLIST_EMPTY(&qiv->stack)) {
/* Starting at root, name is ignored. */
+ assert(qiv->root);
return qiv->root;
}
/* We are in a container; find the next element. */
- tos = &qiv->stack[qiv->nb_stack - 1];
+ tos = QSLIST_FIRST(&qiv->stack);
qobj = tos->obj;
assert(qobj);
}
static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
- Error **errp)
+ void *qapi, Error **errp)
{
GHashTable *h;
- StackObject *tos = &qiv->stack[qiv->nb_stack];
+ StackObject *tos = g_new0(StackObject, 1);
assert(obj);
- if (qiv->nb_stack >= QIV_STACK_SIZE) {
- error_setg(errp, "An internal buffer overran");
- return NULL;
- }
-
tos->obj = obj;
- assert(!tos->h);
- assert(!tos->entry);
+ tos->qapi = qapi;
if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
h = g_hash_table_new(g_str_hash, g_str_equal);
tos->entry = qlist_first(qobject_to_qlist(obj));
}
- qiv->nb_stack++;
+ QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
return tos->entry;
}
static void qmp_input_check_struct(Visitor *v, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- StackObject *tos = &qiv->stack[qiv->nb_stack - 1];
-
- assert(qiv->nb_stack > 0);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+ assert(tos && !tos->entry);
if (qiv->strict) {
GHashTable *const top_ht = tos->h;
if (top_ht) {
}
}
-static void qmp_input_pop(Visitor *v)
+static void qmp_input_stack_object_free(StackObject *tos)
{
- QmpInputVisitor *qiv = to_qiv(v);
- StackObject *tos = &qiv->stack[qiv->nb_stack - 1];
+ if (tos->h) {
+ g_hash_table_unref(tos->h);
+ }
- assert(qiv->nb_stack > 0);
+ g_free(tos);
+}
- if (qiv->strict) {
- GHashTable * const top_ht = qiv->stack[qiv->nb_stack - 1].h;
- if (top_ht) {
- g_hash_table_unref(top_ht);
- }
- tos->h = NULL;
- }
+static void qmp_input_pop(Visitor *v, void **obj)
+{
+ QmpInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
- qiv->nb_stack--;
+ assert(tos && tos->qapi == obj);
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qmp_input_stack_object_free(tos);
}
static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
return;
}
- qmp_input_push(qiv, qobj, &err);
+ qmp_input_push(qiv, qobj, obj, &err);
if (err) {
error_propagate(errp, err);
return;
return;
}
- entry = qmp_input_push(qiv, qobj, errp);
+ entry = qmp_input_push(qiv, qobj, list, errp);
if (list) {
if (entry) {
*list = g_malloc0(size);
size_t size)
{
QmpInputVisitor *qiv = to_qiv(v);
- StackObject *so = &qiv->stack[qiv->nb_stack - 1];
+ StackObject *so = QSLIST_FIRST(&qiv->stack);
if (!so->entry) {
return NULL;
QmpInputVisitor *qiv = to_qiv(v);
QObject *qobj = qmp_input_get_object(qiv, name, true);
+ if (!qobj) {
+ error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
+ *obj = NULL;
+ return;
+ }
+
qobject_incref(qobj);
*obj = qobj;
}
QmpInputVisitor *qiv = to_qiv(v);
QObject *qobj = qmp_input_get_object(qiv, name, true);
+ if (!qobj) {
+ error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
+ return;
+ }
+
if (qobject_type(qobj) != QTYPE_QNULL) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"null");
*present = true;
}
-Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
+static void qmp_input_free(Visitor *v)
{
- return &v->visitor;
-}
+ QmpInputVisitor *qiv = to_qiv(v);
+ while (!QSLIST_EMPTY(&qiv->stack)) {
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
-void qmp_input_visitor_cleanup(QmpInputVisitor *v)
-{
- qobject_decref(v->root);
- g_free(v);
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qmp_input_stack_object_free(tos);
+ }
+
+ qobject_decref(qiv->root);
+ g_free(qiv);
}
-QmpInputVisitor *qmp_input_visitor_new(QObject *obj, bool strict)
+Visitor *qmp_input_visitor_new(QObject *obj, bool strict)
{
QmpInputVisitor *v;
+ assert(obj);
v = g_malloc0(sizeof(*v));
v->visitor.type = VISITOR_INPUT;
v->visitor.type_any = qmp_input_type_any;
v->visitor.type_null = qmp_input_type_null;
v->visitor.optional = qmp_input_optional;
+ v->visitor.free = qmp_input_free;
v->strict = strict;
v->root = obj;
qobject_incref(obj);
- return v;
+ return &v->visitor;
}