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