2 * String parsing visitor
4 * Copyright Red Hat, Inc. 2012
6 * Author: Paolo Bonzini <pbonzini@redhat.com>
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.
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 #include "qemu/queue.h"
19 #include "qemu/range.h"
22 struct StringInputVisitor
35 static void free_range(void *range
, void *dummy
)
40 static void parse_str(StringInputVisitor
*siv
, Error
**errp
)
42 char *str
= (char *) siv
->string
;
53 start
= strtoll(str
, &endptr
, 0);
54 if (errno
== 0 && endptr
> str
&& INT64_MIN
<= start
&&
56 if (*endptr
== '\0') {
57 cur
= g_malloc0(sizeof(*cur
));
60 siv
->ranges
= g_list_insert_sorted_merged(siv
->ranges
, cur
,
64 } else if (*endptr
== '-') {
66 end
= strtoll(str
, &endptr
, 0);
67 if (errno
== 0 && endptr
> str
&&
68 INT64_MIN
<= end
&& end
<= INT64_MAX
&& start
<= end
&&
69 (start
> INT64_MAX
- 65536 ||
70 end
< start
+ 65536)) {
71 if (*endptr
== '\0') {
72 cur
= g_malloc0(sizeof(*cur
));
76 g_list_insert_sorted_merged(siv
->ranges
,
81 } else if (*endptr
== ',') {
83 cur
= g_malloc0(sizeof(*cur
));
87 g_list_insert_sorted_merged(siv
->ranges
,
97 } else if (*endptr
== ',') {
99 cur
= g_malloc0(sizeof(*cur
));
101 cur
->end
= start
+ 1;
102 siv
->ranges
= g_list_insert_sorted_merged(siv
->ranges
,
116 g_list_foreach(siv
->ranges
, free_range
, NULL
);
117 g_list_free(siv
->ranges
);
122 start_list(Visitor
*v
, const char *name
, Error
**errp
)
124 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
126 parse_str(siv
, errp
);
128 siv
->cur_range
= g_list_first(siv
->ranges
);
129 if (siv
->cur_range
) {
130 Range
*r
= siv
->cur_range
->data
;
138 next_list(Visitor
*v
, GenericList
**list
, Error
**errp
)
140 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
144 if (!siv
->ranges
|| !siv
->cur_range
) {
148 r
= siv
->cur_range
->data
;
153 if (siv
->cur
< r
->begin
|| siv
->cur
>= r
->end
) {
154 siv
->cur_range
= g_list_next(siv
->cur_range
);
155 if (!siv
->cur_range
) {
158 r
= siv
->cur_range
->data
;
169 link
= &(*list
)->next
;
172 *link
= g_malloc0(sizeof **link
);
177 end_list(Visitor
*v
, Error
**errp
)
179 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
183 static void parse_type_int(Visitor
*v
, int64_t *obj
, const char *name
,
186 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
189 error_set(errp
, QERR_INVALID_PARAMETER_TYPE
, name
? name
: "null",
194 parse_str(siv
, errp
);
200 if (!siv
->cur_range
) {
203 siv
->cur_range
= g_list_first(siv
->ranges
);
204 if (!siv
->cur_range
) {
208 r
= siv
->cur_range
->data
;
221 error_set(errp
, QERR_INVALID_PARAMETER_VALUE
, name
,
222 "an int64 value or range");
225 static void parse_type_size(Visitor
*v
, uint64_t *obj
, const char *name
,
228 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
233 parse_option_size(name
, siv
->string
, &val
, &err
);
235 error_set(errp
, QERR_INVALID_PARAMETER_TYPE
, name
? name
: "null",
240 error_propagate(errp
, err
);
247 static void parse_type_bool(Visitor
*v
, bool *obj
, const char *name
,
250 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
253 if (!strcasecmp(siv
->string
, "on") ||
254 !strcasecmp(siv
->string
, "yes") ||
255 !strcasecmp(siv
->string
, "true")) {
259 if (!strcasecmp(siv
->string
, "off") ||
260 !strcasecmp(siv
->string
, "no") ||
261 !strcasecmp(siv
->string
, "false")) {
267 error_set(errp
, QERR_INVALID_PARAMETER_TYPE
, name
? name
: "null",
271 static void parse_type_str(Visitor
*v
, char **obj
, const char *name
,
274 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
276 *obj
= g_strdup(siv
->string
);
278 error_set(errp
, QERR_INVALID_PARAMETER_TYPE
, name
? name
: "null",
283 static void parse_type_number(Visitor
*v
, double *obj
, const char *name
,
286 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
287 char *endp
= (char *) siv
->string
;
292 val
= strtod(siv
->string
, &endp
);
294 if (!siv
->string
|| errno
|| endp
== siv
->string
|| *endp
) {
295 error_set(errp
, QERR_INVALID_PARAMETER_TYPE
, name
? name
: "null",
303 static void parse_optional(Visitor
*v
, bool *present
, const char *name
,
306 StringInputVisitor
*siv
= DO_UPCAST(StringInputVisitor
, visitor
, v
);
316 Visitor
*string_input_get_visitor(StringInputVisitor
*v
)
321 void string_input_visitor_cleanup(StringInputVisitor
*v
)
323 g_list_foreach(v
->ranges
, free_range
, NULL
);
324 g_list_free(v
->ranges
);
328 StringInputVisitor
*string_input_visitor_new(const char *str
)
330 StringInputVisitor
*v
;
332 v
= g_malloc0(sizeof(*v
));
334 v
->visitor
.type_enum
= input_type_enum
;
335 v
->visitor
.type_int
= parse_type_int
;
336 v
->visitor
.type_size
= parse_type_size
;
337 v
->visitor
.type_bool
= parse_type_bool
;
338 v
->visitor
.type_str
= parse_type_str
;
339 v
->visitor
.type_number
= parse_type_number
;
340 v
->visitor
.start_list
= start_list
;
341 v
->visitor
.next_list
= next_list
;
342 v
->visitor
.end_list
= end_list
;
343 v
->visitor
.optional
= parse_optional
;