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