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