xref: /qemu/qapi/string-input-visitor.c (revision b2cd7dee)
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 }
139