Merge remote-tracking branch 'spice/spice.v65' into staging
[sdk/emulator/qemu.git] / qapi / string-input-visitor.c
1 /*
2  * String parsing visitor
3  *
4  * Copyright Red Hat, Inc. 2012
5  *
6  * Author: Paolo Bonzini <pbonzini@redhat.com>
7  *
8  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
9  * See the COPYING.LIB file in the top-level directory.
10  *
11  */
12
13 #include "qemu-common.h"
14 #include "string-input-visitor.h"
15 #include "qapi/qapi-visit-impl.h"
16 #include "qerror.h"
17
18 struct StringInputVisitor
19 {
20     Visitor visitor;
21     const char *string;
22 };
23
24 static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
25                            Error **errp)
26 {
27     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
28     char *endp = (char *) siv->string;
29     long long val;
30
31     errno = 0;
32     if (siv->string) {
33         val = strtoll(siv->string, &endp, 0);
34     }
35     if (!siv->string || errno || endp == siv->string || *endp) {
36         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
37                   "integer");
38         return;
39     }
40
41     *obj = val;
42 }
43
44 static void parse_type_bool(Visitor *v, bool *obj, const char *name,
45                             Error **errp)
46 {
47     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
48
49     if (siv->string) {
50         if (!strcasecmp(siv->string, "on") ||
51             !strcasecmp(siv->string, "yes") ||
52             !strcasecmp(siv->string, "true")) {
53             *obj = true;
54             return;
55         }
56         if (!strcasecmp(siv->string, "off") ||
57             !strcasecmp(siv->string, "no") ||
58             !strcasecmp(siv->string, "false")) {
59             *obj = false;
60             return;
61         }
62     }
63
64     error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
65               "boolean");
66 }
67
68 static void parse_type_str(Visitor *v, char **obj, const char *name,
69                            Error **errp)
70 {
71     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
72     if (siv->string) {
73         *obj = g_strdup(siv->string);
74     } else {
75         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
76                   "string");
77     }
78 }
79
80 static void parse_type_number(Visitor *v, double *obj, const char *name,
81                               Error **errp)
82 {
83     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
84     char *endp = (char *) siv->string;
85     double val;
86
87     errno = 0;
88     if (siv->string) {
89         val = strtod(siv->string, &endp);
90     }
91     if (!siv->string || errno || endp == siv->string || *endp) {
92         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
93                   "number");
94         return;
95     }
96
97     *obj = val;
98 }
99
100 static void parse_start_optional(Visitor *v, bool *present,
101                                  const char *name, Error **errp)
102 {
103     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
104
105     if (!siv->string) {
106         *present = false;
107         return;
108     }
109
110     *present = true;
111 }
112
113 Visitor *string_input_get_visitor(StringInputVisitor *v)
114 {
115     return &v->visitor;
116 }
117
118 void string_input_visitor_cleanup(StringInputVisitor *v)
119 {
120     g_free(v);
121 }
122
123 StringInputVisitor *string_input_visitor_new(const char *str)
124 {
125     StringInputVisitor *v;
126
127     v = g_malloc0(sizeof(*v));
128
129     v->visitor.type_enum = input_type_enum;
130     v->visitor.type_int = parse_type_int;
131     v->visitor.type_bool = parse_type_bool;
132     v->visitor.type_str = parse_type_str;
133     v->visitor.type_number = parse_type_number;
134     v->visitor.start_optional = parse_start_optional;
135
136     v->string = str;
137     return v;
138 }