mirror of https://github.com/xemu-project/xemu.git
QAPI patches for 2016-10-25
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJYD4CrAAoJEDhwtADrkYZTH68P/jYNK4vDZP7q3qxeh1sYDIOO GsOO/dOZ6v+L3fEpbbHe45veGEPLs/fH96Xw6C5GEKC3TYR8OGiSoh3Yr+B4Alo1 b1VtozOcdoqKlmMqgDDfh8tm3k8hgKDFmYvt3gitz15jcnWc4xuY139Hx3PTbivj zOIvvEEIb7wF+pof/rd++SpnWMBUeKRe81QuNobQULl/dmoJOLshitcQFRuEGAwC Z3VcGetgILFNtoDJ8cyIj080davgmAihQbfgJT/oXJ5QLR1lggCdbjLb7c4fRgSE Jf+VUzJ/nZg0gVemwqnfaGD3APt3ioJuBo/EL2pNwhlXaHxJHyg2tmaedUqetMxJ BRw2ibKSrXcGEZk09Y3vlhyJowjmSnFS5LkGVhCIBQXsuvduMu4DwvoEFJUzlpWy hn6P+pu7ycYKhuYMychHpCjNCk6KjQbux5j+tnlNyCHMHEAH7sr2xn9tEvP7NaW3 nydJkE982+117RNGHbjIiYn1RPjWjmyZDX5b/HXQjIXXv4L06SwRVM2UNnXXrJYW BBTz9ZDBWM8QO2pVXZsy0cXbb9vpHvr09Nia2kVzTGwGQnrt8+uNQ61b5uLQNavm dJ8yl7b3sCAANN1mUbzrYifTM+pS7h3ekbi5kNPkBfD6RKBlthrJe2+JhcEmql8H Hup8I8bDMBNBvD/09JHs =13Ss -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-10-25' into staging QAPI patches for 2016-10-25 # gpg: Signature made Tue 25 Oct 2016 16:56:27 BST # gpg: using RSA key 0x3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2016-10-25: qdict: implement a qdict_crumple method for un-flattening a dict qapi: don't pass two copies of TestInputVisitorData to tests qapi: rename QmpOutputVisitor to QObjectOutputVisitor qapi: rename QmpInputVisitor to QObjectInputVisitor qapi: rename *qmp-*-visitor* to *qobject-*-visitor* qapi: add trace events for visitor trivial: Restore blank line in qapi-schema Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
ede0cbeb78
|
@ -162,3 +162,4 @@ trace-events-y += target-s390x/trace-events
|
|||
trace-events-y += target-ppc/trace-events
|
||||
trace-events-y += qom/trace-events
|
||||
trace-events-y += linux-user/trace-events
|
||||
trace-events-y += qapi/trace-events
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "block/write-threshold.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
@ -691,7 +691,7 @@ void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
|
|||
ImageInfoSpecific *info_spec)
|
||||
{
|
||||
QObject *obj, *data;
|
||||
Visitor *v = qmp_output_visitor_new(&obj);
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "qapi/qmp/types.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/util.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "block/block_int.h"
|
||||
|
@ -3776,7 +3776,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
|||
{
|
||||
BlockDriverState *bs;
|
||||
QObject *obj;
|
||||
Visitor *v = qmp_output_visitor_new(&obj);
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
QDict *qdict;
|
||||
Error *local_err = NULL;
|
||||
|
||||
|
|
|
@ -1005,7 +1005,7 @@ Example:
|
|||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = qmp_output_visitor_new(ret_out);
|
||||
v = qobject_output_visitor_new(ret_out);
|
||||
visit_type_UserDefOne(v, "unused", &ret_in, &err);
|
||||
if (!err) {
|
||||
visit_complete(v, ret_out);
|
||||
|
@ -1024,7 +1024,7 @@ Example:
|
|||
Visitor *v;
|
||||
UserDefOneList *arg1 = NULL;
|
||||
|
||||
v = qmp_input_visitor_new(QOBJECT(args), true);
|
||||
v = qobject_input_visitor_new(QOBJECT(args), true);
|
||||
visit_start_struct(v, NULL, NULL, 0, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
|
|
|
@ -73,6 +73,7 @@ void qdict_flatten(QDict *qdict);
|
|||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
||||
void qdict_array_split(QDict *src, QList **dst);
|
||||
int qdict_array_entries(QDict *src, const char *subqdict);
|
||||
QObject *qdict_crumple(const QDict *src, Error **errp);
|
||||
|
||||
void qdict_join(QDict *dest, QDict *src, bool overwrite);
|
||||
|
||||
|
|
|
@ -11,20 +11,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef QMP_INPUT_VISITOR_H
|
||||
#define QMP_INPUT_VISITOR_H
|
||||
#ifndef QOBJECT_INPUT_VISITOR_H
|
||||
#define QOBJECT_INPUT_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QmpInputVisitor QmpInputVisitor;
|
||||
typedef struct QObjectInputVisitor QObjectInputVisitor;
|
||||
|
||||
/*
|
||||
* Return a new input visitor that converts QMP to QAPI.
|
||||
* Return a new input visitor that converts a QObject to a QAPI object.
|
||||
*
|
||||
* Set @strict to reject a parse that doesn't consume all keys of a
|
||||
* dictionary; otherwise excess input is ignored.
|
||||
*/
|
||||
Visitor *qmp_input_visitor_new(QObject *obj, bool strict);
|
||||
Visitor *qobject_input_visitor_new(QObject *obj, bool strict);
|
||||
|
||||
#endif
|
|
@ -11,20 +11,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef QMP_OUTPUT_VISITOR_H
|
||||
#define QMP_OUTPUT_VISITOR_H
|
||||
#ifndef QOBJECT_OUTPUT_VISITOR_H
|
||||
#define QOBJECT_OUTPUT_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QmpOutputVisitor QmpOutputVisitor;
|
||||
typedef struct QObjectOutputVisitor QObjectOutputVisitor;
|
||||
|
||||
/*
|
||||
* Create a new QMP output visitor.
|
||||
* Create a new QObject output visitor.
|
||||
*
|
||||
* If everything else succeeds, pass @result to visit_complete() to
|
||||
* collect the result of the visit.
|
||||
*/
|
||||
Visitor *qmp_output_visitor_new(QObject **result);
|
||||
Visitor *qobject_output_visitor_new(QObject **result);
|
||||
|
||||
#endif
|
|
@ -25,14 +25,14 @@
|
|||
* for doing work at each node of a QAPI graph; it can also be used
|
||||
* for a virtual walk, where there is no actual QAPI C struct.
|
||||
*
|
||||
* There are four kinds of visitor classes: input visitors (QMP,
|
||||
* There are four kinds of visitor classes: input visitors (QObject,
|
||||
* string, and QemuOpts) parse an external representation and build
|
||||
* the corresponding QAPI graph, output visitors (QMP and string) take
|
||||
* the corresponding QAPI graph, output visitors (QObject and string) take
|
||||
* a completed QAPI graph and generate an external representation, the
|
||||
* dealloc visitor can take a QAPI graph (possibly partially
|
||||
* constructed) and recursively free its resources, and the clone
|
||||
* visitor performs a deep clone of one QAPI object to another. While
|
||||
* the dealloc and QMP input/output visitors are general, the string,
|
||||
* the dealloc and QObject input/output visitors are general, the string,
|
||||
* QemuOpts, and clone visitors have some implementation limitations;
|
||||
* see the documentation for each visitor for more details on what it
|
||||
* supports. Also, see visitor-impl.h for the callback contracts
|
||||
|
|
|
@ -950,7 +950,7 @@ EventInfoList *qmp_query_events(Error **errp)
|
|||
* directly into QObject instead of first parsing it with
|
||||
* visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it
|
||||
* to QObject with generated output marshallers, every time. Instead,
|
||||
* we do it in test-qmp-input-visitor.c, just to make sure
|
||||
* we do it in test-qobject-input-visitor.c, just to make sure
|
||||
* qapi-introspect.py's output actually conforms to the schema.
|
||||
*/
|
||||
static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
|
||||
|
|
|
@ -737,6 +737,7 @@
|
|||
'*tls-hostname': 'str',
|
||||
'*max-bandwidth': 'int',
|
||||
'*downtime-limit': 'int'} }
|
||||
|
||||
##
|
||||
# @query-migrate-parameters
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
|
||||
util-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
|
||||
util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qobject-input-visitor.o
|
||||
util-obj-y += qobject-output-visitor.o qmp-registry.o qmp-dispatch.o
|
||||
util-obj-y += string-input-visitor.o string-output-visitor.o
|
||||
util-obj-y += opts-visitor.o qapi-clone-visitor.o
|
||||
util-obj-y += qmp-event.o
|
||||
|
|
|
@ -110,7 +110,7 @@ static void qapi_clone_type_str(Visitor *v, const char *name, char **obj,
|
|||
assert(qcv->depth);
|
||||
/*
|
||||
* Pointer was already cloned by g_memdup; create fresh copy.
|
||||
* Note that as long as qmp-output-visitor accepts NULL instead of
|
||||
* Note that as long as qobject-output-visitor accepts NULL instead of
|
||||
* "", then we must do likewise. However, we want to obey the
|
||||
* input visitor semantics of never producing NULL when the empty
|
||||
* string is intended.
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
#include "trace.h"
|
||||
|
||||
void visit_complete(Visitor *v, void *opaque)
|
||||
{
|
||||
assert(v->type != VISITOR_OUTPUT || v->complete);
|
||||
trace_visit_complete(v, opaque);
|
||||
if (v->complete) {
|
||||
v->complete(v, opaque);
|
||||
}
|
||||
|
@ -30,6 +32,7 @@ void visit_complete(Visitor *v, void *opaque)
|
|||
|
||||
void visit_free(Visitor *v)
|
||||
{
|
||||
trace_visit_free(v);
|
||||
if (v) {
|
||||
v->free(v);
|
||||
}
|
||||
|
@ -40,6 +43,7 @@ void visit_start_struct(Visitor *v, const char *name, void **obj,
|
|||
{
|
||||
Error *err = NULL;
|
||||
|
||||
trace_visit_start_struct(v, name, obj, size);
|
||||
if (obj) {
|
||||
assert(size);
|
||||
assert(!(v->type & VISITOR_OUTPUT) || *obj);
|
||||
|
@ -53,6 +57,7 @@ void visit_start_struct(Visitor *v, const char *name, void **obj,
|
|||
|
||||
void visit_check_struct(Visitor *v, Error **errp)
|
||||
{
|
||||
trace_visit_check_struct(v);
|
||||
if (v->check_struct) {
|
||||
v->check_struct(v, errp);
|
||||
}
|
||||
|
@ -60,6 +65,7 @@ void visit_check_struct(Visitor *v, Error **errp)
|
|||
|
||||
void visit_end_struct(Visitor *v, void **obj)
|
||||
{
|
||||
trace_visit_end_struct(v, obj);
|
||||
v->end_struct(v, obj);
|
||||
}
|
||||
|
||||
|
@ -69,6 +75,7 @@ void visit_start_list(Visitor *v, const char *name, GenericList **list,
|
|||
Error *err = NULL;
|
||||
|
||||
assert(!list || size >= sizeof(GenericList));
|
||||
trace_visit_start_list(v, name, list, size);
|
||||
v->start_list(v, name, list, size, &err);
|
||||
if (list && (v->type & VISITOR_INPUT)) {
|
||||
assert(!(err && *list));
|
||||
|
@ -79,11 +86,13 @@ void visit_start_list(Visitor *v, const char *name, GenericList **list,
|
|||
GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
|
||||
{
|
||||
assert(tail && size >= sizeof(GenericList));
|
||||
trace_visit_next_list(v, tail, size);
|
||||
return v->next_list(v, tail, size);
|
||||
}
|
||||
|
||||
void visit_end_list(Visitor *v, void **obj)
|
||||
{
|
||||
trace_visit_end_list(v, obj);
|
||||
v->end_list(v, obj);
|
||||
}
|
||||
|
||||
|
@ -95,6 +104,7 @@ void visit_start_alternate(Visitor *v, const char *name,
|
|||
|
||||
assert(obj && size >= sizeof(GenericAlternate));
|
||||
assert(!(v->type & VISITOR_OUTPUT) || *obj);
|
||||
trace_visit_start_alternate(v, name, obj, size, promote_int);
|
||||
if (v->start_alternate) {
|
||||
v->start_alternate(v, name, obj, size, promote_int, &err);
|
||||
}
|
||||
|
@ -106,6 +116,7 @@ void visit_start_alternate(Visitor *v, const char *name,
|
|||
|
||||
void visit_end_alternate(Visitor *v, void **obj)
|
||||
{
|
||||
trace_visit_end_alternate(v, obj);
|
||||
if (v->end_alternate) {
|
||||
v->end_alternate(v, obj);
|
||||
}
|
||||
|
@ -113,6 +124,7 @@ void visit_end_alternate(Visitor *v, void **obj)
|
|||
|
||||
bool visit_optional(Visitor *v, const char *name, bool *present)
|
||||
{
|
||||
trace_visit_optional(v, name, present);
|
||||
if (v->optional) {
|
||||
v->optional(v, name, present);
|
||||
}
|
||||
|
@ -127,6 +139,7 @@ bool visit_is_input(Visitor *v)
|
|||
void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
|
||||
{
|
||||
assert(obj);
|
||||
trace_visit_type_int(v, name, obj);
|
||||
v->type_int64(v, name, obj, errp);
|
||||
}
|
||||
|
||||
|
@ -150,7 +163,10 @@ static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
|
|||
void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t value = *obj;
|
||||
uint64_t value;
|
||||
|
||||
trace_visit_type_uint8(v, name, obj);
|
||||
value = *obj;
|
||||
visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
|
||||
*obj = value;
|
||||
}
|
||||
|
@ -158,7 +174,10 @@ void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
|
|||
void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t value = *obj;
|
||||
uint64_t value;
|
||||
|
||||
trace_visit_type_uint16(v, name, obj);
|
||||
value = *obj;
|
||||
visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
|
||||
*obj = value;
|
||||
}
|
||||
|
@ -166,7 +185,10 @@ void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
|
|||
void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t value = *obj;
|
||||
uint64_t value;
|
||||
|
||||
trace_visit_type_uint32(v, name, obj);
|
||||
value = *obj;
|
||||
visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
|
||||
*obj = value;
|
||||
}
|
||||
|
@ -175,6 +197,7 @@ void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
|||
Error **errp)
|
||||
{
|
||||
assert(obj);
|
||||
trace_visit_type_uint64(v, name, obj);
|
||||
v->type_uint64(v, name, obj, errp);
|
||||
}
|
||||
|
||||
|
@ -198,7 +221,10 @@ static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
|
|||
|
||||
void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
|
||||
{
|
||||
int64_t value = *obj;
|
||||
int64_t value;
|
||||
|
||||
trace_visit_type_int8(v, name, obj);
|
||||
value = *obj;
|
||||
visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
|
||||
*obj = value;
|
||||
}
|
||||
|
@ -206,7 +232,10 @@ void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
|
|||
void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
int64_t value = *obj;
|
||||
int64_t value;
|
||||
|
||||
trace_visit_type_int16(v, name, obj);
|
||||
value = *obj;
|
||||
visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
|
||||
*obj = value;
|
||||
}
|
||||
|
@ -214,7 +243,10 @@ void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
|
|||
void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
int64_t value = *obj;
|
||||
int64_t value;
|
||||
|
||||
trace_visit_type_int32(v, name, obj);
|
||||
value = *obj;
|
||||
visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
|
||||
*obj = value;
|
||||
}
|
||||
|
@ -223,6 +255,7 @@ void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
|
|||
Error **errp)
|
||||
{
|
||||
assert(obj);
|
||||
trace_visit_type_int64(v, name, obj);
|
||||
v->type_int64(v, name, obj, errp);
|
||||
}
|
||||
|
||||
|
@ -230,6 +263,7 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
|
|||
Error **errp)
|
||||
{
|
||||
assert(obj);
|
||||
trace_visit_type_size(v, name, obj);
|
||||
if (v->type_size) {
|
||||
v->type_size(v, name, obj, errp);
|
||||
} else {
|
||||
|
@ -240,6 +274,7 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
|
|||
void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
|
||||
{
|
||||
assert(obj);
|
||||
trace_visit_type_bool(v, name, obj);
|
||||
v->type_bool(v, name, obj, errp);
|
||||
}
|
||||
|
||||
|
@ -252,6 +287,7 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
|
|||
* can enable:
|
||||
assert(!(v->type & VISITOR_OUTPUT) || *obj);
|
||||
*/
|
||||
trace_visit_type_str(v, name, obj);
|
||||
v->type_str(v, name, obj, &err);
|
||||
if (v->type & VISITOR_INPUT) {
|
||||
assert(!err != !*obj);
|
||||
|
@ -263,6 +299,7 @@ void visit_type_number(Visitor *v, const char *name, double *obj,
|
|||
Error **errp)
|
||||
{
|
||||
assert(obj);
|
||||
trace_visit_type_number(v, name, obj);
|
||||
v->type_number(v, name, obj, errp);
|
||||
}
|
||||
|
||||
|
@ -272,6 +309,7 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
|
|||
|
||||
assert(obj);
|
||||
assert(v->type != VISITOR_OUTPUT || *obj);
|
||||
trace_visit_type_any(v, name, obj);
|
||||
v->type_any(v, name, obj, &err);
|
||||
if (v->type == VISITOR_INPUT) {
|
||||
assert(!err != !*obj);
|
||||
|
@ -281,6 +319,7 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
|
|||
|
||||
void visit_type_null(Visitor *v, const char *name, Error **errp)
|
||||
{
|
||||
trace_visit_type_null(v, name);
|
||||
v->type_null(v, name, errp);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
* Core Definitions for QAPI/QMP Command Registry
|
||||
*
|
||||
* Copyright (C) 2012-2016 Red Hat, Inc.
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
|
||||
typedef struct QStackEntry
|
||||
{
|
||||
QObject *value;
|
||||
void *qapi; /* sanity check that caller uses same pointer */
|
||||
QSLIST_ENTRY(QStackEntry) node;
|
||||
} QStackEntry;
|
||||
|
||||
struct QmpOutputVisitor
|
||||
{
|
||||
Visitor visitor;
|
||||
QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
|
||||
QObject *root; /* Root of the output visit */
|
||||
QObject **result; /* User's storage location for result */
|
||||
};
|
||||
|
||||
#define qmp_output_add(qov, name, value) \
|
||||
qmp_output_add_obj(qov, name, QOBJECT(value))
|
||||
#define qmp_output_push(qov, value, qapi) \
|
||||
qmp_output_push_obj(qov, QOBJECT(value), qapi)
|
||||
|
||||
static QmpOutputVisitor *to_qov(Visitor *v)
|
||||
{
|
||||
return container_of(v, QmpOutputVisitor, visitor);
|
||||
}
|
||||
|
||||
/* Push @value onto the stack of current QObjects being built */
|
||||
static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value,
|
||||
void *qapi)
|
||||
{
|
||||
QStackEntry *e = g_malloc0(sizeof(*e));
|
||||
|
||||
assert(qov->root);
|
||||
assert(value);
|
||||
e->value = value;
|
||||
e->qapi = qapi;
|
||||
QSLIST_INSERT_HEAD(&qov->stack, e, node);
|
||||
}
|
||||
|
||||
/* Pop a value off the stack of QObjects being built, and return it. */
|
||||
static QObject *qmp_output_pop(QmpOutputVisitor *qov, void *qapi)
|
||||
{
|
||||
QStackEntry *e = QSLIST_FIRST(&qov->stack);
|
||||
QObject *value;
|
||||
|
||||
assert(e);
|
||||
assert(e->qapi == qapi);
|
||||
QSLIST_REMOVE_HEAD(&qov->stack, node);
|
||||
value = e->value;
|
||||
assert(value);
|
||||
g_free(e);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Add @value to the current QObject being built.
|
||||
* If the stack is visiting a dictionary or list, @value is now owned
|
||||
* by that container. Otherwise, @value is now the root. */
|
||||
static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
|
||||
QObject *value)
|
||||
{
|
||||
QStackEntry *e = QSLIST_FIRST(&qov->stack);
|
||||
QObject *cur = e ? e->value : NULL;
|
||||
|
||||
if (!cur) {
|
||||
/* Don't allow reuse of visitor on more than one root */
|
||||
assert(!qov->root);
|
||||
qov->root = value;
|
||||
} else {
|
||||
switch (qobject_type(cur)) {
|
||||
case QTYPE_QDICT:
|
||||
assert(name);
|
||||
qdict_put_obj(qobject_to_qdict(cur), name, value);
|
||||
break;
|
||||
case QTYPE_QLIST:
|
||||
assert(!name);
|
||||
qlist_append_obj(qobject_to_qlist(cur), value);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void qmp_output_start_struct(Visitor *v, const char *name, void **obj,
|
||||
size_t unused, Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
QDict *dict = qdict_new();
|
||||
|
||||
qmp_output_add(qov, name, dict);
|
||||
qmp_output_push(qov, dict, obj);
|
||||
}
|
||||
|
||||
static void qmp_output_end_struct(Visitor *v, void **obj)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
QObject *value = qmp_output_pop(qov, obj);
|
||||
assert(qobject_type(value) == QTYPE_QDICT);
|
||||
}
|
||||
|
||||
static void qmp_output_start_list(Visitor *v, const char *name,
|
||||
GenericList **listp, size_t size,
|
||||
Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
QList *list = qlist_new();
|
||||
|
||||
qmp_output_add(qov, name, list);
|
||||
qmp_output_push(qov, list, listp);
|
||||
}
|
||||
|
||||
static GenericList *qmp_output_next_list(Visitor *v, GenericList *tail,
|
||||
size_t size)
|
||||
{
|
||||
return tail->next;
|
||||
}
|
||||
|
||||
static void qmp_output_end_list(Visitor *v, void **obj)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
QObject *value = qmp_output_pop(qov, obj);
|
||||
assert(qobject_type(value) == QTYPE_QLIST);
|
||||
}
|
||||
|
||||
static void qmp_output_type_int64(Visitor *v, const char *name, int64_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
qmp_output_add(qov, name, qint_from_int(*obj));
|
||||
}
|
||||
|
||||
static void qmp_output_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
/* FIXME: QMP outputs values larger than INT64_MAX as negative */
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
qmp_output_add(qov, name, qint_from_int(*obj));
|
||||
}
|
||||
|
||||
static void qmp_output_type_bool(Visitor *v, const char *name, bool *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
qmp_output_add(qov, name, qbool_from_bool(*obj));
|
||||
}
|
||||
|
||||
static void qmp_output_type_str(Visitor *v, const char *name, char **obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
if (*obj) {
|
||||
qmp_output_add(qov, name, qstring_from_str(*obj));
|
||||
} else {
|
||||
qmp_output_add(qov, name, qstring_from_str(""));
|
||||
}
|
||||
}
|
||||
|
||||
static void qmp_output_type_number(Visitor *v, const char *name, double *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
qmp_output_add(qov, name, qfloat_from_double(*obj));
|
||||
}
|
||||
|
||||
static void qmp_output_type_any(Visitor *v, const char *name, QObject **obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
qobject_incref(*obj);
|
||||
qmp_output_add_obj(qov, name, *obj);
|
||||
}
|
||||
|
||||
static void qmp_output_type_null(Visitor *v, const char *name, Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
qmp_output_add_obj(qov, name, qnull());
|
||||
}
|
||||
|
||||
/* Finish building, and return the root object.
|
||||
* The root object is never null. The caller becomes the object's
|
||||
* owner, and should use qobject_decref() when done with it. */
|
||||
static void qmp_output_complete(Visitor *v, void *opaque)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
|
||||
/* A visit must have occurred, with each start paired with end. */
|
||||
assert(qov->root && QSLIST_EMPTY(&qov->stack));
|
||||
assert(opaque == qov->result);
|
||||
|
||||
qobject_incref(qov->root);
|
||||
*qov->result = qov->root;
|
||||
qov->result = NULL;
|
||||
}
|
||||
|
||||
static void qmp_output_free(Visitor *v)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
QStackEntry *e;
|
||||
|
||||
while (!QSLIST_EMPTY(&qov->stack)) {
|
||||
e = QSLIST_FIRST(&qov->stack);
|
||||
QSLIST_REMOVE_HEAD(&qov->stack, node);
|
||||
g_free(e);
|
||||
}
|
||||
|
||||
qobject_decref(qov->root);
|
||||
g_free(qov);
|
||||
}
|
||||
|
||||
Visitor *qmp_output_visitor_new(QObject **result)
|
||||
{
|
||||
QmpOutputVisitor *v;
|
||||
|
||||
v = g_malloc0(sizeof(*v));
|
||||
|
||||
v->visitor.type = VISITOR_OUTPUT;
|
||||
v->visitor.start_struct = qmp_output_start_struct;
|
||||
v->visitor.end_struct = qmp_output_end_struct;
|
||||
v->visitor.start_list = qmp_output_start_list;
|
||||
v->visitor.next_list = qmp_output_next_list;
|
||||
v->visitor.end_list = qmp_output_end_list;
|
||||
v->visitor.type_int64 = qmp_output_type_int64;
|
||||
v->visitor.type_uint64 = qmp_output_type_uint64;
|
||||
v->visitor.type_bool = qmp_output_type_bool;
|
||||
v->visitor.type_str = qmp_output_type_str;
|
||||
v->visitor.type_number = qmp_output_type_number;
|
||||
v->visitor.type_any = qmp_output_type_any;
|
||||
v->visitor.type_null = qmp_output_type_null;
|
||||
v->visitor.complete = qmp_output_complete;
|
||||
v->visitor.free = qmp_output_free;
|
||||
|
||||
*result = NULL;
|
||||
v->result = result;
|
||||
|
||||
return &v->visitor;
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu-common.h"
|
||||
|
@ -34,7 +34,7 @@ typedef struct StackObject
|
|||
QSLIST_ENTRY(StackObject) node;
|
||||
} StackObject;
|
||||
|
||||
struct QmpInputVisitor
|
||||
struct QObjectInputVisitor
|
||||
{
|
||||
Visitor visitor;
|
||||
|
||||
|
@ -49,14 +49,14 @@ struct QmpInputVisitor
|
|||
bool strict;
|
||||
};
|
||||
|
||||
static QmpInputVisitor *to_qiv(Visitor *v)
|
||||
static QObjectInputVisitor *to_qiv(Visitor *v)
|
||||
{
|
||||
return container_of(v, QmpInputVisitor, visitor);
|
||||
return container_of(v, QObjectInputVisitor, visitor);
|
||||
}
|
||||
|
||||
static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
|
||||
const char *name,
|
||||
bool consume, Error **errp)
|
||||
static QObject *qobject_input_get_object(QObjectInputVisitor *qiv,
|
||||
const char *name,
|
||||
bool consume, Error **errp)
|
||||
{
|
||||
StackObject *tos;
|
||||
QObject *qobj;
|
||||
|
@ -102,8 +102,9 @@ static void qdict_add_key(const char *key, QObject *obj, void *opaque)
|
|||
g_hash_table_insert(h, (gpointer) key, NULL);
|
||||
}
|
||||
|
||||
static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
|
||||
void *qapi, Error **errp)
|
||||
static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
|
||||
QObject *obj, void *qapi,
|
||||
Error **errp)
|
||||
{
|
||||
GHashTable *h;
|
||||
StackObject *tos = g_new0(StackObject, 1);
|
||||
|
@ -125,9 +126,9 @@ static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
|
|||
}
|
||||
|
||||
|
||||
static void qmp_input_check_struct(Visitor *v, Error **errp)
|
||||
static void qobject_input_check_struct(Visitor *v, Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
StackObject *tos = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
assert(tos && !tos->entry);
|
||||
|
@ -145,7 +146,7 @@ static void qmp_input_check_struct(Visitor *v, Error **errp)
|
|||
}
|
||||
}
|
||||
|
||||
static void qmp_input_stack_object_free(StackObject *tos)
|
||||
static void qobject_input_stack_object_free(StackObject *tos)
|
||||
{
|
||||
if (tos->h) {
|
||||
g_hash_table_unref(tos->h);
|
||||
|
@ -154,21 +155,21 @@ static void qmp_input_stack_object_free(StackObject *tos)
|
|||
g_free(tos);
|
||||
}
|
||||
|
||||
static void qmp_input_pop(Visitor *v, void **obj)
|
||||
static void qobject_input_pop(Visitor *v, void **obj)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
StackObject *tos = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
assert(tos && tos->qapi == obj);
|
||||
QSLIST_REMOVE_HEAD(&qiv->stack, node);
|
||||
qmp_input_stack_object_free(tos);
|
||||
qobject_input_stack_object_free(tos);
|
||||
}
|
||||
|
||||
static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
|
||||
size_t size, Error **errp)
|
||||
static void qobject_input_start_struct(Visitor *v, const char *name, void **obj,
|
||||
size_t size, Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
Error *err = NULL;
|
||||
|
||||
if (obj) {
|
||||
|
@ -183,7 +184,7 @@ static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
|
|||
return;
|
||||
}
|
||||
|
||||
qmp_input_push(qiv, qobj, obj, &err);
|
||||
qobject_input_push(qiv, qobj, obj, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
|
@ -195,11 +196,12 @@ static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
|
|||
}
|
||||
|
||||
|
||||
static void qmp_input_start_list(Visitor *v, const char *name,
|
||||
GenericList **list, size_t size, Error **errp)
|
||||
static void qobject_input_start_list(Visitor *v, const char *name,
|
||||
GenericList **list, size_t size,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
const QListEntry *entry;
|
||||
|
||||
if (!qobj) {
|
||||
|
@ -214,7 +216,7 @@ static void qmp_input_start_list(Visitor *v, const char *name,
|
|||
return;
|
||||
}
|
||||
|
||||
entry = qmp_input_push(qiv, qobj, list, errp);
|
||||
entry = qobject_input_push(qiv, qobj, list, errp);
|
||||
if (list) {
|
||||
if (entry) {
|
||||
*list = g_malloc0(size);
|
||||
|
@ -224,10 +226,10 @@ static void qmp_input_start_list(Visitor *v, const char *name,
|
|||
}
|
||||
}
|
||||
|
||||
static GenericList *qmp_input_next_list(Visitor *v, GenericList *tail,
|
||||
size_t size)
|
||||
static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
|
||||
size_t size)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
StackObject *so = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
if (!so->entry) {
|
||||
|
@ -238,12 +240,12 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList *tail,
|
|||
}
|
||||
|
||||
|
||||
static void qmp_input_start_alternate(Visitor *v, const char *name,
|
||||
GenericAlternate **obj, size_t size,
|
||||
bool promote_int, Error **errp)
|
||||
static void qobject_input_start_alternate(Visitor *v, const char *name,
|
||||
GenericAlternate **obj, size_t size,
|
||||
bool promote_int, Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, false, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
|
||||
|
||||
if (!qobj) {
|
||||
*obj = NULL;
|
||||
|
@ -256,11 +258,11 @@ static void qmp_input_start_alternate(Visitor *v, const char *name,
|
|||
}
|
||||
}
|
||||
|
||||
static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj,
|
||||
Error **errp)
|
||||
static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QInt *qint;
|
||||
|
||||
if (!qobj) {
|
||||
|
@ -276,12 +278,12 @@ static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj,
|
|||
*obj = qint_get_int(qint);
|
||||
}
|
||||
|
||||
static void qmp_input_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
||||
Error **errp)
|
||||
static void qobject_input_type_uint64(Visitor *v, const char *name,
|
||||
uint64_t *obj, Error **errp)
|
||||
{
|
||||
/* FIXME: qobject_to_qint mishandles values over INT64_MAX */
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QInt *qint;
|
||||
|
||||
if (!qobj) {
|
||||
|
@ -297,11 +299,11 @@ static void qmp_input_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
|||
*obj = qint_get_int(qint);
|
||||
}
|
||||
|
||||
static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj,
|
||||
Error **errp)
|
||||
static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QBool *qbool;
|
||||
|
||||
if (!qobj) {
|
||||
|
@ -317,11 +319,11 @@ static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj,
|
|||
*obj = qbool_get_bool(qbool);
|
||||
}
|
||||
|
||||
static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
|
||||
Error **errp)
|
||||
static void qobject_input_type_str(Visitor *v, const char *name, char **obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QString *qstr;
|
||||
|
||||
*obj = NULL;
|
||||
|
@ -338,11 +340,11 @@ static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
|
|||
*obj = g_strdup(qstring_get_str(qstr));
|
||||
}
|
||||
|
||||
static void qmp_input_type_number(Visitor *v, const char *name, double *obj,
|
||||
Error **errp)
|
||||
static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QInt *qint;
|
||||
QFloat *qfloat;
|
||||
|
||||
|
@ -365,11 +367,11 @@ static void qmp_input_type_number(Visitor *v, const char *name, double *obj,
|
|||
"number");
|
||||
}
|
||||
|
||||
static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj,
|
||||
Error **errp)
|
||||
static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
|
||||
*obj = NULL;
|
||||
if (!qobj) {
|
||||
|
@ -380,10 +382,10 @@ static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj,
|
|||
*obj = qobj;
|
||||
}
|
||||
|
||||
static void qmp_input_type_null(Visitor *v, const char *name, Error **errp)
|
||||
static void qobject_input_type_null(Visitor *v, const char *name, Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
|
||||
if (!qobj) {
|
||||
return;
|
||||
|
@ -395,10 +397,10 @@ static void qmp_input_type_null(Visitor *v, const char *name, Error **errp)
|
|||
}
|
||||
}
|
||||
|
||||
static void qmp_input_optional(Visitor *v, const char *name, bool *present)
|
||||
static void qobject_input_optional(Visitor *v, const char *name, bool *present)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, false, NULL);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, false, NULL);
|
||||
|
||||
if (!qobj) {
|
||||
*present = false;
|
||||
|
@ -408,44 +410,44 @@ static void qmp_input_optional(Visitor *v, const char *name, bool *present)
|
|||
*present = true;
|
||||
}
|
||||
|
||||
static void qmp_input_free(Visitor *v)
|
||||
static void qobject_input_free(Visitor *v)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
while (!QSLIST_EMPTY(&qiv->stack)) {
|
||||
StackObject *tos = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
QSLIST_REMOVE_HEAD(&qiv->stack, node);
|
||||
qmp_input_stack_object_free(tos);
|
||||
qobject_input_stack_object_free(tos);
|
||||
}
|
||||
|
||||
qobject_decref(qiv->root);
|
||||
g_free(qiv);
|
||||
}
|
||||
|
||||
Visitor *qmp_input_visitor_new(QObject *obj, bool strict)
|
||||
Visitor *qobject_input_visitor_new(QObject *obj, bool strict)
|
||||
{
|
||||
QmpInputVisitor *v;
|
||||
QObjectInputVisitor *v;
|
||||
|
||||
assert(obj);
|
||||
v = g_malloc0(sizeof(*v));
|
||||
|
||||
v->visitor.type = VISITOR_INPUT;
|
||||
v->visitor.start_struct = qmp_input_start_struct;
|
||||
v->visitor.check_struct = qmp_input_check_struct;
|
||||
v->visitor.end_struct = qmp_input_pop;
|
||||
v->visitor.start_list = qmp_input_start_list;
|
||||
v->visitor.next_list = qmp_input_next_list;
|
||||
v->visitor.end_list = qmp_input_pop;
|
||||
v->visitor.start_alternate = qmp_input_start_alternate;
|
||||
v->visitor.type_int64 = qmp_input_type_int64;
|
||||
v->visitor.type_uint64 = qmp_input_type_uint64;
|
||||
v->visitor.type_bool = qmp_input_type_bool;
|
||||
v->visitor.type_str = qmp_input_type_str;
|
||||
v->visitor.type_number = qmp_input_type_number;
|
||||
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->visitor.start_struct = qobject_input_start_struct;
|
||||
v->visitor.check_struct = qobject_input_check_struct;
|
||||
v->visitor.end_struct = qobject_input_pop;
|
||||
v->visitor.start_list = qobject_input_start_list;
|
||||
v->visitor.next_list = qobject_input_next_list;
|
||||
v->visitor.end_list = qobject_input_pop;
|
||||
v->visitor.start_alternate = qobject_input_start_alternate;
|
||||
v->visitor.type_int64 = qobject_input_type_int64;
|
||||
v->visitor.type_uint64 = qobject_input_type_uint64;
|
||||
v->visitor.type_bool = qobject_input_type_bool;
|
||||
v->visitor.type_str = qobject_input_type_str;
|
||||
v->visitor.type_number = qobject_input_type_number;
|
||||
v->visitor.type_any = qobject_input_type_any;
|
||||
v->visitor.type_null = qobject_input_type_null;
|
||||
v->visitor.optional = qobject_input_optional;
|
||||
v->visitor.free = qobject_input_free;
|
||||
v->strict = strict;
|
||||
|
||||
v->root = obj;
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Core Definitions for QAPI/QMP Command Registry
|
||||
*
|
||||
* Copyright (C) 2012-2016 Red Hat, Inc.
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
|
||||
typedef struct QStackEntry {
|
||||
QObject *value;
|
||||
void *qapi; /* sanity check that caller uses same pointer */
|
||||
QSLIST_ENTRY(QStackEntry) node;
|
||||
} QStackEntry;
|
||||
|
||||
struct QObjectOutputVisitor {
|
||||
Visitor visitor;
|
||||
QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
|
||||
QObject *root; /* Root of the output visit */
|
||||
QObject **result; /* User's storage location for result */
|
||||
};
|
||||
|
||||
#define qobject_output_add(qov, name, value) \
|
||||
qobject_output_add_obj(qov, name, QOBJECT(value))
|
||||
#define qobject_output_push(qov, value, qapi) \
|
||||
qobject_output_push_obj(qov, QOBJECT(value), qapi)
|
||||
|
||||
static QObjectOutputVisitor *to_qov(Visitor *v)
|
||||
{
|
||||
return container_of(v, QObjectOutputVisitor, visitor);
|
||||
}
|
||||
|
||||
/* Push @value onto the stack of current QObjects being built */
|
||||
static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value,
|
||||
void *qapi)
|
||||
{
|
||||
QStackEntry *e = g_malloc0(sizeof(*e));
|
||||
|
||||
assert(qov->root);
|
||||
assert(value);
|
||||
e->value = value;
|
||||
e->qapi = qapi;
|
||||
QSLIST_INSERT_HEAD(&qov->stack, e, node);
|
||||
}
|
||||
|
||||
/* Pop a value off the stack of QObjects being built, and return it. */
|
||||
static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi)
|
||||
{
|
||||
QStackEntry *e = QSLIST_FIRST(&qov->stack);
|
||||
QObject *value;
|
||||
|
||||
assert(e);
|
||||
assert(e->qapi == qapi);
|
||||
QSLIST_REMOVE_HEAD(&qov->stack, node);
|
||||
value = e->value;
|
||||
assert(value);
|
||||
g_free(e);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Add @value to the current QObject being built.
|
||||
* If the stack is visiting a dictionary or list, @value is now owned
|
||||
* by that container. Otherwise, @value is now the root. */
|
||||
static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name,
|
||||
QObject *value)
|
||||
{
|
||||
QStackEntry *e = QSLIST_FIRST(&qov->stack);
|
||||
QObject *cur = e ? e->value : NULL;
|
||||
|
||||
if (!cur) {
|
||||
/* Don't allow reuse of visitor on more than one root */
|
||||
assert(!qov->root);
|
||||
qov->root = value;
|
||||
} else {
|
||||
switch (qobject_type(cur)) {
|
||||
case QTYPE_QDICT:
|
||||
assert(name);
|
||||
qdict_put_obj(qobject_to_qdict(cur), name, value);
|
||||
break;
|
||||
case QTYPE_QLIST:
|
||||
assert(!name);
|
||||
qlist_append_obj(qobject_to_qlist(cur), value);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void qobject_output_start_struct(Visitor *v, const char *name,
|
||||
void **obj, size_t unused, Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
QDict *dict = qdict_new();
|
||||
|
||||
qobject_output_add(qov, name, dict);
|
||||
qobject_output_push(qov, dict, obj);
|
||||
}
|
||||
|
||||
static void qobject_output_end_struct(Visitor *v, void **obj)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
QObject *value = qobject_output_pop(qov, obj);
|
||||
assert(qobject_type(value) == QTYPE_QDICT);
|
||||
}
|
||||
|
||||
static void qobject_output_start_list(Visitor *v, const char *name,
|
||||
GenericList **listp, size_t size,
|
||||
Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
QList *list = qlist_new();
|
||||
|
||||
qobject_output_add(qov, name, list);
|
||||
qobject_output_push(qov, list, listp);
|
||||
}
|
||||
|
||||
static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail,
|
||||
size_t size)
|
||||
{
|
||||
return tail->next;
|
||||
}
|
||||
|
||||
static void qobject_output_end_list(Visitor *v, void **obj)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
QObject *value = qobject_output_pop(qov, obj);
|
||||
assert(qobject_type(value) == QTYPE_QLIST);
|
||||
}
|
||||
|
||||
static void qobject_output_type_int64(Visitor *v, const char *name,
|
||||
int64_t *obj, Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add(qov, name, qint_from_int(*obj));
|
||||
}
|
||||
|
||||
static void qobject_output_type_uint64(Visitor *v, const char *name,
|
||||
uint64_t *obj, Error **errp)
|
||||
{
|
||||
/* FIXME values larger than INT64_MAX become negative */
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add(qov, name, qint_from_int(*obj));
|
||||
}
|
||||
|
||||
static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add(qov, name, qbool_from_bool(*obj));
|
||||
}
|
||||
|
||||
static void qobject_output_type_str(Visitor *v, const char *name, char **obj,
|
||||
Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
if (*obj) {
|
||||
qobject_output_add(qov, name, qstring_from_str(*obj));
|
||||
} else {
|
||||
qobject_output_add(qov, name, qstring_from_str(""));
|
||||
}
|
||||
}
|
||||
|
||||
static void qobject_output_type_number(Visitor *v, const char *name,
|
||||
double *obj, Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add(qov, name, qfloat_from_double(*obj));
|
||||
}
|
||||
|
||||
static void qobject_output_type_any(Visitor *v, const char *name,
|
||||
QObject **obj, Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_incref(*obj);
|
||||
qobject_output_add_obj(qov, name, *obj);
|
||||
}
|
||||
|
||||
static void qobject_output_type_null(Visitor *v, const char *name, Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add_obj(qov, name, qnull());
|
||||
}
|
||||
|
||||
/* Finish building, and return the root object.
|
||||
* The root object is never null. The caller becomes the object's
|
||||
* owner, and should use qobject_decref() when done with it. */
|
||||
static void qobject_output_complete(Visitor *v, void *opaque)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
|
||||
/* A visit must have occurred, with each start paired with end. */
|
||||
assert(qov->root && QSLIST_EMPTY(&qov->stack));
|
||||
assert(opaque == qov->result);
|
||||
|
||||
qobject_incref(qov->root);
|
||||
*qov->result = qov->root;
|
||||
qov->result = NULL;
|
||||
}
|
||||
|
||||
static void qobject_output_free(Visitor *v)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
QStackEntry *e;
|
||||
|
||||
while (!QSLIST_EMPTY(&qov->stack)) {
|
||||
e = QSLIST_FIRST(&qov->stack);
|
||||
QSLIST_REMOVE_HEAD(&qov->stack, node);
|
||||
g_free(e);
|
||||
}
|
||||
|
||||
qobject_decref(qov->root);
|
||||
g_free(qov);
|
||||
}
|
||||
|
||||
Visitor *qobject_output_visitor_new(QObject **result)
|
||||
{
|
||||
QObjectOutputVisitor *v;
|
||||
|
||||
v = g_malloc0(sizeof(*v));
|
||||
|
||||
v->visitor.type = VISITOR_OUTPUT;
|
||||
v->visitor.start_struct = qobject_output_start_struct;
|
||||
v->visitor.end_struct = qobject_output_end_struct;
|
||||
v->visitor.start_list = qobject_output_start_list;
|
||||
v->visitor.next_list = qobject_output_next_list;
|
||||
v->visitor.end_list = qobject_output_end_list;
|
||||
v->visitor.type_int64 = qobject_output_type_int64;
|
||||
v->visitor.type_uint64 = qobject_output_type_uint64;
|
||||
v->visitor.type_bool = qobject_output_type_bool;
|
||||
v->visitor.type_str = qobject_output_type_str;
|
||||
v->visitor.type_number = qobject_output_type_number;
|
||||
v->visitor.type_any = qobject_output_type_any;
|
||||
v->visitor.type_null = qobject_output_type_null;
|
||||
v->visitor.complete = qobject_output_complete;
|
||||
v->visitor.free = qobject_output_free;
|
||||
|
||||
*result = NULL;
|
||||
v->result = result;
|
||||
|
||||
return &v->visitor;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
# qapi-visit-core.c
|
||||
visit_free(void *v) "v=%p"
|
||||
visit_complete(void *v, void *opaque) "v=%p opaque=%p"
|
||||
|
||||
visit_start_struct(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
|
||||
visit_check_struct(void *v) "v=%p"
|
||||
visit_end_struct(void *v, void *obj) "v=%p obj=%p"
|
||||
|
||||
visit_start_list(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
|
||||
visit_next_list(void *v, void *tail, size_t size) "v=%p tail=%p size=%zu"
|
||||
visit_end_list(void *v, void *obj) "v=%p obj=%p"
|
||||
|
||||
visit_start_alternate(void *v, const char *name, void *obj, size_t size, bool promote_int) "v=%p name=%s obj=%p size=%zu promote_int=%d"
|
||||
visit_end_alternate(void *v, void *obj) "v=%p obj=%p"
|
||||
|
||||
visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p"
|
||||
|
||||
visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_uint8(void *v, const char *name, uint8_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_uint16(void *v, const char *name, uint16_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_uint32(void *v, const char *name, uint32_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_uint64(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_int8(void *v, const char *name, int8_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_int16(void *v, const char *name, int16_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_int32(void *v, const char *name, int32_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_int64(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_size(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_bool(void *v, const char *name, bool *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_str(void *v, const char *name, char **obj) "v=%p name=%s obj=%p"
|
||||
visit_type_number(void *v, const char *name, double *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_any(void *v, const char *name, void *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_null(void *v, const char *name) "v=%p name=%s"
|
|
@ -25,7 +25,7 @@
|
|||
#include "qemu-version.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
@ -500,7 +500,7 @@ static void dump_json_image_check(ImageCheck *check, bool quiet)
|
|||
{
|
||||
QString *str;
|
||||
QObject *obj;
|
||||
Visitor *v = qmp_output_visitor_new(&obj);
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageCheck(v, NULL, &check, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
|
@ -2193,7 +2193,7 @@ static void dump_json_image_info_list(ImageInfoList *list)
|
|||
{
|
||||
QString *str;
|
||||
QObject *obj;
|
||||
Visitor *v = qmp_output_visitor_new(&obj);
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageInfoList(v, NULL, &list, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
|
@ -2209,7 +2209,7 @@ static void dump_json_image_info(ImageInfo *info)
|
|||
{
|
||||
QString *str;
|
||||
QObject *obj;
|
||||
Visitor *v = qmp_output_visitor_new(&obj);
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageInfo(v, NULL, &info, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
|
|
4
qmp.c
4
qmp.c
|
@ -31,7 +31,7 @@
|
|||
#include "qom/qom-qobject.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
|
@ -675,7 +675,7 @@ void qmp_object_add(const char *type, const char *id,
|
|||
pdict = qdict_new();
|
||||
}
|
||||
|
||||
v = qmp_input_visitor_new(QOBJECT(pdict), true);
|
||||
v = qobject_input_visitor_new(QOBJECT(pdict), true);
|
||||
obj = user_creatable_add_type(type, id, pdict, v, errp);
|
||||
visit_free(v);
|
||||
if (obj) {
|
||||
|
|
277
qobject/qdict.c
277
qobject/qdict.c
|
@ -17,6 +17,7 @@
|
|||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
@ -683,6 +684,282 @@ void qdict_array_split(QDict *src, QList **dst)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* qdict_split_flat_key:
|
||||
* @key: the key string to split
|
||||
* @prefix: non-NULL pointer to hold extracted prefix
|
||||
* @suffix: non-NULL pointer to remaining suffix
|
||||
*
|
||||
* Given a flattened key such as 'foo.0.bar', split it into two parts
|
||||
* at the first '.' separator. Allows double dot ('..') to escape the
|
||||
* normal separator.
|
||||
*
|
||||
* e.g.
|
||||
* 'foo.0.bar' -> prefix='foo' and suffix='0.bar'
|
||||
* 'foo..0.bar' -> prefix='foo.0' and suffix='bar'
|
||||
*
|
||||
* The '..' sequence will be unescaped in the returned 'prefix'
|
||||
* string. The 'suffix' string will be left in escaped format, so it
|
||||
* can be fed back into the qdict_split_flat_key() key as the input
|
||||
* later.
|
||||
*
|
||||
* The caller is responsible for freeing the string returned in @prefix
|
||||
* using g_free().
|
||||
*/
|
||||
static void qdict_split_flat_key(const char *key, char **prefix,
|
||||
const char **suffix)
|
||||
{
|
||||
const char *separator;
|
||||
size_t i, j;
|
||||
|
||||
/* Find first '.' separator, but if there is a pair '..'
|
||||
* that acts as an escape, so skip over '..' */
|
||||
separator = NULL;
|
||||
do {
|
||||
if (separator) {
|
||||
separator += 2;
|
||||
} else {
|
||||
separator = key;
|
||||
}
|
||||
separator = strchr(separator, '.');
|
||||
} while (separator && separator[1] == '.');
|
||||
|
||||
if (separator) {
|
||||
*prefix = g_strndup(key, separator - key);
|
||||
*suffix = separator + 1;
|
||||
} else {
|
||||
*prefix = g_strdup(key);
|
||||
*suffix = NULL;
|
||||
}
|
||||
|
||||
/* Unescape the '..' sequence into '.' */
|
||||
for (i = 0, j = 0; (*prefix)[i] != '\0'; i++, j++) {
|
||||
if ((*prefix)[i] == '.') {
|
||||
assert((*prefix)[i + 1] == '.');
|
||||
i++;
|
||||
}
|
||||
(*prefix)[j] = (*prefix)[i];
|
||||
}
|
||||
(*prefix)[j] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* qdict_is_list:
|
||||
* @maybe_list: dict to check if keys represent list elements.
|
||||
*
|
||||
* Determine whether all keys in @maybe_list are valid list elements.
|
||||
* If @maybe_list is non-zero in length and all the keys look like
|
||||
* valid list indexes, this will return 1. If @maybe_list is zero
|
||||
* length or all keys are non-numeric then it will return 0 to indicate
|
||||
* it is a normal qdict. If there is a mix of numeric and non-numeric
|
||||
* keys, or the list indexes are non-contiguous, an error is reported.
|
||||
*
|
||||
* Returns: 1 if a valid list, 0 if a dict, -1 on error
|
||||
*/
|
||||
static int qdict_is_list(QDict *maybe_list, Error **errp)
|
||||
{
|
||||
const QDictEntry *ent;
|
||||
ssize_t len = 0;
|
||||
ssize_t max = -1;
|
||||
int is_list = -1;
|
||||
int64_t val;
|
||||
|
||||
for (ent = qdict_first(maybe_list); ent != NULL;
|
||||
ent = qdict_next(maybe_list, ent)) {
|
||||
|
||||
if (qemu_strtoll(ent->key, NULL, 10, &val) == 0) {
|
||||
if (is_list == -1) {
|
||||
is_list = 1;
|
||||
} else if (!is_list) {
|
||||
error_setg(errp,
|
||||
"Cannot mix list and non-list keys");
|
||||
return -1;
|
||||
}
|
||||
len++;
|
||||
if (val > max) {
|
||||
max = val;
|
||||
}
|
||||
} else {
|
||||
if (is_list == -1) {
|
||||
is_list = 0;
|
||||
} else if (is_list) {
|
||||
error_setg(errp,
|
||||
"Cannot mix list and non-list keys");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_list == -1) {
|
||||
assert(!qdict_size(maybe_list));
|
||||
is_list = 0;
|
||||
}
|
||||
|
||||
/* NB this isn't a perfect check - e.g. it won't catch
|
||||
* a list containing '1', '+1', '01', '3', but that
|
||||
* does not matter - we've still proved that the
|
||||
* input is a list. It is up the caller to do a
|
||||
* stricter check if desired */
|
||||
if (len != (max + 1)) {
|
||||
error_setg(errp, "List indices are not contiguous, "
|
||||
"saw %zd elements but %zd largest index",
|
||||
len, max);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return is_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* qdict_crumple:
|
||||
* @src: the original flat dictionary (only scalar values) to crumple
|
||||
*
|
||||
* Takes a flat dictionary whose keys use '.' separator to indicate
|
||||
* nesting, and values are scalars, and crumples it into a nested
|
||||
* structure.
|
||||
*
|
||||
* To include a literal '.' in a key name, it must be escaped as '..'
|
||||
*
|
||||
* For example, an input of:
|
||||
*
|
||||
* { 'foo.0.bar': 'one', 'foo.0.wizz': '1',
|
||||
* 'foo.1.bar': 'two', 'foo.1.wizz': '2' }
|
||||
*
|
||||
* will result in an output of:
|
||||
*
|
||||
* {
|
||||
* 'foo': [
|
||||
* { 'bar': 'one', 'wizz': '1' },
|
||||
* { 'bar': 'two', 'wizz': '2' }
|
||||
* ],
|
||||
* }
|
||||
*
|
||||
* The following scenarios in the input dict will result in an
|
||||
* error being returned:
|
||||
*
|
||||
* - Any values in @src are non-scalar types
|
||||
* - If keys in @src imply that a particular level is both a
|
||||
* list and a dict. e.g., "foo.0.bar" and "foo.eek.bar".
|
||||
* - If keys in @src imply that a particular level is a list,
|
||||
* but the indices are non-contiguous. e.g. "foo.0.bar" and
|
||||
* "foo.2.bar" without any "foo.1.bar" present.
|
||||
* - If keys in @src represent list indexes, but are not in
|
||||
* the "%zu" format. e.g. "foo.+0.bar"
|
||||
*
|
||||
* Returns: either a QDict or QList for the nested data structure, or NULL
|
||||
* on error
|
||||
*/
|
||||
QObject *qdict_crumple(const QDict *src, Error **errp)
|
||||
{
|
||||
const QDictEntry *ent;
|
||||
QDict *two_level, *multi_level = NULL;
|
||||
QObject *dst = NULL, *child;
|
||||
size_t i;
|
||||
char *prefix = NULL;
|
||||
const char *suffix = NULL;
|
||||
int is_list;
|
||||
|
||||
two_level = qdict_new();
|
||||
|
||||
/* Step 1: split our totally flat dict into a two level dict */
|
||||
for (ent = qdict_first(src); ent != NULL; ent = qdict_next(src, ent)) {
|
||||
if (qobject_type(ent->value) == QTYPE_QDICT ||
|
||||
qobject_type(ent->value) == QTYPE_QLIST) {
|
||||
error_setg(errp, "Value %s is not a scalar",
|
||||
ent->key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
qdict_split_flat_key(ent->key, &prefix, &suffix);
|
||||
|
||||
child = qdict_get(two_level, prefix);
|
||||
if (suffix) {
|
||||
if (child) {
|
||||
if (qobject_type(child) != QTYPE_QDICT) {
|
||||
error_setg(errp, "Key %s prefix is already set as a scalar",
|
||||
prefix);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
child = QOBJECT(qdict_new());
|
||||
qdict_put_obj(two_level, prefix, child);
|
||||
}
|
||||
qobject_incref(ent->value);
|
||||
qdict_put_obj(qobject_to_qdict(child), suffix, ent->value);
|
||||
} else {
|
||||
if (child) {
|
||||
error_setg(errp, "Key %s prefix is already set as a dict",
|
||||
prefix);
|
||||
goto error;
|
||||
}
|
||||
qobject_incref(ent->value);
|
||||
qdict_put_obj(two_level, prefix, ent->value);
|
||||
}
|
||||
|
||||
g_free(prefix);
|
||||
prefix = NULL;
|
||||
}
|
||||
|
||||
/* Step 2: optionally process the two level dict recursively
|
||||
* into a multi-level dict */
|
||||
multi_level = qdict_new();
|
||||
for (ent = qdict_first(two_level); ent != NULL;
|
||||
ent = qdict_next(two_level, ent)) {
|
||||
|
||||
if (qobject_type(ent->value) == QTYPE_QDICT) {
|
||||
child = qdict_crumple(qobject_to_qdict(ent->value), errp);
|
||||
if (!child) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
qdict_put_obj(multi_level, ent->key, child);
|
||||
} else {
|
||||
qobject_incref(ent->value);
|
||||
qdict_put_obj(multi_level, ent->key, ent->value);
|
||||
}
|
||||
}
|
||||
QDECREF(two_level);
|
||||
two_level = NULL;
|
||||
|
||||
/* Step 3: detect if we need to turn our dict into list */
|
||||
is_list = qdict_is_list(multi_level, errp);
|
||||
if (is_list < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (is_list) {
|
||||
dst = QOBJECT(qlist_new());
|
||||
|
||||
for (i = 0; i < qdict_size(multi_level); i++) {
|
||||
char *key = g_strdup_printf("%zu", i);
|
||||
|
||||
child = qdict_get(multi_level, key);
|
||||
g_free(key);
|
||||
|
||||
if (!child) {
|
||||
error_setg(errp, "Missing list index %zu", i);
|
||||
goto error;
|
||||
}
|
||||
|
||||
qobject_incref(child);
|
||||
qlist_append_obj(qobject_to_qlist(dst), child);
|
||||
}
|
||||
QDECREF(multi_level);
|
||||
multi_level = NULL;
|
||||
} else {
|
||||
dst = QOBJECT(multi_level);
|
||||
}
|
||||
|
||||
return dst;
|
||||
|
||||
error:
|
||||
g_free(prefix);
|
||||
QDECREF(multi_level);
|
||||
QDECREF(two_level);
|
||||
qobject_decref(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* qdict_array_entries(): Returns the number of direct array entries if the
|
||||
* sub-QDict of src specified by the prefix in subqdict (or src itself for
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "qom/object_interfaces.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
|
||||
void user_creatable_complete(Object *obj, Error **errp)
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
#include "qom/object.h"
|
||||
#include "qom/qom-qobject.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
|
||||
void object_property_set_qobject(Object *obj, QObject *value,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
Visitor *v;
|
||||
/* TODO: Should we reject, rather than ignore, excess input? */
|
||||
v = qmp_input_visitor_new(value, false);
|
||||
v = qobject_input_visitor_new(value, false);
|
||||
object_property_set(obj, v, name, errp);
|
||||
visit_free(v);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ QObject *object_property_get_qobject(Object *obj, const char *name,
|
|||
Error *local_err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = qmp_output_visitor_new(&ret);
|
||||
v = qobject_output_visitor_new(&ret);
|
||||
object_property_get(obj, v, name, &local_err);
|
||||
if (!local_err) {
|
||||
visit_complete(v, &ret);
|
||||
|
|
|
@ -68,7 +68,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out,
|
|||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = qmp_output_visitor_new(ret_out);
|
||||
v = qobject_output_visitor_new(ret_out);
|
||||
visit_type_%(c_name)s(v, "unused", &ret_in, &err);
|
||||
if (!err) {
|
||||
visit_complete(v, ret_out);
|
||||
|
@ -130,7 +130,7 @@ def gen_marshal(name, arg_type, boxed, ret_type):
|
|||
push_indent()
|
||||
|
||||
ret += mcgen('''
|
||||
v = qmp_input_visitor_new(QOBJECT(args), true);
|
||||
v = qobject_input_visitor_new(QOBJECT(args), true);
|
||||
visit_start_struct(v, NULL, NULL, 0, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
|
@ -293,8 +293,8 @@ fdef.write(mcgen('''
|
|||
#include "qapi/qmp/types.h"
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/dealloc-visitor.h"
|
||||
#include "%(prefix)sqapi-types.h"
|
||||
#include "%(prefix)sqapi-visit.h"
|
||||
|
|
|
@ -98,7 +98,7 @@ def gen_event_send(name, arg_type, boxed):
|
|||
|
||||
if arg_type and not arg_type.is_empty():
|
||||
ret += mcgen('''
|
||||
v = qmp_output_visitor_new(&obj);
|
||||
v = qobject_output_visitor_new(&obj);
|
||||
''')
|
||||
if not arg_type.is_implicit():
|
||||
ret += mcgen('''
|
||||
|
@ -209,7 +209,7 @@ fdef.write(mcgen('''
|
|||
#include "qemu-common.h"
|
||||
#include "%(prefix)sqapi-event.h"
|
||||
#include "%(prefix)sqapi-visit.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/qmp-event.h"
|
||||
|
||||
''',
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "qapi/visitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "sysemu/arch_init.h"
|
||||
|
@ -345,7 +345,7 @@ static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
|
|||
}
|
||||
|
||||
if (qdict) {
|
||||
visitor = qmp_input_visitor_new(info->props, true);
|
||||
visitor = qobject_input_visitor_new(info->props, true);
|
||||
visit_start_struct(visitor, NULL, NULL, 0, errp);
|
||||
if (*errp) {
|
||||
object_unref(obj);
|
||||
|
|
|
@ -59,11 +59,11 @@ test-qht-par
|
|||
test-qmp-commands
|
||||
test-qmp-commands.h
|
||||
test-qmp-event
|
||||
test-qmp-input-strict
|
||||
test-qmp-input-visitor
|
||||
test-qobject-input-strict
|
||||
test-qobject-input-visitor
|
||||
test-qmp-introspect.[ch]
|
||||
test-qmp-marshal.c
|
||||
test-qmp-output-visitor
|
||||
test-qobject-output-visitor
|
||||
test-rcu-list
|
||||
test-replication
|
||||
test-rfifolock
|
||||
|
|
|
@ -22,13 +22,13 @@ check-unit-y += tests/check-qnull$(EXESUF)
|
|||
gcov-files-check-qnull-y = qobject/qnull.c
|
||||
check-unit-y += tests/check-qjson$(EXESUF)
|
||||
gcov-files-check-qjson-y = qobject/qjson.c
|
||||
check-unit-y += tests/test-qmp-output-visitor$(EXESUF)
|
||||
gcov-files-test-qmp-output-visitor-y = qapi/qmp-output-visitor.c
|
||||
check-unit-y += tests/test-qobject-output-visitor$(EXESUF)
|
||||
gcov-files-test-qobject-output-visitor-y = qapi/qobject-output-visitor.c
|
||||
check-unit-y += tests/test-clone-visitor$(EXESUF)
|
||||
gcov-files-test-clone-visitor-y = qapi/qapi-clone-visitor.c
|
||||
check-unit-y += tests/test-qmp-input-visitor$(EXESUF)
|
||||
gcov-files-test-qmp-input-visitor-y = qapi/qmp-input-visitor.c
|
||||
check-unit-y += tests/test-qmp-input-strict$(EXESUF)
|
||||
check-unit-y += tests/test-qobject-input-visitor$(EXESUF)
|
||||
gcov-files-test-qobject-input-visitor-y = qapi/qobject-input-visitor.c
|
||||
check-unit-y += tests/test-qobject-input-strict$(EXESUF)
|
||||
check-unit-y += tests/test-qmp-commands$(EXESUF)
|
||||
gcov-files-test-qmp-commands-y = qapi/qmp-dispatch.c
|
||||
check-unit-y += tests/test-string-input-visitor$(EXESUF)
|
||||
|
@ -452,9 +452,9 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
|
|||
tests/check-qlist.o tests/check-qfloat.o tests/check-qnull.o \
|
||||
tests/check-qjson.o \
|
||||
tests/test-coroutine.o tests/test-string-output-visitor.o \
|
||||
tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
|
||||
tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
|
||||
tests/test-clone-visitor.o \
|
||||
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
|
||||
tests/test-qobject-input-visitor.o tests/test-qobject-input-strict.o \
|
||||
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
|
||||
tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
|
||||
tests/test-opts-visitor.o tests/test-qmp-event.o \
|
||||
|
@ -558,10 +558,10 @@ $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-int
|
|||
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
|
||||
tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qobject-input-strict$(EXESUF): tests/test-qobject-input-strict.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
|
||||
tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
|
||||
tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/*
|
||||
|
@ -412,7 +413,6 @@ static void qdict_array_split_test(void)
|
|||
|
||||
QDECREF(test_dict);
|
||||
|
||||
|
||||
/*
|
||||
* Test the split of
|
||||
*
|
||||
|
@ -518,7 +518,6 @@ static void qdict_join_test(void)
|
|||
dict1 = qdict_new();
|
||||
dict2 = qdict_new();
|
||||
|
||||
|
||||
/* Test everything once without overwrite and once with */
|
||||
do
|
||||
{
|
||||
|
@ -528,7 +527,6 @@ static void qdict_join_test(void)
|
|||
g_assert(qdict_size(dict1) == 0);
|
||||
g_assert(qdict_size(dict2) == 0);
|
||||
|
||||
|
||||
/* First iteration: Test movement */
|
||||
/* Second iteration: Test empty source and non-empty destination */
|
||||
qdict_put(dict2, "foo", qint_from_int(42));
|
||||
|
@ -542,7 +540,6 @@ static void qdict_join_test(void)
|
|||
g_assert(qdict_get_int(dict1, "foo") == 42);
|
||||
}
|
||||
|
||||
|
||||
/* Test non-empty source and destination without conflict */
|
||||
qdict_put(dict2, "bar", qint_from_int(23));
|
||||
|
||||
|
@ -554,7 +551,6 @@ static void qdict_join_test(void)
|
|||
g_assert(qdict_get_int(dict1, "foo") == 42);
|
||||
g_assert(qdict_get_int(dict1, "bar") == 23);
|
||||
|
||||
|
||||
/* Test conflict */
|
||||
qdict_put(dict2, "foo", qint_from_int(84));
|
||||
|
||||
|
@ -570,7 +566,6 @@ static void qdict_join_test(void)
|
|||
g_assert(qdict_get_int(dict2, "foo") == 84);
|
||||
}
|
||||
|
||||
|
||||
/* Check the references */
|
||||
g_assert(qdict_get(dict1, "foo")->refcnt == 1);
|
||||
g_assert(qdict_get(dict1, "bar")->refcnt == 1);
|
||||
|
@ -579,7 +574,6 @@ static void qdict_join_test(void)
|
|||
g_assert(qdict_get(dict2, "foo")->refcnt == 1);
|
||||
}
|
||||
|
||||
|
||||
/* Clean up */
|
||||
qdict_del(dict1, "foo");
|
||||
qdict_del(dict1, "bar");
|
||||
|
@ -590,11 +584,152 @@ static void qdict_join_test(void)
|
|||
}
|
||||
while (overwrite ^= true);
|
||||
|
||||
|
||||
QDECREF(dict1);
|
||||
QDECREF(dict2);
|
||||
}
|
||||
|
||||
static void qdict_crumple_test_recursive(void)
|
||||
{
|
||||
QDict *src, *dst, *rule, *vnc, *acl, *listen;
|
||||
QObject *child, *res;
|
||||
QList *rules;
|
||||
|
||||
src = qdict_new();
|
||||
qdict_put(src, "vnc.listen.addr", qstring_from_str("127.0.0.1"));
|
||||
qdict_put(src, "vnc.listen.port", qstring_from_str("5901"));
|
||||
qdict_put(src, "vnc.acl.rules.0.match", qstring_from_str("fred"));
|
||||
qdict_put(src, "vnc.acl.rules.0.policy", qstring_from_str("allow"));
|
||||
qdict_put(src, "vnc.acl.rules.1.match", qstring_from_str("bob"));
|
||||
qdict_put(src, "vnc.acl.rules.1.policy", qstring_from_str("deny"));
|
||||
qdict_put(src, "vnc.acl.default", qstring_from_str("deny"));
|
||||
qdict_put(src, "vnc.acl..name", qstring_from_str("acl0"));
|
||||
qdict_put(src, "vnc.acl.rule..name", qstring_from_str("acl0"));
|
||||
|
||||
res = qdict_crumple(src, &error_abort);
|
||||
|
||||
g_assert_cmpint(qobject_type(res), ==, QTYPE_QDICT);
|
||||
|
||||
dst = qobject_to_qdict(res);
|
||||
|
||||
g_assert_cmpint(qdict_size(dst), ==, 1);
|
||||
|
||||
child = qdict_get(dst, "vnc");
|
||||
g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
|
||||
vnc = qobject_to_qdict(child);
|
||||
|
||||
child = qdict_get(vnc, "listen");
|
||||
g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
|
||||
listen = qobject_to_qdict(child);
|
||||
g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr"));
|
||||
g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port"));
|
||||
|
||||
child = qdict_get(vnc, "acl");
|
||||
g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
|
||||
acl = qobject_to_qdict(child);
|
||||
|
||||
child = qdict_get(acl, "rules");
|
||||
g_assert_cmpint(qobject_type(child), ==, QTYPE_QLIST);
|
||||
rules = qobject_to_qlist(child);
|
||||
g_assert_cmpint(qlist_size(rules), ==, 2);
|
||||
|
||||
rule = qobject_to_qdict(qlist_pop(rules));
|
||||
g_assert_cmpint(qdict_size(rule), ==, 2);
|
||||
g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
|
||||
g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
|
||||
QDECREF(rule);
|
||||
|
||||
rule = qobject_to_qdict(qlist_pop(rules));
|
||||
g_assert_cmpint(qdict_size(rule), ==, 2);
|
||||
g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
|
||||
g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy"));
|
||||
QDECREF(rule);
|
||||
|
||||
/* With recursive crumpling, we should see all names unescaped */
|
||||
g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name"));
|
||||
child = qdict_get(vnc, "acl");
|
||||
g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
|
||||
acl = qdict_get_qdict(vnc, "acl");
|
||||
g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name"));
|
||||
|
||||
QDECREF(src);
|
||||
QDECREF(dst);
|
||||
}
|
||||
|
||||
static void qdict_crumple_test_empty(void)
|
||||
{
|
||||
QDict *src, *dst;
|
||||
|
||||
src = qdict_new();
|
||||
|
||||
dst = (QDict *)qdict_crumple(src, &error_abort);
|
||||
|
||||
g_assert_cmpint(qdict_size(dst), ==, 0);
|
||||
|
||||
QDECREF(src);
|
||||
QDECREF(dst);
|
||||
}
|
||||
|
||||
static void qdict_crumple_test_bad_inputs(void)
|
||||
{
|
||||
QDict *src;
|
||||
Error *error = NULL;
|
||||
|
||||
src = qdict_new();
|
||||
/* rule.0 can't be both a string and a dict */
|
||||
qdict_put(src, "rule.0", qstring_from_str("fred"));
|
||||
qdict_put(src, "rule.0.policy", qstring_from_str("allow"));
|
||||
|
||||
g_assert(qdict_crumple(src, &error) == NULL);
|
||||
g_assert(error != NULL);
|
||||
error_free(error);
|
||||
error = NULL;
|
||||
QDECREF(src);
|
||||
|
||||
src = qdict_new();
|
||||
/* rule can't be both a list and a dict */
|
||||
qdict_put(src, "rule.0", qstring_from_str("fred"));
|
||||
qdict_put(src, "rule.a", qstring_from_str("allow"));
|
||||
|
||||
g_assert(qdict_crumple(src, &error) == NULL);
|
||||
g_assert(error != NULL);
|
||||
error_free(error);
|
||||
error = NULL;
|
||||
QDECREF(src);
|
||||
|
||||
src = qdict_new();
|
||||
/* The input should be flat, ie no dicts or lists */
|
||||
qdict_put(src, "rule.a", qdict_new());
|
||||
qdict_put(src, "rule.b", qstring_from_str("allow"));
|
||||
|
||||
g_assert(qdict_crumple(src, &error) == NULL);
|
||||
g_assert(error != NULL);
|
||||
error_free(error);
|
||||
error = NULL;
|
||||
QDECREF(src);
|
||||
|
||||
src = qdict_new();
|
||||
/* List indexes must not have gaps */
|
||||
qdict_put(src, "rule.0", qstring_from_str("deny"));
|
||||
qdict_put(src, "rule.3", qstring_from_str("allow"));
|
||||
|
||||
g_assert(qdict_crumple(src, &error) == NULL);
|
||||
g_assert(error != NULL);
|
||||
error_free(error);
|
||||
error = NULL;
|
||||
QDECREF(src);
|
||||
|
||||
src = qdict_new();
|
||||
/* List indexes must be in %zu format */
|
||||
qdict_put(src, "rule.0", qstring_from_str("deny"));
|
||||
qdict_put(src, "rule.+1", qstring_from_str("allow"));
|
||||
|
||||
g_assert(qdict_crumple(src, &error) == NULL);
|
||||
g_assert(error != NULL);
|
||||
error_free(error);
|
||||
error = NULL;
|
||||
QDECREF(src);
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors test-cases
|
||||
*/
|
||||
|
@ -742,6 +877,13 @@ int main(int argc, char **argv)
|
|||
g_test_add_func("/errors/put_exists", qdict_put_exists_test);
|
||||
g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
|
||||
|
||||
g_test_add_func("/public/crumple/recursive",
|
||||
qdict_crumple_test_recursive);
|
||||
g_test_add_func("/public/crumple/empty",
|
||||
qdict_crumple_test_empty);
|
||||
g_test_add_func("/public/crumple/bad_inputs",
|
||||
qdict_crumple_test_bad_inputs);
|
||||
|
||||
/* The Big one */
|
||||
if (g_test_slow()) {
|
||||
g_test_add_func("/stress/test", qdict_stress_test);
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
/*
|
||||
|
@ -47,12 +47,12 @@ static void qnull_visit_test(void)
|
|||
|
||||
g_assert(qnull_.refcnt == 1);
|
||||
obj = qnull();
|
||||
v = qmp_input_visitor_new(obj, true);
|
||||
v = qobject_input_visitor_new(obj, true);
|
||||
qobject_decref(obj);
|
||||
visit_type_null(v, NULL, &error_abort);
|
||||
visit_free(v);
|
||||
|
||||
v = qmp_output_visitor_new(&obj);
|
||||
v = qobject_output_visitor_new(&obj);
|
||||
visit_type_null(v, NULL, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
g_assert(obj == &qnull_);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "test-qmp-commands.h"
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "tests/test-qapi-types.h"
|
||||
#include "tests/test-qapi-visit.h"
|
||||
|
||||
|
@ -244,7 +244,7 @@ static void test_dealloc_partial(void)
|
|||
ud2_dict = qdict_new();
|
||||
qdict_put_obj(ud2_dict, "string0", QOBJECT(qstring_from_str(text)));
|
||||
|
||||
v = qmp_input_visitor_new(QOBJECT(ud2_dict), true);
|
||||
v = qobject_input_visitor_new(QOBJECT(ud2_dict), true);
|
||||
visit_type_UserDefTwo(v, NULL, &ud2, &err);
|
||||
visit_free(v);
|
||||
QDECREF(ud2_dict);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* QMP Input Visitor unit-tests (strict mode).
|
||||
* QObject Input Visitor unit-tests (strict mode).
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2015 Red Hat Inc.
|
||||
*
|
||||
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
|
@ -53,7 +53,7 @@ static Visitor *validate_test_init_internal(TestInputVisitorData *data,
|
|||
data->obj = qobject_from_jsonv(json_string, ap);
|
||||
g_assert(data->obj);
|
||||
|
||||
data->qiv = qmp_input_visitor_new(data->obj, true);
|
||||
data->qiv = qobject_input_visitor_new(data->obj, true);
|
||||
g_assert(data->qiv);
|
||||
return data->qiv;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* QMP Input Visitor unit-tests.
|
||||
* QObject Input Visitor unit-tests.
|
||||
*
|
||||
* Copyright (C) 2011-2016 Red Hat Inc.
|
||||
*
|
||||
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
|
@ -49,7 +49,7 @@ static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
|
|||
data->obj = qobject_from_jsonv(json_string, ap);
|
||||
g_assert(data->obj);
|
||||
|
||||
data->qiv = qmp_input_visitor_new(data->obj, false);
|
||||
data->qiv = qobject_input_visitor_new(data->obj, false);
|
||||
g_assert(data->qiv);
|
||||
return data->qiv;
|
||||
}
|
||||
|
@ -747,10 +747,11 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
|
|||
}
|
||||
|
||||
static void input_visitor_test_add(const char *testpath,
|
||||
TestInputVisitorData *data,
|
||||
void (*test_func)(TestInputVisitorData *data, const void *user_data))
|
||||
const void *user_data,
|
||||
void (*test_func)(TestInputVisitorData *data,
|
||||
const void *user_data))
|
||||
{
|
||||
g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
|
||||
g_test_add(testpath, TestInputVisitorData, user_data, NULL, test_func,
|
||||
visitor_input_teardown);
|
||||
}
|
||||
|
||||
|
@ -833,77 +834,64 @@ static void test_visitor_in_wrong_type(TestInputVisitorData *data,
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestInputVisitorData in_visitor_data;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
input_visitor_test_add("/visitor/input/int",
|
||||
&in_visitor_data, test_visitor_in_int);
|
||||
NULL, test_visitor_in_int);
|
||||
input_visitor_test_add("/visitor/input/int_overflow",
|
||||
&in_visitor_data, test_visitor_in_int_overflow);
|
||||
NULL, test_visitor_in_int_overflow);
|
||||
input_visitor_test_add("/visitor/input/bool",
|
||||
&in_visitor_data, test_visitor_in_bool);
|
||||
NULL, test_visitor_in_bool);
|
||||
input_visitor_test_add("/visitor/input/number",
|
||||
&in_visitor_data, test_visitor_in_number);
|
||||
NULL, test_visitor_in_number);
|
||||
input_visitor_test_add("/visitor/input/string",
|
||||
&in_visitor_data, test_visitor_in_string);
|
||||
NULL, test_visitor_in_string);
|
||||
input_visitor_test_add("/visitor/input/enum",
|
||||
&in_visitor_data, test_visitor_in_enum);
|
||||
NULL, test_visitor_in_enum);
|
||||
input_visitor_test_add("/visitor/input/struct",
|
||||
&in_visitor_data, test_visitor_in_struct);
|
||||
NULL, test_visitor_in_struct);
|
||||
input_visitor_test_add("/visitor/input/struct-nested",
|
||||
&in_visitor_data, test_visitor_in_struct_nested);
|
||||
NULL, test_visitor_in_struct_nested);
|
||||
input_visitor_test_add("/visitor/input/list",
|
||||
&in_visitor_data, test_visitor_in_list);
|
||||
NULL, test_visitor_in_list);
|
||||
input_visitor_test_add("/visitor/input/any",
|
||||
&in_visitor_data, test_visitor_in_any);
|
||||
NULL, test_visitor_in_any);
|
||||
input_visitor_test_add("/visitor/input/null",
|
||||
&in_visitor_data, test_visitor_in_null);
|
||||
NULL, test_visitor_in_null);
|
||||
input_visitor_test_add("/visitor/input/union-flat",
|
||||
&in_visitor_data, test_visitor_in_union_flat);
|
||||
NULL, test_visitor_in_union_flat);
|
||||
input_visitor_test_add("/visitor/input/alternate",
|
||||
&in_visitor_data, test_visitor_in_alternate);
|
||||
NULL, test_visitor_in_alternate);
|
||||
input_visitor_test_add("/visitor/input/errors",
|
||||
&in_visitor_data, test_visitor_in_errors);
|
||||
NULL, test_visitor_in_errors);
|
||||
input_visitor_test_add("/visitor/input/wrong-type",
|
||||
&in_visitor_data, test_visitor_in_wrong_type);
|
||||
NULL, test_visitor_in_wrong_type);
|
||||
input_visitor_test_add("/visitor/input/alternate-number",
|
||||
&in_visitor_data, test_visitor_in_alternate_number);
|
||||
NULL, test_visitor_in_alternate_number);
|
||||
input_visitor_test_add("/visitor/input/native_list/int",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int);
|
||||
NULL, test_visitor_in_native_list_int);
|
||||
input_visitor_test_add("/visitor/input/native_list/int8",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int8);
|
||||
NULL, test_visitor_in_native_list_int8);
|
||||
input_visitor_test_add("/visitor/input/native_list/int16",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int16);
|
||||
NULL, test_visitor_in_native_list_int16);
|
||||
input_visitor_test_add("/visitor/input/native_list/int32",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int32);
|
||||
NULL, test_visitor_in_native_list_int32);
|
||||
input_visitor_test_add("/visitor/input/native_list/int64",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int64);
|
||||
NULL, test_visitor_in_native_list_int64);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint8",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_uint8);
|
||||
NULL, test_visitor_in_native_list_uint8);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint16",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_uint16);
|
||||
NULL, test_visitor_in_native_list_uint16);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint32",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_uint32);
|
||||
NULL, test_visitor_in_native_list_uint32);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint64",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_uint64);
|
||||
NULL, test_visitor_in_native_list_uint64);
|
||||
input_visitor_test_add("/visitor/input/native_list/bool",
|
||||
&in_visitor_data, test_visitor_in_native_list_bool);
|
||||
NULL, test_visitor_in_native_list_bool);
|
||||
input_visitor_test_add("/visitor/input/native_list/str",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_string);
|
||||
NULL, test_visitor_in_native_list_string);
|
||||
input_visitor_test_add("/visitor/input/native_list/number",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_number);
|
||||
NULL, test_visitor_in_native_list_number);
|
||||
|
||||
g_test_run();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* QMP Output Visitor unit-tests.
|
||||
* QObject Output Visitor unit-tests.
|
||||
*
|
||||
* Copyright (C) 2011-2016 Red Hat Inc.
|
||||
*
|
||||
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
|
@ -28,7 +28,7 @@ typedef struct TestOutputVisitorData {
|
|||
static void visitor_output_setup(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
data->ov = qmp_output_visitor_new(&data->obj);
|
||||
data->ov = qobject_output_visitor_new(&data->obj);
|
||||
g_assert(data->ov);
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2012 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-input-visitor)
|
||||
* Paolo Bonzini <pbonzini@redhat.com> (based on test-qobject-input-visitor)
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2012 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-output-visitor)
|
||||
* Paolo Bonzini <pbonzini@redhat.com> (based on test-qobject-output-visitor)
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "qapi/string-output-visitor.h"
|
||||
#include "qapi-types.h"
|
||||
|
@ -1022,7 +1022,7 @@ static void qmp_serialize(void *native_in, void **datap,
|
|||
{
|
||||
QmpSerializeData *d = g_malloc0(sizeof(*d));
|
||||
|
||||
d->qov = qmp_output_visitor_new(&d->obj);
|
||||
d->qov = qobject_output_visitor_new(&d->obj);
|
||||
visit(d->qov, &native_in, errp);
|
||||
*datap = d;
|
||||
}
|
||||
|
@ -1040,7 +1040,7 @@ static void qmp_deserialize(void **native_out, void *datap,
|
|||
obj = qobject_from_json(qstring_get_str(output_json));
|
||||
|
||||
QDECREF(output_json);
|
||||
d->qiv = qmp_input_visitor_new(obj, true);
|
||||
d->qiv = qobject_input_visitor_new(obj, true);
|
||||
qobject_decref(obj_orig);
|
||||
qobject_decref(obj);
|
||||
visit(d->qiv, native_out, errp);
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "qapi/error.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue