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_start_optional(Visitor *v, bool *present, 124 const char *name, 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.start_optional = parse_start_optional; 159 160 v->string = str; 161 return v; 162 } 163