diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index c4af3e042f..6a1ddfbd9a 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -22,22 +22,23 @@ struct Visitor size_t size, Error **errp); void (*end_struct)(Visitor *v, Error **errp); - void (*start_implicit_struct)(Visitor *v, void **obj, size_t size, - Error **errp); - /* May be NULL */ - void (*end_implicit_struct)(Visitor *v); - void (*start_list)(Visitor *v, const char *name, Error **errp); /* Must be set */ GenericList *(*next_list)(Visitor *v, GenericList **list, size_t size); /* Must be set */ void (*end_list)(Visitor *v); + /* Optional, needed for input and dealloc visitors. */ + void (*start_alternate)(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + bool promote_int, Error **errp); + + /* Optional, needed for dealloc visitor. */ + void (*end_alternate)(Visitor *v); + + /* Must be set. */ void (*type_enum)(Visitor *v, const char *name, int *obj, const char *const strings[], Error **errp); - /* May be NULL; only needed for input visitors. */ - void (*get_next_type)(Visitor *v, const char *name, QType *type, - bool promote_int, Error **errp); /* Must be set. */ void (*type_int64)(Visitor *v, const char *name, int64_t *obj, diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index a6678b16ef..83cad74c88 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -27,17 +27,52 @@ typedef struct GenericList { char padding[]; } GenericList; +/* This struct is layout-compatible with all Alternate types + * created by the qapi generator. */ +typedef struct GenericAlternate { + QType type; + char padding[]; +} GenericAlternate; + void visit_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp); void visit_end_struct(Visitor *v, Error **errp); -void visit_start_implicit_struct(Visitor *v, void **obj, size_t size, - Error **errp); -void visit_end_implicit_struct(Visitor *v); void visit_start_list(Visitor *v, const char *name, Error **errp); GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size); void visit_end_list(Visitor *v); +/* + * Start the visit of an alternate @obj with the given @size. + * + * @name specifies the relationship to the containing struct (ignored + * for a top level visit, the name of the key if this alternate is + * part of an object, or NULL if this alternate is part of a list). + * + * @obj must not be NULL. Input visitors will allocate @obj and + * determine the qtype of the next thing to be visited, stored in + * (*@obj)->type. Other visitors will leave @obj unchanged. + * + * If @promote_int, treat integers as QTYPE_FLOAT. + * + * If successful, this must be paired with visit_end_alternate(), even + * if visiting the contents of the alternate fails. + */ +void visit_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + bool promote_int, Error **errp); + +/* + * Finish visiting an alternate type. + * + * Must be called after a successful visit_start_alternate(), even if + * an error occurred in the meantime. + * + * TODO: Should all the visit_end_* interfaces take obj parameter, so + * that dealloc visitor need not track what was passed in visit_start? + */ +void visit_end_alternate(Visitor *v); + /** * Check if an optional member @name of an object needs visiting. * For input visitors, set *@present according to whether the @@ -46,14 +81,6 @@ void visit_end_list(Visitor *v); */ bool visit_optional(Visitor *v, const char *name, bool *present); -/** - * Determine the qtype of the item @name in the current object visit. - * For input visitors, set *@type to the correct qtype of a qapi - * alternate type; for other visitors, leave *@type unchanged. - * If @promote_int, treat integers as QTYPE_FLOAT. - */ -void visit_get_next_type(Visitor *v, const char *name, QType *type, - bool promote_int, Error **errp); void visit_type_enum(Visitor *v, const char *name, int *obj, const char *const strings[], Error **errp); void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c index 4eae555ace..69221794ec 100644 --- a/qapi/qapi-dealloc-visitor.c +++ b/qapi/qapi-dealloc-visitor.c @@ -76,16 +76,15 @@ static void qapi_dealloc_end_struct(Visitor *v, Error **errp) } } -static void qapi_dealloc_start_implicit_struct(Visitor *v, - void **obj, - size_t size, - Error **errp) +static void qapi_dealloc_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + bool promote_int, Error **errp) { QapiDeallocVisitor *qov = to_qov(v); qapi_dealloc_push(qov, obj); } -static void qapi_dealloc_end_implicit_struct(Visitor *v) +static void qapi_dealloc_end_alternate(Visitor *v) { QapiDeallocVisitor *qov = to_qov(v); void **obj = qapi_dealloc_pop(qov); @@ -187,8 +186,8 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void) v->visitor.start_struct = qapi_dealloc_start_struct; v->visitor.end_struct = qapi_dealloc_end_struct; - v->visitor.start_implicit_struct = qapi_dealloc_start_implicit_struct; - v->visitor.end_implicit_struct = qapi_dealloc_end_implicit_struct; + v->visitor.start_alternate = qapi_dealloc_start_alternate; + v->visitor.end_alternate = qapi_dealloc_end_alternate; v->visitor.start_list = qapi_dealloc_start_list; v->visitor.next_list = qapi_dealloc_next_list; v->visitor.end_list = qapi_dealloc_end_list; diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index f7b99807b0..856606b253 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -30,21 +30,6 @@ void visit_end_struct(Visitor *v, Error **errp) v->end_struct(v, errp); } -void visit_start_implicit_struct(Visitor *v, void **obj, size_t size, - Error **errp) -{ - if (v->start_implicit_struct) { - v->start_implicit_struct(v, obj, size, errp); - } -} - -void visit_end_implicit_struct(Visitor *v) -{ - if (v->end_implicit_struct) { - v->end_implicit_struct(v); - } -} - void visit_start_list(Visitor *v, const char *name, Error **errp) { v->start_list(v, name, errp); @@ -61,6 +46,23 @@ void visit_end_list(Visitor *v) v->end_list(v); } +void visit_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + bool promote_int, Error **errp) +{ + assert(obj && size >= sizeof(GenericAlternate)); + if (v->start_alternate) { + v->start_alternate(v, name, obj, size, promote_int, errp); + } +} + +void visit_end_alternate(Visitor *v) +{ + if (v->end_alternate) { + v->end_alternate(v); + } +} + bool visit_optional(Visitor *v, const char *name, bool *present) { if (v->optional) { @@ -69,14 +71,6 @@ bool visit_optional(Visitor *v, const char *name, bool *present) return *present; } -void visit_get_next_type(Visitor *v, const char *name, QType *type, - bool promote_int, Error **errp) -{ - if (v->get_next_type) { - v->get_next_type(v, name, type, promote_int, errp); - } -} - void visit_type_enum(Visitor *v, const char *name, int *obj, const char *const strings[], Error **errp) { diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 26216604cc..e6598327c3 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -143,14 +143,6 @@ static void qmp_input_end_struct(Visitor *v, Error **errp) qmp_input_pop(qiv, errp); } -static void qmp_input_start_implicit_struct(Visitor *v, void **obj, - size_t size, Error **errp) -{ - if (obj) { - *obj = g_malloc0(size); - } -} - static void qmp_input_start_list(Visitor *v, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); @@ -202,19 +194,22 @@ static void qmp_input_end_list(Visitor *v) qmp_input_pop(qiv, &error_abort); } -static void qmp_input_get_next_type(Visitor *v, const char *name, QType *type, - bool promote_int, Error **errp) +static void qmp_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); if (!qobj) { + *obj = NULL; error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null"); return; } - *type = qobject_type(qobj); - if (promote_int && *type == QTYPE_QINT) { - *type = QTYPE_QFLOAT; + *obj = g_malloc0(size); + (*obj)->type = qobject_type(qobj); + if (promote_int && (*obj)->type == QTYPE_QINT) { + (*obj)->type = QTYPE_QFLOAT; } } @@ -345,10 +340,10 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) v->visitor.start_struct = qmp_input_start_struct; v->visitor.end_struct = qmp_input_end_struct; - v->visitor.start_implicit_struct = qmp_input_start_implicit_struct; v->visitor.start_list = qmp_input_start_list; v->visitor.next_list = qmp_input_next_list; v->visitor.end_list = qmp_input_end_list; + v->visitor.start_alternate = qmp_input_start_alternate; v->visitor.type_enum = input_type_enum; v->visitor.type_int64 = qmp_input_type_int64; v->visitor.type_uint64 = qmp_input_type_uint64; @@ -357,7 +352,6 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) v->visitor.type_number = qmp_input_type_number; v->visitor.type_any = qmp_input_type_any; v->visitor.optional = qmp_input_optional; - v->visitor.get_next_type = qmp_input_get_next_type; qmp_input_push(v, obj, NULL); qobject_incref(obj); diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 3a3918f952..2308268a62 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -182,14 +182,11 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error { Error *err = NULL; - visit_start_implicit_struct(v, (void**) obj, sizeof(%(c_name)s), &err); + visit_start_alternate(v, name, (GenericAlternate **)obj, sizeof(**obj), + %(promote_int)s, &err); if (err) { goto out; } - visit_get_next_type(v, name, &(*obj)->type, %(promote_int)s, &err); - if (err) { - goto out_obj; - } switch ((*obj)->type) { ''', c_name=c_name(name), promote_int=promote_int) @@ -227,8 +224,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "%(name)s"); } -out_obj: - visit_end_implicit_struct(v); + visit_end_alternate(v); out: error_propagate(errp, err); }