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