2
0

qobject-output-visitor.c 7.6 KB

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