From a020f9809cff1cfdb99c64348400cf86a0bbe40a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Feb 2012 09:36:37 +0100 Subject: [PATCH] qapi: add string-based visitors String based visitors provide a consistent interface for parsing strings to C values, as well as consuming C values as strings. They will be used to parse command-line options. Signed-off-by: Paolo Bonzini --- Makefile.objs | 5 +- qapi/string-input-visitor.c | 138 +++++++++++++++++++++++++++++++++++ qapi/string-input-visitor.h | 25 +++++++ qapi/string-output-visitor.c | 89 ++++++++++++++++++++++ qapi/string-output-visitor.h | 26 +++++++ 5 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 qapi/string-input-visitor.c create mode 100644 qapi/string-input-visitor.h create mode 100644 qapi/string-output-visitor.c create mode 100644 qapi/string-output-visitor.h diff --git a/Makefile.objs b/Makefile.objs index 391e524525..2a4dbd1ea2 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -412,8 +412,9 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o ###################################################################### # qapi -qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o -qapi-nested-y += qmp-registry.o qmp-dispatch.o +qapi-nested-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o +qapi-nested-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o +qapi-nested-y += string-input-visitor.o string-output-visitor.o qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y)) common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o $(qapi-obj-y) diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c new file mode 100644 index 0000000000..497eb9a60a --- /dev/null +++ b/qapi/string-input-visitor.c @@ -0,0 +1,138 @@ +/* + * String parsing visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Paolo Bonzini + * + * 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-common.h" +#include "string-input-visitor.h" +#include "qapi/qapi-visit-impl.h" +#include "qerror.h" + +struct StringInputVisitor +{ + Visitor visitor; + const char *string; +}; + +static void parse_type_int(Visitor *v, int64_t *obj, const char *name, + Error **errp) +{ + StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); + char *endp = (char *) siv->string; + long long val; + + errno = 0; + if (siv->string) { + val = strtoll(siv->string, &endp, 0); + } + if (!siv->string || errno || endp == siv->string || *endp) { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "integer"); + return; + } + + *obj = val; +} + +static void parse_type_bool(Visitor *v, bool *obj, const char *name, + Error **errp) +{ + StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); + + if (siv->string) { + if (!strcasecmp(siv->string, "on") || + !strcasecmp(siv->string, "yes") || + !strcasecmp(siv->string, "true")) { + *obj = true; + return; + } + if (!strcasecmp(siv->string, "off") || + !strcasecmp(siv->string, "no") || + !strcasecmp(siv->string, "false")) { + *obj = false; + return; + } + } + + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "boolean"); +} + +static void parse_type_str(Visitor *v, char **obj, const char *name, + Error **errp) +{ + StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); + if (siv->string) { + *obj = g_strdup(siv->string); + } else { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "string"); + } +} + +static void parse_type_number(Visitor *v, double *obj, const char *name, + Error **errp) +{ + StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); + char *endp = (char *) siv->string; + double val; + + errno = 0; + if (siv->string) { + val = strtod(siv->string, &endp); + } + if (!siv->string || errno || endp == siv->string || *endp) { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "number"); + return; + } + + *obj = val; +} + +static void parse_start_optional(Visitor *v, bool *present, + const char *name, Error **errp) +{ + StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); + + if (!siv->string) { + *present = false; + return; + } + + *present = true; +} + +Visitor *string_input_get_visitor(StringInputVisitor *v) +{ + return &v->visitor; +} + +void string_input_visitor_cleanup(StringInputVisitor *v) +{ + g_free(v); +} + +StringInputVisitor *string_input_visitor_new(const char *str) +{ + StringInputVisitor *v; + + v = g_malloc0(sizeof(*v)); + + v->visitor.type_enum = input_type_enum; + v->visitor.type_int = parse_type_int; + v->visitor.type_bool = parse_type_bool; + v->visitor.type_str = parse_type_str; + v->visitor.type_number = parse_type_number; + v->visitor.start_optional = parse_start_optional; + + v->string = str; + return v; +} diff --git a/qapi/string-input-visitor.h b/qapi/string-input-visitor.h new file mode 100644 index 0000000000..d269d42cef --- /dev/null +++ b/qapi/string-input-visitor.h @@ -0,0 +1,25 @@ +/* + * String parsing Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Paolo Bonzini + * + * 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. + * + */ + +#ifndef STRING_INPUT_VISITOR_H +#define STRING_INPUT_VISITOR_H + +#include "qapi-visit-core.h" + +typedef struct StringInputVisitor StringInputVisitor; + +StringInputVisitor *string_input_visitor_new(const char *str); +void string_input_visitor_cleanup(StringInputVisitor *v); + +Visitor *string_input_get_visitor(StringInputVisitor *v); + +#endif diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c new file mode 100644 index 0000000000..92b0305212 --- /dev/null +++ b/qapi/string-output-visitor.c @@ -0,0 +1,89 @@ +/* + * String printing Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Paolo Bonzini + * + * 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-common.h" +#include "string-output-visitor.h" +#include "qapi/qapi-visit-impl.h" +#include "qerror.h" + +struct StringOutputVisitor +{ + Visitor visitor; + char *string; +}; + +static void string_output_set(StringOutputVisitor *sov, char *string) +{ + g_free(sov->string); + sov->string = string; +} + +static void print_type_int(Visitor *v, int64_t *obj, const char *name, + Error **errp) +{ + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); + string_output_set(sov, g_strdup_printf("%lld", (long long) *obj)); +} + +static void print_type_bool(Visitor *v, bool *obj, const char *name, + Error **errp) +{ + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); + string_output_set(sov, g_strdup(*obj ? "true" : "false")); +} + +static void print_type_str(Visitor *v, char **obj, const char *name, + Error **errp) +{ + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); + string_output_set(sov, g_strdup(*obj ? *obj : "")); +} + +static void print_type_number(Visitor *v, double *obj, const char *name, + Error **errp) +{ + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); + string_output_set(sov, g_strdup_printf("%g", *obj)); +} + +char *string_output_get_string(StringOutputVisitor *sov) +{ + char *string = sov->string; + sov->string = NULL; + return string; +} + +Visitor *string_output_get_visitor(StringOutputVisitor *sov) +{ + return &sov->visitor; +} + +void string_output_visitor_cleanup(StringOutputVisitor *sov) +{ + g_free(sov->string); + g_free(sov); +} + +StringOutputVisitor *string_output_visitor_new(void) +{ + StringOutputVisitor *v; + + v = g_malloc0(sizeof(*v)); + + v->visitor.type_enum = output_type_enum; + v->visitor.type_int = print_type_int; + v->visitor.type_bool = print_type_bool; + v->visitor.type_str = print_type_str; + v->visitor.type_number = print_type_number; + + return v; +} diff --git a/qapi/string-output-visitor.h b/qapi/string-output-visitor.h new file mode 100644 index 0000000000..8868454110 --- /dev/null +++ b/qapi/string-output-visitor.h @@ -0,0 +1,26 @@ +/* + * String printing Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Paolo Bonzini + * + * 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. + * + */ + +#ifndef STRING_OUTPUT_VISITOR_H +#define STRING_OUTPUT_VISITOR_H + +#include "qapi-visit-core.h" + +typedef struct StringOutputVisitor StringOutputVisitor; + +StringOutputVisitor *string_output_visitor_new(void); +void string_output_visitor_cleanup(StringOutputVisitor *v); + +char *string_output_get_string(StringOutputVisitor *v); +Visitor *string_output_get_visitor(StringOutputVisitor *v); + +#endif