| 
									
										
										
										
											2012-02-09 09:36:37 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * String parsing visitor | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright Red Hat, Inc. 2012 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Author: Paolo Bonzini <pbonzini@redhat.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. | 
					
						
							|  |  |  |  * See the COPYING.LIB file in the top-level directory. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "qemu-common.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-17 18:19:43 +01:00
										 |  |  | #include "qapi/string-input-visitor.h"
 | 
					
						
							|  |  |  | #include "qapi/visitor-impl.h"
 | 
					
						
							|  |  |  | #include "qapi/qmp/qerror.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-08 11:01:44 +01:00
										 |  |  | #include "qemu/option.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-09 09:36:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct StringInputVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Visitor visitor; | 
					
						
							|  |  |  |     const char *string; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parse_type_int(Visitor *v, int64_t *obj, const char *name, | 
					
						
							|  |  |  |                            Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); | 
					
						
							|  |  |  |     char *endp = (char *) siv->string; | 
					
						
							|  |  |  |     long long val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     errno = 0; | 
					
						
							|  |  |  |     if (siv->string) { | 
					
						
							|  |  |  |         val = strtoll(siv->string, &endp, 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!siv->string || errno || endp == siv->string || *endp) { | 
					
						
							|  |  |  |         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", | 
					
						
							|  |  |  |                   "integer"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *obj = val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-08 11:01:44 +01:00
										 |  |  | static void parse_type_size(Visitor *v, uint64_t *obj, const char *name, | 
					
						
							|  |  |  |                             Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); | 
					
						
							|  |  |  |     Error *err = NULL; | 
					
						
							|  |  |  |     uint64_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (siv->string) { | 
					
						
							|  |  |  |         parse_option_size(name, siv->string, &val, &err); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", | 
					
						
							|  |  |  |                   "size"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         error_propagate(errp, err); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *obj = val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-09 09:36:37 +01:00
										 |  |  | static void parse_type_bool(Visitor *v, bool *obj, const char *name, | 
					
						
							|  |  |  |                             Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (siv->string) { | 
					
						
							|  |  |  |         if (!strcasecmp(siv->string, "on") || | 
					
						
							|  |  |  |             !strcasecmp(siv->string, "yes") || | 
					
						
							|  |  |  |             !strcasecmp(siv->string, "true")) { | 
					
						
							|  |  |  |             *obj = true; | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!strcasecmp(siv->string, "off") || | 
					
						
							|  |  |  |             !strcasecmp(siv->string, "no") || | 
					
						
							|  |  |  |             !strcasecmp(siv->string, "false")) { | 
					
						
							|  |  |  |             *obj = false; | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", | 
					
						
							|  |  |  |               "boolean"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parse_type_str(Visitor *v, char **obj, const char *name, | 
					
						
							|  |  |  |                            Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); | 
					
						
							|  |  |  |     if (siv->string) { | 
					
						
							|  |  |  |         *obj = g_strdup(siv->string); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", | 
					
						
							|  |  |  |                   "string"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parse_type_number(Visitor *v, double *obj, const char *name, | 
					
						
							|  |  |  |                               Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); | 
					
						
							|  |  |  |     char *endp = (char *) siv->string; | 
					
						
							|  |  |  |     double val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     errno = 0; | 
					
						
							|  |  |  |     if (siv->string) { | 
					
						
							|  |  |  |         val = strtod(siv->string, &endp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!siv->string || errno || endp == siv->string || *endp) { | 
					
						
							|  |  |  |         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", | 
					
						
							|  |  |  |                   "number"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *obj = val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-07 09:53:46 +02:00
										 |  |  | static void parse_optional(Visitor *v, bool *present, const char *name, | 
					
						
							|  |  |  |                            Error **errp) | 
					
						
							| 
									
										
										
										
											2012-02-09 09:36:37 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!siv->string) { | 
					
						
							|  |  |  |         *present = false; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *present = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Visitor *string_input_get_visitor(StringInputVisitor *v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return &v->visitor; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void string_input_visitor_cleanup(StringInputVisitor *v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     g_free(v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StringInputVisitor *string_input_visitor_new(const char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringInputVisitor *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     v = g_malloc0(sizeof(*v)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     v->visitor.type_enum = input_type_enum; | 
					
						
							|  |  |  |     v->visitor.type_int = parse_type_int; | 
					
						
							| 
									
										
										
										
											2014-02-08 11:01:44 +01:00
										 |  |  |     v->visitor.type_size = parse_type_size; | 
					
						
							| 
									
										
										
										
											2012-02-09 09:36:37 +01:00
										 |  |  |     v->visitor.type_bool = parse_type_bool; | 
					
						
							|  |  |  |     v->visitor.type_str = parse_type_str; | 
					
						
							|  |  |  |     v->visitor.type_number = parse_type_number; | 
					
						
							| 
									
										
										
										
											2014-05-07 09:53:46 +02:00
										 |  |  |     v->visitor.optional = parse_optional; | 
					
						
							| 
									
										
										
										
											2012-02-09 09:36:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     v->string = str; | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  | } |