qapi-visit-core.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. * Core Definitions for QAPI Visitor Classes
  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/error.h"
  16. #include "qapi/qmp/qerror.h"
  17. #include "qapi/visitor.h"
  18. #include "qapi/visitor-impl.h"
  19. #include "trace.h"
  20. void visit_complete(Visitor *v, void *opaque)
  21. {
  22. assert(v->type != VISITOR_OUTPUT || v->complete);
  23. trace_visit_complete(v, opaque);
  24. if (v->complete) {
  25. v->complete(v, opaque);
  26. }
  27. }
  28. void visit_free(Visitor *v)
  29. {
  30. trace_visit_free(v);
  31. if (v) {
  32. v->free(v);
  33. }
  34. }
  35. bool visit_start_struct(Visitor *v, const char *name, void **obj,
  36. size_t size, Error **errp)
  37. {
  38. bool ok;
  39. trace_visit_start_struct(v, name, obj, size);
  40. if (obj) {
  41. assert(size);
  42. assert(!(v->type & VISITOR_OUTPUT) || *obj);
  43. }
  44. ok = v->start_struct(v, name, obj, size, errp);
  45. if (obj && (v->type & VISITOR_INPUT)) {
  46. assert(ok != !*obj);
  47. }
  48. return ok;
  49. }
  50. bool visit_check_struct(Visitor *v, Error **errp)
  51. {
  52. trace_visit_check_struct(v);
  53. return v->check_struct ? v->check_struct(v, errp) : true;
  54. }
  55. void visit_end_struct(Visitor *v, void **obj)
  56. {
  57. trace_visit_end_struct(v, obj);
  58. v->end_struct(v, obj);
  59. }
  60. bool visit_start_list(Visitor *v, const char *name, GenericList **list,
  61. size_t size, Error **errp)
  62. {
  63. bool ok;
  64. assert(!list || size >= sizeof(GenericList));
  65. trace_visit_start_list(v, name, list, size);
  66. ok = v->start_list(v, name, list, size, errp);
  67. if (list && (v->type & VISITOR_INPUT)) {
  68. assert(ok || !*list);
  69. }
  70. return ok;
  71. }
  72. GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
  73. {
  74. assert(tail && size >= sizeof(GenericList));
  75. trace_visit_next_list(v, tail, size);
  76. return v->next_list(v, tail, size);
  77. }
  78. bool visit_check_list(Visitor *v, Error **errp)
  79. {
  80. trace_visit_check_list(v);
  81. return v->check_list ? v->check_list(v, errp) : true;
  82. }
  83. void visit_end_list(Visitor *v, void **obj)
  84. {
  85. trace_visit_end_list(v, obj);
  86. v->end_list(v, obj);
  87. }
  88. bool visit_start_alternate(Visitor *v, const char *name,
  89. GenericAlternate **obj, size_t size,
  90. Error **errp)
  91. {
  92. bool ok;
  93. assert(obj && size >= sizeof(GenericAlternate));
  94. assert(!(v->type & VISITOR_OUTPUT) || *obj);
  95. trace_visit_start_alternate(v, name, obj, size);
  96. if (!v->start_alternate) {
  97. assert(!(v->type & VISITOR_INPUT));
  98. return true;
  99. }
  100. ok = v->start_alternate(v, name, obj, size, errp);
  101. if (v->type & VISITOR_INPUT) {
  102. assert(ok != !*obj);
  103. }
  104. return ok;
  105. }
  106. void visit_end_alternate(Visitor *v, void **obj)
  107. {
  108. trace_visit_end_alternate(v, obj);
  109. if (v->end_alternate) {
  110. v->end_alternate(v, obj);
  111. }
  112. }
  113. bool visit_optional(Visitor *v, const char *name, bool *present)
  114. {
  115. trace_visit_optional(v, name, present);
  116. if (v->optional) {
  117. v->optional(v, name, present);
  118. }
  119. return *present;
  120. }
  121. bool visit_is_input(Visitor *v)
  122. {
  123. return v->type == VISITOR_INPUT;
  124. }
  125. bool visit_is_dealloc(Visitor *v)
  126. {
  127. return v->type == VISITOR_DEALLOC;
  128. }
  129. bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
  130. {
  131. assert(obj);
  132. trace_visit_type_int(v, name, obj);
  133. return v->type_int64(v, name, obj, errp);
  134. }
  135. static bool visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
  136. uint64_t max, const char *type, Error **errp)
  137. {
  138. uint64_t value = *obj;
  139. assert(v->type == VISITOR_INPUT || value <= max);
  140. if (!v->type_uint64(v, name, &value, errp)) {
  141. return false;
  142. }
  143. if (value > max) {
  144. assert(v->type == VISITOR_INPUT);
  145. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  146. name ? name : "null", type);
  147. return false;
  148. }
  149. *obj = value;
  150. return true;
  151. }
  152. bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
  153. Error **errp)
  154. {
  155. uint64_t value;
  156. bool ok;
  157. trace_visit_type_uint8(v, name, obj);
  158. value = *obj;
  159. ok = visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
  160. *obj = value;
  161. return ok;
  162. }
  163. bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
  164. Error **errp)
  165. {
  166. uint64_t value;
  167. bool ok;
  168. trace_visit_type_uint16(v, name, obj);
  169. value = *obj;
  170. ok = visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
  171. *obj = value;
  172. return ok;
  173. }
  174. bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
  175. Error **errp)
  176. {
  177. uint64_t value;
  178. bool ok;
  179. trace_visit_type_uint32(v, name, obj);
  180. value = *obj;
  181. ok = visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
  182. *obj = value;
  183. return ok;
  184. }
  185. bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
  186. Error **errp)
  187. {
  188. assert(obj);
  189. trace_visit_type_uint64(v, name, obj);
  190. return v->type_uint64(v, name, obj, errp);
  191. }
  192. static bool visit_type_intN(Visitor *v, int64_t *obj, const char *name,
  193. int64_t min, int64_t max, const char *type,
  194. Error **errp)
  195. {
  196. int64_t value = *obj;
  197. assert(v->type == VISITOR_INPUT || (value >= min && value <= max));
  198. if (!v->type_int64(v, name, &value, errp)) {
  199. return false;
  200. }
  201. if (value < min || value > max) {
  202. assert(v->type == VISITOR_INPUT);
  203. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  204. name ? name : "null", type);
  205. return false;
  206. }
  207. *obj = value;
  208. return true;
  209. }
  210. bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
  211. {
  212. int64_t value;
  213. bool ok;
  214. trace_visit_type_int8(v, name, obj);
  215. value = *obj;
  216. ok = visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
  217. *obj = value;
  218. return ok;
  219. }
  220. bool visit_type_int16(Visitor *v, const char *name, int16_t *obj,
  221. Error **errp)
  222. {
  223. int64_t value;
  224. bool ok;
  225. trace_visit_type_int16(v, name, obj);
  226. value = *obj;
  227. ok = visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t",
  228. errp);
  229. *obj = value;
  230. return ok;
  231. }
  232. bool visit_type_int32(Visitor *v, const char *name, int32_t *obj,
  233. Error **errp)
  234. {
  235. int64_t value;
  236. bool ok;
  237. trace_visit_type_int32(v, name, obj);
  238. value = *obj;
  239. ok = visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t",
  240. errp);
  241. *obj = value;
  242. return ok;
  243. }
  244. bool visit_type_int64(Visitor *v, const char *name, int64_t *obj,
  245. Error **errp)
  246. {
  247. assert(obj);
  248. trace_visit_type_int64(v, name, obj);
  249. return v->type_int64(v, name, obj, errp);
  250. }
  251. bool visit_type_size(Visitor *v, const char *name, uint64_t *obj,
  252. Error **errp)
  253. {
  254. assert(obj);
  255. trace_visit_type_size(v, name, obj);
  256. if (v->type_size) {
  257. return v->type_size(v, name, obj, errp);
  258. }
  259. return v->type_uint64(v, name, obj, errp);
  260. }
  261. bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
  262. {
  263. assert(obj);
  264. trace_visit_type_bool(v, name, obj);
  265. return v->type_bool(v, name, obj, errp);
  266. }
  267. bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
  268. {
  269. bool ok;
  270. assert(obj);
  271. /* TODO: Fix callers to not pass NULL when they mean "", so that we
  272. * can enable:
  273. assert(!(v->type & VISITOR_OUTPUT) || *obj);
  274. */
  275. trace_visit_type_str(v, name, obj);
  276. ok = v->type_str(v, name, obj, errp);
  277. if (v->type & VISITOR_INPUT) {
  278. assert(ok != !*obj);
  279. }
  280. return ok;
  281. }
  282. bool visit_type_number(Visitor *v, const char *name, double *obj,
  283. Error **errp)
  284. {
  285. assert(obj);
  286. trace_visit_type_number(v, name, obj);
  287. return v->type_number(v, name, obj, errp);
  288. }
  289. bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
  290. {
  291. bool ok;
  292. assert(obj);
  293. assert(v->type != VISITOR_OUTPUT || *obj);
  294. trace_visit_type_any(v, name, obj);
  295. ok = v->type_any(v, name, obj, errp);
  296. if (v->type == VISITOR_INPUT) {
  297. assert(ok != !*obj);
  298. }
  299. return ok;
  300. }
  301. bool visit_type_null(Visitor *v, const char *name, QNull **obj,
  302. Error **errp)
  303. {
  304. trace_visit_type_null(v, name, obj);
  305. return v->type_null(v, name, obj, errp);
  306. }
  307. static bool output_type_enum(Visitor *v, const char *name, int *obj,
  308. const QEnumLookup *lookup, Error **errp)
  309. {
  310. int value = *obj;
  311. char *enum_str;
  312. enum_str = (char *)qapi_enum_lookup(lookup, value);
  313. return visit_type_str(v, name, &enum_str, errp);
  314. }
  315. static bool input_type_enum(Visitor *v, const char *name, int *obj,
  316. const QEnumLookup *lookup, Error **errp)
  317. {
  318. int64_t value;
  319. char *enum_str;
  320. if (!visit_type_str(v, name, &enum_str, errp)) {
  321. return false;
  322. }
  323. value = qapi_enum_parse(lookup, enum_str, -1, NULL);
  324. if (value < 0) {
  325. error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
  326. g_free(enum_str);
  327. return false;
  328. }
  329. g_free(enum_str);
  330. *obj = value;
  331. return true;
  332. }
  333. bool visit_type_enum(Visitor *v, const char *name, int *obj,
  334. const QEnumLookup *lookup, Error **errp)
  335. {
  336. assert(obj && lookup);
  337. trace_visit_type_enum(v, name, obj);
  338. switch (v->type) {
  339. case VISITOR_INPUT:
  340. return input_type_enum(v, name, obj, lookup, errp);
  341. case VISITOR_OUTPUT:
  342. return output_type_enum(v, name, obj, lookup, errp);
  343. case VISITOR_CLONE:
  344. /* nothing further to do, scalar value was already copied by
  345. * g_memdup() during visit_start_*() */
  346. return true;
  347. case VISITOR_DEALLOC:
  348. /* nothing to deallocate for a scalar */
  349. return true;
  350. default:
  351. abort();
  352. }
  353. }