|
|
1.1 ! root 1: /* ! 2: * Input Visitor ! 3: * ! 4: * Copyright IBM, Corp. 2011 ! 5: * ! 6: * Authors: ! 7: * Anthony Liguori <[email protected]> ! 8: * ! 9: * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. ! 10: * See the COPYING.LIB file in the top-level directory. ! 11: * ! 12: */ ! 13: ! 14: #include "qmp-input-visitor.h" ! 15: #include "qemu-queue.h" ! 16: #include "qemu-common.h" ! 17: #include "qemu-objects.h" ! 18: #include "qerror.h" ! 19: ! 20: #define QIV_STACK_SIZE 1024 ! 21: ! 22: typedef struct StackObject ! 23: { ! 24: const QObject *obj; ! 25: const QListEntry *entry; ! 26: } StackObject; ! 27: ! 28: struct QmpInputVisitor ! 29: { ! 30: Visitor visitor; ! 31: QObject *obj; ! 32: StackObject stack[QIV_STACK_SIZE]; ! 33: int nb_stack; ! 34: }; ! 35: ! 36: static QmpInputVisitor *to_qiv(Visitor *v) ! 37: { ! 38: return container_of(v, QmpInputVisitor, visitor); ! 39: } ! 40: ! 41: static const QObject *qmp_input_get_object(QmpInputVisitor *qiv, ! 42: const char *name) ! 43: { ! 44: const QObject *qobj; ! 45: ! 46: if (qiv->nb_stack == 0) { ! 47: qobj = qiv->obj; ! 48: } else { ! 49: qobj = qiv->stack[qiv->nb_stack - 1].obj; ! 50: } ! 51: ! 52: if (name && qobject_type(qobj) == QTYPE_QDICT) { ! 53: return qdict_get(qobject_to_qdict(qobj), name); ! 54: } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) { ! 55: return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry); ! 56: } ! 57: ! 58: return qobj; ! 59: } ! 60: ! 61: static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp) ! 62: { ! 63: qiv->stack[qiv->nb_stack].obj = obj; ! 64: if (qobject_type(obj) == QTYPE_QLIST) { ! 65: qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj)); ! 66: } ! 67: qiv->nb_stack++; ! 68: ! 69: if (qiv->nb_stack >= QIV_STACK_SIZE) { ! 70: error_set(errp, QERR_BUFFER_OVERRUN); ! 71: return; ! 72: } ! 73: } ! 74: ! 75: static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp) ! 76: { ! 77: qiv->nb_stack--; ! 78: if (qiv->nb_stack < 0) { ! 79: error_set(errp, QERR_BUFFER_OVERRUN); ! 80: return; ! 81: } ! 82: } ! 83: ! 84: static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind, ! 85: const char *name, size_t size, Error **errp) ! 86: { ! 87: QmpInputVisitor *qiv = to_qiv(v); ! 88: const QObject *qobj = qmp_input_get_object(qiv, name); ! 89: ! 90: if (!qobj || qobject_type(qobj) != QTYPE_QDICT) { ! 91: error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", ! 92: "QDict"); ! 93: return; ! 94: } ! 95: ! 96: qmp_input_push(qiv, qobj, errp); ! 97: if (error_is_set(errp)) { ! 98: return; ! 99: } ! 100: ! 101: if (obj) { ! 102: *obj = qemu_mallocz(size); ! 103: } ! 104: } ! 105: ! 106: static void qmp_input_end_struct(Visitor *v, Error **errp) ! 107: { ! 108: QmpInputVisitor *qiv = to_qiv(v); ! 109: ! 110: qmp_input_pop(qiv, errp); ! 111: } ! 112: ! 113: static void qmp_input_start_list(Visitor *v, const char *name, Error **errp) ! 114: { ! 115: QmpInputVisitor *qiv = to_qiv(v); ! 116: const QObject *qobj = qmp_input_get_object(qiv, name); ! 117: ! 118: if (!qobj || qobject_type(qobj) != QTYPE_QLIST) { ! 119: error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", ! 120: "list"); ! 121: return; ! 122: } ! 123: ! 124: qmp_input_push(qiv, qobj, errp); ! 125: } ! 126: ! 127: static GenericList *qmp_input_next_list(Visitor *v, GenericList **list, ! 128: Error **errp) ! 129: { ! 130: QmpInputVisitor *qiv = to_qiv(v); ! 131: GenericList *entry; ! 132: StackObject *so = &qiv->stack[qiv->nb_stack - 1]; ! 133: ! 134: if (so->entry == NULL) { ! 135: return NULL; ! 136: } ! 137: ! 138: entry = qemu_mallocz(sizeof(*entry)); ! 139: if (*list) { ! 140: so->entry = qlist_next(so->entry); ! 141: if (so->entry == NULL) { ! 142: qemu_free(entry); ! 143: return NULL; ! 144: } ! 145: (*list)->next = entry; ! 146: } ! 147: *list = entry; ! 148: ! 149: ! 150: return entry; ! 151: } ! 152: ! 153: static void qmp_input_end_list(Visitor *v, Error **errp) ! 154: { ! 155: QmpInputVisitor *qiv = to_qiv(v); ! 156: ! 157: qmp_input_pop(qiv, errp); ! 158: } ! 159: ! 160: static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name, ! 161: Error **errp) ! 162: { ! 163: QmpInputVisitor *qiv = to_qiv(v); ! 164: const QObject *qobj = qmp_input_get_object(qiv, name); ! 165: ! 166: if (!qobj || qobject_type(qobj) != QTYPE_QINT) { ! 167: error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", ! 168: "integer"); ! 169: return; ! 170: } ! 171: ! 172: *obj = qint_get_int(qobject_to_qint(qobj)); ! 173: } ! 174: ! 175: static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name, ! 176: Error **errp) ! 177: { ! 178: QmpInputVisitor *qiv = to_qiv(v); ! 179: const QObject *qobj = qmp_input_get_object(qiv, name); ! 180: ! 181: if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) { ! 182: error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", ! 183: "boolean"); ! 184: return; ! 185: } ! 186: ! 187: *obj = qbool_get_int(qobject_to_qbool(qobj)); ! 188: } ! 189: ! 190: static void qmp_input_type_str(Visitor *v, char **obj, const char *name, ! 191: Error **errp) ! 192: { ! 193: QmpInputVisitor *qiv = to_qiv(v); ! 194: const QObject *qobj = qmp_input_get_object(qiv, name); ! 195: ! 196: if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) { ! 197: error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", ! 198: "string"); ! 199: return; ! 200: } ! 201: ! 202: *obj = qemu_strdup(qstring_get_str(qobject_to_qstring(qobj))); ! 203: } ! 204: ! 205: static void qmp_input_type_number(Visitor *v, double *obj, const char *name, ! 206: Error **errp) ! 207: { ! 208: QmpInputVisitor *qiv = to_qiv(v); ! 209: const QObject *qobj = qmp_input_get_object(qiv, name); ! 210: ! 211: if (!qobj || qobject_type(qobj) != QTYPE_QFLOAT) { ! 212: error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", ! 213: "double"); ! 214: return; ! 215: } ! 216: ! 217: *obj = qfloat_get_double(qobject_to_qfloat(qobj)); ! 218: } ! 219: ! 220: static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[], ! 221: const char *kind, const char *name, ! 222: Error **errp) ! 223: { ! 224: int64_t value = 0; ! 225: char *enum_str; ! 226: ! 227: assert(strings); ! 228: ! 229: qmp_input_type_str(v, &enum_str, name, errp); ! 230: if (error_is_set(errp)) { ! 231: return; ! 232: } ! 233: ! 234: while (strings[value] != NULL) { ! 235: if (strcmp(strings[value], enum_str) == 0) { ! 236: break; ! 237: } ! 238: value++; ! 239: } ! 240: ! 241: if (strings[value] == NULL) { ! 242: error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null"); ! 243: return; ! 244: } ! 245: ! 246: *obj = value; ! 247: } ! 248: ! 249: static void qmp_input_start_optional(Visitor *v, bool *present, ! 250: const char *name, Error **errp) ! 251: { ! 252: QmpInputVisitor *qiv = to_qiv(v); ! 253: const QObject *qobj = qmp_input_get_object(qiv, name); ! 254: ! 255: if (!qobj) { ! 256: *present = false; ! 257: return; ! 258: } ! 259: ! 260: *present = true; ! 261: } ! 262: ! 263: static void qmp_input_end_optional(Visitor *v, Error **errp) ! 264: { ! 265: } ! 266: ! 267: Visitor *qmp_input_get_visitor(QmpInputVisitor *v) ! 268: { ! 269: return &v->visitor; ! 270: } ! 271: ! 272: void qmp_input_visitor_cleanup(QmpInputVisitor *v) ! 273: { ! 274: qobject_decref(v->obj); ! 275: qemu_free(v); ! 276: } ! 277: ! 278: QmpInputVisitor *qmp_input_visitor_new(QObject *obj) ! 279: { ! 280: QmpInputVisitor *v; ! 281: ! 282: v = qemu_mallocz(sizeof(*v)); ! 283: ! 284: v->visitor.start_struct = qmp_input_start_struct; ! 285: v->visitor.end_struct = qmp_input_end_struct; ! 286: v->visitor.start_list = qmp_input_start_list; ! 287: v->visitor.next_list = qmp_input_next_list; ! 288: v->visitor.end_list = qmp_input_end_list; ! 289: v->visitor.type_enum = qmp_input_type_enum; ! 290: v->visitor.type_int = qmp_input_type_int; ! 291: v->visitor.type_bool = qmp_input_type_bool; ! 292: v->visitor.type_str = qmp_input_type_str; ! 293: v->visitor.type_number = qmp_input_type_number; ! 294: v->visitor.start_optional = qmp_input_start_optional; ! 295: v->visitor.end_optional = qmp_input_end_optional; ! 296: ! 297: v->obj = obj; ! 298: qobject_incref(v->obj); ! 299: ! 300: return v; ! 301: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.