1 /* 2 * Core Definitions for QAPI/QMP Command Registry 3 * 4 * Copyright (C) 2012-2016 Red Hat, Inc. 5 * Copyright IBM, Corp. 2011 6 * 7 * Authors: 8 * Anthony Liguori <aliguori@us.ibm.com> 9 * 10 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 11 * See the COPYING.LIB file in the top-level directory. 12 * 13 */ 14 15 #include "qemu/osdep.h" 16 #include "qapi/qobject-output-visitor.h" 17 #include "qapi/visitor-impl.h" 18 #include "qemu/queue.h" 19 #include "qemu-common.h" 20 #include "qapi/qmp/types.h" 21 22 typedef struct QStackEntry { 23 QObject *value; 24 void *qapi; /* sanity check that caller uses same pointer */ 25 QSLIST_ENTRY(QStackEntry) node; 26 } QStackEntry; 27 28 struct QObjectOutputVisitor { 29 Visitor visitor; 30 QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */ 31 QObject *root; /* Root of the output visit */ 32 QObject **result; /* User's storage location for result */ 33 }; 34 35 #define qobject_output_add(qov, name, value) \ 36 qobject_output_add_obj(qov, name, QOBJECT(value)) 37 #define qobject_output_push(qov, value, qapi) \ 38 qobject_output_push_obj(qov, QOBJECT(value), qapi) 39 40 static QObjectOutputVisitor *to_qov(Visitor *v) 41 { 42 return container_of(v, QObjectOutputVisitor, visitor); 43 } 44 45 /* Push @value onto the stack of current QObjects being built */ 46 static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value, 47 void *qapi) 48 { 49 QStackEntry *e = g_malloc0(sizeof(*e)); 50 51 assert(qov->root); 52 assert(value); 53 e->value = value; 54 e->qapi = qapi; 55 QSLIST_INSERT_HEAD(&qov->stack, e, node); 56 } 57 58 /* Pop a value off the stack of QObjects being built, and return it. */ 59 static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi) 60 { 61 QStackEntry *e = QSLIST_FIRST(&qov->stack); 62 QObject *value; 63 64 assert(e); 65 assert(e->qapi == qapi); 66 QSLIST_REMOVE_HEAD(&qov->stack, node); 67 value = e->value; 68 assert(value); 69 g_free(e); 70 return value; 71 } 72 73 /* Add @value to the current QObject being built. 74 * If the stack is visiting a dictionary or list, @value is now owned 75 * by that container. Otherwise, @value is now the root. */ 76 static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name, 77 QObject *value) 78 { 79 QStackEntry *e = QSLIST_FIRST(&qov->stack); 80 QObject *cur = e ? e->value : NULL; 81 82 if (!cur) { 83 /* Don't allow reuse of visitor on more than one root */ 84 assert(!qov->root); 85 qov->root = value; 86 } else { 87 switch (qobject_type(cur)) { 88 case QTYPE_QDICT: 89 assert(name); 90 qdict_put_obj(qobject_to_qdict(cur), name, value); 91 break; 92 case QTYPE_QLIST: 93 assert(!name); 94 qlist_append_obj(qobject_to_qlist(cur), value); 95 break; 96 default: 97 g_assert_not_reached(); 98 } 99 } 100 } 101 102 static void qobject_output_start_struct(Visitor *v, const char *name, 103 void **obj, size_t unused, Error **errp) 104 { 105 QObjectOutputVisitor *qov = to_qov(v); 106 QDict *dict = qdict_new(); 107 108 qobject_output_add(qov, name, dict); 109 qobject_output_push(qov, dict, obj); 110 } 111 112 static void qobject_output_end_struct(Visitor *v, void **obj) 113 { 114 QObjectOutputVisitor *qov = to_qov(v); 115 QObject *value = qobject_output_pop(qov, obj); 116 assert(qobject_type(value) == QTYPE_QDICT); 117 } 118 119 static void qobject_output_start_list(Visitor *v, const char *name, 120 GenericList **listp, size_t size, 121 Error **errp) 122 { 123 QObjectOutputVisitor *qov = to_qov(v); 124 QList *list = qlist_new(); 125 126 qobject_output_add(qov, name, list); 127 qobject_output_push(qov, list, listp); 128 } 129 130 static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail, 131 size_t size) 132 { 133 return tail->next; 134 } 135 136 static void qobject_output_end_list(Visitor *v, void **obj) 137 { 138 QObjectOutputVisitor *qov = to_qov(v); 139 QObject *value = qobject_output_pop(qov, obj); 140 assert(qobject_type(value) == QTYPE_QLIST); 141 } 142 143 static void qobject_output_type_int64(Visitor *v, const char *name, 144 int64_t *obj, Error **errp) 145 { 146 QObjectOutputVisitor *qov = to_qov(v); 147 qobject_output_add(qov, name, qnum_from_int(*obj)); 148 } 149 150 static void qobject_output_type_uint64(Visitor *v, const char *name, 151 uint64_t *obj, Error **errp) 152 { 153 QObjectOutputVisitor *qov = to_qov(v); 154 qobject_output_add(qov, name, qnum_from_uint(*obj)); 155 } 156 157 static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj, 158 Error **errp) 159 { 160 QObjectOutputVisitor *qov = to_qov(v); 161 qobject_output_add(qov, name, qbool_from_bool(*obj)); 162 } 163 164 static void qobject_output_type_str(Visitor *v, const char *name, char **obj, 165 Error **errp) 166 { 167 QObjectOutputVisitor *qov = to_qov(v); 168 if (*obj) { 169 qobject_output_add(qov, name, qstring_from_str(*obj)); 170 } else { 171 qobject_output_add(qov, name, qstring_from_str("")); 172 } 173 } 174 175 static void qobject_output_type_number(Visitor *v, const char *name, 176 double *obj, Error **errp) 177 { 178 QObjectOutputVisitor *qov = to_qov(v); 179 qobject_output_add(qov, name, qnum_from_double(*obj)); 180 } 181 182 static void qobject_output_type_any(Visitor *v, const char *name, 183 QObject **obj, Error **errp) 184 { 185 QObjectOutputVisitor *qov = to_qov(v); 186 qobject_incref(*obj); 187 qobject_output_add_obj(qov, name, *obj); 188 } 189 190 static void qobject_output_type_null(Visitor *v, const char *name, 191 QNull **obj, Error **errp) 192 { 193 QObjectOutputVisitor *qov = to_qov(v); 194 qobject_output_add(qov, name, qnull()); 195 } 196 197 /* Finish building, and return the root object. 198 * The root object is never null. The caller becomes the object's 199 * owner, and should use qobject_decref() when done with it. */ 200 static void qobject_output_complete(Visitor *v, void *opaque) 201 { 202 QObjectOutputVisitor *qov = to_qov(v); 203 204 /* A visit must have occurred, with each start paired with end. */ 205 assert(qov->root && QSLIST_EMPTY(&qov->stack)); 206 assert(opaque == qov->result); 207 208 qobject_incref(qov->root); 209 *qov->result = qov->root; 210 qov->result = NULL; 211 } 212 213 static void qobject_output_free(Visitor *v) 214 { 215 QObjectOutputVisitor *qov = to_qov(v); 216 QStackEntry *e; 217 218 while (!QSLIST_EMPTY(&qov->stack)) { 219 e = QSLIST_FIRST(&qov->stack); 220 QSLIST_REMOVE_HEAD(&qov->stack, node); 221 g_free(e); 222 } 223 224 qobject_decref(qov->root); 225 g_free(qov); 226 } 227 228 Visitor *qobject_output_visitor_new(QObject **result) 229 { 230 QObjectOutputVisitor *v; 231 232 v = g_malloc0(sizeof(*v)); 233 234 v->visitor.type = VISITOR_OUTPUT; 235 v->visitor.start_struct = qobject_output_start_struct; 236 v->visitor.end_struct = qobject_output_end_struct; 237 v->visitor.start_list = qobject_output_start_list; 238 v->visitor.next_list = qobject_output_next_list; 239 v->visitor.end_list = qobject_output_end_list; 240 v->visitor.type_int64 = qobject_output_type_int64; 241 v->visitor.type_uint64 = qobject_output_type_uint64; 242 v->visitor.type_bool = qobject_output_type_bool; 243 v->visitor.type_str = qobject_output_type_str; 244 v->visitor.type_number = qobject_output_type_number; 245 v->visitor.type_any = qobject_output_type_any; 246 v->visitor.type_null = qobject_output_type_null; 247 v->visitor.complete = qobject_output_complete; 248 v->visitor.free = qobject_output_free; 249 250 *result = NULL; 251 v->result = result; 252 253 return &v->visitor; 254 } 255