diff --git a/qemu/include/qapi/visitor-impl.h b/qemu/include/qapi/visitor-impl.h index 60be6b73..be1d1ed6 100644 --- a/qemu/include/qapi/visitor-impl.h +++ b/qemu/include/qapi/visitor-impl.h @@ -15,6 +15,17 @@ #include "qapi/error.h" #include "qapi/visitor.h" +/* + * There are three classes of visitors; setting the class determines + * how QAPI enums are visited, as well as what additional restrictions + * can be asserted. + */ +typedef enum VisitorType { + VISITOR_INPUT, + VISITOR_OUTPUT, + VISITOR_DEALLOC, +} VisitorType; + struct Visitor { /* Must be set */ @@ -30,12 +41,9 @@ struct Visitor GenericList *(*next_list)(Visitor *v, GenericList **list); void (*end_list)(Visitor *v); - 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, Error **errp); /* Must be set. */ @@ -54,11 +62,9 @@ struct Visitor /* May be NULL; most useful for input visitors. */ void (*optional)(Visitor *v, const char *name, bool *present); + + /* Must be set */ + VisitorType type; }; -void input_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp); -void output_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp); - #endif diff --git a/qemu/include/qapi/visitor.h b/qemu/include/qapi/visitor.h index 621b8b08..1cf4634d 100644 --- a/qemu/include/qapi/visitor.h +++ b/qemu/include/qapi/visitor.h @@ -53,8 +53,19 @@ bool visit_optional(Visitor *v, const char *name, bool *present); */ void visit_get_next_type(Visitor *v, const char *name, QType *type, bool promote_int, Error **errp); +/* + * Visit an enum value. + * + * @strings expresses the mapping between C enum values and QAPI enum + * names; it should be the ENUM_lookup array from visit-types.h. + * + * May call visit_type_str() under the hood, and the enum visit may + * fail even if the corresponding string visit succeeded; this implies + * that visit_type_str() must have no unwelcome side effects. + */ 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); void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, Error **errp); diff --git a/qemu/qapi/qapi-dealloc-visitor.c b/qemu/qapi/qapi-dealloc-visitor.c index 0152f0fa..e1bb5718 100644 --- a/qemu/qapi/qapi-dealloc-visitor.c +++ b/qemu/qapi/qapi-dealloc-visitor.c @@ -169,11 +169,6 @@ static void qapi_dealloc_type_size(Visitor *v, const char *name, uint64_t *obj, { } -static void qapi_dealloc_type_enum(Visitor *v, const char *name, int *obj, - const char * const strings[], Error **errp) -{ -} - Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v) { return &v->visitor; @@ -190,6 +185,7 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void) v = g_malloc0(sizeof(*v)); + v->visitor.type = VISITOR_DEALLOC; 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; @@ -197,7 +193,6 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void) v->visitor.start_list = qapi_dealloc_start_list; v->visitor.next_list = qapi_dealloc_next_list; v->visitor.end_list = qapi_dealloc_end_list; - v->visitor.type_enum = qapi_dealloc_type_enum; v->visitor.type_int64 = qapi_dealloc_type_int64; v->visitor.type_uint64 = qapi_dealloc_type_uint64; v->visitor.type_bool = qapi_dealloc_type_bool; diff --git a/qemu/qapi/qapi-visit-core.c b/qemu/qapi/qapi-visit-core.c index f8680b42..59b01bb1 100644 --- a/qemu/qapi/qapi-visit-core.c +++ b/qemu/qapi/qapi-visit-core.c @@ -78,12 +78,6 @@ void visit_get_next_type(Visitor *v, const char *name, QType *type, } } -void visit_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp) -{ - v->type_enum(v, name, obj, strings, errp); -} - void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) { v->type_int64(v, name, obj, errp); @@ -211,14 +205,13 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) v->type_any(v, name, obj, errp); } -void output_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp) +static void output_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp) { int i = 0; int value = *obj; char *enum_str; - assert(strings); while (strings[i++] != NULL); if (value < 0 || value >= i - 1) { error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null"); @@ -229,15 +222,13 @@ void output_type_enum(Visitor *v, const char *name, int *obj, visit_type_str(v, name, &enum_str, errp); } -void input_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp) +static void input_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp) { Error *local_err = NULL; int64_t value = 0; char *enum_str; - assert(strings); - visit_type_str(v, name, &enum_str, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -260,3 +251,14 @@ void input_type_enum(Visitor *v, const char *name, int *obj, g_free(enum_str); *obj = (int)value; } + +void visit_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp) +{ + assert(strings); + if (v->type == VISITOR_INPUT) { + input_type_enum(v, name, obj, strings, errp); + } else if (v->type == VISITOR_OUTPUT) { + output_type_enum(v, name, obj, strings, errp); + } +} diff --git a/qemu/qapi/qmp-input-visitor.c b/qemu/qapi/qmp-input-visitor.c index 0c6fbbee..3fb9f0e9 100644 --- a/qemu/qapi/qmp-input-visitor.c +++ b/qemu/qapi/qmp-input-visitor.c @@ -350,6 +350,7 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) v = g_malloc0(sizeof(*v)); + v->visitor.type = VISITOR_INPUT; 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; @@ -357,7 +358,6 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) 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.type_enum = input_type_enum; v->visitor.type_int64 = qmp_input_type_int64; v->visitor.type_uint64 = qmp_input_type_uint64; v->visitor.type_bool = qmp_input_type_bool; diff --git a/qemu/qapi/qmp-output-visitor.c b/qemu/qapi/qmp-output-visitor.c index c0c7c551..af8d1866 100644 --- a/qemu/qapi/qmp-output-visitor.c +++ b/qemu/qapi/qmp-output-visitor.c @@ -234,12 +234,12 @@ QmpOutputVisitor *qmp_output_visitor_new(void) 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_enum = output_type_enum; v->visitor.type_int64 = qmp_output_type_int64; v->visitor.type_uint64 = qmp_output_type_uint64; v->visitor.type_bool = qmp_output_type_bool; diff --git a/qemu/qapi/string-input-visitor.c b/qemu/qapi/string-input-visitor.c index 7d5fe5c9..d695f072 100644 --- a/qemu/qapi/string-input-visitor.c +++ b/qemu/qapi/string-input-visitor.c @@ -328,7 +328,7 @@ StringInputVisitor *string_input_visitor_new(const char *str) v = g_malloc0(sizeof(*v)); - v->visitor.type_enum = input_type_enum; + v->visitor.type = VISITOR_INPUT; v->visitor.type_int64 = parse_type_int64; v->visitor.type_uint64 = parse_type_uint64; v->visitor.type_size = NULL;