|
|
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.