2
0

qobject-input-visitor.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /*
  2. * Input Visitor
  3. *
  4. * Copyright (C) 2012-2017 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 <math.h>
  16. #include "qapi/error.h"
  17. #include "qapi/qobject-input-visitor.h"
  18. #include "qapi/visitor-impl.h"
  19. #include "qemu/queue.h"
  20. #include "qapi/qmp/qjson.h"
  21. #include "qapi/qmp/qbool.h"
  22. #include "qapi/qmp/qdict.h"
  23. #include "qapi/qmp/qerror.h"
  24. #include "qapi/qmp/qlist.h"
  25. #include "qapi/qmp/qnull.h"
  26. #include "qapi/qmp/qnum.h"
  27. #include "qapi/qmp/qstring.h"
  28. #include "qemu/cutils.h"
  29. #include "qemu/option.h"
  30. typedef struct StackObject {
  31. const char *name; /* Name of @obj in its parent, if any */
  32. QObject *obj; /* QDict or QList being visited */
  33. void *qapi; /* sanity check that caller uses same pointer */
  34. GHashTable *h; /* If @obj is QDict: unvisited keys */
  35. const QListEntry *entry; /* If @obj is QList: unvisited tail */
  36. unsigned index; /* If @obj is QList: list index of @entry */
  37. QSLIST_ENTRY(StackObject) node; /* parent */
  38. } StackObject;
  39. struct QObjectInputVisitor {
  40. Visitor visitor;
  41. /* Root of visit at visitor creation. */
  42. QObject *root;
  43. bool keyval; /* Assume @root made with keyval_parse() */
  44. /* Stack of objects being visited (all entries will be either
  45. * QDict or QList). */
  46. QSLIST_HEAD(, StackObject) stack;
  47. GString *errname; /* Accumulator for full_name() */
  48. };
  49. static QObjectInputVisitor *to_qiv(Visitor *v)
  50. {
  51. return container_of(v, QObjectInputVisitor, visitor);
  52. }
  53. /*
  54. * Find the full name of something @qiv is currently visiting.
  55. * @qiv is visiting something named @name in the stack of containers
  56. * @qiv->stack.
  57. * If @n is zero, return its full name.
  58. * If @n is positive, return the full name of the @n-th container
  59. * counting from the top. The stack of containers must have at least
  60. * @n elements.
  61. * The returned string is valid until the next full_name_nth(@v) or
  62. * destruction of @v.
  63. */
  64. static const char *full_name_nth(QObjectInputVisitor *qiv, const char *name,
  65. int n)
  66. {
  67. StackObject *so;
  68. char buf[32];
  69. if (qiv->errname) {
  70. g_string_truncate(qiv->errname, 0);
  71. } else {
  72. qiv->errname = g_string_new("");
  73. }
  74. QSLIST_FOREACH(so , &qiv->stack, node) {
  75. if (n) {
  76. n--;
  77. } else if (qobject_type(so->obj) == QTYPE_QDICT) {
  78. g_string_prepend(qiv->errname, name ?: "<anonymous>");
  79. g_string_prepend_c(qiv->errname, '.');
  80. } else {
  81. snprintf(buf, sizeof(buf),
  82. qiv->keyval ? ".%u" : "[%u]",
  83. so->index);
  84. g_string_prepend(qiv->errname, buf);
  85. }
  86. name = so->name;
  87. }
  88. assert(!n);
  89. if (name) {
  90. g_string_prepend(qiv->errname, name);
  91. } else if (qiv->errname->str[0] == '.') {
  92. g_string_erase(qiv->errname, 0, 1);
  93. } else if (!qiv->errname->str[0]) {
  94. return "<anonymous>";
  95. }
  96. return qiv->errname->str;
  97. }
  98. static const char *full_name(QObjectInputVisitor *qiv, const char *name)
  99. {
  100. return full_name_nth(qiv, name, 0);
  101. }
  102. static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv,
  103. const char *name,
  104. bool consume)
  105. {
  106. StackObject *tos;
  107. QObject *qobj;
  108. QObject *ret;
  109. if (QSLIST_EMPTY(&qiv->stack)) {
  110. /* Starting at root, name is ignored. */
  111. assert(qiv->root);
  112. return qiv->root;
  113. }
  114. /* We are in a container; find the next element. */
  115. tos = QSLIST_FIRST(&qiv->stack);
  116. qobj = tos->obj;
  117. assert(qobj);
  118. if (qobject_type(qobj) == QTYPE_QDICT) {
  119. assert(name);
  120. ret = qdict_get(qobject_to(QDict, qobj), name);
  121. if (tos->h && consume && ret) {
  122. bool removed = g_hash_table_remove(tos->h, name);
  123. assert(removed);
  124. }
  125. } else {
  126. assert(qobject_type(qobj) == QTYPE_QLIST);
  127. assert(!name);
  128. if (tos->entry) {
  129. ret = qlist_entry_obj(tos->entry);
  130. if (consume) {
  131. tos->entry = qlist_next(tos->entry);
  132. }
  133. } else {
  134. ret = NULL;
  135. }
  136. if (consume) {
  137. tos->index++;
  138. }
  139. }
  140. return ret;
  141. }
  142. static QObject *qobject_input_get_object(QObjectInputVisitor *qiv,
  143. const char *name,
  144. bool consume, Error **errp)
  145. {
  146. QObject *obj = qobject_input_try_get_object(qiv, name, consume);
  147. if (!obj) {
  148. error_setg(errp, QERR_MISSING_PARAMETER, full_name(qiv, name));
  149. }
  150. return obj;
  151. }
  152. static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv,
  153. const char *name,
  154. Error **errp)
  155. {
  156. QObject *qobj;
  157. QString *qstr;
  158. qobj = qobject_input_get_object(qiv, name, true, errp);
  159. if (!qobj) {
  160. return NULL;
  161. }
  162. qstr = qobject_to(QString, qobj);
  163. if (!qstr) {
  164. switch (qobject_type(qobj)) {
  165. case QTYPE_QDICT:
  166. case QTYPE_QLIST:
  167. error_setg(errp, "Parameters '%s.*' are unexpected",
  168. full_name(qiv, name));
  169. return NULL;
  170. default:
  171. /* Non-string scalar (should this be an assertion?) */
  172. error_setg(errp, "Internal error: parameter %s invalid",
  173. full_name(qiv, name));
  174. return NULL;
  175. }
  176. }
  177. return qstring_get_str(qstr);
  178. }
  179. static void qdict_add_key(const char *key, QObject *obj, void *opaque)
  180. {
  181. GHashTable *h = opaque;
  182. g_hash_table_insert(h, (gpointer) key, NULL);
  183. }
  184. static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
  185. const char *name,
  186. QObject *obj, void *qapi)
  187. {
  188. GHashTable *h;
  189. StackObject *tos = g_new0(StackObject, 1);
  190. assert(obj);
  191. tos->name = name;
  192. tos->obj = obj;
  193. tos->qapi = qapi;
  194. if (qobject_type(obj) == QTYPE_QDICT) {
  195. h = g_hash_table_new(g_str_hash, g_str_equal);
  196. qdict_iter(qobject_to(QDict, obj), qdict_add_key, h);
  197. tos->h = h;
  198. } else {
  199. assert(qobject_type(obj) == QTYPE_QLIST);
  200. tos->entry = qlist_first(qobject_to(QList, obj));
  201. tos->index = -1;
  202. }
  203. QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
  204. return tos->entry;
  205. }
  206. static void qobject_input_check_struct(Visitor *v, Error **errp)
  207. {
  208. QObjectInputVisitor *qiv = to_qiv(v);
  209. StackObject *tos = QSLIST_FIRST(&qiv->stack);
  210. GHashTableIter iter;
  211. const char *key;
  212. assert(tos && !tos->entry);
  213. g_hash_table_iter_init(&iter, tos->h);
  214. if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
  215. error_setg(errp, "Parameter '%s' is unexpected",
  216. full_name(qiv, key));
  217. }
  218. }
  219. static void qobject_input_stack_object_free(StackObject *tos)
  220. {
  221. if (tos->h) {
  222. g_hash_table_unref(tos->h);
  223. }
  224. g_free(tos);
  225. }
  226. static void qobject_input_pop(Visitor *v, void **obj)
  227. {
  228. QObjectInputVisitor *qiv = to_qiv(v);
  229. StackObject *tos = QSLIST_FIRST(&qiv->stack);
  230. assert(tos && tos->qapi == obj);
  231. QSLIST_REMOVE_HEAD(&qiv->stack, node);
  232. qobject_input_stack_object_free(tos);
  233. }
  234. static void qobject_input_start_struct(Visitor *v, const char *name, void **obj,
  235. size_t size, Error **errp)
  236. {
  237. QObjectInputVisitor *qiv = to_qiv(v);
  238. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  239. if (obj) {
  240. *obj = NULL;
  241. }
  242. if (!qobj) {
  243. return;
  244. }
  245. if (qobject_type(qobj) != QTYPE_QDICT) {
  246. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  247. full_name(qiv, name), "object");
  248. return;
  249. }
  250. qobject_input_push(qiv, name, qobj, obj);
  251. if (obj) {
  252. *obj = g_malloc0(size);
  253. }
  254. }
  255. static void qobject_input_end_struct(Visitor *v, void **obj)
  256. {
  257. QObjectInputVisitor *qiv = to_qiv(v);
  258. StackObject *tos = QSLIST_FIRST(&qiv->stack);
  259. assert(qobject_type(tos->obj) == QTYPE_QDICT && tos->h);
  260. qobject_input_pop(v, obj);
  261. }
  262. static void qobject_input_start_list(Visitor *v, const char *name,
  263. GenericList **list, size_t size,
  264. Error **errp)
  265. {
  266. QObjectInputVisitor *qiv = to_qiv(v);
  267. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  268. const QListEntry *entry;
  269. if (list) {
  270. *list = NULL;
  271. }
  272. if (!qobj) {
  273. return;
  274. }
  275. if (qobject_type(qobj) != QTYPE_QLIST) {
  276. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  277. full_name(qiv, name), "array");
  278. return;
  279. }
  280. entry = qobject_input_push(qiv, name, qobj, list);
  281. if (entry && list) {
  282. *list = g_malloc0(size);
  283. }
  284. }
  285. static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
  286. size_t size)
  287. {
  288. QObjectInputVisitor *qiv = to_qiv(v);
  289. StackObject *tos = QSLIST_FIRST(&qiv->stack);
  290. assert(tos && qobject_to(QList, tos->obj));
  291. if (!tos->entry) {
  292. return NULL;
  293. }
  294. tail->next = g_malloc0(size);
  295. return tail->next;
  296. }
  297. static void qobject_input_check_list(Visitor *v, Error **errp)
  298. {
  299. QObjectInputVisitor *qiv = to_qiv(v);
  300. StackObject *tos = QSLIST_FIRST(&qiv->stack);
  301. assert(tos && qobject_to(QList, tos->obj));
  302. if (tos->entry) {
  303. error_setg(errp, "Only %u list elements expected in %s",
  304. tos->index + 1, full_name_nth(qiv, NULL, 1));
  305. }
  306. }
  307. static void qobject_input_end_list(Visitor *v, void **obj)
  308. {
  309. QObjectInputVisitor *qiv = to_qiv(v);
  310. StackObject *tos = QSLIST_FIRST(&qiv->stack);
  311. assert(qobject_type(tos->obj) == QTYPE_QLIST && !tos->h);
  312. qobject_input_pop(v, obj);
  313. }
  314. static void qobject_input_start_alternate(Visitor *v, const char *name,
  315. GenericAlternate **obj, size_t size,
  316. Error **errp)
  317. {
  318. QObjectInputVisitor *qiv = to_qiv(v);
  319. QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
  320. if (!qobj) {
  321. *obj = NULL;
  322. return;
  323. }
  324. *obj = g_malloc0(size);
  325. (*obj)->type = qobject_type(qobj);
  326. }
  327. static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
  328. Error **errp)
  329. {
  330. QObjectInputVisitor *qiv = to_qiv(v);
  331. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  332. QNum *qnum;
  333. if (!qobj) {
  334. return;
  335. }
  336. qnum = qobject_to(QNum, qobj);
  337. if (!qnum || !qnum_get_try_int(qnum, obj)) {
  338. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  339. full_name(qiv, name), "integer");
  340. }
  341. }
  342. static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
  343. int64_t *obj, Error **errp)
  344. {
  345. QObjectInputVisitor *qiv = to_qiv(v);
  346. const char *str = qobject_input_get_keyval(qiv, name, errp);
  347. if (!str) {
  348. return;
  349. }
  350. if (qemu_strtoi64(str, NULL, 0, obj) < 0) {
  351. /* TODO report -ERANGE more nicely */
  352. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  353. full_name(qiv, name), "integer");
  354. }
  355. }
  356. static void qobject_input_type_uint64(Visitor *v, const char *name,
  357. uint64_t *obj, Error **errp)
  358. {
  359. QObjectInputVisitor *qiv = to_qiv(v);
  360. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  361. QNum *qnum;
  362. int64_t val;
  363. if (!qobj) {
  364. return;
  365. }
  366. qnum = qobject_to(QNum, qobj);
  367. if (!qnum) {
  368. goto err;
  369. }
  370. if (qnum_get_try_uint(qnum, obj)) {
  371. return;
  372. }
  373. /* Need to accept negative values for backward compatibility */
  374. if (qnum_get_try_int(qnum, &val)) {
  375. *obj = val;
  376. return;
  377. }
  378. err:
  379. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  380. full_name(qiv, name), "uint64");
  381. }
  382. static void qobject_input_type_uint64_keyval(Visitor *v, const char *name,
  383. uint64_t *obj, Error **errp)
  384. {
  385. QObjectInputVisitor *qiv = to_qiv(v);
  386. const char *str = qobject_input_get_keyval(qiv, name, errp);
  387. if (!str) {
  388. return;
  389. }
  390. if (qemu_strtou64(str, NULL, 0, obj) < 0) {
  391. /* TODO report -ERANGE more nicely */
  392. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  393. full_name(qiv, name), "integer");
  394. }
  395. }
  396. static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
  397. Error **errp)
  398. {
  399. QObjectInputVisitor *qiv = to_qiv(v);
  400. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  401. QBool *qbool;
  402. if (!qobj) {
  403. return;
  404. }
  405. qbool = qobject_to(QBool, qobj);
  406. if (!qbool) {
  407. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  408. full_name(qiv, name), "boolean");
  409. return;
  410. }
  411. *obj = qbool_get_bool(qbool);
  412. }
  413. static void qobject_input_type_bool_keyval(Visitor *v, const char *name,
  414. bool *obj, Error **errp)
  415. {
  416. QObjectInputVisitor *qiv = to_qiv(v);
  417. const char *str = qobject_input_get_keyval(qiv, name, errp);
  418. if (!str) {
  419. return;
  420. }
  421. if (!strcmp(str, "on")) {
  422. *obj = true;
  423. } else if (!strcmp(str, "off")) {
  424. *obj = false;
  425. } else {
  426. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  427. full_name(qiv, name), "'on' or 'off'");
  428. }
  429. }
  430. static void qobject_input_type_str(Visitor *v, const char *name, char **obj,
  431. Error **errp)
  432. {
  433. QObjectInputVisitor *qiv = to_qiv(v);
  434. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  435. QString *qstr;
  436. *obj = NULL;
  437. if (!qobj) {
  438. return;
  439. }
  440. qstr = qobject_to(QString, qobj);
  441. if (!qstr) {
  442. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  443. full_name(qiv, name), "string");
  444. return;
  445. }
  446. *obj = g_strdup(qstring_get_str(qstr));
  447. }
  448. static void qobject_input_type_str_keyval(Visitor *v, const char *name,
  449. char **obj, Error **errp)
  450. {
  451. QObjectInputVisitor *qiv = to_qiv(v);
  452. const char *str = qobject_input_get_keyval(qiv, name, errp);
  453. *obj = g_strdup(str);
  454. }
  455. static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
  456. Error **errp)
  457. {
  458. QObjectInputVisitor *qiv = to_qiv(v);
  459. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  460. QNum *qnum;
  461. if (!qobj) {
  462. return;
  463. }
  464. qnum = qobject_to(QNum, qobj);
  465. if (!qnum) {
  466. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  467. full_name(qiv, name), "number");
  468. return;
  469. }
  470. *obj = qnum_get_double(qnum);
  471. }
  472. static void qobject_input_type_number_keyval(Visitor *v, const char *name,
  473. double *obj, Error **errp)
  474. {
  475. QObjectInputVisitor *qiv = to_qiv(v);
  476. const char *str = qobject_input_get_keyval(qiv, name, errp);
  477. double val;
  478. if (!str) {
  479. return;
  480. }
  481. if (qemu_strtod_finite(str, NULL, &val)) {
  482. /* TODO report -ERANGE more nicely */
  483. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  484. full_name(qiv, name), "number");
  485. return;
  486. }
  487. *obj = val;
  488. }
  489. static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
  490. Error **errp)
  491. {
  492. QObjectInputVisitor *qiv = to_qiv(v);
  493. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  494. *obj = NULL;
  495. if (!qobj) {
  496. return;
  497. }
  498. *obj = qobject_ref(qobj);
  499. }
  500. static void qobject_input_type_null(Visitor *v, const char *name,
  501. QNull **obj, Error **errp)
  502. {
  503. QObjectInputVisitor *qiv = to_qiv(v);
  504. QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
  505. *obj = NULL;
  506. if (!qobj) {
  507. return;
  508. }
  509. if (qobject_type(qobj) != QTYPE_QNULL) {
  510. error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
  511. full_name(qiv, name), "null");
  512. return;
  513. }
  514. *obj = qnull();
  515. }
  516. static void qobject_input_type_size_keyval(Visitor *v, const char *name,
  517. uint64_t *obj, Error **errp)
  518. {
  519. QObjectInputVisitor *qiv = to_qiv(v);
  520. const char *str = qobject_input_get_keyval(qiv, name, errp);
  521. if (!str) {
  522. return;
  523. }
  524. if (qemu_strtosz(str, NULL, obj) < 0) {
  525. /* TODO report -ERANGE more nicely */
  526. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  527. full_name(qiv, name), "size");
  528. }
  529. }
  530. static void qobject_input_optional(Visitor *v, const char *name, bool *present)
  531. {
  532. QObjectInputVisitor *qiv = to_qiv(v);
  533. QObject *qobj = qobject_input_try_get_object(qiv, name, false);
  534. if (!qobj) {
  535. *present = false;
  536. return;
  537. }
  538. *present = true;
  539. }
  540. static void qobject_input_free(Visitor *v)
  541. {
  542. QObjectInputVisitor *qiv = to_qiv(v);
  543. while (!QSLIST_EMPTY(&qiv->stack)) {
  544. StackObject *tos = QSLIST_FIRST(&qiv->stack);
  545. QSLIST_REMOVE_HEAD(&qiv->stack, node);
  546. qobject_input_stack_object_free(tos);
  547. }
  548. qobject_unref(qiv->root);
  549. if (qiv->errname) {
  550. g_string_free(qiv->errname, TRUE);
  551. }
  552. g_free(qiv);
  553. }
  554. static QObjectInputVisitor *qobject_input_visitor_base_new(QObject *obj)
  555. {
  556. QObjectInputVisitor *v = g_malloc0(sizeof(*v));
  557. assert(obj);
  558. v->visitor.type = VISITOR_INPUT;
  559. v->visitor.start_struct = qobject_input_start_struct;
  560. v->visitor.check_struct = qobject_input_check_struct;
  561. v->visitor.end_struct = qobject_input_end_struct;
  562. v->visitor.start_list = qobject_input_start_list;
  563. v->visitor.next_list = qobject_input_next_list;
  564. v->visitor.check_list = qobject_input_check_list;
  565. v->visitor.end_list = qobject_input_end_list;
  566. v->visitor.start_alternate = qobject_input_start_alternate;
  567. v->visitor.optional = qobject_input_optional;
  568. v->visitor.free = qobject_input_free;
  569. v->root = qobject_ref(obj);
  570. return v;
  571. }
  572. Visitor *qobject_input_visitor_new(QObject *obj)
  573. {
  574. QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);
  575. v->visitor.type_int64 = qobject_input_type_int64;
  576. v->visitor.type_uint64 = qobject_input_type_uint64;
  577. v->visitor.type_bool = qobject_input_type_bool;
  578. v->visitor.type_str = qobject_input_type_str;
  579. v->visitor.type_number = qobject_input_type_number;
  580. v->visitor.type_any = qobject_input_type_any;
  581. v->visitor.type_null = qobject_input_type_null;
  582. return &v->visitor;
  583. }
  584. Visitor *qobject_input_visitor_new_keyval(QObject *obj)
  585. {
  586. QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);
  587. v->visitor.type_int64 = qobject_input_type_int64_keyval;
  588. v->visitor.type_uint64 = qobject_input_type_uint64_keyval;
  589. v->visitor.type_bool = qobject_input_type_bool_keyval;
  590. v->visitor.type_str = qobject_input_type_str_keyval;
  591. v->visitor.type_number = qobject_input_type_number_keyval;
  592. v->visitor.type_any = qobject_input_type_any;
  593. v->visitor.type_null = qobject_input_type_null;
  594. v->visitor.type_size = qobject_input_type_size_keyval;
  595. v->keyval = true;
  596. return &v->visitor;
  597. }
  598. Visitor *qobject_input_visitor_new_str(const char *str,
  599. const char *implied_key,
  600. Error **errp)
  601. {
  602. bool is_json = str[0] == '{';
  603. QObject *obj;
  604. QDict *args;
  605. Visitor *v;
  606. if (is_json) {
  607. obj = qobject_from_json(str, errp);
  608. if (!obj) {
  609. return NULL;
  610. }
  611. args = qobject_to(QDict, obj);
  612. assert(args);
  613. v = qobject_input_visitor_new(QOBJECT(args));
  614. } else {
  615. args = keyval_parse(str, implied_key, errp);
  616. if (!args) {
  617. return NULL;
  618. }
  619. v = qobject_input_visitor_new_keyval(QOBJECT(args));
  620. }
  621. qobject_unref(args);
  622. return v;
  623. }