qapi-visit-core.c 11 KB

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