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