2
0

qmp-output-visitor.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Core Definitions for QAPI/QMP Command Registry
  3. *
  4. * Copyright IBM, Corp. 2011
  5. *
  6. * Authors:
  7. * Anthony Liguori <aliguori@us.ibm.com>
  8. *
  9. * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  10. * See the COPYING.LIB file in the top-level directory.
  11. *
  12. */
  13. #include "qmp-output-visitor.h"
  14. #include "qemu-queue.h"
  15. #include "qemu-common.h"
  16. #include "qemu-objects.h"
  17. #include "qerror.h"
  18. typedef struct QStackEntry
  19. {
  20. QObject *value;
  21. QTAILQ_ENTRY(QStackEntry) node;
  22. } QStackEntry;
  23. typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
  24. struct QmpOutputVisitor
  25. {
  26. Visitor visitor;
  27. QStack stack;
  28. };
  29. #define qmp_output_add(qov, name, value) \
  30. qmp_output_add_obj(qov, name, QOBJECT(value))
  31. #define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))
  32. static QmpOutputVisitor *to_qov(Visitor *v)
  33. {
  34. return container_of(v, QmpOutputVisitor, visitor);
  35. }
  36. static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
  37. {
  38. QStackEntry *e = qemu_mallocz(sizeof(*e));
  39. e->value = value;
  40. QTAILQ_INSERT_HEAD(&qov->stack, e, node);
  41. }
  42. static QObject *qmp_output_pop(QmpOutputVisitor *qov)
  43. {
  44. QStackEntry *e = QTAILQ_FIRST(&qov->stack);
  45. QObject *value;
  46. QTAILQ_REMOVE(&qov->stack, e, node);
  47. value = e->value;
  48. qemu_free(e);
  49. return value;
  50. }
  51. static QObject *qmp_output_first(QmpOutputVisitor *qov)
  52. {
  53. QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack);
  54. return e->value;
  55. }
  56. static QObject *qmp_output_last(QmpOutputVisitor *qov)
  57. {
  58. QStackEntry *e = QTAILQ_FIRST(&qov->stack);
  59. return e->value;
  60. }
  61. static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
  62. QObject *value)
  63. {
  64. QObject *cur;
  65. if (QTAILQ_EMPTY(&qov->stack)) {
  66. qmp_output_push_obj(qov, value);
  67. return;
  68. }
  69. cur = qmp_output_last(qov);
  70. switch (qobject_type(cur)) {
  71. case QTYPE_QDICT:
  72. qdict_put_obj(qobject_to_qdict(cur), name, value);
  73. break;
  74. case QTYPE_QLIST:
  75. qlist_append_obj(qobject_to_qlist(cur), value);
  76. break;
  77. default:
  78. qobject_decref(qmp_output_pop(qov));
  79. qmp_output_push_obj(qov, value);
  80. break;
  81. }
  82. }
  83. static void qmp_output_start_struct(Visitor *v, void **obj, const char *kind,
  84. const char *name, size_t unused,
  85. Error **errp)
  86. {
  87. QmpOutputVisitor *qov = to_qov(v);
  88. QDict *dict = qdict_new();
  89. qmp_output_add(qov, name, dict);
  90. qmp_output_push(qov, dict);
  91. }
  92. static void qmp_output_end_struct(Visitor *v, Error **errp)
  93. {
  94. QmpOutputVisitor *qov = to_qov(v);
  95. qmp_output_pop(qov);
  96. }
  97. static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
  98. {
  99. QmpOutputVisitor *qov = to_qov(v);
  100. QList *list = qlist_new();
  101. qmp_output_add(qov, name, list);
  102. qmp_output_push(qov, list);
  103. }
  104. static GenericList *qmp_output_next_list(Visitor *v, GenericList **list,
  105. Error **errp)
  106. {
  107. GenericList *retval = *list;
  108. *list = retval->next;
  109. return retval;
  110. }
  111. static void qmp_output_end_list(Visitor *v, Error **errp)
  112. {
  113. QmpOutputVisitor *qov = to_qov(v);
  114. qmp_output_pop(qov);
  115. }
  116. static void qmp_output_type_int(Visitor *v, int64_t *obj, const char *name,
  117. Error **errp)
  118. {
  119. QmpOutputVisitor *qov = to_qov(v);
  120. qmp_output_add(qov, name, qint_from_int(*obj));
  121. }
  122. static void qmp_output_type_bool(Visitor *v, bool *obj, const char *name,
  123. Error **errp)
  124. {
  125. QmpOutputVisitor *qov = to_qov(v);
  126. qmp_output_add(qov, name, qbool_from_int(*obj));
  127. }
  128. static void qmp_output_type_str(Visitor *v, char **obj, const char *name,
  129. Error **errp)
  130. {
  131. QmpOutputVisitor *qov = to_qov(v);
  132. if (*obj) {
  133. qmp_output_add(qov, name, qstring_from_str(*obj));
  134. } else {
  135. qmp_output_add(qov, name, qstring_from_str(""));
  136. }
  137. }
  138. static void qmp_output_type_number(Visitor *v, double *obj, const char *name,
  139. Error **errp)
  140. {
  141. QmpOutputVisitor *qov = to_qov(v);
  142. qmp_output_add(qov, name, qfloat_from_double(*obj));
  143. }
  144. static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[],
  145. const char *kind, const char *name,
  146. Error **errp)
  147. {
  148. int i = 0;
  149. int value = *obj;
  150. char *enum_str;
  151. assert(strings);
  152. while (strings[i++] != NULL);
  153. if (value >= i - 1) {
  154. error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
  155. return;
  156. }
  157. enum_str = (char *)strings[value];
  158. qmp_output_type_str(v, &enum_str, name, errp);
  159. }
  160. QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
  161. {
  162. QObject *obj = qmp_output_first(qov);
  163. if (obj) {
  164. qobject_incref(obj);
  165. }
  166. return obj;
  167. }
  168. Visitor *qmp_output_get_visitor(QmpOutputVisitor *v)
  169. {
  170. return &v->visitor;
  171. }
  172. void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
  173. {
  174. QStackEntry *e, *tmp;
  175. QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
  176. QTAILQ_REMOVE(&v->stack, e, node);
  177. if (e->value) {
  178. qobject_decref(e->value);
  179. }
  180. qemu_free(e);
  181. }
  182. qemu_free(v);
  183. }
  184. QmpOutputVisitor *qmp_output_visitor_new(void)
  185. {
  186. QmpOutputVisitor *v;
  187. v = qemu_mallocz(sizeof(*v));
  188. v->visitor.start_struct = qmp_output_start_struct;
  189. v->visitor.end_struct = qmp_output_end_struct;
  190. v->visitor.start_list = qmp_output_start_list;
  191. v->visitor.next_list = qmp_output_next_list;
  192. v->visitor.end_list = qmp_output_end_list;
  193. v->visitor.type_enum = qmp_output_type_enum;
  194. v->visitor.type_int = qmp_output_type_int;
  195. v->visitor.type_bool = qmp_output_type_bool;
  196. v->visitor.type_str = qmp_output_type_str;
  197. v->visitor.type_number = qmp_output_type_number;
  198. QTAILQ_INIT(&v->stack);
  199. return v;
  200. }