2
0

qjson.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * QObject JSON integration
  3. *
  4. * Copyright IBM, Corp. 2009
  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 "qemu/osdep.h"
  14. #include "qapi/error.h"
  15. #include "qobject/json-parser.h"
  16. #include "qobject/json-writer.h"
  17. #include "qobject/qjson.h"
  18. #include "qobject/qbool.h"
  19. #include "qobject/qdict.h"
  20. #include "qobject/qlist.h"
  21. #include "qobject/qnum.h"
  22. #include "qobject/qstring.h"
  23. typedef struct JSONParsingState {
  24. JSONMessageParser parser;
  25. QObject *result;
  26. Error *err;
  27. } JSONParsingState;
  28. static void consume_json(void *opaque, QObject *json, Error *err)
  29. {
  30. JSONParsingState *s = opaque;
  31. assert(!json != !err);
  32. assert(!s->result || !s->err);
  33. if (s->result) {
  34. qobject_unref(s->result);
  35. s->result = NULL;
  36. error_setg(&s->err, "Expecting at most one JSON value");
  37. }
  38. if (s->err) {
  39. qobject_unref(json);
  40. error_free(err);
  41. return;
  42. }
  43. s->result = json;
  44. s->err = err;
  45. }
  46. /*
  47. * Parse @string as JSON value.
  48. * If @ap is non-null, interpolate %-escapes.
  49. * Takes ownership of %p arguments.
  50. * On success, return the JSON value.
  51. * On failure, store an error through @errp and return NULL.
  52. * Ownership of %p arguments becomes indeterminate then. To avoid
  53. * leaks, callers passing %p must terminate on error, e.g. by passing
  54. * &error_abort.
  55. */
  56. static QObject *qobject_from_jsonv(const char *string, va_list *ap,
  57. Error **errp)
  58. {
  59. JSONParsingState state = {};
  60. json_message_parser_init(&state.parser, consume_json, &state, ap);
  61. json_message_parser_feed(&state.parser, string, strlen(string));
  62. json_message_parser_flush(&state.parser);
  63. json_message_parser_destroy(&state.parser);
  64. if (!state.result && !state.err) {
  65. error_setg(&state.err, "Expecting a JSON value");
  66. }
  67. error_propagate(errp, state.err);
  68. return state.result;
  69. }
  70. QObject *qobject_from_json(const char *string, Error **errp)
  71. {
  72. return qobject_from_jsonv(string, NULL, errp);
  73. }
  74. /*
  75. * Parse @string as JSON value with %-escapes interpolated.
  76. * Abort on error. Do not use with untrusted @string.
  77. * Return the resulting QObject. It is never null.
  78. */
  79. QObject *qobject_from_vjsonf_nofail(const char *string, va_list ap)
  80. {
  81. va_list ap_copy;
  82. QObject *obj;
  83. /* va_copy() is needed when va_list is an array type */
  84. va_copy(ap_copy, ap);
  85. obj = qobject_from_jsonv(string, &ap_copy, &error_abort);
  86. va_end(ap_copy);
  87. assert(obj);
  88. return obj;
  89. }
  90. /*
  91. * Parse @string as JSON value with %-escapes interpolated.
  92. * Abort on error. Do not use with untrusted @string.
  93. * Return the resulting QObject. It is never null.
  94. */
  95. QObject *qobject_from_jsonf_nofail(const char *string, ...)
  96. {
  97. QObject *obj;
  98. va_list ap;
  99. va_start(ap, string);
  100. obj = qobject_from_vjsonf_nofail(string, ap);
  101. va_end(ap);
  102. return obj;
  103. }
  104. /*
  105. * Parse @string as JSON object with %-escapes interpolated.
  106. * Abort on error. Do not use with untrusted @string.
  107. * Return the resulting QDict. It is never null.
  108. */
  109. QDict *qdict_from_vjsonf_nofail(const char *string, va_list ap)
  110. {
  111. QDict *qdict;
  112. qdict = qobject_to(QDict, qobject_from_vjsonf_nofail(string, ap));
  113. assert(qdict);
  114. return qdict;
  115. }
  116. /*
  117. * Parse @string as JSON object with %-escapes interpolated.
  118. * Abort on error. Do not use with untrusted @string.
  119. * Return the resulting QDict. It is never null.
  120. */
  121. QDict *qdict_from_jsonf_nofail(const char *string, ...)
  122. {
  123. QDict *qdict;
  124. va_list ap;
  125. va_start(ap, string);
  126. qdict = qdict_from_vjsonf_nofail(string, ap);
  127. va_end(ap);
  128. return qdict;
  129. }
  130. static void to_json(JSONWriter *writer, const char *name,
  131. const QObject *obj)
  132. {
  133. switch (qobject_type(obj)) {
  134. case QTYPE_QNULL:
  135. json_writer_null(writer, name);
  136. break;
  137. case QTYPE_QNUM: {
  138. QNum *val = qobject_to(QNum, obj);
  139. switch (val->kind) {
  140. case QNUM_I64:
  141. json_writer_int64(writer, name, val->u.i64);
  142. break;
  143. case QNUM_U64:
  144. json_writer_uint64(writer, name, val->u.u64);
  145. break;
  146. case QNUM_DOUBLE:
  147. json_writer_double(writer, name, val->u.dbl);
  148. break;
  149. default:
  150. abort();
  151. }
  152. break;
  153. }
  154. case QTYPE_QSTRING: {
  155. QString *val = qobject_to(QString, obj);
  156. json_writer_str(writer, name, qstring_get_str(val));
  157. break;
  158. }
  159. case QTYPE_QDICT: {
  160. QDict *val = qobject_to(QDict, obj);
  161. const QDictEntry *entry;
  162. json_writer_start_object(writer, name);
  163. for (entry = qdict_first(val);
  164. entry;
  165. entry = qdict_next(val, entry)) {
  166. to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry));
  167. }
  168. json_writer_end_object(writer);
  169. break;
  170. }
  171. case QTYPE_QLIST: {
  172. QList *val = qobject_to(QList, obj);
  173. QListEntry *entry;
  174. json_writer_start_array(writer, name);
  175. QLIST_FOREACH_ENTRY(val, entry) {
  176. to_json(writer, NULL, qlist_entry_obj(entry));
  177. }
  178. json_writer_end_array(writer);
  179. break;
  180. }
  181. case QTYPE_QBOOL: {
  182. QBool *val = qobject_to(QBool, obj);
  183. json_writer_bool(writer, name, qbool_get_bool(val));
  184. break;
  185. }
  186. default:
  187. abort();
  188. }
  189. }
  190. GString *qobject_to_json_pretty(const QObject *obj, bool pretty)
  191. {
  192. JSONWriter *writer = json_writer_new(pretty);
  193. to_json(writer, NULL, obj);
  194. return json_writer_get_and_free(writer);
  195. }
  196. GString *qobject_to_json(const QObject *obj)
  197. {
  198. return qobject_to_json_pretty(obj, false);
  199. }