diff options
Diffstat (limited to 'include/qapi')
28 files changed, 2599 insertions, 0 deletions
diff --git a/include/qapi/clone-visitor.h b/include/qapi/clone-visitor.h new file mode 100644 index 000000000..adf9a788e --- /dev/null +++ b/include/qapi/clone-visitor.h @@ -0,0 +1,51 @@ +/* + * Clone Visitor + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QAPI_CLONE_VISITOR_H +#define QAPI_CLONE_VISITOR_H + +#include "qapi/visitor.h" + +/* + * The clone visitor is for direct use only by the QAPI_CLONE() macro; + * it requires that the root visit occur on an object, list, or + * alternate, and is not usable directly on built-in QAPI types. + */ +typedef struct QapiCloneVisitor QapiCloneVisitor; + +void *qapi_clone(const void *src, bool (*visit_type)(Visitor *, const char *, + void **, Error **)); +void qapi_clone_members(void *dst, const void *src, size_t sz, + bool (*visit_type_members)(Visitor *, void *, + Error **)); + +/* + * Deep-clone QAPI object @src of the given @type, and return the result. + * + * Not usable on QAPI scalars (integers, strings, enums), nor on a + * QAPI object that references the 'any' type. Safe when @src is NULL. + */ +#define QAPI_CLONE(type, src) \ + ((type *)qapi_clone(src, \ + (bool (*)(Visitor *, const char *, void **, \ + Error **))visit_type_ ## type)) + +/* + * Copy deep clones of @type members from @src to @dst. + * + * Not usable on QAPI scalars (integers, strings, enums), nor on a + * QAPI object that references the 'any' type. + */ +#define QAPI_CLONE_MEMBERS(type, dst, src) \ + qapi_clone_members(dst, src, sizeof(type), \ + (bool (*)(Visitor *, void *, \ + Error **))visit_type_ ## type ## _members) + +#endif diff --git a/include/qapi/compat-policy.h b/include/qapi/compat-policy.h new file mode 100644 index 000000000..8b7b25c0b --- /dev/null +++ b/include/qapi/compat-policy.h @@ -0,0 +1,45 @@ +/* + * Policy for handling "funny" management interfaces + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef QAPI_COMPAT_POLICY_H +#define QAPI_COMPAT_POLICY_H + +#include "qapi/error.h" +#include "qapi/qapi-types-compat.h" + +extern CompatPolicy compat_policy; + +bool compat_policy_input_ok(unsigned special_features, + const CompatPolicy *policy, + ErrorClass error_class, + const char *kind, const char *name, + Error **errp); + +/* + * Create a QObject input visitor for @obj for use with QMP + * + * This is like qobject_input_visitor_new(), except it obeys the + * policy for handling deprecated management interfaces set with + * -compat. + */ +Visitor *qobject_input_visitor_new_qmp(QObject *obj); + +/* + * Create a QObject output visitor for @obj for use with QMP + * + * This is like qobject_output_visitor_new(), except it obeys the + * policy for handling deprecated management interfaces set with + * -compat. + */ +Visitor *qobject_output_visitor_new_qmp(QObject **result); + +#endif diff --git a/include/qapi/dealloc-visitor.h b/include/qapi/dealloc-visitor.h new file mode 100644 index 000000000..c36715fdf --- /dev/null +++ b/include/qapi/dealloc-visitor.h @@ -0,0 +1,28 @@ +/* + * Dealloc Visitor + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Michael Roth <mdroth@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QAPI_DEALLOC_VISITOR_H +#define QAPI_DEALLOC_VISITOR_H + +#include "qapi/visitor.h" + +typedef struct QapiDeallocVisitor QapiDeallocVisitor; + +/* + * The dealloc visitor is primarily used only by generated + * qapi_free_FOO() functions, and is the only visitor designed to work + * correctly in the face of a partially-constructed QAPI tree. + */ +Visitor *qapi_dealloc_visitor_new(void); + +#endif diff --git a/include/qapi/error.h b/include/qapi/error.h new file mode 100644 index 000000000..4a9260b0c --- /dev/null +++ b/include/qapi/error.h @@ -0,0 +1,534 @@ +/* + * QEMU Error Objects + * + * Copyright IBM, Corp. 2011 + * Copyright (C) 2011-2015 Red Hat, Inc. + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * Markus Armbruster <armbru@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ + +/* + * Error reporting system loosely patterned after Glib's GError. + * + * = Rules = + * + * - Functions that use Error to report errors have an Error **errp + * parameter. It should be the last parameter, except for functions + * taking variable arguments. + * + * - You may pass NULL to not receive the error, &error_abort to abort + * on error, &error_fatal to exit(1) on error, or a pointer to a + * variable containing NULL to receive the error. + * + * - Separation of concerns: the function is responsible for detecting + * errors and failing cleanly; handling the error is its caller's + * job. Since the value of @errp is about handling the error, the + * function should not examine it. + * + * - The function may pass @errp to functions it calls to pass on + * their errors to its caller. If it dereferences @errp to check + * for errors, it must use ERRP_GUARD(). + * + * - On success, the function should not touch *errp. On failure, it + * should set a new error, e.g. with error_setg(errp, ...), or + * propagate an existing one, e.g. with error_propagate(errp, ...). + * + * - Whenever practical, also return a value that indicates success / + * failure. This can make the error checking more concise, and can + * avoid useless error object creation and destruction. Note that + * we still have many functions returning void. We recommend + * • bool-valued functions return true on success / false on failure, + * • pointer-valued functions return non-null / null pointer, and + * • integer-valued functions return non-negative / negative. + * + * = Creating errors = + * + * Create an error: + * error_setg(errp, "situation normal, all fouled up"); + * where @errp points to the location to receive the error. + * + * Create an error and add additional explanation: + * error_setg(errp, "invalid quark"); + * error_append_hint(errp, "Valid quarks are up, down, strange, " + * "charm, top, bottom.\n"); + * This may require use of ERRP_GUARD(); more on that below. + * + * Do *not* contract this to + * error_setg(errp, "invalid quark\n" // WRONG! + * "Valid quarks are up, down, strange, charm, top, bottom."); + * + * = Reporting and destroying errors = + * + * Report an error to the current monitor if we have one, else stderr: + * error_report_err(err); + * This frees the error object. + * + * Likewise, but with additional text prepended: + * error_reportf_err(err, "Could not frobnicate '%s': ", name); + * + * Report an error somewhere else: + * const char *msg = error_get_pretty(err); + * do with msg what needs to be done... + * error_free(err); + * Note that this loses hints added with error_append_hint(). + * + * Call a function ignoring errors: + * foo(arg, NULL); + * This is more concise than + * Error *err = NULL; + * foo(arg, &err); + * error_free(err); // don't do this + * + * Call a function aborting on errors: + * foo(arg, &error_abort); + * This is more concise and fails more nicely than + * Error *err = NULL; + * foo(arg, &err); + * assert(!err); // don't do this + * + * Call a function treating errors as fatal: + * foo(arg, &error_fatal); + * This is more concise than + * Error *err = NULL; + * foo(arg, &err); + * if (err) { // don't do this + * error_report_err(err); + * exit(1); + * } + * + * Handle an error without reporting it (just for completeness): + * error_free(err); + * + * Assert that an expected error occurred, but clean it up without + * reporting it (primarily useful in testsuites): + * error_free_or_abort(&err); + * + * = Passing errors around = + * + * Errors get passed to the caller through the conventional @errp + * parameter. + * + * Create a new error and pass it to the caller: + * error_setg(errp, "situation normal, all fouled up"); + * + * Call a function, receive an error from it, and pass it to the caller + * - when the function returns a value that indicates failure, say + * false: + * if (!foo(arg, errp)) { + * handle the error... + * } + * - when it does not, say because it is a void function: + * ERRP_GUARD(); + * foo(arg, errp); + * if (*errp) { + * handle the error... + * } + * More on ERRP_GUARD() below. + * + * Code predating ERRP_GUARD() still exists, and looks like this: + * Error *err = NULL; + * foo(arg, &err); + * if (err) { + * handle the error... + * error_propagate(errp, err); // deprecated + * } + * Avoid in new code. Do *not* "optimize" it to + * foo(arg, errp); + * if (*errp) { // WRONG! + * handle the error... + * } + * because errp may be NULL without the ERRP_GUARD() guard. + * + * But when all you do with the error is pass it on, please use + * foo(arg, errp); + * for readability. + * + * Receive an error, and handle it locally + * - when the function returns a value that indicates failure, say + * false: + * Error *err = NULL; + * if (!foo(arg, &err)) { + * handle the error... + * } + * - when it does not, say because it is a void function: + * Error *err = NULL; + * foo(arg, &err); + * if (err) { + * handle the error... + * } + * + * Pass an existing error to the caller: + * error_propagate(errp, err); + * This is rarely needed. When @err is a local variable, use of + * ERRP_GUARD() commonly results in more readable code. + * + * Pass an existing error to the caller with the message modified: + * error_propagate_prepend(errp, err, + * "Could not frobnicate '%s': ", name); + * This is more concise than + * error_propagate(errp, err); // don't do this + * error_prepend(errp, "Could not frobnicate '%s': ", name); + * and works even when @errp is &error_fatal. + * + * Receive and accumulate multiple errors (first one wins): + * Error *err = NULL, *local_err = NULL; + * foo(arg, &err); + * bar(arg, &local_err); + * error_propagate(&err, local_err); + * if (err) { + * handle the error... + * } + * + * Do *not* "optimize" this to + * Error *err = NULL; + * foo(arg, &err); + * bar(arg, &err); // WRONG! + * if (err) { + * handle the error... + * } + * because this may pass a non-null err to bar(). + * + * Likewise, do *not* + * Error *err = NULL; + * if (cond1) { + * error_setg(&err, ...); + * } + * if (cond2) { + * error_setg(&err, ...); // WRONG! + * } + * because this may pass a non-null err to error_setg(). + * + * = Why, when and how to use ERRP_GUARD() = + * + * Without ERRP_GUARD(), use of the @errp parameter is restricted: + * - It must not be dereferenced, because it may be null. + * - It should not be passed to error_prepend() or + * error_append_hint(), because that doesn't work with &error_fatal. + * ERRP_GUARD() lifts these restrictions. + * + * To use ERRP_GUARD(), add it right at the beginning of the function. + * @errp can then be used without worrying about the argument being + * NULL or &error_fatal. + * + * Using it when it's not needed is safe, but please avoid cluttering + * the source with useless code. + * + * = Converting to ERRP_GUARD() = + * + * To convert a function to use ERRP_GUARD(): + * + * 0. If the Error ** parameter is not named @errp, rename it to + * @errp. + * + * 1. Add an ERRP_GUARD() invocation, by convention right at the + * beginning of the function. This makes @errp safe to use. + * + * 2. Replace &err by errp, and err by *errp. Delete local variable + * @err. + * + * 3. Delete error_propagate(errp, *errp), replace + * error_propagate_prepend(errp, *errp, ...) by error_prepend(errp, ...) + * + * 4. Ensure @errp is valid at return: when you destroy *errp, set + * *errp = NULL. + * + * Example: + * + * bool fn(..., Error **errp) + * { + * Error *err = NULL; + * + * foo(arg, &err); + * if (err) { + * handle the error... + * error_propagate(errp, err); + * return false; + * } + * ... + * } + * + * becomes + * + * bool fn(..., Error **errp) + * { + * ERRP_GUARD(); + * + * foo(arg, errp); + * if (*errp) { + * handle the error... + * return false; + * } + * ... + * } + * + * For mass-conversion, use scripts/coccinelle/errp-guard.cocci. + */ + +#ifndef ERROR_H +#define ERROR_H + +#include "qapi/qapi-types-error.h" + +/* + * Overall category of an error. + * Based on the qapi type QapiErrorClass, but reproduced here for nicer + * enum names. + */ +typedef enum ErrorClass { + ERROR_CLASS_GENERIC_ERROR = QAPI_ERROR_CLASS_GENERICERROR, + ERROR_CLASS_COMMAND_NOT_FOUND = QAPI_ERROR_CLASS_COMMANDNOTFOUND, + ERROR_CLASS_DEVICE_NOT_ACTIVE = QAPI_ERROR_CLASS_DEVICENOTACTIVE, + ERROR_CLASS_DEVICE_NOT_FOUND = QAPI_ERROR_CLASS_DEVICENOTFOUND, + ERROR_CLASS_KVM_MISSING_CAP = QAPI_ERROR_CLASS_KVMMISSINGCAP, +} ErrorClass; + +/* + * Get @err's human-readable error message. + */ +const char *error_get_pretty(const Error *err); + +/* + * Get @err's error class. + * Note: use of error classes other than ERROR_CLASS_GENERIC_ERROR is + * strongly discouraged. + */ +ErrorClass error_get_class(const Error *err); + +/* + * Create a new error object and assign it to *@errp. + * If @errp is NULL, the error is ignored. Don't bother creating one + * then. + * If @errp is &error_abort, print a suitable message and abort(). + * If @errp is &error_fatal, print a suitable message and exit(1). + * If @errp is anything else, *@errp must be NULL. + * The new error's class is ERROR_CLASS_GENERIC_ERROR, and its + * human-readable error message is made from printf-style @fmt, ... + * The resulting message should be a single phrase, with no newline or + * trailing punctuation. + * Please don't error_setg(&error_fatal, ...), use error_report() and + * exit(), because that's more obvious. + * Likewise, don't error_setg(&error_abort, ...), use assert(). + */ +#define error_setg(errp, fmt, ...) \ + error_setg_internal((errp), __FILE__, __LINE__, __func__, \ + (fmt), ## __VA_ARGS__) +void error_setg_internal(Error **errp, + const char *src, int line, const char *func, + const char *fmt, ...) + GCC_FMT_ATTR(5, 6); + +/* + * Just like error_setg(), with @os_error info added to the message. + * If @os_error is non-zero, ": " + strerror(os_error) is appended to + * the human-readable error message. + * + * The value of errno (which usually can get clobbered by almost any + * function call) will be preserved. + */ +#define error_setg_errno(errp, os_error, fmt, ...) \ + error_setg_errno_internal((errp), __FILE__, __LINE__, __func__, \ + (os_error), (fmt), ## __VA_ARGS__) +void error_setg_errno_internal(Error **errp, + const char *fname, int line, const char *func, + int os_error, const char *fmt, ...) + GCC_FMT_ATTR(6, 7); + +#ifdef _WIN32 +/* + * Just like error_setg(), with @win32_error info added to the message. + * If @win32_error is non-zero, ": " + g_win32_error_message(win32_err) + * is appended to the human-readable error message. + */ +#define error_setg_win32(errp, win32_err, fmt, ...) \ + error_setg_win32_internal((errp), __FILE__, __LINE__, __func__, \ + (win32_err), (fmt), ## __VA_ARGS__) +void error_setg_win32_internal(Error **errp, + const char *src, int line, const char *func, + int win32_err, const char *fmt, ...) + GCC_FMT_ATTR(6, 7); +#endif + +/* + * Propagate error object (if any) from @local_err to @dst_errp. + * If @local_err is NULL, do nothing (because there's nothing to + * propagate). + * Else, if @dst_errp is NULL, errors are being ignored. Free the + * error object. + * Else, if @dst_errp is &error_abort, print a suitable message and + * abort(). + * Else, if @dst_errp is &error_fatal, print a suitable message and + * exit(1). + * Else, if @dst_errp already contains an error, ignore this one: free + * the error object. + * Else, move the error object from @local_err to *@dst_errp. + * On return, @local_err is invalid. + * Please use ERRP_GUARD() instead when possible. + * Please don't error_propagate(&error_fatal, ...), use + * error_report_err() and exit(), because that's more obvious. + */ +void error_propagate(Error **dst_errp, Error *local_err); + + +/* + * Propagate error object (if any) with some text prepended. + * Behaves like + * error_prepend(&local_err, fmt, ...); + * error_propagate(dst_errp, local_err); + * Please use ERRP_GUARD() and error_prepend() instead when possible. + */ +void error_propagate_prepend(Error **dst_errp, Error *local_err, + const char *fmt, ...) + GCC_FMT_ATTR(3, 4); + +/* + * Prepend some text to @errp's human-readable error message. + * The text is made by formatting @fmt, @ap like vprintf(). + */ +void error_vprepend(Error *const *errp, const char *fmt, va_list ap) + GCC_FMT_ATTR(2, 0); + +/* + * Prepend some text to @errp's human-readable error message. + * The text is made by formatting @fmt, ... like printf(). + */ +void error_prepend(Error *const *errp, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/* + * Append a printf-style human-readable explanation to an existing error. + * If the error is later reported to a human user with + * error_report_err() or warn_report_err(), the hints will be shown, + * too. If it's reported via QMP, the hints will be ignored. + * Intended use is adding helpful hints on the human user interface, + * e.g. a list of valid values. It's not for clarifying a confusing + * error message. + * @errp may be NULL, but not &error_fatal or &error_abort. + * Trivially the case if you call it only after error_setg() or + * error_propagate(). + * May be called multiple times. The resulting hint should end with a + * newline. + */ +void error_append_hint(Error *const *errp, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/* + * Convenience function to report open() failure. + */ +#define error_setg_file_open(errp, os_errno, filename) \ + error_setg_file_open_internal((errp), __FILE__, __LINE__, __func__, \ + (os_errno), (filename)) +void error_setg_file_open_internal(Error **errp, + const char *src, int line, const char *func, + int os_errno, const char *filename); + +/* + * Return an exact copy of @err. + */ +Error *error_copy(const Error *err); + +/* + * Free @err. + * @err may be NULL. + */ +void error_free(Error *err); + +/* + * Convenience function to assert that *@errp is set, then silently free it. + */ +void error_free_or_abort(Error **errp); + +/* + * Convenience function to warn_report() and free @err. + * The report includes hints added with error_append_hint(). + */ +void warn_report_err(Error *err); + +/* + * Convenience function to error_report() and free @err. + * The report includes hints added with error_append_hint(). + */ +void error_report_err(Error *err); + +/* + * Convenience function to error_prepend(), warn_report() and free @err. + */ +void warn_reportf_err(Error *err, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/* + * Convenience function to error_prepend(), error_report() and free @err. + */ +void error_reportf_err(Error *err, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/* + * Just like error_setg(), except you get to specify the error class. + * Note: use of error classes other than ERROR_CLASS_GENERIC_ERROR is + * strongly discouraged. + */ +#define error_set(errp, err_class, fmt, ...) \ + error_set_internal((errp), __FILE__, __LINE__, __func__, \ + (err_class), (fmt), ## __VA_ARGS__) +void error_set_internal(Error **errp, + const char *src, int line, const char *func, + ErrorClass err_class, const char *fmt, ...) + GCC_FMT_ATTR(6, 7); + +/* + * Make @errp parameter easier to use regardless of argument value + * + * This macro is for use right at the beginning of a function that + * takes an Error **errp parameter to pass errors to its caller. The + * parameter must be named @errp. + * + * It must be used when the function dereferences @errp or passes + * @errp to error_prepend(), error_vprepend(), or error_append_hint(). + * It is safe to use even when it's not needed, but please avoid + * cluttering the source with useless code. + * + * If @errp is NULL or &error_fatal, rewrite it to point to a local + * Error variable, which will be automatically propagated to the + * original @errp on function exit. + * + * Note: &error_abort is not rewritten, because that would move the + * abort from the place where the error is created to the place where + * it's propagated. + */ +#define ERRP_GUARD() \ + g_auto(ErrorPropagator) _auto_errp_prop = {.errp = errp}; \ + do { \ + if (!errp || errp == &error_fatal) { \ + errp = &_auto_errp_prop.local_err; \ + } \ + } while (0) + +typedef struct ErrorPropagator { + Error *local_err; + Error **errp; +} ErrorPropagator; + +static inline void error_propagator_cleanup(ErrorPropagator *prop) +{ + error_propagate(prop->errp, prop->local_err); +} + +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup); + +/* + * Special error destination to abort on error. + * See error_setg() and error_propagate() for details. + */ +extern Error *error_abort; + +/* + * Special error destination to exit(1) on error. + * See error_setg() and error_propagate() for details. + */ +extern Error *error_fatal; + +#endif diff --git a/include/qapi/forward-visitor.h b/include/qapi/forward-visitor.h new file mode 100644 index 000000000..50fb3e9d5 --- /dev/null +++ b/include/qapi/forward-visitor.h @@ -0,0 +1,27 @@ +/* + * Forwarding visitor + * + * Copyright Red Hat, Inc. 2021 + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef FORWARD_VISITOR_H +#define FORWARD_VISITOR_H + +#include "qapi/visitor.h" + +typedef struct ForwardFieldVisitor ForwardFieldVisitor; + +/* + * The forwarding visitor only expects a single name, @from, to be passed for + * toplevel fields. It is converted to @to and forwarded to the @target visitor. + * Calls within a struct are forwarded without changing the name. + */ +Visitor *visitor_forward_field(Visitor *target, const char *from, const char *to); + +#endif diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h new file mode 100644 index 000000000..9b989e7e0 --- /dev/null +++ b/include/qapi/opts-visitor.h @@ -0,0 +1,39 @@ +/* + * Options Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Laszlo Ersek <lersek@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef OPTS_VISITOR_H +#define OPTS_VISITOR_H + +#include "qapi/visitor.h" + +/* Inclusive upper bound on the size of any flattened range. This is a safety + * (= anti-annoyance) measure; wrong ranges should not cause long startup + * delays nor exhaust virtual memory. + */ +#define OPTS_VISITOR_RANGE_MAX 65536 + +typedef struct OptsVisitor OptsVisitor; + +/* Contrarily to qemu-option.c::parse_option_number(), OptsVisitor's "int" + * parser relies on strtoll() instead of strtoull(). Consequences: + * - string representations of negative numbers yield negative values, + * - values below INT64_MIN or LLONG_MIN are rejected, + * - values above INT64_MAX or LLONG_MAX are rejected. + * + * The Opts input visitor does not implement support for visiting QAPI + * alternates, numbers (other than integers), null, or arbitrary + * QTypes. It also requires a non-null list argument to + * visit_start_list(). + */ +Visitor *opts_visitor_new(const QemuOpts *opts); + +#endif diff --git a/include/qapi/qmp-event.h b/include/qapi/qmp-event.h new file mode 100644 index 000000000..b60f1d3a8 --- /dev/null +++ b/include/qapi/qmp-event.h @@ -0,0 +1,18 @@ +/* + * QMP Event related + * + * Copyright (c) 2014 Wenchao Xia + * + * Authors: + * Wenchao Xia <wenchaoqemu@gmail.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QMP_EVENT_H +#define QMP_EVENT_H + +QDict *qmp_event_build_dict(const char *event_name); +#endif diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h new file mode 100644 index 000000000..1e4240fd0 --- /dev/null +++ b/include/qapi/qmp/dispatch.h @@ -0,0 +1,67 @@ +/* + * Core Definitions for QAPI/QMP Dispatch + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QAPI_QMP_DISPATCH_H +#define QAPI_QMP_DISPATCH_H + +#include "monitor/monitor.h" +#include "qemu/queue.h" + +typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); + +typedef enum QmpCommandOptions +{ + QCO_NO_SUCCESS_RESP = (1U << 0), + QCO_ALLOW_OOB = (1U << 1), + QCO_ALLOW_PRECONFIG = (1U << 2), + QCO_COROUTINE = (1U << 3), +} QmpCommandOptions; + +typedef struct QmpCommand +{ + const char *name; + /* Runs in coroutine context if QCO_COROUTINE is set */ + QmpCommandFunc *fn; + QmpCommandOptions options; + unsigned special_features; + QTAILQ_ENTRY(QmpCommand) node; + bool enabled; + const char *disable_reason; +} QmpCommand; + +typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList; + +void qmp_register_command(QmpCommandList *cmds, const char *name, + QmpCommandFunc *fn, QmpCommandOptions options, + unsigned special_features); +const QmpCommand *qmp_find_command(const QmpCommandList *cmds, + const char *name); +void qmp_disable_command(QmpCommandList *cmds, const char *name, + const char *err_msg); +void qmp_enable_command(QmpCommandList *cmds, const char *name); + +bool qmp_command_is_enabled(const QmpCommand *cmd); +bool qmp_command_available(const QmpCommand *cmd, Error **errp); +const char *qmp_command_name(const QmpCommand *cmd); +bool qmp_has_success_response(const QmpCommand *cmd); +QDict *qmp_error_response(Error *err); +QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, + bool allow_oob, Monitor *cur_mon); +bool qmp_is_oob(const QDict *dict); + +typedef void (*qmp_cmd_callback_fn)(const QmpCommand *cmd, void *opaque); + +void qmp_for_each_command(const QmpCommandList *cmds, qmp_cmd_callback_fn fn, + void *opaque); + +#endif diff --git a/include/qapi/qmp/json-parser.h b/include/qapi/qmp/json-parser.h new file mode 100644 index 000000000..7345a9bd5 --- /dev/null +++ b/include/qapi/qmp/json-parser.h @@ -0,0 +1,46 @@ +/* + * JSON Parser + * + * Copyright IBM, Corp. 2009 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QAPI_QMP_JSON_PARSER_H +#define QAPI_QMP_JSON_PARSER_H + +typedef struct JSONLexer { + int start_state, state; + GString *token; + int x, y; +} JSONLexer; + +typedef struct JSONMessageParser { + void (*emit)(void *opaque, QObject *json, Error *err); + void *opaque; + va_list *ap; + JSONLexer lexer; + int brace_count; + int bracket_count; + GQueue tokens; + uint64_t token_size; +} JSONMessageParser; + +void json_message_parser_init(JSONMessageParser *parser, + void (*emit)(void *opaque, QObject *json, + Error *err), + void *opaque, va_list *ap); + +void json_message_parser_feed(JSONMessageParser *parser, + const char *buffer, size_t size); + +void json_message_parser_flush(JSONMessageParser *parser); + +void json_message_parser_destroy(JSONMessageParser *parser); + +#endif diff --git a/include/qapi/qmp/json-writer.h b/include/qapi/qmp/json-writer.h new file mode 100644 index 000000000..b70ba6407 --- /dev/null +++ b/include/qapi/qmp/json-writer.h @@ -0,0 +1,35 @@ +/* + * JSON Writer + * + * Copyright (c) 2020 Red Hat Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef JSON_WRITER_H +#define JSON_WRITER_H + +JSONWriter *json_writer_new(bool pretty); +const char *json_writer_get(JSONWriter *); +GString *json_writer_get_and_free(JSONWriter *); +void json_writer_free(JSONWriter *); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(JSONWriter, json_writer_free) + +void json_writer_start_object(JSONWriter *, const char *name); +void json_writer_end_object(JSONWriter *); +void json_writer_start_array(JSONWriter *, const char *name); +void json_writer_end_array(JSONWriter *); +void json_writer_bool(JSONWriter *, const char *name, bool val); +void json_writer_null(JSONWriter *, const char *name); +void json_writer_int64(JSONWriter *, const char *name, int64_t val); +void json_writer_uint64(JSONWriter *, const char *name, uint64_t val); +void json_writer_double(JSONWriter *, const char *name, double val); +void json_writer_str(JSONWriter *, const char *name, const char *str); + +#endif diff --git a/include/qapi/qmp/qbool.h b/include/qapi/qmp/qbool.h new file mode 100644 index 000000000..2f888d105 --- /dev/null +++ b/include/qapi/qmp/qbool.h @@ -0,0 +1,27 @@ +/* + * QBool Module + * + * Copyright IBM, Corp. 2009 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QBOOL_H +#define QBOOL_H + +#include "qapi/qmp/qobject.h" + +struct QBool { + struct QObjectBase_ base; + bool value; +}; + +QBool *qbool_from_bool(bool value); +bool qbool_get_bool(const QBool *qb); + +#endif /* QBOOL_H */ diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h new file mode 100644 index 000000000..d5b5430e2 --- /dev/null +++ b/include/qapi/qmp/qdict.h @@ -0,0 +1,70 @@ +/* + * QDict Module + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino <lcapitulino@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +#ifndef QDICT_H +#define QDICT_H + +#include "qapi/qmp/qobject.h" +#include "qemu/queue.h" + +#define QDICT_BUCKET_MAX 512 + +typedef struct QDictEntry { + char *key; + QObject *value; + QLIST_ENTRY(QDictEntry) next; +} QDictEntry; + +struct QDict { + struct QObjectBase_ base; + size_t size; + QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX]; +}; + +/* Object API */ +QDict *qdict_new(void); +const char *qdict_entry_key(const QDictEntry *entry); +QObject *qdict_entry_value(const QDictEntry *entry); +size_t qdict_size(const QDict *qdict); +void qdict_put_obj(QDict *qdict, const char *key, QObject *value); +void qdict_del(QDict *qdict, const char *key); +int qdict_haskey(const QDict *qdict, const char *key); +QObject *qdict_get(const QDict *qdict, const char *key); +const QDictEntry *qdict_first(const QDict *qdict); +const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry); + +/* Helper to qdict_put_obj(), accepts any object */ +#define qdict_put(qdict, key, obj) \ + qdict_put_obj(qdict, key, QOBJECT(obj)) + +void qdict_put_bool(QDict *qdict, const char *key, bool value); +void qdict_put_int(QDict *qdict, const char *key, int64_t value); +void qdict_put_null(QDict *qdict, const char *key); +void qdict_put_str(QDict *qdict, const char *key, const char *value); + +double qdict_get_double(const QDict *qdict, const char *key); +int64_t qdict_get_int(const QDict *qdict, const char *key); +bool qdict_get_bool(const QDict *qdict, const char *key); +QList *qdict_get_qlist(const QDict *qdict, const char *key); +QDict *qdict_get_qdict(const QDict *qdict, const char *key); +const char *qdict_get_str(const QDict *qdict, const char *key); +int64_t qdict_get_try_int(const QDict *qdict, const char *key, + int64_t def_value); +bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value); +const char *qdict_get_try_str(const QDict *qdict, const char *key); + +QDict *qdict_clone_shallow(const QDict *src); + +QObject *qdict_crumple(const QDict *src, Error **errp); +void qdict_flatten(QDict *qdict); + +#endif /* QDICT_H */ diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h new file mode 100644 index 000000000..596fce0c5 --- /dev/null +++ b/include/qapi/qmp/qerror.h @@ -0,0 +1,71 @@ +/* + * QError Module + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino <lcapitulino@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ +#ifndef QERROR_H +#define QERROR_H + +/* + * These macros will go away, please don't use in new code, and do not + * add new ones! + */ + +#define QERR_BUS_NO_HOTPLUG \ + "Bus '%s' does not support hotplugging" + +#define QERR_DEVICE_HAS_NO_MEDIUM \ + "Device '%s' has no medium" + +#define QERR_DEVICE_IN_USE \ + "Device '%s' is in use" + +#define QERR_DEVICE_NO_HOTPLUG \ + "Device '%s' does not support hotplugging" + +#define QERR_FEATURE_DISABLED \ + "The feature '%s' is not enabled" + +#define QERR_INVALID_PARAMETER \ + "Invalid parameter '%s'" + +#define QERR_INVALID_PARAMETER_TYPE \ + "Invalid parameter type for '%s', expected: %s" + +#define QERR_INVALID_PARAMETER_VALUE \ + "Parameter '%s' expects %s" + +#define QERR_IO_ERROR \ + "An IO error has occurred" + +#define QERR_MIGRATION_ACTIVE \ + "There's a migration process in progress" + +#define QERR_MISSING_PARAMETER \ + "Parameter '%s' is missing" + +#define QERR_PERMISSION_DENIED \ + "Insufficient permission to perform this operation" + +#define QERR_PROPERTY_VALUE_BAD \ + "Property '%s.%s' doesn't take value '%s'" + +#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ + "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")" + +#define QERR_QGA_COMMAND_FAILED \ + "Guest agent command failed, error was '%s'" + +#define QERR_REPLAY_NOT_SUPPORTED \ + "Record/replay feature is not supported for '%s'" + +#define QERR_UNSUPPORTED \ + "this feature or command is not currently supported" + +#endif /* QERROR_H */ diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h new file mode 100644 index 000000000..593b40b4e --- /dev/null +++ b/include/qapi/qmp/qjson.h @@ -0,0 +1,31 @@ +/* + * QObject JSON integration + * + * Copyright IBM, Corp. 2009 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QJSON_H +#define QJSON_H + +QObject *qobject_from_json(const char *string, Error **errp); + +QObject *qobject_from_vjsonf_nofail(const char *string, va_list ap) + GCC_FMT_ATTR(1, 0); +QObject *qobject_from_jsonf_nofail(const char *string, ...) + GCC_FMT_ATTR(1, 2); +QDict *qdict_from_vjsonf_nofail(const char *string, va_list ap) + GCC_FMT_ATTR(1, 0); +QDict *qdict_from_jsonf_nofail(const char *string, ...) + GCC_FMT_ATTR(1, 2); + +GString *qobject_to_json(const QObject *obj); +GString *qobject_to_json_pretty(const QObject *obj, bool pretty); + +#endif /* QJSON_H */ diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h new file mode 100644 index 000000000..06e98ad5f --- /dev/null +++ b/include/qapi/qmp/qlist.h @@ -0,0 +1,65 @@ +/* + * QList Module + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino <lcapitulino@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +#ifndef QLIST_H +#define QLIST_H + +#include "qapi/qmp/qobject.h" +#include "qemu/queue.h" + +typedef struct QListEntry { + QObject *value; + QTAILQ_ENTRY(QListEntry) next; +} QListEntry; + +struct QList { + struct QObjectBase_ base; + QTAILQ_HEAD(,QListEntry) head; +}; + +#define qlist_append(qlist, obj) \ + qlist_append_obj(qlist, QOBJECT(obj)) + +void qlist_append_bool(QList *qlist, bool value); +void qlist_append_int(QList *qlist, int64_t value); +void qlist_append_null(QList *qlist); +void qlist_append_str(QList *qlist, const char *value); + +#define QLIST_FOREACH_ENTRY(qlist, var) \ + for ((var) = QTAILQ_FIRST(&(qlist)->head); \ + (var); \ + (var) = QTAILQ_NEXT((var), next)) + +static inline QObject *qlist_entry_obj(const QListEntry *entry) +{ + return entry->value; +} + +QList *qlist_new(void); +QList *qlist_copy(QList *src); +void qlist_append_obj(QList *qlist, QObject *obj); +QObject *qlist_pop(QList *qlist); +QObject *qlist_peek(QList *qlist); +int qlist_empty(const QList *qlist); +size_t qlist_size(const QList *qlist); + +static inline const QListEntry *qlist_first(const QList *qlist) +{ + return QTAILQ_FIRST(&qlist->head); +} + +static inline const QListEntry *qlist_next(const QListEntry *entry) +{ + return QTAILQ_NEXT(entry, next); +} + +#endif /* QLIST_H */ diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h new file mode 100644 index 000000000..c0676d5da --- /dev/null +++ b/include/qapi/qmp/qlit.h @@ -0,0 +1,55 @@ +/* + * Copyright IBM, Corp. 2009 + * Copyright (c) 2013, 2015, 2017 Red Hat Inc. + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * Markus Armbruster <armbru@redhat.com> + * Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ +#ifndef QLIT_H +#define QLIT_H + +#include "qobject.h" + +typedef struct QLitDictEntry QLitDictEntry; +typedef struct QLitObject QLitObject; + +struct QLitObject { + QType type; + union { + bool qbool; + int64_t qnum; + const char *qstr; + QLitDictEntry *qdict; + QLitObject *qlist; + } value; +}; + +struct QLitDictEntry { + const char *key; + QLitObject value; +}; + +#define QLIT_QNULL \ + { .type = QTYPE_QNULL } +#define QLIT_QBOOL(val) \ + { .type = QTYPE_QBOOL, .value.qbool = (val) } +#define QLIT_QNUM(val) \ + { .type = QTYPE_QNUM, .value.qnum = (val) } +#define QLIT_QSTR(val) \ + { .type = QTYPE_QSTRING, .value.qstr = (val) } +#define QLIT_QDICT(val) \ + { .type = QTYPE_QDICT, .value.qdict = (val) } +#define QLIT_QLIST(val) \ + { .type = QTYPE_QLIST, .value.qlist = (val) } + +bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs); + +QObject *qobject_from_qlit(const QLitObject *qlit); + +#endif /* QLIT_H */ diff --git a/include/qapi/qmp/qnull.h b/include/qapi/qmp/qnull.h new file mode 100644 index 000000000..e84ecceed --- /dev/null +++ b/include/qapi/qmp/qnull.h @@ -0,0 +1,29 @@ +/* + * QNull + * + * Copyright (C) 2015 Red Hat, Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 + * or later. See the COPYING.LIB file in the top-level directory. + */ + +#ifndef QNULL_H +#define QNULL_H + +#include "qapi/qmp/qobject.h" + +struct QNull { + struct QObjectBase_ base; +}; + +extern QNull qnull_; + +static inline QNull *qnull(void) +{ + return qobject_ref(&qnull_); +} + +#endif /* QNULL_H */ diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h new file mode 100644 index 000000000..7f84e20bf --- /dev/null +++ b/include/qapi/qmp/qnum.h @@ -0,0 +1,71 @@ +/* + * QNum Module + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino <lcapitulino@redhat.com> + * Anthony Liguori <aliguori@us.ibm.com> + * Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +#ifndef QNUM_H +#define QNUM_H + +#include "qapi/qmp/qobject.h" + +typedef enum { + QNUM_I64, + QNUM_U64, + QNUM_DOUBLE +} QNumKind; + +/* + * QNum encapsulates how our dialect of JSON fills in the blanks left + * by the JSON specification (RFC 8259) regarding numbers. + * + * Conceptually, we treat number as an abstract type with three + * concrete subtypes: floating-point, signed integer, unsigned + * integer. QNum implements this as a discriminated union of double, + * int64_t, uint64_t. + * + * The JSON parser picks the subtype as follows. If the number has a + * decimal point or an exponent, it is floating-point. Else if it + * fits into int64_t, it's signed integer. Else if it fits into + * uint64_t, it's unsigned integer. Else it's floating-point. + * + * Any number can serve as double: qnum_get_double() converts under + * the hood. + * + * An integer can serve as signed / unsigned integer as long as it is + * in range: qnum_get_try_int() / qnum_get_try_uint() check range and + * convert under the hood. + */ +struct QNum { + struct QObjectBase_ base; + QNumKind kind; + union { + int64_t i64; + uint64_t u64; + double dbl; + } u; +}; + +QNum *qnum_from_int(int64_t value); +QNum *qnum_from_uint(uint64_t value); +QNum *qnum_from_double(double value); + +bool qnum_get_try_int(const QNum *qn, int64_t *val); +int64_t qnum_get_int(const QNum *qn); + +bool qnum_get_try_uint(const QNum *qn, uint64_t *val); +uint64_t qnum_get_uint(const QNum *qn); + +double qnum_get_double(QNum *qn); + +char *qnum_to_string(QNum *qn); + +#endif /* QNUM_H */ diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h new file mode 100644 index 000000000..9003b71fd --- /dev/null +++ b/include/qapi/qmp/qobject.h @@ -0,0 +1,138 @@ +/* + * QEMU Object Model. + * + * Based on ideas by Avi Kivity <avi@redhat.com> + * + * Copyright (C) 2009, 2015 Red Hat Inc. + * + * Authors: + * Luiz Capitulino <lcapitulino@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + * QObject Reference Counts Terminology + * ------------------------------------ + * + * - Returning references: A function that returns an object may + * return it as either a weak or a strong reference. If the + * reference is strong, you are responsible for calling + * qobject_unref() on the reference when you are done. + * + * If the reference is weak, the owner of the reference may free it at + * any time in the future. Before storing the reference anywhere, you + * should call qobject_ref() to make the reference strong. + * + * - Transferring ownership: when you transfer ownership of a reference + * by calling a function, you are no longer responsible for calling + * qobject_unref() when the reference is no longer needed. In other words, + * when the function returns you must behave as if the reference to the + * passed object was weak. + */ +#ifndef QOBJECT_H +#define QOBJECT_H + +#include "qapi/qapi-builtin-types.h" + +/* Not for use outside include/qapi/qmp/ */ +struct QObjectBase_ { + QType type; + size_t refcnt; +}; + +/* this struct must have no other members than base */ +struct QObject { + struct QObjectBase_ base; +}; + +#define QOBJECT(obj) ({ \ + typeof(obj) _obj = (obj); \ + _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ +}) + +/* Required for qobject_to() */ +#define QTYPE_CAST_TO_QNull QTYPE_QNULL +#define QTYPE_CAST_TO_QNum QTYPE_QNUM +#define QTYPE_CAST_TO_QString QTYPE_QSTRING +#define QTYPE_CAST_TO_QDict QTYPE_QDICT +#define QTYPE_CAST_TO_QList QTYPE_QLIST +#define QTYPE_CAST_TO_QBool QTYPE_QBOOL + +QEMU_BUILD_BUG_MSG(QTYPE__MAX != 7, + "The QTYPE_CAST_TO_* list needs to be extended"); + +#define qobject_to(type, obj) \ + ((type *)qobject_check_type(obj, glue(QTYPE_CAST_TO_, type))) + +static inline void qobject_ref_impl(QObject *obj) +{ + if (obj) { + obj->base.refcnt++; + } +} + +/** + * qobject_is_equal(): Return whether the two objects are equal. + * + * Any of the pointers may be NULL; return true if both are. Always + * return false if only one is (therefore a QNull object is not + * considered equal to a NULL pointer). + */ +bool qobject_is_equal(const QObject *x, const QObject *y); + +/** + * qobject_destroy(): Free resources used by the object + * For use via qobject_unref() only! + */ +void qobject_destroy(QObject *obj); + +static inline void qobject_unref_impl(QObject *obj) +{ + assert(!obj || obj->base.refcnt); + if (obj && --obj->base.refcnt == 0) { + qobject_destroy(obj); + } +} + +/** + * qobject_ref(): Increment QObject's reference count + * + * Returns: the same @obj. The type of @obj will be propagated to the + * return type. + */ +#define qobject_ref(obj) ({ \ + typeof(obj) _o = (obj); \ + qobject_ref_impl(QOBJECT(_o)); \ + _o; \ +}) + +/** + * qobject_unref(): Decrement QObject's reference count, deallocate + * when it reaches zero + */ +#define qobject_unref(obj) qobject_unref_impl(QOBJECT(obj)) + +/** + * qobject_type(): Return the QObject's type + */ +static inline QType qobject_type(const QObject *obj) +{ + assert(QTYPE_NONE < obj->base.type && obj->base.type < QTYPE__MAX); + return obj->base.type; +} + +/** + * qobject_check_type(): Helper function for the qobject_to() macro. + * Return @obj, but only if @obj is not NULL and @type is equal to + * @obj's type. Return NULL otherwise. + */ +static inline QObject *qobject_check_type(const QObject *obj, QType type) +{ + if (obj && qobject_type(obj) == type) { + return (QObject *)obj; + } else { + return NULL; + } +} + +#endif /* QOBJECT_H */ diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h new file mode 100644 index 000000000..1d8ba4693 --- /dev/null +++ b/include/qapi/qmp/qstring.h @@ -0,0 +1,29 @@ +/* + * QString Module + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino <lcapitulino@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +#ifndef QSTRING_H +#define QSTRING_H + +#include "qapi/qmp/qobject.h" + +struct QString { + struct QObjectBase_ base; + const char *string; +}; + +QString *qstring_new(void); +QString *qstring_from_str(const char *str); +QString *qstring_from_substr(const char *str, size_t start, size_t end); +QString *qstring_from_gstring(GString *gstr); +const char *qstring_get_str(const QString *qstring); + +#endif /* QSTRING_H */ diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-input-visitor.h new file mode 100644 index 000000000..95985e25e --- /dev/null +++ b/include/qapi/qobject-input-visitor.h @@ -0,0 +1,82 @@ +/* + * Input Visitor + * + * Copyright (C) 2017 Red Hat, Inc. + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QOBJECT_INPUT_VISITOR_H +#define QOBJECT_INPUT_VISITOR_H + +#include "qapi/visitor.h" + +typedef struct QObjectInputVisitor QObjectInputVisitor; + +/* + * Create a QObject input visitor for @obj + * + * A QObject input visitor visit builds a QAPI object from a QObject. + * This simultaneously walks the QAPI object being built and the + * QObject. The latter walk starts at @obj. + * + * visit_type_FOO() creates an instance of QAPI type FOO. The visited + * QObject must match FOO. QDict matches struct/union types, QList + * matches list types, QString matches type 'str' and enumeration + * types, QNum matches integer and float types, QBool matches type + * 'bool'. Type 'any' is matched by QObject. A QAPI alternate type + * is matched when one of its member types is. + * + * visit_start_struct() ... visit_end_struct() visits a QDict and + * creates a QAPI struct/union. Visits in between visit the + * dictionary members. visit_optional() is true when the QDict has + * this member. visit_check_struct() fails if unvisited members + * remain. + * + * visit_start_list() ... visit_end_list() visits a QList and creates + * a QAPI list. Visits in between visit list members, one after the + * other. visit_next_list() returns NULL when all QList members have + * been visited. visit_check_list() fails if unvisited members + * remain. + * + * visit_start_alternate() ... visit_end_alternate() visits a QObject + * and creates a QAPI alternate. The visit in between visits the same + * QObject and initializes the alternate member that is in use. + * + * Error messages refer to parts of @obj in JavaScript/Python syntax. + * For example, 'a.b[2]' refers to the second member of the QList + * member 'b' of the QDict member 'a' of QDict @obj. + * + * The caller is responsible for freeing the visitor with + * visit_free(). + */ +Visitor *qobject_input_visitor_new(QObject *obj); + +/* + * Create a QObject input visitor for @obj for use with keyval_parse() + * + * This is like qobject_input_visitor_new(), except scalars are all + * QString, and error messages refer to parts of @obj in the syntax + * keyval_parse() uses for KEYs. + */ +Visitor *qobject_input_visitor_new_keyval(QObject *obj); + +/* + * Create a QObject input visitor for parsing @str. + * + * If @str looks like JSON, parse it as JSON, else as KEY=VALUE,... + * @implied_key applies to KEY=VALUE, and works as in keyval_parse(). + * On failure, store an error through @errp and return NULL. + * On success, return a new QObject input visitor for the parse. + */ +Visitor *qobject_input_visitor_new_str(const char *str, + const char *implied_key, + Error **errp); + +#endif diff --git a/include/qapi/qobject-output-visitor.h b/include/qapi/qobject-output-visitor.h new file mode 100644 index 000000000..2b1726baf --- /dev/null +++ b/include/qapi/qobject-output-visitor.h @@ -0,0 +1,56 @@ +/* + * Output Visitor + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QOBJECT_OUTPUT_VISITOR_H +#define QOBJECT_OUTPUT_VISITOR_H + +#include "qapi/visitor.h" + +typedef struct QObjectOutputVisitor QObjectOutputVisitor; + +/** + * Create a QObject output visitor for @obj + * + * A QObject output visitor visit builds a QObject from QAPI Object. + * This simultaneously walks the QAPI object and the QObject being + * built. The latter walk starts at @obj. + * + * visit_type_FOO() creates a QObject for QAPI type FOO. It creates a + * QDict for struct/union types, a QList for list types, QString for + * type 'str' and enumeration types, QNum for integer and float + * types, QBool for type 'bool'. For type 'any', it increments the + * QObject's reference count. For QAPI alternate types, it creates + * the QObject for the member that is in use. + * + * visit_start_struct() ... visit_end_struct() visits a QAPI + * struct/union and creates a QDict. Visits in between visit the + * members. visit_optional() is true when the struct/union has this + * member. visit_check_struct() does nothing. + * + * visit_start_list() ... visit_end_list() visits a QAPI list and + * creates a QList. Visits in between visit list members, one after + * the other. visit_next_list() returns NULL when all QAPI list + * members have been visited. visit_check_list() does nothing. + * + * visit_start_alternate() ... visit_end_alternate() visits a QAPI + * alternate. The visit in between creates the QObject for the + * alternate member that is in use. + * + * Errors are not expected to happen. + * + * The caller is responsible for freeing the visitor with + * visit_free(). + */ +Visitor *qobject_output_visitor_new(QObject **result); + +#endif diff --git a/include/qapi/string-input-visitor.h b/include/qapi/string-input-visitor.h new file mode 100644 index 000000000..921f3875b --- /dev/null +++ b/include/qapi/string-input-visitor.h @@ -0,0 +1,27 @@ +/* + * String parsing Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef STRING_INPUT_VISITOR_H +#define STRING_INPUT_VISITOR_H + +#include "qapi/visitor.h" + +typedef struct StringInputVisitor StringInputVisitor; + +/* + * The string input visitor does not implement support for visiting + * QAPI structs, alternates, null, or arbitrary QTypes. Only flat lists + * of integers (except type "size") are supported. + */ +Visitor *string_input_visitor_new(const char *str); + +#endif diff --git a/include/qapi/string-output-visitor.h b/include/qapi/string-output-visitor.h new file mode 100644 index 000000000..268dfe998 --- /dev/null +++ b/include/qapi/string-output-visitor.h @@ -0,0 +1,35 @@ +/* + * String printing Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef STRING_OUTPUT_VISITOR_H +#define STRING_OUTPUT_VISITOR_H + +#include "qapi/visitor.h" + +typedef struct StringOutputVisitor StringOutputVisitor; + +/* + * Create a new string output visitor. + * + * Using @human creates output that is a bit easier for humans to read + * (for example, showing integer values in both decimal and hex). + * + * If everything else succeeds, pass @result to visit_complete() to + * collect the result of the visit. + * + * The string output visitor does not implement support for visiting + * QAPI structs, alternates, null, or arbitrary QTypes. It also + * requires a non-null list argument to visit_start_list(). + */ +Visitor *string_output_visitor_new(bool human, char **result); + +#endif diff --git a/include/qapi/type-helpers.h b/include/qapi/type-helpers.h new file mode 100644 index 000000000..be1f18152 --- /dev/null +++ b/include/qapi/type-helpers.h @@ -0,0 +1,14 @@ +/* + * QAPI common helper functions + * + * This file provides helper functions related to types defined + * in the QAPI schema. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qapi/qapi-types-common.h" + +HumanReadableText *human_readable_text_from_str(GString *str); diff --git a/include/qapi/util.h b/include/qapi/util.h new file mode 100644 index 000000000..81a2b13a3 --- /dev/null +++ b/include/qapi/util.h @@ -0,0 +1,59 @@ +/* + * QAPI util functions + * + * Copyright Fujitsu, Inc. 2014 + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QAPI_UTIL_H +#define QAPI_UTIL_H + +typedef enum { + QAPI_DEPRECATED, + QAPI_UNSTABLE, +} QapiSpecialFeature; + +typedef struct QEnumLookup { + const char *const *array; + const unsigned char *const special_features; + const int size; +} QEnumLookup; + +const char *qapi_enum_lookup(const QEnumLookup *lookup, int val); +int qapi_enum_parse(const QEnumLookup *lookup, const char *buf, + int def, Error **errp); +bool qapi_bool_parse(const char *name, const char *value, bool *obj, + Error **errp); + +int parse_qapi_name(const char *name, bool complete); + +/* + * For any GenericList @list, insert @element at the front. + * + * Note that this macro evaluates @element exactly once, so it is safe + * to have side-effects with that argument. + */ +#define QAPI_LIST_PREPEND(list, element) do { \ + typeof(list) _tmp = g_malloc(sizeof(*(list))); \ + _tmp->value = (element); \ + _tmp->next = (list); \ + (list) = _tmp; \ +} while (0) + +/* + * For any pointer to a GenericList @tail (usually the 'next' member of a + * list element), insert @element at the back and update the tail. + * + * Note that this macro evaluates @element exactly once, so it is safe + * to have side-effects with that argument. + */ +#define QAPI_LIST_APPEND(tail, element) do { \ + *(tail) = g_malloc0(sizeof(**(tail))); \ + (*(tail))->value = (element); \ + (tail) = &(*(tail))->next; \ +} while (0) + +#endif diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h new file mode 100644 index 000000000..2badec5ba --- /dev/null +++ b/include/qapi/visitor-impl.h @@ -0,0 +1,137 @@ +/* + * Core Definitions for QAPI Visitor implementations + * + * Copyright (C) 2012-2016 Red Hat, Inc. + * + * Author: Paolo Bonizni <pbonzini@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ +#ifndef QAPI_VISITOR_IMPL_H +#define QAPI_VISITOR_IMPL_H + +#include "qapi/visitor.h" + +/* + * This file describes the callback interface for implementing a QAPI + * visitor. For the client interface, see visitor.h. When + * implementing the callbacks, it is easiest to declare a struct with + * 'Visitor visitor;' as the first member. A callback's contract + * matches the corresponding public functions' contract unless stated + * otherwise. In the comments below, some callbacks are marked "must + * be set for $TYPE visits to work"; if a visitor implementation omits + * that callback, it should also document that it is only useful for a + * subset of QAPI. + */ + +/* + * There are four classes of visitors; setting the class determines + * how QAPI enums are visited, as well as what additional restrictions + * can be asserted. The values are intentionally chosen so as to + * permit some assertions based on whether a given bit is set (that + * is, some assertions apply to input and clone visitors, some + * assertions apply to output and clone visitors). + */ +typedef enum VisitorType { + VISITOR_INPUT = 1, + VISITOR_OUTPUT = 2, + VISITOR_CLONE = 3, + VISITOR_DEALLOC = 4, +} VisitorType; + +struct Visitor +{ + /* + * Only input visitors may fail! + */ + + /* Must be set to visit structs */ + bool (*start_struct)(Visitor *v, const char *name, void **obj, + size_t size, Error **errp); + + /* Optional; intended for input visitors */ + bool (*check_struct)(Visitor *v, Error **errp); + + /* Must be set to visit structs */ + void (*end_struct)(Visitor *v, void **obj); + + /* Must be set; implementations may require @list to be non-null, + * but must document it. */ + bool (*start_list)(Visitor *v, const char *name, GenericList **list, + size_t size, Error **errp); + + /* Must be set */ + GenericList *(*next_list)(Visitor *v, GenericList *tail, size_t size); + + /* Optional; intended for input visitors */ + bool (*check_list)(Visitor *v, Error **errp); + + /* Must be set */ + void (*end_list)(Visitor *v, void **list); + + /* Must be set by input and clone visitors to visit alternates */ + bool (*start_alternate)(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + Error **errp); + + /* Optional */ + void (*end_alternate)(Visitor *v, void **obj); + + /* Must be set */ + bool (*type_int64)(Visitor *v, const char *name, int64_t *obj, + Error **errp); + + /* Must be set */ + bool (*type_uint64)(Visitor *v, const char *name, uint64_t *obj, + Error **errp); + + /* Optional; fallback is type_uint64() */ + bool (*type_size)(Visitor *v, const char *name, uint64_t *obj, + Error **errp); + + /* Must be set */ + bool (*type_bool)(Visitor *v, const char *name, bool *obj, Error **errp); + + /* Must be set */ + bool (*type_str)(Visitor *v, const char *name, char **obj, Error **errp); + + /* Must be set to visit numbers */ + bool (*type_number)(Visitor *v, const char *name, double *obj, + Error **errp); + + /* Must be set to visit arbitrary QTypes */ + bool (*type_any)(Visitor *v, const char *name, QObject **obj, + Error **errp); + + /* Must be set to visit explicit null values. */ + bool (*type_null)(Visitor *v, const char *name, QNull **obj, + Error **errp); + + /* Must be set for input visitors to visit structs, optional otherwise. + The core takes care of the return type in the public interface. */ + void (*optional)(Visitor *v, const char *name, bool *present); + + /* Optional */ + bool (*policy_reject)(Visitor *v, const char *name, + unsigned special_features, Error **errp); + + /* Optional */ + bool (*policy_skip)(Visitor *v, const char *name, + unsigned special_features); + + /* Must be set */ + VisitorType type; + + /* Optional */ + struct CompatPolicy compat_policy; + + /* Must be set for output visitors, optional otherwise. */ + void (*complete)(Visitor *v, void *opaque); + + /* Must be set */ + void (*free)(Visitor *v); +}; + +#endif diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h new file mode 100644 index 000000000..d53a84c9b --- /dev/null +++ b/include/qapi/visitor.h @@ -0,0 +1,713 @@ +/* + * Core Definitions for QAPI Visitor Classes + * + * Copyright (C) 2012-2016 Red Hat, Inc. + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QAPI_VISITOR_H +#define QAPI_VISITOR_H + +#include "qapi/qapi-builtin-types.h" +#include "qapi/qapi-types-compat.h" + +/* + * The QAPI schema defines both a set of C data types, and a QMP wire + * format. QAPI objects can contain references to other QAPI objects, + * resulting in a directed acyclic graph. QAPI also generates visitor + * functions to walk these graphs. This file represents the interface + * for doing work at each node of a QAPI graph; it can also be used + * for a virtual walk, where there is no actual QAPI C struct. + * + * There are four kinds of visitors: input visitors (QObject, string, + * and QemuOpts) parse an external representation and build the + * corresponding QAPI object, output visitors (QObject and string) + * take a QAPI object and generate an external representation, the + * dealloc visitor takes a QAPI object (possibly partially + * constructed) and recursively frees it, and the clone visitor + * performs a deep clone of a QAPI object. + * + * While the dealloc and QObject input/output visitors are general, + * the string, QemuOpts, and clone visitors have some implementation + * limitations; see the documentation for each visitor for more + * details on what it supports. Also, see visitor-impl.h for the + * callback contracts implemented by each visitor, and + * docs/devel/qapi-code-gen.txt for more about the QAPI code + * generator. + * + * All of the visitors are created via: + * + * Visitor *subtype_visitor_new(parameters...); + * + * A visitor should be used for exactly one top-level visit_type_FOO() + * or virtual walk; if that is successful, the caller can optionally + * call visit_complete() (useful only for output visits, but safe to + * call on all visits). Then, regardless of success or failure, the + * user should call visit_free() to clean up resources. It is okay to + * free the visitor without completing the visit, if some other error + * is detected in the meantime. + * + * The clone and dealloc visitor should not be used directly outside + * of QAPI code. Use the qapi_free_FOO() and QAPI_CLONE() instead, + * described below. + * + * All QAPI types have a corresponding function with a signature + * roughly compatible with this: + * + * bool visit_type_FOO(Visitor *v, const char *name, T obj, Error **errp); + * + * where T is FOO for scalar types, and FOO * otherwise. The scalar + * visitors are declared here; the remaining visitors are generated in + * qapi-visit-MODULE.h. + * + * The @name parameter of visit_type_FOO() describes the relation + * between this QAPI value and its parent container. When visiting + * the root of a tree, @name is ignored; when visiting a member of an + * object, @name is the key associated with the value; when visiting a + * member of a list, @name is NULL; and when visiting the member of an + * alternate, @name should equal the name used for visiting the + * alternate. + * + * The visit_type_FOO() functions take a non-null @obj argument; they + * allocate *@obj during input visits, leave it unchanged during + * output and clone visits, and free it (recursively) during a dealloc + * visit. + * + * Each function also takes the customary @errp argument (see + * qapi/error.h for details), for reporting any errors (such as if a + * member @name is not present, or is present but not the specified + * type). Only input visitors can fail. + * + * If an error is detected during visit_type_FOO() with an input + * visitor, then *@obj will be set to NULL for pointer types, and left + * unchanged for scalar types. + * + * Using an output or clone visitor with an incomplete object has + * undefined behavior (other than a special case for visit_type_str() + * treating NULL like ""), while the dealloc visitor safely handles + * incomplete objects. Since input visitors never produce an + * incomplete object, such an object is possible only by manual + * construction. + * + * visit_type_FOO() returns true on success, false on error. + * + * For the QAPI object types (structs, unions, and alternates), there + * is an additional generated function in qapi-visit-MODULE.h + * compatible with: + * + * bool visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp); + * + * for visiting the members of a type without also allocating the QAPI + * struct. It also returns true on success, false on error. + * + * Additionally, QAPI pointer types (structs, unions, alternates, and + * lists) have a generated function in qapi-types-MODULE.h compatible + * with: + * + * void qapi_free_FOO(FOO *obj); + * + * Does nothing when @obj is NULL. + * + * Such objects may also be used with macro + * + * Type *QAPI_CLONE(Type, src); + * + * in order to perform a deep clone of @src. + * + * For QAPI types can that inherit from a base type, a function is + * generated for going from the derived type to the base type: + * + * BASE *qapi_CHILD_base(CHILD *obj); + * + * Typical input visitor usage involves: + * + * <example> + * Foo *f; + * Error *err = NULL; + * Visitor *v; + * + * v = FOO_visitor_new(...); + * if (!visit_type_Foo(v, NULL, &f, &err)) { + * ...handle error... + * } else { + * ...use f... + * } + * visit_free(v); + * qapi_free_Foo(f); + * </example> + * + * For a list, it is: + * <example> + * FooList *l; + * Error *err = NULL; + * Visitor *v; + * + * v = FOO_visitor_new(...); + * if (!visit_type_FooList(v, NULL, &l, &err)) { + * ...handle error... + * } else { + * for ( ; l; l = l->next) { + * ...use l->value... + * } + * } + * visit_free(v); + * qapi_free_FooList(l); + * </example> + * + * Typical output visitor usage: + * + * <example> + * Foo *f = ...obtain populated object... + * Visitor *v; + * Type *result; + * + * v = FOO_visitor_new(..., &result); + * visit_type_Foo(v, NULL, &f, &error_abort); + * visit_complete(v, &result); + * visit_free(v); + * ...use result... + * </example> + * + * It is also possible to use the visitors to do a virtual walk, where + * no actual QAPI object is present. In this situation, decisions + * about what needs to be walked are made by the calling code, and + * structured visits are split between pairs of start and end methods + * (where the end method must be called if the start function + * succeeded, even if an intermediate visit encounters an error). + * Thus, a virtual walk corresponding to '{ "list": [1, 2] }' looks + * like: + * + * <example> + * Visitor *v; + * Error *err = NULL; + * bool ok = false; + * int value; + * + * v = FOO_visitor_new(...); + * if (!visit_start_struct(v, NULL, NULL, 0, &err)) { + * goto out; + * } + * if (!visit_start_list(v, "list", NULL, 0, &err)) { + * goto outobj; + * } + * value = 1; + * if (!visit_type_int(v, NULL, &value, &err)) { + * goto outlist; + * } + * value = 2; + * if (!visit_type_int(v, NULL, &value, &err)) { + * goto outlist; + * } + * ok = true; + * outlist: + * if (ok) { + * ok = visit_check_list(v, &err); + * } + * visit_end_list(v, NULL); + * if (ok) { + * ok = visit_check_struct(v, &err); + * } + * outobj: + * visit_end_struct(v, NULL); + * out: + * visit_free(v); + * </example> + * + * This file provides helpers for use by the generated + * visit_type_FOO(): visit_optional() for the 'has_member' field + * associated with optional 'member' in the C struct, + * visit_next_list() for advancing through a FooList linked list, and + * visit_is_input() for cleaning up on failure. + */ + +/*** Useful types ***/ + +/* This struct is layout-compatible with all other *List structs + * created by the QAPI generator. It is used as a typical + * singly-linked list. */ +typedef struct GenericList { + struct GenericList *next; + char padding[]; +} GenericList; + +/* This struct is layout-compatible with all Alternate types + * created by the QAPI generator. */ +typedef struct GenericAlternate { + QType type; + char padding[]; +} GenericAlternate; + +/*** Visitor cleanup ***/ + +/* + * Complete the visit, collecting any output. + * + * May only be called only once after a successful top-level + * visit_type_FOO() or visit_end_ITEM(), and marks the end of the + * visit. The @opaque pointer should match the output parameter + * passed to the subtype_visitor_new() used to create an output + * visitor, or NULL for any other visitor. Needed for output + * visitors, but may also be called with other visitors. + */ +void visit_complete(Visitor *v, void *opaque); + +/* + * Free @v and any resources it has tied up. + * + * May be called whether or not the visit has been successfully + * completed, but should not be called until a top-level + * visit_type_FOO() or visit_start_ITEM() has been performed on the + * visitor. Safe if @v is NULL. + */ +void visit_free(Visitor *v); + + +/*** Visiting structures ***/ + +/* + * Start visiting an object @obj (struct or union). + * + * @name expresses the relationship of this object to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL for a real walk, in which case @size + * determines how much memory an input or clone visitor will allocate + * into *@obj. @obj may also be NULL for a virtual walk, in which + * case @size is ignored. + * + * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. + * + * Return true on success, false on failure. + * + * After visit_start_struct() succeeds, the caller may visit its + * members one after the other, passing the member's name and address + * within the struct. Finally, visit_end_struct() needs to be called + * with the same @obj to clean up, even if intermediate visits fail. + * See the examples above. + * + * FIXME Should this be named visit_start_object, since it is also + * used for QAPI unions, and maps to JSON objects? + */ +bool visit_start_struct(Visitor *v, const char *name, void **obj, + size_t size, Error **errp); + +/* + * Prepare for completing an object visit. + * + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. + * + * Return true on success, false on failure. + * + * Should be called prior to visit_end_struct() if all other + * intermediate visit steps were successful, to allow the visitor one + * last chance to report errors. May be skipped on a cleanup path, + * where there is no need to check for further errors. + */ +bool visit_check_struct(Visitor *v, Error **errp); + +/* + * Complete an object visit started earlier. + * + * @obj must match what was passed to the paired visit_start_struct(). + * + * Must be called after any successful use of visit_start_struct(), + * even if intermediate processing was skipped due to errors, to allow + * the backend to release any resources. Destroying the visitor early + * with visit_free() behaves as if this was implicitly called. + */ +void visit_end_struct(Visitor *v, void **obj); + + +/*** Visiting lists ***/ + +/* + * Start visiting a list. + * + * @name expresses the relationship of this list to its parent + * container; see the general description of @name above. + * + * @list must be non-NULL for a real walk, in which case @size + * determines how much memory an input or clone visitor will allocate + * into *@list (at least sizeof(GenericList)). Some visitors also + * allow @list to be NULL for a virtual walk, in which case @size is + * ignored. + * + * On failure, set *@list to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. + * + * Return true on success, false on failure. + * + * After visit_start_list() succeeds, the caller may visit its members + * one after the other. A real visit (where @list is non-NULL) uses + * visit_next_list() for traversing the linked list, while a virtual + * visit (where @list is NULL) uses other means. For each list + * element, call the appropriate visit_type_FOO() with name set to + * NULL and obj set to the address of the value member of the list + * element. Finally, visit_end_list() needs to be called with the + * same @list to clean up, even if intermediate visits fail. See the + * examples above. + */ +bool visit_start_list(Visitor *v, const char *name, GenericList **list, + size_t size, Error **errp); + +/* + * Iterate over a GenericList during a non-virtual list visit. + * + * @size represents the size of a linked list node (at least + * sizeof(GenericList)). + * + * @tail must not be NULL; on the first call, @tail is the value of + * *list after visit_start_list(), and on subsequent calls @tail must + * be the previously returned value. Should be called in a loop until + * a NULL return; for each non-NULL return, the caller then calls the + * appropriate visit_type_*() for the element type of the list, with + * that function's name parameter set to NULL and obj set to the + * address of @tail->value. + */ +GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); + +/* + * Prepare for completing a list visit. + * + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. + * + * Return true on success, false on failure. + * + * Should be called prior to visit_end_list() if all other + * intermediate visit steps were successful, to allow the visitor one + * last chance to report errors. May be skipped on a cleanup path, + * where there is no need to check for further errors. + */ +bool visit_check_list(Visitor *v, Error **errp); + +/* + * Complete a list visit started earlier. + * + * @list must match what was passed to the paired visit_start_list(). + * + * Must be called after any successful use of visit_start_list(), even + * if intermediate processing was skipped due to errors, to allow the + * backend to release any resources. Destroying the visitor early + * with visit_free() behaves as if this was implicitly called. + */ +void visit_end_list(Visitor *v, void **list); + + +/*** Visiting alternates ***/ + +/* + * Start the visit of an alternate @obj. + * + * @name expresses the relationship of this alternate to its parent + * container; see the general description of @name above. + * + * @obj must not be NULL. Input and clone visitors use @size to + * determine how much memory to allocate into *@obj, then determine + * the qtype of the next thing to be visited, and store it in + * (*@obj)->type. Other visitors leave @obj unchanged. + * + * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. + * + * Return true on success, false on failure. + * + * If successful, this must be paired with visit_end_alternate() with + * the same @obj to clean up, even if visiting the contents of the + * alternate fails. + */ +bool visit_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + Error **errp); + +/* + * Finish visiting an alternate type. + * + * @obj must match what was passed to the paired visit_start_alternate(). + * + * Must be called after any successful use of visit_start_alternate(), + * even if intermediate processing was skipped due to errors, to allow + * the backend to release any resources. Destroying the visitor early + * with visit_free() behaves as if this was implicitly called. + * + */ +void visit_end_alternate(Visitor *v, void **obj); + + +/*** Other helpers ***/ + +/* + * Does optional struct member @name need visiting? + * + * @name must not be NULL. This function is only useful between + * visit_start_struct() and visit_end_struct(), since only objects + * have optional keys. + * + * @present points to the address of the optional member's has_ flag. + * + * Input visitors set *@present according to input; other visitors + * leave it unchanged. In either case, return *@present for + * convenience. + */ +bool visit_optional(Visitor *v, const char *name, bool *present); + +/* + * Should we reject member @name due to policy? + * + * @special_features is the member's special features encoded as a + * bitset of QapiSpecialFeature. + * + * @name must not be NULL. This function is only useful between + * visit_start_struct() and visit_end_struct(), since only objects + * have deprecated members. + */ +bool visit_policy_reject(Visitor *v, const char *name, + unsigned special_features, Error **errp); + +/* + * + * Should we skip member @name due to policy? + * + * @special_features is the member's special features encoded as a + * bitset of QapiSpecialFeature. + * + * @name must not be NULL. This function is only useful between + * visit_start_struct() and visit_end_struct(), since only objects + * have deprecated members. + */ +bool visit_policy_skip(Visitor *v, const char *name, + unsigned special_features); + +/* + * Set policy for handling deprecated management interfaces. + * + * Intended use: call visit_set_policy(v, &compat_policy) when + * visiting management interface input or output. + */ +void visit_set_policy(Visitor *v, CompatPolicy *policy); + +/* + * Visit an enum value. + * + * @name expresses the relationship of this enum to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL. Input visitors parse input and set *@obj to + * the enumeration value, leaving @obj unchanged on error; other + * visitors use *@obj but leave it unchanged. + * + * Currently, all input visitors parse text input, and all output + * visitors produce text output. The mapping between enumeration + * values and strings is done by the visitor core, using @lookup. + * + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. + * + * Return true on success, false on failure. + * + * May call visit_type_str() under the hood, and the enum visit may + * fail even if the corresponding string visit succeeded; this implies + * that an input visitor's visit_type_str() must have no unwelcome + * side effects. + */ +bool visit_type_enum(Visitor *v, const char *name, int *obj, + const QEnumLookup *lookup, Error **errp); + +/* + * Check if visitor is an input visitor. + */ +bool visit_is_input(Visitor *v); + +/* + * Check if visitor is a dealloc visitor. + */ +bool visit_is_dealloc(Visitor *v); + +/*** Visiting built-in types ***/ + +/* + * Visit an integer value. + * + * @name expresses the relationship of this integer to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. + * + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. + * + * Return true on success, false on failure. + */ +bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); + +/* + * Visit a uint8_t value. + * Like visit_type_int(), except clamps the value to uint8_t range. + */ +bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, + Error **errp); + +/* + * Visit a uint16_t value. + * Like visit_type_int(), except clamps the value to uint16_t range. + */ +bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, + Error **errp); + +/* + * Visit a uint32_t value. + * Like visit_type_int(), except clamps the value to uint32_t range. + */ +bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, + Error **errp); + +/* + * Visit a uint64_t value. + * Like visit_type_int(), except clamps the value to uint64_t range, + * that is, ensures it is unsigned. + */ +bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, + Error **errp); + +/* + * Visit an int8_t value. + * Like visit_type_int(), except clamps the value to int8_t range. + */ +bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp); + +/* + * Visit an int16_t value. + * Like visit_type_int(), except clamps the value to int16_t range. + */ +bool visit_type_int16(Visitor *v, const char *name, int16_t *obj, + Error **errp); + +/* + * Visit an int32_t value. + * Like visit_type_int(), except clamps the value to int32_t range. + */ +bool visit_type_int32(Visitor *v, const char *name, int32_t *obj, + Error **errp); + +/* + * Visit an int64_t value. + * Identical to visit_type_int(). + */ +bool visit_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp); + +/* + * Visit a uint64_t value. + * Like visit_type_uint64(), except that some visitors may choose to + * recognize additional syntax, such as suffixes for easily scaling + * values. + */ +bool visit_type_size(Visitor *v, const char *name, uint64_t *obj, + Error **errp); + +/* + * Visit a boolean value. + * + * @name expresses the relationship of this boolean to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. + * + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. + * + * Return true on success, false on failure. + */ +bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); + +/* + * Visit a string value. + * + * @name expresses the relationship of this string to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL. Input and clone visitors set *@obj to the + * value (always using "" rather than NULL for an empty string). + * Other visitors leave *@obj unchanged, and commonly treat NULL like + * "". + * + * It is safe to cast away const when preparing a (const char *) value + * into @obj for use by an output visitor. + * + * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. + * + * Return true on success, false on failure. + * + * FIXME: Callers that try to output NULL *obj should not be allowed. + */ +bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); + +/* + * Visit a number (i.e. double) value. + * + * @name expresses the relationship of this number to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. Visitors should + * document if infinity or NaN are not permitted. + * + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. + * + * Return true on success, false on failure. + */ +bool visit_type_number(Visitor *v, const char *name, double *obj, + Error **errp); + +/* + * Visit an arbitrary value. + * + * @name expresses the relationship of this value to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. *@obj must be non-NULL + * for output visitors. + * + * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. + * + * Return true on success, false on failure. + * + * Note that some kinds of input can't express arbitrary QObject. + * E.g. the visitor returned by qobject_input_visitor_new_keyval() + * can't create numbers or booleans, only strings. + */ +bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); + +/* + * Visit a JSON null value. + * + * @name expresses the relationship of the null value to its parent + * container; see the general description of @name above. + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors ignore *@obj. + * + * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. + * + * Return true on success, false on failure. + */ +bool visit_type_null(Visitor *v, const char *name, QNull **obj, + Error **errp); + +#endif |