|
|
1.1 ! root 1: /* ! 2: * Core Definitions for QAPI/QMP Command Registry ! 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-output-visitor.h" ! 15: #include "qemu-queue.h" ! 16: #include "qemu-common.h" ! 17: #include "qemu-objects.h" ! 18: #include "qerror.h" ! 19: ! 20: typedef struct QStackEntry ! 21: { ! 22: QObject *value; ! 23: QTAILQ_ENTRY(QStackEntry) node; ! 24: } QStackEntry; ! 25: ! 26: typedef QTAILQ_HEAD(QStack, QStackEntry) QStack; ! 27: ! 28: struct QmpOutputVisitor ! 29: { ! 30: Visitor visitor; ! 31: QStack stack; ! 32: }; ! 33: ! 34: #define qmp_output_add(qov, name, value) \ ! 35: qmp_output_add_obj(qov, name, QOBJECT(value)) ! 36: #define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value)) ! 37: ! 38: static QmpOutputVisitor *to_qov(Visitor *v) ! 39: { ! 40: return container_of(v, QmpOutputVisitor, visitor); ! 41: } ! 42: ! 43: static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value) ! 44: { ! 45: QStackEntry *e = qemu_mallocz(sizeof(*e)); ! 46: ! 47: e->value = value; ! 48: QTAILQ_INSERT_HEAD(&qov->stack, e, node); ! 49: } ! 50: ! 51: static QObject *qmp_output_pop(QmpOutputVisitor *qov) ! 52: { ! 53: QStackEntry *e = QTAILQ_FIRST(&qov->stack); ! 54: QObject *value; ! 55: QTAILQ_REMOVE(&qov->stack, e, node); ! 56: value = e->value; ! 57: qemu_free(e); ! 58: return value; ! 59: } ! 60: ! 61: static QObject *qmp_output_first(QmpOutputVisitor *qov) ! 62: { ! 63: QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack); ! 64: return e->value; ! 65: } ! 66: ! 67: static QObject *qmp_output_last(QmpOutputVisitor *qov) ! 68: { ! 69: QStackEntry *e = QTAILQ_FIRST(&qov->stack); ! 70: return e->value; ! 71: } ! 72: ! 73: static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name, ! 74: QObject *value) ! 75: { ! 76: QObject *cur; ! 77: ! 78: if (QTAILQ_EMPTY(&qov->stack)) { ! 79: qmp_output_push_obj(qov, value); ! 80: return; ! 81: } ! 82: ! 83: cur = qmp_output_last(qov); ! 84: ! 85: switch (qobject_type(cur)) { ! 86: case QTYPE_QDICT: ! 87: qdict_put_obj(qobject_to_qdict(cur), name, value); ! 88: break; ! 89: case QTYPE_QLIST: ! 90: qlist_append_obj(qobject_to_qlist(cur), value); ! 91: break; ! 92: default: ! 93: qobject_decref(qmp_output_pop(qov)); ! 94: qmp_output_push_obj(qov, value); ! 95: break; ! 96: } ! 97: } ! 98: ! 99: static void qmp_output_start_struct(Visitor *v, void **obj, const char *kind, ! 100: const char *name, size_t unused, ! 101: Error **errp) ! 102: { ! 103: QmpOutputVisitor *qov = to_qov(v); ! 104: QDict *dict = qdict_new(); ! 105: ! 106: qmp_output_add(qov, name, dict); ! 107: qmp_output_push(qov, dict); ! 108: } ! 109: ! 110: static void qmp_output_end_struct(Visitor *v, Error **errp) ! 111: { ! 112: QmpOutputVisitor *qov = to_qov(v); ! 113: qmp_output_pop(qov); ! 114: } ! 115: ! 116: static void qmp_output_start_list(Visitor *v, const char *name, Error **errp) ! 117: { ! 118: QmpOutputVisitor *qov = to_qov(v); ! 119: QList *list = qlist_new(); ! 120: ! 121: qmp_output_add(qov, name, list); ! 122: qmp_output_push(qov, list); ! 123: } ! 124: ! 125: static GenericList *qmp_output_next_list(Visitor *v, GenericList **list, ! 126: Error **errp) ! 127: { ! 128: GenericList *retval = *list; ! 129: *list = retval->next; ! 130: return retval; ! 131: } ! 132: ! 133: static void qmp_output_end_list(Visitor *v, Error **errp) ! 134: { ! 135: QmpOutputVisitor *qov = to_qov(v); ! 136: qmp_output_pop(qov); ! 137: } ! 138: ! 139: static void qmp_output_type_int(Visitor *v, int64_t *obj, const char *name, ! 140: Error **errp) ! 141: { ! 142: QmpOutputVisitor *qov = to_qov(v); ! 143: qmp_output_add(qov, name, qint_from_int(*obj)); ! 144: } ! 145: ! 146: static void qmp_output_type_bool(Visitor *v, bool *obj, const char *name, ! 147: Error **errp) ! 148: { ! 149: QmpOutputVisitor *qov = to_qov(v); ! 150: qmp_output_add(qov, name, qbool_from_int(*obj)); ! 151: } ! 152: ! 153: static void qmp_output_type_str(Visitor *v, char **obj, const char *name, ! 154: Error **errp) ! 155: { ! 156: QmpOutputVisitor *qov = to_qov(v); ! 157: if (*obj) { ! 158: qmp_output_add(qov, name, qstring_from_str(*obj)); ! 159: } else { ! 160: qmp_output_add(qov, name, qstring_from_str("")); ! 161: } ! 162: } ! 163: ! 164: static void qmp_output_type_number(Visitor *v, double *obj, const char *name, ! 165: Error **errp) ! 166: { ! 167: QmpOutputVisitor *qov = to_qov(v); ! 168: qmp_output_add(qov, name, qfloat_from_double(*obj)); ! 169: } ! 170: ! 171: static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[], ! 172: const char *kind, const char *name, ! 173: Error **errp) ! 174: { ! 175: int i = 0; ! 176: int value = *obj; ! 177: char *enum_str; ! 178: ! 179: assert(strings); ! 180: while (strings[i++] != NULL); ! 181: if (value >= i - 1) { ! 182: error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null"); ! 183: return; ! 184: } ! 185: ! 186: enum_str = (char *)strings[value]; ! 187: qmp_output_type_str(v, &enum_str, name, errp); ! 188: } ! 189: ! 190: QObject *qmp_output_get_qobject(QmpOutputVisitor *qov) ! 191: { ! 192: QObject *obj = qmp_output_first(qov); ! 193: if (obj) { ! 194: qobject_incref(obj); ! 195: } ! 196: return obj; ! 197: } ! 198: ! 199: Visitor *qmp_output_get_visitor(QmpOutputVisitor *v) ! 200: { ! 201: return &v->visitor; ! 202: } ! 203: ! 204: void qmp_output_visitor_cleanup(QmpOutputVisitor *v) ! 205: { ! 206: QStackEntry *e, *tmp; ! 207: ! 208: QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) { ! 209: QTAILQ_REMOVE(&v->stack, e, node); ! 210: if (e->value) { ! 211: qobject_decref(e->value); ! 212: } ! 213: qemu_free(e); ! 214: } ! 215: ! 216: qemu_free(v); ! 217: } ! 218: ! 219: QmpOutputVisitor *qmp_output_visitor_new(void) ! 220: { ! 221: QmpOutputVisitor *v; ! 222: ! 223: v = qemu_mallocz(sizeof(*v)); ! 224: ! 225: v->visitor.start_struct = qmp_output_start_struct; ! 226: v->visitor.end_struct = qmp_output_end_struct; ! 227: v->visitor.start_list = qmp_output_start_list; ! 228: v->visitor.next_list = qmp_output_next_list; ! 229: v->visitor.end_list = qmp_output_end_list; ! 230: v->visitor.type_enum = qmp_output_type_enum; ! 231: v->visitor.type_int = qmp_output_type_int; ! 232: v->visitor.type_bool = qmp_output_type_bool; ! 233: v->visitor.type_str = qmp_output_type_str; ! 234: v->visitor.type_number = qmp_output_type_number; ! 235: ! 236: QTAILQ_INIT(&v->stack); ! 237: ! 238: return v; ! 239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.