diff options
author | Peter Maydell | 2016-05-12 16:06:38 +0200 |
---|---|---|
committer | Peter Maydell | 2016-05-12 16:06:38 +0200 |
commit | 6ddeeffffecf1f78acf6c93cbf267a8abe755836 (patch) | |
tree | a3cba08b27f87adb9c0ed2badaa9945856c39144 /qapi/opts-visitor.c | |
parent | Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20160511-1' into s... (diff) | |
parent | qapi: Change visit_type_FOO() to no longer return partial objects (diff) | |
download | qemu-6ddeeffffecf1f78acf6c93cbf267a8abe755836.tar.gz qemu-6ddeeffffecf1f78acf6c93cbf267a8abe755836.tar.xz qemu-6ddeeffffecf1f78acf6c93cbf267a8abe755836.zip |
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-05-12' into staging
QAPI patches for 2016-05-12
# gpg: Signature made Thu 12 May 2016 08:49:04 BST using RSA key ID EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg: aka "Markus Armbruster <armbru@pond.sub.org>"
* remotes/armbru/tags/pull-qapi-2016-05-12: (23 commits)
qapi: Change visit_type_FOO() to no longer return partial objects
qapi: Simplify semantics of visit_next_list()
qapi: Fix string input visitor handling of invalid list
tests/string-input-visitor: Add negative integer tests
qapi: Split visit_end_struct() into pieces
qmp: Tighten output visitor rules
qmp: Don't reuse qmp visitor after grabbing output
spapr_drc: Expose 'null' in qom-get when there is no fdt
qmp: Support explicit null during visits
qapi: Add visit_type_null() visitor
tests: Add check-qnull
qapi: Document visitor interfaces, add assertions
qmp-input: Refactor when list is advanced
qmp-input: Require struct push to visit members of top dict
qom: Wrap prop visit in visit_start_struct
qapi-commands: Wrap argument visit in visit_start_struct
qmp-input: Don't consume input when checking has_member
qapi: Use strict QMP input visitor in more places
qapi: Consolidate QMP input visitor creation
qmp-input: Clean up stack handling
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'qapi/opts-visitor.c')
-rw-r--r-- | qapi/opts-visitor.c | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index 602f2609cc..4cf1cf885b 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -23,9 +23,8 @@ enum ListMode { LM_NONE, /* not traversing a list of repeated options */ - LM_STARTED, /* opts_start_list() succeeded */ - LM_IN_PROGRESS, /* opts_next_list() has been called. + LM_IN_PROGRESS, /* opts_next_list() ready to be called. * * Generating the next list link will consume the most * recently parsed QemuOpt instance of the repeated @@ -133,7 +132,7 @@ opts_start_struct(Visitor *v, const char *name, void **obj, const QemuOpt *opt; if (obj) { - *obj = g_malloc0(size > 0 ? size : 1); + *obj = g_malloc0(size); } if (ov->depth++ > 0) { return; @@ -159,13 +158,13 @@ opts_start_struct(Visitor *v, const char *name, void **obj, static void -opts_end_struct(Visitor *v, Error **errp) +opts_check_struct(Visitor *v, Error **errp) { OptsVisitor *ov = to_ov(v); GHashTableIter iter; GQueue *any; - if (--ov->depth > 0) { + if (ov->depth > 0) { return; } @@ -177,6 +176,18 @@ opts_end_struct(Visitor *v, Error **errp) first = g_queue_peek_head(any); error_setg(errp, QERR_INVALID_PARAMETER, first->name); } +} + + +static void +opts_end_struct(Visitor *v) +{ + OptsVisitor *ov = to_ov(v); + + if (--ov->depth > 0) { + return; + } + g_hash_table_destroy(ov->unprocessed_opts); ov->unprocessed_opts = NULL; if (ov->fake_id_opt) { @@ -202,35 +213,33 @@ lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) static void -opts_start_list(Visitor *v, const char *name, Error **errp) +opts_start_list(Visitor *v, const char *name, GenericList **list, size_t size, + Error **errp) { OptsVisitor *ov = to_ov(v); /* we can't traverse a list in a list */ assert(ov->list_mode == LM_NONE); + /* we don't support visits without a list */ + assert(list); ov->repeated_opts = lookup_distinct(ov, name, errp); - if (ov->repeated_opts != NULL) { - ov->list_mode = LM_STARTED; + if (ov->repeated_opts) { + ov->list_mode = LM_IN_PROGRESS; + *list = g_malloc0(size); + } else { + *list = NULL; } } static GenericList * -opts_next_list(Visitor *v, GenericList **list, size_t size) +opts_next_list(Visitor *v, GenericList *tail, size_t size) { OptsVisitor *ov = to_ov(v); - GenericList **link; switch (ov->list_mode) { - case LM_STARTED: - ov->list_mode = LM_IN_PROGRESS; - link = list; - break; - case LM_SIGNED_INTERVAL: case LM_UNSIGNED_INTERVAL: - link = &(*list)->next; - if (ov->list_mode == LM_SIGNED_INTERVAL) { if (ov->range_next.s < ov->range_limit.s) { ++ov->range_next.s; @@ -251,7 +260,6 @@ opts_next_list(Visitor *v, GenericList **list, size_t size) g_hash_table_remove(ov->unprocessed_opts, opt->name); return NULL; } - link = &(*list)->next; break; } @@ -259,8 +267,8 @@ opts_next_list(Visitor *v, GenericList **list, size_t size) abort(); } - *link = g_malloc0(size); - return *link; + tail->next = g_malloc0(size); + return tail->next; } @@ -269,8 +277,7 @@ opts_end_list(Visitor *v) { OptsVisitor *ov = to_ov(v); - assert(ov->list_mode == LM_STARTED || - ov->list_mode == LM_IN_PROGRESS || + assert(ov->list_mode == LM_IN_PROGRESS || ov->list_mode == LM_SIGNED_INTERVAL || ov->list_mode == LM_UNSIGNED_INTERVAL); ov->repeated_opts = NULL; @@ -314,9 +321,15 @@ opts_type_str(Visitor *v, const char *name, char **obj, Error **errp) opt = lookup_scalar(ov, name, errp); if (!opt) { + *obj = NULL; return; } *obj = g_strdup(opt->str ? opt->str : ""); + /* Note that we consume a string even if this is called as part of + * an enum visit that later fails because the string is not a + * valid enum value; this is harmless because tracking what gets + * consumed only matters to visit_end_struct() as the final error + * check if there were no other failures during the visit. */ processed(ov, name); } @@ -507,23 +520,16 @@ opts_visitor_new(const QemuOpts *opts) ov = g_malloc0(sizeof *ov); + ov->visitor.type = VISITOR_INPUT; + ov->visitor.start_struct = &opts_start_struct; + ov->visitor.check_struct = &opts_check_struct; ov->visitor.end_struct = &opts_end_struct; ov->visitor.start_list = &opts_start_list; ov->visitor.next_list = &opts_next_list; ov->visitor.end_list = &opts_end_list; - /* input_type_enum() covers both "normal" enums and union discriminators. - * The union discriminator field is always generated as "type"; it should - * match the "type" QemuOpt child of any QemuOpts. - * - * input_type_enum() will remove the looked-up key from the - * "unprocessed_opts" hash even if the lookup fails, because the removal is - * done earlier in opts_type_str(). This should be harmless. - */ - ov->visitor.type_enum = &input_type_enum; - ov->visitor.type_int64 = &opts_type_int64; ov->visitor.type_uint64 = &opts_type_uint64; ov->visitor.type_size = &opts_type_size; |