qapi: Change visit_start_implicit_struct to visit_start_alternate
After recent changes, the only remaining use of visit_start_implicit_struct() is for allocating the space needed when visiting an alternate. Since the term 'implicit struct' is hard to explain, rename the function to its current usage. While at it, we can merge the functionality of visit_get_next_type() into the same function, making it more like visit_start_struct(). Generated code is now slightly smaller: | { | Error *err = NULL; | |- visit_start_implicit_struct(v, (void**) obj, sizeof(BlockdevRef), &err); |+ visit_start_alternate(v, name, (GenericAlternate **)obj, sizeof(**obj), |+ true, &err); | if (err) { | goto out; | } |- visit_get_next_type(v, name, &(*obj)->type, true, &err); |- if (err) { |- goto out_obj; |- } | switch ((*obj)->type) { | case QTYPE_QDICT: | visit_start_struct(v, name, NULL, 0, &err); ... | } |-out_obj: |- visit_end_implicit_struct(v); |+ visit_end_alternate(v); | out: | error_propagate(errp, err); | } Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1455778109-6278-16-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
parent
544a373159
commit
dbf1192262
@ -22,22 +22,23 @@ struct Visitor
|
|||||||
size_t size, Error **errp);
|
size_t size, Error **errp);
|
||||||
void (*end_struct)(Visitor *v, 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);
|
void (*start_list)(Visitor *v, const char *name, Error **errp);
|
||||||
/* Must be set */
|
/* Must be set */
|
||||||
GenericList *(*next_list)(Visitor *v, GenericList **list, size_t size);
|
GenericList *(*next_list)(Visitor *v, GenericList **list, size_t size);
|
||||||
/* Must be set */
|
/* Must be set */
|
||||||
void (*end_list)(Visitor *v);
|
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,
|
void (*type_enum)(Visitor *v, const char *name, int *obj,
|
||||||
const char *const strings[], Error **errp);
|
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. */
|
/* Must be set. */
|
||||||
void (*type_int64)(Visitor *v, const char *name, int64_t *obj,
|
void (*type_int64)(Visitor *v, const char *name, int64_t *obj,
|
||||||
|
@ -27,17 +27,52 @@ typedef struct GenericList {
|
|||||||
char padding[];
|
char padding[];
|
||||||
} GenericList;
|
} 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,
|
void visit_start_struct(Visitor *v, const char *name, void **obj,
|
||||||
size_t size, Error **errp);
|
size_t size, Error **errp);
|
||||||
void visit_end_struct(Visitor *v, 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);
|
void visit_start_list(Visitor *v, const char *name, Error **errp);
|
||||||
GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size);
|
GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size);
|
||||||
void visit_end_list(Visitor *v);
|
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.
|
* Check if an optional member @name of an object needs visiting.
|
||||||
* For input visitors, set *@present according to whether the
|
* 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);
|
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,
|
void visit_type_enum(Visitor *v, const char *name, int *obj,
|
||||||
const char *const strings[], Error **errp);
|
const char *const strings[], Error **errp);
|
||||||
void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp);
|
void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp);
|
||||||
|
@ -76,16 +76,15 @@ static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qapi_dealloc_start_implicit_struct(Visitor *v,
|
static void qapi_dealloc_start_alternate(Visitor *v, const char *name,
|
||||||
void **obj,
|
GenericAlternate **obj, size_t size,
|
||||||
size_t size,
|
bool promote_int, Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
QapiDeallocVisitor *qov = to_qov(v);
|
QapiDeallocVisitor *qov = to_qov(v);
|
||||||
qapi_dealloc_push(qov, obj);
|
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);
|
QapiDeallocVisitor *qov = to_qov(v);
|
||||||
void **obj = qapi_dealloc_pop(qov);
|
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.start_struct = qapi_dealloc_start_struct;
|
||||||
v->visitor.end_struct = qapi_dealloc_end_struct;
|
v->visitor.end_struct = qapi_dealloc_end_struct;
|
||||||
v->visitor.start_implicit_struct = qapi_dealloc_start_implicit_struct;
|
v->visitor.start_alternate = qapi_dealloc_start_alternate;
|
||||||
v->visitor.end_implicit_struct = qapi_dealloc_end_implicit_struct;
|
v->visitor.end_alternate = qapi_dealloc_end_alternate;
|
||||||
v->visitor.start_list = qapi_dealloc_start_list;
|
v->visitor.start_list = qapi_dealloc_start_list;
|
||||||
v->visitor.next_list = qapi_dealloc_next_list;
|
v->visitor.next_list = qapi_dealloc_next_list;
|
||||||
v->visitor.end_list = qapi_dealloc_end_list;
|
v->visitor.end_list = qapi_dealloc_end_list;
|
||||||
|
@ -30,21 +30,6 @@ void visit_end_struct(Visitor *v, Error **errp)
|
|||||||
v->end_struct(v, 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)
|
void visit_start_list(Visitor *v, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
v->start_list(v, name, errp);
|
v->start_list(v, name, errp);
|
||||||
@ -61,6 +46,23 @@ void visit_end_list(Visitor *v)
|
|||||||
v->end_list(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)
|
bool visit_optional(Visitor *v, const char *name, bool *present)
|
||||||
{
|
{
|
||||||
if (v->optional) {
|
if (v->optional) {
|
||||||
@ -69,14 +71,6 @@ bool visit_optional(Visitor *v, const char *name, bool *present)
|
|||||||
return *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,
|
void visit_type_enum(Visitor *v, const char *name, int *obj,
|
||||||
const char *const strings[], Error **errp)
|
const char *const strings[], Error **errp)
|
||||||
{
|
{
|
||||||
|
@ -143,14 +143,6 @@ static void qmp_input_end_struct(Visitor *v, Error **errp)
|
|||||||
qmp_input_pop(qiv, 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)
|
static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
QmpInputVisitor *qiv = to_qiv(v);
|
QmpInputVisitor *qiv = to_qiv(v);
|
||||||
@ -202,19 +194,22 @@ static void qmp_input_end_list(Visitor *v)
|
|||||||
qmp_input_pop(qiv, &error_abort);
|
qmp_input_pop(qiv, &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qmp_input_get_next_type(Visitor *v, const char *name, QType *type,
|
static void qmp_input_start_alternate(Visitor *v, const char *name,
|
||||||
|
GenericAlternate **obj, size_t size,
|
||||||
bool promote_int, Error **errp)
|
bool promote_int, Error **errp)
|
||||||
{
|
{
|
||||||
QmpInputVisitor *qiv = to_qiv(v);
|
QmpInputVisitor *qiv = to_qiv(v);
|
||||||
QObject *qobj = qmp_input_get_object(qiv, name, false);
|
QObject *qobj = qmp_input_get_object(qiv, name, false);
|
||||||
|
|
||||||
if (!qobj) {
|
if (!qobj) {
|
||||||
|
*obj = NULL;
|
||||||
error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
|
error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*type = qobject_type(qobj);
|
*obj = g_malloc0(size);
|
||||||
if (promote_int && *type == QTYPE_QINT) {
|
(*obj)->type = qobject_type(qobj);
|
||||||
*type = QTYPE_QFLOAT;
|
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.start_struct = qmp_input_start_struct;
|
||||||
v->visitor.end_struct = qmp_input_end_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.start_list = qmp_input_start_list;
|
||||||
v->visitor.next_list = qmp_input_next_list;
|
v->visitor.next_list = qmp_input_next_list;
|
||||||
v->visitor.end_list = qmp_input_end_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_enum = input_type_enum;
|
||||||
v->visitor.type_int64 = qmp_input_type_int64;
|
v->visitor.type_int64 = qmp_input_type_int64;
|
||||||
v->visitor.type_uint64 = qmp_input_type_uint64;
|
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_number = qmp_input_type_number;
|
||||||
v->visitor.type_any = qmp_input_type_any;
|
v->visitor.type_any = qmp_input_type_any;
|
||||||
v->visitor.optional = qmp_input_optional;
|
v->visitor.optional = qmp_input_optional;
|
||||||
v->visitor.get_next_type = qmp_input_get_next_type;
|
|
||||||
|
|
||||||
qmp_input_push(v, obj, NULL);
|
qmp_input_push(v, obj, NULL);
|
||||||
qobject_incref(obj);
|
qobject_incref(obj);
|
||||||
|
@ -182,14 +182,11 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
|
|||||||
{
|
{
|
||||||
Error *err = NULL;
|
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) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
visit_get_next_type(v, name, &(*obj)->type, %(promote_int)s, &err);
|
|
||||||
if (err) {
|
|
||||||
goto out_obj;
|
|
||||||
}
|
|
||||||
switch ((*obj)->type) {
|
switch ((*obj)->type) {
|
||||||
''',
|
''',
|
||||||
c_name=c_name(name), promote_int=promote_int)
|
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",
|
error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||||
"%(name)s");
|
"%(name)s");
|
||||||
}
|
}
|
||||||
out_obj:
|
visit_end_alternate(v);
|
||||||
visit_end_implicit_struct(v);
|
|
||||||
out:
|
out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user