1a020f980SPaolo Bonzini /*
2a020f980SPaolo Bonzini * String parsing visitor
3a020f980SPaolo Bonzini *
408f9541dSEric Blake * Copyright Red Hat, Inc. 2012-2016
5a020f980SPaolo Bonzini *
6a020f980SPaolo Bonzini * Author: Paolo Bonzini <pbonzini@redhat.com>
7c9fba9deSDavid Hildenbrand * David Hildenbrand <david@redhat.com>
8a020f980SPaolo Bonzini *
9a020f980SPaolo Bonzini * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10a020f980SPaolo Bonzini * See the COPYING.LIB file in the top-level directory.
11a020f980SPaolo Bonzini */
12a020f980SPaolo Bonzini
13cbf21151SPeter Maydell #include "qemu/osdep.h"
14da34e65cSMarkus Armbruster #include "qapi/error.h"
157b1b5d19SPaolo Bonzini #include "qapi/string-input-visitor.h"
167b1b5d19SPaolo Bonzini #include "qapi/visitor-impl.h"
177b1b5d19SPaolo Bonzini #include "qapi/qmp/qerror.h"
1884be629dSMax Reitz #include "qapi/qmp/qnull.h"
19a5829ccfSPaolo Bonzini #include "qemu/option.h"
204b69d4c3SDavid Hildenbrand #include "qemu/cutils.h"
21659268ffSHu Tao
22c9fba9deSDavid Hildenbrand typedef enum ListMode {
23c9fba9deSDavid Hildenbrand /* no list parsing active / no list expected */
24c9fba9deSDavid Hildenbrand LM_NONE,
25c9fba9deSDavid Hildenbrand /* we have an unparsed string remaining */
26c9fba9deSDavid Hildenbrand LM_UNPARSED,
27c9fba9deSDavid Hildenbrand /* we have an unfinished int64 range */
28c9fba9deSDavid Hildenbrand LM_INT64_RANGE,
29c9fba9deSDavid Hildenbrand /* we have an unfinished uint64 range */
30c9fba9deSDavid Hildenbrand LM_UINT64_RANGE,
31c9fba9deSDavid Hildenbrand /* we have parsed the string completely and no range is remaining */
32c9fba9deSDavid Hildenbrand LM_END,
33c9fba9deSDavid Hildenbrand } ListMode;
34c9fba9deSDavid Hildenbrand
35c9fba9deSDavid Hildenbrand /* protect against DOS attacks, limit the amount of elements per range */
36c9fba9deSDavid Hildenbrand #define RANGE_MAX_ELEMENTS 65536
37c9fba9deSDavid Hildenbrand
38c9fba9deSDavid Hildenbrand typedef union RangeElement {
39c9fba9deSDavid Hildenbrand int64_t i64;
40c9fba9deSDavid Hildenbrand uint64_t u64;
41c9fba9deSDavid Hildenbrand } RangeElement;
42a020f980SPaolo Bonzini
43a020f980SPaolo Bonzini struct StringInputVisitor
44a020f980SPaolo Bonzini {
45a020f980SPaolo Bonzini Visitor visitor;
46659268ffSHu Tao
47c9fba9deSDavid Hildenbrand /* List parsing state */
48c9fba9deSDavid Hildenbrand ListMode lm;
49c9fba9deSDavid Hildenbrand RangeElement rangeNext;
50c9fba9deSDavid Hildenbrand RangeElement rangeEnd;
51c9fba9deSDavid Hildenbrand const char *unparsed_string;
52c9fba9deSDavid Hildenbrand void *list;
53659268ffSHu Tao
54c9fba9deSDavid Hildenbrand /* The original string to parse */
55a020f980SPaolo Bonzini const char *string;
56a020f980SPaolo Bonzini };
57a020f980SPaolo Bonzini
to_siv(Visitor * v)58d7bea75dSEric Blake static StringInputVisitor *to_siv(Visitor *v)
59d7bea75dSEric Blake {
60d7bea75dSEric Blake return container_of(v, StringInputVisitor, visitor);
61d7bea75dSEric Blake }
62d7bea75dSEric Blake
start_list(Visitor * v,const char * name,GenericList ** list,size_t size,Error ** errp)63012d4c96SMarkus Armbruster static bool start_list(Visitor *v, const char *name, GenericList **list,
64c9fba9deSDavid Hildenbrand size_t size, Error **errp)
65659268ffSHu Tao {
66d7bea75dSEric Blake StringInputVisitor *siv = to_siv(v);
67659268ffSHu Tao
68c9fba9deSDavid Hildenbrand assert(siv->lm == LM_NONE);
691158bb2aSEric Blake siv->list = list;
70c9fba9deSDavid Hildenbrand siv->unparsed_string = siv->string;
71d9f62ddeSEric Blake
72c9fba9deSDavid Hildenbrand if (!siv->string[0]) {
73c9fba9deSDavid Hildenbrand if (list) {
74d9f62ddeSEric Blake *list = NULL;
7574f24cb6SEric Blake }
76c9fba9deSDavid Hildenbrand siv->lm = LM_END;
77d9f62ddeSEric Blake } else {
78c9fba9deSDavid Hildenbrand if (list) {
79c9fba9deSDavid Hildenbrand *list = g_malloc0(size);
80c9fba9deSDavid Hildenbrand }
81c9fba9deSDavid Hildenbrand siv->lm = LM_UNPARSED;
82659268ffSHu Tao }
83012d4c96SMarkus Armbruster return true;
84659268ffSHu Tao }
85659268ffSHu Tao
next_list(Visitor * v,GenericList * tail,size_t size)86d9f62ddeSEric Blake static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
87659268ffSHu Tao {
88d7bea75dSEric Blake StringInputVisitor *siv = to_siv(v);
89659268ffSHu Tao
90c9fba9deSDavid Hildenbrand switch (siv->lm) {
91c9fba9deSDavid Hildenbrand case LM_END:
92659268ffSHu Tao return NULL;
93c9fba9deSDavid Hildenbrand case LM_INT64_RANGE:
94c9fba9deSDavid Hildenbrand case LM_UINT64_RANGE:
95c9fba9deSDavid Hildenbrand case LM_UNPARSED:
96c9fba9deSDavid Hildenbrand /* we have an unparsed string or something left in a range */
97c9fba9deSDavid Hildenbrand break;
98c9fba9deSDavid Hildenbrand default:
99c9fba9deSDavid Hildenbrand abort();
100659268ffSHu Tao }
101659268ffSHu Tao
102d9f62ddeSEric Blake tail->next = g_malloc0(size);
103d9f62ddeSEric Blake return tail->next;
104659268ffSHu Tao }
105659268ffSHu Tao
check_list(Visitor * v,Error ** errp)106012d4c96SMarkus Armbruster static bool check_list(Visitor *v, Error **errp)
107a4a1c70dSMarkus Armbruster {
108a4a1c70dSMarkus Armbruster const StringInputVisitor *siv = to_siv(v);
109a4a1c70dSMarkus Armbruster
110c9fba9deSDavid Hildenbrand switch (siv->lm) {
111c9fba9deSDavid Hildenbrand case LM_INT64_RANGE:
112c9fba9deSDavid Hildenbrand case LM_UINT64_RANGE:
113c9fba9deSDavid Hildenbrand case LM_UNPARSED:
114c9fba9deSDavid Hildenbrand error_setg(errp, "Fewer list elements expected");
115012d4c96SMarkus Armbruster return false;
116c9fba9deSDavid Hildenbrand case LM_END:
117012d4c96SMarkus Armbruster return true;
118c9fba9deSDavid Hildenbrand default:
119c9fba9deSDavid Hildenbrand abort();
120a4a1c70dSMarkus Armbruster }
121a4a1c70dSMarkus Armbruster }
122a4a1c70dSMarkus Armbruster
end_list(Visitor * v,void ** obj)1231158bb2aSEric Blake static void end_list(Visitor *v, void **obj)
124659268ffSHu Tao {
1251158bb2aSEric Blake StringInputVisitor *siv = to_siv(v);
1261158bb2aSEric Blake
127c9fba9deSDavid Hildenbrand assert(siv->lm != LM_NONE);
1281158bb2aSEric Blake assert(siv->list == obj);
129c9fba9deSDavid Hildenbrand siv->list = NULL;
130c9fba9deSDavid Hildenbrand siv->unparsed_string = NULL;
131c9fba9deSDavid Hildenbrand siv->lm = LM_NONE;
132c9fba9deSDavid Hildenbrand }
133c9fba9deSDavid Hildenbrand
try_parse_int64_list_entry(StringInputVisitor * siv,int64_t * obj)134c9fba9deSDavid Hildenbrand static int try_parse_int64_list_entry(StringInputVisitor *siv, int64_t *obj)
135c9fba9deSDavid Hildenbrand {
136c9fba9deSDavid Hildenbrand const char *endptr;
137c9fba9deSDavid Hildenbrand int64_t start, end;
138c9fba9deSDavid Hildenbrand
139c9fba9deSDavid Hildenbrand /* parse a simple int64 or range */
140c9fba9deSDavid Hildenbrand if (qemu_strtoi64(siv->unparsed_string, &endptr, 0, &start)) {
141c9fba9deSDavid Hildenbrand return -EINVAL;
142c9fba9deSDavid Hildenbrand }
143c9fba9deSDavid Hildenbrand end = start;
144c9fba9deSDavid Hildenbrand
145c9fba9deSDavid Hildenbrand switch (endptr[0]) {
146c9fba9deSDavid Hildenbrand case '\0':
147c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr;
148c9fba9deSDavid Hildenbrand break;
149c9fba9deSDavid Hildenbrand case ',':
150c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr + 1;
151c9fba9deSDavid Hildenbrand break;
152c9fba9deSDavid Hildenbrand case '-':
153c9fba9deSDavid Hildenbrand /* parse the end of the range */
154c9fba9deSDavid Hildenbrand if (qemu_strtoi64(endptr + 1, &endptr, 0, &end)) {
155c9fba9deSDavid Hildenbrand return -EINVAL;
156c9fba9deSDavid Hildenbrand }
157c9fba9deSDavid Hildenbrand if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
158c9fba9deSDavid Hildenbrand return -EINVAL;
159c9fba9deSDavid Hildenbrand }
160c9fba9deSDavid Hildenbrand switch (endptr[0]) {
161c9fba9deSDavid Hildenbrand case '\0':
162c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr;
163c9fba9deSDavid Hildenbrand break;
164c9fba9deSDavid Hildenbrand case ',':
165c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr + 1;
166c9fba9deSDavid Hildenbrand break;
167c9fba9deSDavid Hildenbrand default:
168c9fba9deSDavid Hildenbrand return -EINVAL;
169c9fba9deSDavid Hildenbrand }
170c9fba9deSDavid Hildenbrand break;
171c9fba9deSDavid Hildenbrand default:
172c9fba9deSDavid Hildenbrand return -EINVAL;
173c9fba9deSDavid Hildenbrand }
174c9fba9deSDavid Hildenbrand
175c9fba9deSDavid Hildenbrand /* we have a proper range (with maybe only one element) */
176c9fba9deSDavid Hildenbrand siv->lm = LM_INT64_RANGE;
177c9fba9deSDavid Hildenbrand siv->rangeNext.i64 = start;
178c9fba9deSDavid Hildenbrand siv->rangeEnd.i64 = end;
179c9fba9deSDavid Hildenbrand return 0;
180659268ffSHu Tao }
181659268ffSHu Tao
parse_type_int64(Visitor * v,const char * name,int64_t * obj,Error ** errp)182012d4c96SMarkus Armbruster static bool parse_type_int64(Visitor *v, const char *name, int64_t *obj,
183a020f980SPaolo Bonzini Error **errp)
184a020f980SPaolo Bonzini {
185d7bea75dSEric Blake StringInputVisitor *siv = to_siv(v);
186c9fba9deSDavid Hildenbrand int64_t val;
187a020f980SPaolo Bonzini
188c9fba9deSDavid Hildenbrand switch (siv->lm) {
189c9fba9deSDavid Hildenbrand case LM_NONE:
190c9fba9deSDavid Hildenbrand /* just parse a simple int64, bail out if not completely consumed */
191c9fba9deSDavid Hildenbrand if (qemu_strtoi64(siv->string, NULL, 0, &val)) {
192c9fba9deSDavid Hildenbrand error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
193c9fba9deSDavid Hildenbrand name ? name : "null", "int64");
194012d4c96SMarkus Armbruster return false;
19574f24cb6SEric Blake }
196c9fba9deSDavid Hildenbrand *obj = val;
197012d4c96SMarkus Armbruster return true;
198c9fba9deSDavid Hildenbrand case LM_UNPARSED:
199c9fba9deSDavid Hildenbrand if (try_parse_int64_list_entry(siv, obj)) {
2000a40bdabSEric Blake error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
201c9fba9deSDavid Hildenbrand "list of int64 values or ranges");
202012d4c96SMarkus Armbruster return false;
203c9fba9deSDavid Hildenbrand }
204c9fba9deSDavid Hildenbrand assert(siv->lm == LM_INT64_RANGE);
205c9fba9deSDavid Hildenbrand /* fall through */
206c9fba9deSDavid Hildenbrand case LM_INT64_RANGE:
207c9fba9deSDavid Hildenbrand /* return the next element in the range */
208c9fba9deSDavid Hildenbrand assert(siv->rangeNext.i64 <= siv->rangeEnd.i64);
209c9fba9deSDavid Hildenbrand *obj = siv->rangeNext.i64++;
210c9fba9deSDavid Hildenbrand
211c9fba9deSDavid Hildenbrand if (siv->rangeNext.i64 > siv->rangeEnd.i64 || *obj == INT64_MAX) {
212c9fba9deSDavid Hildenbrand /* end of range, check if there is more to parse */
213c9fba9deSDavid Hildenbrand siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
214c9fba9deSDavid Hildenbrand }
215012d4c96SMarkus Armbruster return true;
216c9fba9deSDavid Hildenbrand case LM_END:
217c9fba9deSDavid Hildenbrand error_setg(errp, "Fewer list elements expected");
218012d4c96SMarkus Armbruster return false;
219c9fba9deSDavid Hildenbrand default:
220c9fba9deSDavid Hildenbrand abort();
221c9fba9deSDavid Hildenbrand }
222c9fba9deSDavid Hildenbrand }
223c9fba9deSDavid Hildenbrand
try_parse_uint64_list_entry(StringInputVisitor * siv,uint64_t * obj)224c9fba9deSDavid Hildenbrand static int try_parse_uint64_list_entry(StringInputVisitor *siv, uint64_t *obj)
225c9fba9deSDavid Hildenbrand {
226c9fba9deSDavid Hildenbrand const char *endptr;
227c9fba9deSDavid Hildenbrand uint64_t start, end;
228c9fba9deSDavid Hildenbrand
229c9fba9deSDavid Hildenbrand /* parse a simple uint64 or range */
230c9fba9deSDavid Hildenbrand if (qemu_strtou64(siv->unparsed_string, &endptr, 0, &start)) {
231c9fba9deSDavid Hildenbrand return -EINVAL;
232c9fba9deSDavid Hildenbrand }
233c9fba9deSDavid Hildenbrand end = start;
234c9fba9deSDavid Hildenbrand
235c9fba9deSDavid Hildenbrand switch (endptr[0]) {
236c9fba9deSDavid Hildenbrand case '\0':
237c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr;
238c9fba9deSDavid Hildenbrand break;
239c9fba9deSDavid Hildenbrand case ',':
240c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr + 1;
241c9fba9deSDavid Hildenbrand break;
242c9fba9deSDavid Hildenbrand case '-':
243c9fba9deSDavid Hildenbrand /* parse the end of the range */
244c9fba9deSDavid Hildenbrand if (qemu_strtou64(endptr + 1, &endptr, 0, &end)) {
245c9fba9deSDavid Hildenbrand return -EINVAL;
246c9fba9deSDavid Hildenbrand }
247c9fba9deSDavid Hildenbrand if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
248c9fba9deSDavid Hildenbrand return -EINVAL;
249c9fba9deSDavid Hildenbrand }
250c9fba9deSDavid Hildenbrand switch (endptr[0]) {
251c9fba9deSDavid Hildenbrand case '\0':
252c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr;
253c9fba9deSDavid Hildenbrand break;
254c9fba9deSDavid Hildenbrand case ',':
255c9fba9deSDavid Hildenbrand siv->unparsed_string = endptr + 1;
256c9fba9deSDavid Hildenbrand break;
257c9fba9deSDavid Hildenbrand default:
258c9fba9deSDavid Hildenbrand return -EINVAL;
259c9fba9deSDavid Hildenbrand }
260c9fba9deSDavid Hildenbrand break;
261c9fba9deSDavid Hildenbrand default:
262c9fba9deSDavid Hildenbrand return -EINVAL;
263c9fba9deSDavid Hildenbrand }
264c9fba9deSDavid Hildenbrand
265c9fba9deSDavid Hildenbrand /* we have a proper range (with maybe only one element) */
266c9fba9deSDavid Hildenbrand siv->lm = LM_UINT64_RANGE;
267c9fba9deSDavid Hildenbrand siv->rangeNext.u64 = start;
268c9fba9deSDavid Hildenbrand siv->rangeEnd.u64 = end;
269c9fba9deSDavid Hildenbrand return 0;
270a020f980SPaolo Bonzini }
271a020f980SPaolo Bonzini
parse_type_uint64(Visitor * v,const char * name,uint64_t * obj,Error ** errp)272012d4c96SMarkus Armbruster static bool parse_type_uint64(Visitor *v, const char *name, uint64_t *obj,
273f755dea7SEric Blake Error **errp)
274f755dea7SEric Blake {
275c9fba9deSDavid Hildenbrand StringInputVisitor *siv = to_siv(v);
276c9fba9deSDavid Hildenbrand uint64_t val;
277c9fba9deSDavid Hildenbrand
278c9fba9deSDavid Hildenbrand switch (siv->lm) {
279c9fba9deSDavid Hildenbrand case LM_NONE:
280c9fba9deSDavid Hildenbrand /* just parse a simple uint64, bail out if not completely consumed */
281c9fba9deSDavid Hildenbrand if (qemu_strtou64(siv->string, NULL, 0, &val)) {
282c9fba9deSDavid Hildenbrand error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
283c9fba9deSDavid Hildenbrand "uint64");
284012d4c96SMarkus Armbruster return false;
285c9fba9deSDavid Hildenbrand }
286c9fba9deSDavid Hildenbrand *obj = val;
287012d4c96SMarkus Armbruster return true;
288c9fba9deSDavid Hildenbrand case LM_UNPARSED:
289c9fba9deSDavid Hildenbrand if (try_parse_uint64_list_entry(siv, obj)) {
290c9fba9deSDavid Hildenbrand error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
291c9fba9deSDavid Hildenbrand "list of uint64 values or ranges");
292012d4c96SMarkus Armbruster return false;
293c9fba9deSDavid Hildenbrand }
294c9fba9deSDavid Hildenbrand assert(siv->lm == LM_UINT64_RANGE);
295c9fba9deSDavid Hildenbrand /* fall through */
296c9fba9deSDavid Hildenbrand case LM_UINT64_RANGE:
297c9fba9deSDavid Hildenbrand /* return the next element in the range */
298c9fba9deSDavid Hildenbrand assert(siv->rangeNext.u64 <= siv->rangeEnd.u64);
299c9fba9deSDavid Hildenbrand *obj = siv->rangeNext.u64++;
300c9fba9deSDavid Hildenbrand
301c9fba9deSDavid Hildenbrand if (siv->rangeNext.u64 > siv->rangeEnd.u64 || *obj == UINT64_MAX) {
302c9fba9deSDavid Hildenbrand /* end of range, check if there is more to parse */
303c9fba9deSDavid Hildenbrand siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
304c9fba9deSDavid Hildenbrand }
305012d4c96SMarkus Armbruster return true;
306c9fba9deSDavid Hildenbrand case LM_END:
307c9fba9deSDavid Hildenbrand error_setg(errp, "Fewer list elements expected");
308012d4c96SMarkus Armbruster return false;
309c9fba9deSDavid Hildenbrand default:
310c9fba9deSDavid Hildenbrand abort();
311f755dea7SEric Blake }
312f755dea7SEric Blake }
313f755dea7SEric Blake
parse_type_size(Visitor * v,const char * name,uint64_t * obj,Error ** errp)314012d4c96SMarkus Armbruster static bool parse_type_size(Visitor *v, const char *name, uint64_t *obj,
315a5829ccfSPaolo Bonzini Error **errp)
316a5829ccfSPaolo Bonzini {
317d7bea75dSEric Blake StringInputVisitor *siv = to_siv(v);
318a5829ccfSPaolo Bonzini uint64_t val;
319a5829ccfSPaolo Bonzini
320c9fba9deSDavid Hildenbrand assert(siv->lm == LM_NONE);
321668f62ecSMarkus Armbruster if (!parse_option_size(name, siv->string, &val, errp)) {
322012d4c96SMarkus Armbruster return false;
323a5829ccfSPaolo Bonzini }
324a5829ccfSPaolo Bonzini
325a5829ccfSPaolo Bonzini *obj = val;
326012d4c96SMarkus Armbruster return true;
327a5829ccfSPaolo Bonzini }
328a5829ccfSPaolo Bonzini
parse_type_bool(Visitor * v,const char * name,bool * obj,Error ** errp)329012d4c96SMarkus Armbruster static bool parse_type_bool(Visitor *v, const char *name, bool *obj,
330a020f980SPaolo Bonzini Error **errp)
331a020f980SPaolo Bonzini {
332d7bea75dSEric Blake StringInputVisitor *siv = to_siv(v);
333a020f980SPaolo Bonzini
334c9fba9deSDavid Hildenbrand assert(siv->lm == LM_NONE);
335372bcb25SPaolo Bonzini return qapi_bool_parse(name ? name : "null", siv->string, obj, errp);
336a020f980SPaolo Bonzini }
337a020f980SPaolo Bonzini
parse_type_str(Visitor * v,const char * name,char ** obj,Error ** errp)338012d4c96SMarkus Armbruster static bool parse_type_str(Visitor *v, const char *name, char **obj,
339a020f980SPaolo Bonzini Error **errp)
340a020f980SPaolo Bonzini {
341d7bea75dSEric Blake StringInputVisitor *siv = to_siv(v);
342f332e830SMarkus Armbruster
343c9fba9deSDavid Hildenbrand assert(siv->lm == LM_NONE);
344a020f980SPaolo Bonzini *obj = g_strdup(siv->string);
345012d4c96SMarkus Armbruster return true;
346a020f980SPaolo Bonzini }
347a020f980SPaolo Bonzini
parse_type_number(Visitor * v,const char * name,double * obj,Error ** errp)348012d4c96SMarkus Armbruster static bool parse_type_number(Visitor *v, const char *name, double *obj,
349a020f980SPaolo Bonzini Error **errp)
350a020f980SPaolo Bonzini {
351d7bea75dSEric Blake StringInputVisitor *siv = to_siv(v);
352a020f980SPaolo Bonzini double val;
353a020f980SPaolo Bonzini
354c9fba9deSDavid Hildenbrand assert(siv->lm == LM_NONE);
3554b69d4c3SDavid Hildenbrand if (qemu_strtod_finite(siv->string, NULL, &val)) {
356*aaeafa50SPhilippe Mathieu-Daudé error_setg(errp, "Invalid parameter type for '%s', expected: number",
357*aaeafa50SPhilippe Mathieu-Daudé name ? name : "null");
358012d4c96SMarkus Armbruster return false;
359a020f980SPaolo Bonzini }
360a020f980SPaolo Bonzini
361a020f980SPaolo Bonzini *obj = val;
362012d4c96SMarkus Armbruster return true;
363a020f980SPaolo Bonzini }
364a020f980SPaolo Bonzini
parse_type_null(Visitor * v,const char * name,QNull ** obj,Error ** errp)365012d4c96SMarkus Armbruster static bool parse_type_null(Visitor *v, const char *name, QNull **obj,
366d2f95f4dSMarkus Armbruster Error **errp)
367a7333712SGreg Kurz {
368a7333712SGreg Kurz StringInputVisitor *siv = to_siv(v);
369a7333712SGreg Kurz
370c9fba9deSDavid Hildenbrand assert(siv->lm == LM_NONE);
371d2f95f4dSMarkus Armbruster *obj = NULL;
372d2f95f4dSMarkus Armbruster
373c9fba9deSDavid Hildenbrand if (siv->string[0]) {
374*aaeafa50SPhilippe Mathieu-Daudé error_setg(errp, "Invalid parameter type for '%s', expected: null",
375*aaeafa50SPhilippe Mathieu-Daudé name ? name : "null");
376012d4c96SMarkus Armbruster return false;
377a7333712SGreg Kurz }
378d2f95f4dSMarkus Armbruster
379d2f95f4dSMarkus Armbruster *obj = qnull();
380012d4c96SMarkus Armbruster return true;
381a7333712SGreg Kurz }
382a7333712SGreg Kurz
string_input_free(Visitor * v)3832c0ef9f4SEric Blake static void string_input_free(Visitor *v)
3842c0ef9f4SEric Blake {
3852c0ef9f4SEric Blake StringInputVisitor *siv = to_siv(v);
3862c0ef9f4SEric Blake
3877a0525c7SEric Blake g_free(siv);
3882c0ef9f4SEric Blake }
3892c0ef9f4SEric Blake
string_input_visitor_new(const char * str)3907a0525c7SEric Blake Visitor *string_input_visitor_new(const char *str)
391a020f980SPaolo Bonzini {
392a020f980SPaolo Bonzini StringInputVisitor *v;
393a020f980SPaolo Bonzini
394f332e830SMarkus Armbruster assert(str);
395a020f980SPaolo Bonzini v = g_malloc0(sizeof(*v));
396a020f980SPaolo Bonzini
397983f52d4SEric Blake v->visitor.type = VISITOR_INPUT;
3984c40314aSEric Blake v->visitor.type_int64 = parse_type_int64;
399f755dea7SEric Blake v->visitor.type_uint64 = parse_type_uint64;
400a5829ccfSPaolo Bonzini v->visitor.type_size = parse_type_size;
401a020f980SPaolo Bonzini v->visitor.type_bool = parse_type_bool;
402a020f980SPaolo Bonzini v->visitor.type_str = parse_type_str;
403a020f980SPaolo Bonzini v->visitor.type_number = parse_type_number;
404a7333712SGreg Kurz v->visitor.type_null = parse_type_null;
405659268ffSHu Tao v->visitor.start_list = start_list;
406659268ffSHu Tao v->visitor.next_list = next_list;
407a4a1c70dSMarkus Armbruster v->visitor.check_list = check_list;
408659268ffSHu Tao v->visitor.end_list = end_list;
4092c0ef9f4SEric Blake v->visitor.free = string_input_free;
410a020f980SPaolo Bonzini
411a020f980SPaolo Bonzini v->string = str;
412c9fba9deSDavid Hildenbrand v->lm = LM_NONE;
4137a0525c7SEric Blake return &v->visitor;
414a020f980SPaolo Bonzini }
415