2
0

qapi-visit-core.c 9.8 KB

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