1 /* 2 * Core Definitions for QAPI Visitor Classes 3 * 4 * Copyright (C) 2012-2016 Red Hat, Inc. 5 * Copyright IBM, Corp. 2011 6 * 7 * Authors: 8 * Anthony Liguori <aliguori@us.ibm.com> 9 * 10 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 11 * See the COPYING.LIB file in the top-level directory. 12 * 13 */ 14 15 #include "qemu/osdep.h" 16 #include "qapi/error.h" 17 #include "qemu-common.h" 18 #include "qapi/qmp/qobject.h" 19 #include "qapi/qmp/qerror.h" 20 #include "qapi/visitor.h" 21 #include "qapi/visitor-impl.h" 22 23 void visit_start_struct(Visitor *v, const char *name, void **obj, 24 size_t size, Error **errp) 25 { 26 Error *err = NULL; 27 28 v->start_struct(v, name, obj, size, &err); 29 if (obj && v->type == VISITOR_INPUT) { 30 assert(!err != !*obj); 31 } 32 error_propagate(errp, err); 33 } 34 35 void visit_end_struct(Visitor *v, Error **errp) 36 { 37 v->end_struct(v, errp); 38 } 39 40 void visit_start_list(Visitor *v, const char *name, Error **errp) 41 { 42 v->start_list(v, name, errp); 43 } 44 45 GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size) 46 { 47 assert(list && size >= sizeof(GenericList)); 48 return v->next_list(v, list, size); 49 } 50 51 void visit_end_list(Visitor *v) 52 { 53 v->end_list(v); 54 } 55 56 void visit_start_alternate(Visitor *v, const char *name, 57 GenericAlternate **obj, size_t size, 58 bool promote_int, Error **errp) 59 { 60 Error *err = NULL; 61 62 assert(obj && size >= sizeof(GenericAlternate)); 63 if (v->start_alternate) { 64 v->start_alternate(v, name, obj, size, promote_int, &err); 65 } 66 if (v->type == VISITOR_INPUT) { 67 assert(v->start_alternate && !err != !*obj); 68 } 69 error_propagate(errp, err); 70 } 71 72 void visit_end_alternate(Visitor *v) 73 { 74 if (v->end_alternate) { 75 v->end_alternate(v); 76 } 77 } 78 79 bool visit_optional(Visitor *v, const char *name, bool *present) 80 { 81 if (v->optional) { 82 v->optional(v, name, present); 83 } 84 return *present; 85 } 86 87 void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) 88 { 89 v->type_int64(v, name, obj, errp); 90 } 91 92 static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name, 93 uint64_t max, const char *type, Error **errp) 94 { 95 Error *err = NULL; 96 uint64_t value = *obj; 97 98 v->type_uint64(v, name, &value, &err); 99 if (err) { 100 error_propagate(errp, err); 101 } else if (value > max) { 102 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 103 name ? name : "null", type); 104 } else { 105 *obj = value; 106 } 107 } 108 109 void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, 110 Error **errp) 111 { 112 uint64_t value = *obj; 113 visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp); 114 *obj = value; 115 } 116 117 void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, 118 Error **errp) 119 { 120 uint64_t value = *obj; 121 visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp); 122 *obj = value; 123 } 124 125 void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, 126 Error **errp) 127 { 128 uint64_t value = *obj; 129 visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp); 130 *obj = value; 131 } 132 133 void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, 134 Error **errp) 135 { 136 v->type_uint64(v, name, obj, errp); 137 } 138 139 static void visit_type_intN(Visitor *v, int64_t *obj, const char *name, 140 int64_t min, int64_t max, const char *type, 141 Error **errp) 142 { 143 Error *err = NULL; 144 int64_t value = *obj; 145 146 v->type_int64(v, name, &value, &err); 147 if (err) { 148 error_propagate(errp, err); 149 } else if (value < min || value > max) { 150 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 151 name ? name : "null", type); 152 } else { 153 *obj = value; 154 } 155 } 156 157 void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp) 158 { 159 int64_t value = *obj; 160 visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp); 161 *obj = value; 162 } 163 164 void visit_type_int16(Visitor *v, const char *name, int16_t *obj, 165 Error **errp) 166 { 167 int64_t value = *obj; 168 visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp); 169 *obj = value; 170 } 171 172 void visit_type_int32(Visitor *v, const char *name, int32_t *obj, 173 Error **errp) 174 { 175 int64_t value = *obj; 176 visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp); 177 *obj = value; 178 } 179 180 void visit_type_int64(Visitor *v, const char *name, int64_t *obj, 181 Error **errp) 182 { 183 v->type_int64(v, name, obj, errp); 184 } 185 186 void visit_type_size(Visitor *v, const char *name, uint64_t *obj, 187 Error **errp) 188 { 189 if (v->type_size) { 190 v->type_size(v, name, obj, errp); 191 } else { 192 v->type_uint64(v, name, obj, errp); 193 } 194 } 195 196 void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) 197 { 198 v->type_bool(v, name, obj, errp); 199 } 200 201 void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp) 202 { 203 Error *err = NULL; 204 205 assert(obj); 206 v->type_str(v, name, obj, &err); 207 if (v->type == VISITOR_INPUT) { 208 assert(!err != !*obj); 209 } 210 error_propagate(errp, err); 211 } 212 213 void visit_type_number(Visitor *v, const char *name, double *obj, 214 Error **errp) 215 { 216 v->type_number(v, name, obj, errp); 217 } 218 219 void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) 220 { 221 Error *err = NULL; 222 223 assert(obj); 224 v->type_any(v, name, obj, &err); 225 if (v->type == VISITOR_INPUT) { 226 assert(!err != !*obj); 227 } 228 error_propagate(errp, err); 229 } 230 231 static void output_type_enum(Visitor *v, const char *name, int *obj, 232 const char *const strings[], Error **errp) 233 { 234 int i = 0; 235 int value = *obj; 236 char *enum_str; 237 238 while (strings[i++] != NULL); 239 if (value < 0 || value >= i - 1) { 240 error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null"); 241 return; 242 } 243 244 enum_str = (char *)strings[value]; 245 visit_type_str(v, name, &enum_str, errp); 246 } 247 248 static void input_type_enum(Visitor *v, const char *name, int *obj, 249 const char *const strings[], Error **errp) 250 { 251 Error *local_err = NULL; 252 int64_t value = 0; 253 char *enum_str; 254 255 visit_type_str(v, name, &enum_str, &local_err); 256 if (local_err) { 257 error_propagate(errp, local_err); 258 return; 259 } 260 261 while (strings[value] != NULL) { 262 if (strcmp(strings[value], enum_str) == 0) { 263 break; 264 } 265 value++; 266 } 267 268 if (strings[value] == NULL) { 269 error_setg(errp, QERR_INVALID_PARAMETER, enum_str); 270 g_free(enum_str); 271 return; 272 } 273 274 g_free(enum_str); 275 *obj = value; 276 } 277 278 void visit_type_enum(Visitor *v, const char *name, int *obj, 279 const char *const strings[], Error **errp) 280 { 281 assert(strings); 282 if (v->type == VISITOR_INPUT) { 283 input_type_enum(v, name, obj, strings, errp); 284 } else if (v->type == VISITOR_OUTPUT) { 285 output_type_enum(v, name, obj, strings, errp); 286 } 287 } 288