xref: /qemu/qapi/string-input-visitor.c (revision 72ac97cd)
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 "qapi/string-input-visitor.h"
15 #include "qapi/visitor-impl.h"
16 #include "qapi/qmp/qerror.h"
17 #include "qemu/option.h"
18 
19 struct StringInputVisitor
20 {
21     Visitor visitor;
22     const char *string;
23 };
24 
25 static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
26                            Error **errp)
27 {
28     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
29     char *endp = (char *) siv->string;
30     long long val;
31 
32     errno = 0;
33     if (siv->string) {
34         val = strtoll(siv->string, &endp, 0);
35     }
36     if (!siv->string || errno || endp == siv->string || *endp) {
37         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
38                   "integer");
39         return;
40     }
41 
42     *obj = val;
43 }
44 
45 static void parse_type_size(Visitor *v, uint64_t *obj, const char *name,
46                             Error **errp)
47 {
48     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
49     Error *err = NULL;
50     uint64_t val;
51 
52     if (siv->string) {
53         parse_option_size(name, siv->string, &val, &err);
54     } else {
55         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
56                   "size");
57         return;
58     }
59     if (err) {
60         error_propagate(errp, err);
61         return;
62     }
63 
64     *obj = val;
65 }
66 
67 static void parse_type_bool(Visitor *v, bool *obj, const char *name,
68                             Error **errp)
69 {
70     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
71 
72     if (siv->string) {
73         if (!strcasecmp(siv->string, "on") ||
74             !strcasecmp(siv->string, "yes") ||
75             !strcasecmp(siv->string, "true")) {
76             *obj = true;
77             return;
78         }
79         if (!strcasecmp(siv->string, "off") ||
80             !strcasecmp(siv->string, "no") ||
81             !strcasecmp(siv->string, "false")) {
82             *obj = false;
83             return;
84         }
85     }
86 
87     error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
88               "boolean");
89 }
90 
91 static void parse_type_str(Visitor *v, char **obj, const char *name,
92                            Error **errp)
93 {
94     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
95     if (siv->string) {
96         *obj = g_strdup(siv->string);
97     } else {
98         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
99                   "string");
100     }
101 }
102 
103 static void parse_type_number(Visitor *v, double *obj, const char *name,
104                               Error **errp)
105 {
106     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
107     char *endp = (char *) siv->string;
108     double val;
109 
110     errno = 0;
111     if (siv->string) {
112         val = strtod(siv->string, &endp);
113     }
114     if (!siv->string || errno || endp == siv->string || *endp) {
115         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
116                   "number");
117         return;
118     }
119 
120     *obj = val;
121 }
122 
123 static void parse_optional(Visitor *v, bool *present, const char *name,
124                            Error **errp)
125 {
126     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
127 
128     if (!siv->string) {
129         *present = false;
130         return;
131     }
132 
133     *present = true;
134 }
135 
136 Visitor *string_input_get_visitor(StringInputVisitor *v)
137 {
138     return &v->visitor;
139 }
140 
141 void string_input_visitor_cleanup(StringInputVisitor *v)
142 {
143     g_free(v);
144 }
145 
146 StringInputVisitor *string_input_visitor_new(const char *str)
147 {
148     StringInputVisitor *v;
149 
150     v = g_malloc0(sizeof(*v));
151 
152     v->visitor.type_enum = input_type_enum;
153     v->visitor.type_int = parse_type_int;
154     v->visitor.type_size = parse_type_size;
155     v->visitor.type_bool = parse_type_bool;
156     v->visitor.type_str = parse_type_str;
157     v->visitor.type_number = parse_type_number;
158     v->visitor.optional = parse_optional;
159 
160     v->string = str;
161     return v;
162 }
163