diff options
author | Don Dugger <n0ano@n0ano.com> | 2016-06-03 03:33:22 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@172.30.200.206> | 2016-06-03 03:33:23 +0000 |
commit | da27230f80795d0028333713f036d44c53cb0e68 (patch) | |
tree | b3d379eaf000adf72b36cb01cdf4d79c3e3f064c /qemu/include/qapi | |
parent | 0e68cb048bb8aadb14675f5d4286d8ab2fc35449 (diff) | |
parent | 437fd90c0250dee670290f9b714253671a990160 (diff) |
Merge "These changes are the raw update to qemu-2.6."
Diffstat (limited to 'qemu/include/qapi')
-rw-r--r-- | qemu/include/qapi/error.h | 312 | ||||
-rw-r--r-- | qemu/include/qapi/qmp-event.h | 1 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/dispatch.h | 1 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/json-lexer.h | 15 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/json-parser.h | 5 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/json-streamer.h | 14 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qbool.h | 4 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qdict.h | 5 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qerror.h | 6 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qfloat.h | 4 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qint.h | 4 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qjson.h | 2 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qlist.h | 3 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qobject.h | 57 | ||||
-rw-r--r-- | qemu/include/qapi/qmp/qstring.h | 4 | ||||
-rw-r--r-- | qemu/include/qapi/visitor-impl.h | 75 | ||||
-rw-r--r-- | qemu/include/qapi/visitor.h | 123 |
17 files changed, 431 insertions, 204 deletions
diff --git a/qemu/include/qapi/error.h b/qemu/include/qapi/error.h index f44c45183..11be2327c 100644 --- a/qemu/include/qapi/error.h +++ b/qemu/include/qapi/error.h @@ -2,107 +2,301 @@ * 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. + * + * Create an error: + * error_setg(&err, "situation normal, all fouled up"); + * + * Create an error and add additional explanation: + * error_setg(&err, "invalid quark"); + * error_append_hint(&err, "Valid quarks are up, down, strange, " + * "charm, top, bottom.\n"); + * + * Do *not* contract this to + * error_setg(&err, "invalid quark\n" + * "Valid quarks are up, down, strange, charm, top, bottom."); + * + * 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(). + * + * 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); + * + * Pass an existing error to the caller: + * error_propagate(errp, err); + * where Error **errp is a parameter, by convention the last one. + * + * Pass an existing error to the caller with the message modified: + * error_propagate(errp, err); + * error_prepend(errp, "Could not frobnicate '%s': ", name); + * + * Create a new error and pass it to the caller: + * error_setg(errp, "situation normal, all fouled up"); + * + * Call a function and receive an error from it: + * Error *err = NULL; + * foo(arg, &err); + * if (err) { + * handle the error... + * } + * + * Call a function ignoring errors: + * foo(arg, NULL); + * + * Call a function aborting on errors: + * foo(arg, &error_abort); + * + * Call a function treating errors as fatal: + * foo(arg, &error_fatal); + * + * Receive an error and pass it on to the caller: + * Error *err = NULL; + * foo(arg, &err); + * if (err) { + * handle the error... + * error_propagate(errp, err); + * } + * where Error **errp is a parameter, by convention the last one. + * + * Do *not* "optimize" this to + * foo(arg, errp); + * if (*errp) { // WRONG! + * handle the error... + * } + * because errp may be NULL! + * + * But when all you do with the error is pass it on, please use + * foo(arg, errp); + * for readability. + * + * 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 + * foo(arg, &err); + * bar(arg, &err); // WRONG! + * if (err) { + * handle the error... + * } + * because this may pass a non-null err to bar(). + */ + #ifndef ERROR_H #define ERROR_H -#include "qemu/compiler.h" #include "qapi-types.h" -#include <stdbool.h> -/** - * A class representing internal errors within QEMU. An error has a ErrorClass - * code and a human message. +/* + * Overall category of an error. + * Based on the qapi type QapiErrorClass, but reproduced here for nicer + * enum names. */ -typedef struct Error Error; +typedef enum ErrorClass { + ERROR_CLASS_GENERIC_ERROR = QAPI_ERROR_CLASS_GENERICERROR, + ERROR_CLASS_COMMAND_NOT_FOUND = QAPI_ERROR_CLASS_COMMANDNOTFOUND, + ERROR_CLASS_DEVICE_ENCRYPTED = QAPI_ERROR_CLASS_DEVICEENCRYPTED, + 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; -/** - * Set an indirect pointer to an error given a ErrorClass value and a - * printf-style human message. This function is not meant to be used outside - * of QEMU. +/* + * Get @err's human-readable error message. */ -void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) - GCC_FMT_ATTR(3, 4); +const char *error_get_pretty(Error *err); -/** - * Set an indirect pointer to an error given a ErrorClass value and a - * printf-style human message, followed by a strerror() string if - * @os_error is not zero. +/* + * Get @err's error class. + * Note: use of error classes other than ERROR_CLASS_GENERIC_ERROR is + * strongly discouraged. */ -void error_set_errno(Error **errp, int os_error, ErrorClass err_class, - const char *fmt, ...) GCC_FMT_ATTR(4, 5); +ErrorClass error_get_class(const Error *err); -#ifdef _WIN32 -/** - * Set an indirect pointer to an error given a ErrorClass value and a - * printf-style human message, followed by a g_win32_error_message() string if - * @win32_err is not zero. +/* + * 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(). */ -void error_set_win32(Error **errp, int win32_err, ErrorClass err_class, - const char *fmt, ...) GCC_FMT_ATTR(4, 5); -#endif +#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); -/** - * Same as error_set(), but sets a generic error +/* + * 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. */ -#define error_setg(errp, fmt, ...) \ - error_set(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) -#define error_setg_errno(errp, os_error, fmt, ...) \ - error_set_errno(errp, os_error, ERROR_CLASS_GENERIC_ERROR, \ - fmt, ## __VA_ARGS__) +#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 -#define error_setg_win32(errp, win32_err, fmt, ...) \ - error_set_win32(errp, win32_err, ERROR_CLASS_GENERIC_ERROR, \ - fmt, ## __VA_ARGS__) +/* + * 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 -/** - * Helper for open() errors +/* + * 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 don't error_propagate(&error_fatal, ...), use + * error_report_err() and exit(), because that's more obvious. */ -void error_setg_file_open(Error **errp, int os_errno, const char *filename); +void error_propagate(Error **dst_errp, Error *local_err); /* - * Get the error class of an error object. + * Prepend some text to @errp's human-readable error message. + * The text is made by formatting @fmt, @ap like vprintf(). */ -ErrorClass error_get_class(const Error *err); +void error_vprepend(Error **errp, const char *fmt, va_list ap); -/** - * Returns an exact copy of the error passed as an argument. +/* + * Prepend some text to @errp's human-readable error message. + * The text is made by formatting @fmt, ... like printf(). */ -Error *error_copy(const Error *err); +void error_prepend(Error **errp, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); -/** - * Get a human readable representation of an error object. +/* + * Append a printf-style human-readable explanation to an existing error. + * @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. */ -const char *error_get_pretty(Error *err); +void error_append_hint(Error **errp, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); -/** - * Convenience function to error_report() and free an error object. +/* + * Convenience function to report open() failure. */ -void error_report_err(Error *); +#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); -/** - * Propagate an error to an indirect pointer to an error. This function will - * always transfer ownership of the error reference and handles the case where - * dst_err is NULL correctly. Errors after the first are discarded. +/* + * Return an exact copy of @err. */ -void error_propagate(Error **dst_errp, Error *local_err); +Error *error_copy(const Error *err); -/** - * Free an error object. +/* + * Free @err. + * @err may be NULL. */ void error_free(Error *err); -/** - * If passed to error_set and friends, abort(). +/* + * Convenience function to assert that *@errp is set, then silently free it. + */ +void error_free_or_abort(Error **errp); + +/* + * Convenience function to error_report() and free @err. */ +void error_report_err(Error *err); +/* + * 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); + +/* + * 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/qemu/include/qapi/qmp-event.h b/qemu/include/qapi/qmp-event.h index 8a8ffb571..40fe3cbc1 100644 --- a/qemu/include/qapi/qmp-event.h +++ b/qemu/include/qapi/qmp-event.h @@ -14,7 +14,6 @@ #ifndef QMP_EVENT_H #define QMP_EVENT_H -#include "qapi/error.h" #include "qapi/qmp/qdict.h" typedef void (*QMPEventFuncEmit)(unsigned event, QDict *dict, Error **errp); diff --git a/qemu/include/qapi/qmp/dispatch.h b/qemu/include/qapi/qmp/dispatch.h index e389697f1..495520994 100644 --- a/qemu/include/qapi/qmp/dispatch.h +++ b/qemu/include/qapi/qmp/dispatch.h @@ -16,7 +16,6 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp/qdict.h" -#include "qapi/error.h" typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); diff --git a/qemu/include/qapi/qmp/json-lexer.h b/qemu/include/qapi/qmp/json-lexer.h index cdff0460a..afee7828c 100644 --- a/qemu/include/qapi/qmp/json-lexer.h +++ b/qemu/include/qapi/qmp/json-lexer.h @@ -14,11 +14,15 @@ #ifndef QEMU_JSON_LEXER_H #define QEMU_JSON_LEXER_H -#include "qapi/qmp/qstring.h" -#include "qapi/qmp/qlist.h" typedef enum json_token_type { - JSON_OPERATOR = 100, + JSON_MIN = 100, + JSON_LCURLY = JSON_MIN, + JSON_RCURLY, + JSON_LSQUARE, + JSON_RSQUARE, + JSON_COLON, + JSON_COMMA, JSON_INTEGER, JSON_FLOAT, JSON_KEYWORD, @@ -30,13 +34,14 @@ typedef enum json_token_type { typedef struct JSONLexer JSONLexer; -typedef void (JSONLexerEmitter)(JSONLexer *, QString *, JSONTokenType, int x, int y); +typedef void (JSONLexerEmitter)(JSONLexer *, GString *, + JSONTokenType, int x, int y); struct JSONLexer { JSONLexerEmitter *emit; int state; - QString *token; + GString *token; int x, y; }; diff --git a/qemu/include/qapi/qmp/json-parser.h b/qemu/include/qapi/qmp/json-parser.h index 44d88f346..9987f8ca8 100644 --- a/qemu/include/qapi/qmp/json-parser.h +++ b/qemu/include/qapi/qmp/json-parser.h @@ -16,9 +16,8 @@ #include "qemu-common.h" #include "qapi/qmp/qlist.h" -#include "qapi/error.h" -QObject *json_parser_parse(QList *tokens, va_list *ap); -QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp); +QObject *json_parser_parse(GQueue *tokens, va_list *ap); +QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp); #endif diff --git a/qemu/include/qapi/qmp/json-streamer.h b/qemu/include/qapi/qmp/json-streamer.h index 823f7d7fa..00d8a23af 100644 --- a/qemu/include/qapi/qmp/json-streamer.h +++ b/qemu/include/qapi/qmp/json-streamer.h @@ -14,21 +14,27 @@ #ifndef QEMU_JSON_STREAMER_H #define QEMU_JSON_STREAMER_H -#include "qapi/qmp/qlist.h" #include "qapi/qmp/json-lexer.h" +typedef struct JSONToken { + int type; + int x; + int y; + char str[]; +} JSONToken; + typedef struct JSONMessageParser { - void (*emit)(struct JSONMessageParser *parser, QList *tokens); + void (*emit)(struct JSONMessageParser *parser, GQueue *tokens); JSONLexer lexer; int brace_count; int bracket_count; - QList *tokens; + GQueue *tokens; uint64_t token_size; } JSONMessageParser; void json_message_parser_init(JSONMessageParser *parser, - void (*func)(JSONMessageParser *, QList *)); + void (*func)(JSONMessageParser *, GQueue *)); int json_message_parser_feed(JSONMessageParser *parser, const char *buffer, size_t size); diff --git a/qemu/include/qapi/qmp/qbool.h b/qemu/include/qapi/qmp/qbool.h index 4aa6be3b3..a41111c30 100644 --- a/qemu/include/qapi/qmp/qbool.h +++ b/qemu/include/qapi/qmp/qbool.h @@ -14,16 +14,16 @@ #ifndef QBOOL_H #define QBOOL_H -#include <stdbool.h> #include "qapi/qmp/qobject.h" typedef struct QBool { - QObject_HEAD; + QObject base; bool value; } QBool; QBool *qbool_from_bool(bool value); bool qbool_get_bool(const QBool *qb); QBool *qobject_to_qbool(const QObject *obj); +void qbool_destroy_obj(QObject *obj); #endif /* QBOOL_H */ diff --git a/qemu/include/qapi/qmp/qdict.h b/qemu/include/qapi/qmp/qdict.h index a37f4c156..71b8eb041 100644 --- a/qemu/include/qapi/qmp/qdict.h +++ b/qemu/include/qapi/qmp/qdict.h @@ -16,8 +16,6 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp/qlist.h" #include "qemu/queue.h" -#include <stdbool.h> -#include <stdint.h> #define QDICT_BUCKET_MAX 512 @@ -28,7 +26,7 @@ typedef struct QDictEntry { } QDictEntry; typedef struct QDict { - QObject_HEAD; + QObject base; size_t size; QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX]; } QDict; @@ -48,6 +46,7 @@ void qdict_iter(const QDict *qdict, void *opaque); const QDictEntry *qdict_first(const QDict *qdict); const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry); +void qdict_destroy_obj(QObject *obj); /* Helper to qdict_put_obj(), accepts any object */ #define qdict_put(qdict, key, obj) \ diff --git a/qemu/include/qapi/qmp/qerror.h b/qemu/include/qapi/qmp/qerror.h index 842b27ae1..d08652aaa 100644 --- a/qemu/include/qapi/qmp/qerror.h +++ b/qemu/include/qapi/qmp/qerror.h @@ -100,10 +100,10 @@ #define QERR_UNDEFINED_ERROR \ "An undefined error has occurred" -#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ - "'%s' uses a %s feature which is not supported by this qemu version: %s" - #define QERR_UNSUPPORTED \ "this feature or command is not currently supported" +#define QERR_REPLAY_NOT_SUPPORTED \ + "Record/replay feature is not supported for '%s'" + #endif /* QERROR_H */ diff --git a/qemu/include/qapi/qmp/qfloat.h b/qemu/include/qapi/qmp/qfloat.h index a8658443d..b5d15836b 100644 --- a/qemu/include/qapi/qmp/qfloat.h +++ b/qemu/include/qapi/qmp/qfloat.h @@ -14,16 +14,16 @@ #ifndef QFLOAT_H #define QFLOAT_H -#include <stdint.h> #include "qapi/qmp/qobject.h" typedef struct QFloat { - QObject_HEAD; + QObject base; double value; } QFloat; QFloat *qfloat_from_double(double value); double qfloat_get_double(const QFloat *qi); QFloat *qobject_to_qfloat(const QObject *obj); +void qfloat_destroy_obj(QObject *obj); #endif /* QFLOAT_H */ diff --git a/qemu/include/qapi/qmp/qint.h b/qemu/include/qapi/qmp/qint.h index 48a41b0f2..3aaff768d 100644 --- a/qemu/include/qapi/qmp/qint.h +++ b/qemu/include/qapi/qmp/qint.h @@ -13,16 +13,16 @@ #ifndef QINT_H #define QINT_H -#include <stdint.h> #include "qapi/qmp/qobject.h" typedef struct QInt { - QObject_HEAD; + QObject base; int64_t value; } QInt; QInt *qint_from_int(int64_t value); int64_t qint_get_int(const QInt *qi); QInt *qobject_to_qint(const QObject *obj); +void qint_destroy_obj(QObject *obj); #endif /* QINT_H */ diff --git a/qemu/include/qapi/qmp/qjson.h b/qemu/include/qapi/qmp/qjson.h index ee4d31a46..02b1f2ce3 100644 --- a/qemu/include/qapi/qmp/qjson.h +++ b/qemu/include/qapi/qmp/qjson.h @@ -14,8 +14,6 @@ #ifndef QJSON_H #define QJSON_H -#include <stdarg.h> -#include "qemu/compiler.h" #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" diff --git a/qemu/include/qapi/qmp/qlist.h b/qemu/include/qapi/qmp/qlist.h index 6cc4831df..a84117ecb 100644 --- a/qemu/include/qapi/qmp/qlist.h +++ b/qemu/include/qapi/qmp/qlist.h @@ -22,7 +22,7 @@ typedef struct QListEntry { } QListEntry; typedef struct QList { - QObject_HEAD; + QObject base; QTAILQ_HEAD(,QListEntry) head; } QList; @@ -49,6 +49,7 @@ QObject *qlist_peek(QList *qlist); int qlist_empty(const QList *qlist); size_t qlist_size(const QList *qlist); QList *qobject_to_qlist(const QObject *obj); +void qlist_destroy_obj(QObject *obj); static inline const QListEntry *qlist_first(const QList *qlist) { diff --git a/qemu/include/qapi/qmp/qobject.h b/qemu/include/qapi/qmp/qobject.h index 260d2ed3c..b8ddbca40 100644 --- a/qemu/include/qapi/qmp/qobject.h +++ b/qemu/include/qapi/qmp/qobject.h @@ -32,36 +32,12 @@ #ifndef QOBJECT_H #define QOBJECT_H -#include <stddef.h> -#include <assert.h> +#include "qapi-types.h" -typedef enum { - QTYPE_NONE, /* sentinel value, no QObject has this type code */ - QTYPE_QNULL, - QTYPE_QINT, - QTYPE_QSTRING, - QTYPE_QDICT, - QTYPE_QLIST, - QTYPE_QFLOAT, - QTYPE_QBOOL, - QTYPE_MAX, -} qtype_code; - -struct QObject; - -typedef struct QType { - qtype_code code; - void (*destroy)(struct QObject *); -} QType; - -typedef struct QObject { - const QType *type; +struct QObject { + QType type; size_t refcnt; -} QObject; - -/* Objects definitions must include this */ -#define QObject_HEAD \ - QObject base +}; /* Get the 'base' part of an object */ #define QOBJECT(obj) (&(obj)->base) @@ -75,9 +51,12 @@ typedef struct QObject { qobject_decref(obj ? QOBJECT(obj) : NULL) /* Initialize an object to default values */ -#define QOBJECT_INIT(obj, qtype_type) \ - obj->base.refcnt = 1; \ - obj->base.type = qtype_type +static inline void qobject_init(QObject *obj, QType type) +{ + assert(QTYPE_NONE < type && type < QTYPE__MAX); + obj->refcnt = 1; + obj->type = type; +} /** * qobject_incref(): Increment QObject's reference count @@ -89,25 +68,29 @@ static inline void qobject_incref(QObject *obj) } /** + * qobject_destroy(): Free resources used by the object + */ +void qobject_destroy(QObject *obj); + +/** * qobject_decref(): Decrement QObject's reference count, deallocate * when it reaches zero */ static inline void qobject_decref(QObject *obj) { + assert(!obj || obj->refcnt); if (obj && --obj->refcnt == 0) { - assert(obj->type != NULL); - assert(obj->type->destroy != NULL); - obj->type->destroy(obj); + qobject_destroy(obj); } } /** * qobject_type(): Return the QObject's type */ -static inline qtype_code qobject_type(const QObject *obj) +static inline QType qobject_type(const QObject *obj) { - assert(obj->type != NULL); - return obj->type->code; + assert(QTYPE_NONE < obj->type && obj->type < QTYPE__MAX); + return obj->type; } extern QObject qnull_; diff --git a/qemu/include/qapi/qmp/qstring.h b/qemu/include/qapi/qmp/qstring.h index 1bc366610..10076b7c8 100644 --- a/qemu/include/qapi/qmp/qstring.h +++ b/qemu/include/qapi/qmp/qstring.h @@ -13,11 +13,10 @@ #ifndef QSTRING_H #define QSTRING_H -#include <stdint.h> #include "qapi/qmp/qobject.h" typedef struct QString { - QObject_HEAD; + QObject base; char *string; size_t length; size_t capacity; @@ -32,5 +31,6 @@ void qstring_append_int(QString *qstring, int64_t value); void qstring_append(QString *qstring, const char *str); void qstring_append_chr(QString *qstring, int c); QString *qobject_to_qstring(const QObject *obj); +void qstring_destroy_obj(QObject *obj); #endif /* QSTRING_H */ diff --git a/qemu/include/qapi/visitor-impl.h b/qemu/include/qapi/visitor-impl.h index f4a2f746c..2bd8f292b 100644 --- a/qemu/include/qapi/visitor-impl.h +++ b/qemu/include/qapi/visitor-impl.h @@ -1,7 +1,7 @@ /* * Core Definitions for QAPI Visitor implementations * - * Copyright (C) 2012 Red Hat, Inc. + * Copyright (C) 2012-2016 Red Hat, Inc. * * Author: Paolo Bonizni <pbonzini@redhat.com> * @@ -12,56 +12,57 @@ #ifndef QAPI_VISITOR_IMPL_H #define QAPI_VISITOR_IMPL_H -#include "qapi/error.h" #include "qapi/visitor.h" struct Visitor { /* Must be set */ - void (*start_struct)(Visitor *v, void **obj, const char *kind, - const char *name, size_t size, Error **errp); + void (*start_struct)(Visitor *v, const char *name, void **obj, + size_t size, Error **errp); void (*end_struct)(Visitor *v, Error **errp); - void (*start_implicit_struct)(Visitor *v, void **obj, size_t size, - Error **errp); - void (*end_implicit_struct)(Visitor *v, Error **errp); - void (*start_list)(Visitor *v, const char *name, Error **errp); - GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp); - void (*end_list)(Visitor *v, Error **errp); + /* Must be set */ + GenericList *(*next_list)(Visitor *v, GenericList **list, size_t size); + /* Must be set */ + void (*end_list)(Visitor *v); - void (*type_enum)(Visitor *v, int *obj, const char * const strings[], - const char *kind, const char *name, Error **errp); - void (*get_next_type)(Visitor *v, int *kind, const int *qobjects, - const char *name, Error **errp); + /* Optional, needed for input and dealloc visitors. */ + void (*start_alternate)(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + bool promote_int, Error **errp); - void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp); - void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp); - void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp); - void (*type_number)(Visitor *v, double *obj, const char *name, - Error **errp); + /* Optional, needed for dealloc visitor. */ + void (*end_alternate)(Visitor *v); - /* May be NULL */ - void (*optional)(Visitor *v, bool *present, const char *name, + /* Must be set. */ + void (*type_enum)(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp); + + /* Must be set. */ + void (*type_int64)(Visitor *v, const char *name, int64_t *obj, + Error **errp); + /* Must be set. */ + void (*type_uint64)(Visitor *v, const char *name, uint64_t *obj, + Error **errp); + /* Optional; fallback is type_uint64(). */ + void (*type_size)(Visitor *v, const char *name, uint64_t *obj, + Error **errp); + /* Must be set. */ + void (*type_bool)(Visitor *v, const char *name, bool *obj, Error **errp); + void (*type_str)(Visitor *v, const char *name, char **obj, Error **errp); + void (*type_number)(Visitor *v, const char *name, double *obj, + Error **errp); + void (*type_any)(Visitor *v, const char *name, QObject **obj, Error **errp); - void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp); - void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp); - void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp); - void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name, Error **errp); - void (*type_int8)(Visitor *v, int8_t *obj, const char *name, Error **errp); - void (*type_int16)(Visitor *v, int16_t *obj, const char *name, Error **errp); - void (*type_int32)(Visitor *v, int32_t *obj, const char *name, Error **errp); - void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp); - /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */ - void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp); - bool (*start_union)(Visitor *v, bool data_present, Error **errp); - void (*end_union)(Visitor *v, bool data_present, Error **errp); + /* May be NULL; most useful for input visitors. */ + void (*optional)(Visitor *v, const char *name, bool *present); }; -void input_type_enum(Visitor *v, int *obj, const char * const strings[], - const char *kind, const char *name, Error **errp); -void output_type_enum(Visitor *v, int *obj, const char * const strings[], - const char *kind, const char *name, Error **errp); +void input_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp); +void output_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp); #endif diff --git a/qemu/include/qapi/visitor.h b/qemu/include/qapi/visitor.h index 00ba104cd..9a8d0105f 100644 --- a/qemu/include/qapi/visitor.h +++ b/qemu/include/qapi/visitor.h @@ -1,6 +1,7 @@ /* * Core Definitions for QAPI Visitor Classes * + * Copyright (C) 2012-2016 Red Hat, Inc. * Copyright IBM, Corp. 2011 * * Authors: @@ -13,52 +14,94 @@ #ifndef QAPI_VISITOR_CORE_H #define QAPI_VISITOR_CORE_H -#include "qemu/typedefs.h" #include "qapi/qmp/qobject.h" -#include "qapi/error.h" -#include <stdlib.h> -typedef struct GenericList -{ - union { - void *value; - uint64_t padding; - }; +/* 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; -void visit_start_handle(Visitor *v, void **obj, const char *kind, - const char *name, Error **errp); -void visit_end_handle(Visitor *v, Error **errp); -void visit_start_struct(Visitor *v, void **obj, const char *kind, - const char *name, size_t size, Error **errp); +/* This struct is layout-compatible with all Alternate types + * created by the qapi generator. */ +typedef struct GenericAlternate { + QType type; + char padding[]; +} GenericAlternate; + +void visit_start_struct(Visitor *v, const char *name, void **obj, + size_t size, Error **errp); void visit_end_struct(Visitor *v, Error **errp); -void visit_start_implicit_struct(Visitor *v, void **obj, size_t size, - Error **errp); -void visit_end_implicit_struct(Visitor *v, Error **errp); + void visit_start_list(Visitor *v, const char *name, Error **errp); -GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp); -void visit_end_list(Visitor *v, Error **errp); -void visit_optional(Visitor *v, bool *present, const char *name, - Error **errp); -void visit_get_next_type(Visitor *v, int *obj, const int *qtypes, - const char *name, Error **errp); -void visit_type_enum(Visitor *v, int *obj, const char * const strings[], - const char *kind, const char *name, Error **errp); -void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp); -void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp); -void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp); -void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp); -void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp); -void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp); -void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp); -void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp); -void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp); -void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp); -void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp); -void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp); -void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp); -bool visit_start_union(Visitor *v, bool data_present, Error **errp); -void visit_end_union(Visitor *v, bool data_present, Error **errp); +GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size); +void visit_end_list(Visitor *v); + +/* + * Start the visit of an alternate @obj with the given @size. + * + * @name specifies the relationship to the containing struct (ignored + * for a top level visit, the name of the key if this alternate is + * part of an object, or NULL if this alternate is part of a list). + * + * @obj must not be NULL. Input visitors will allocate @obj and + * determine the qtype of the next thing to be visited, stored in + * (*@obj)->type. Other visitors will leave @obj unchanged. + * + * If @promote_int, treat integers as QTYPE_FLOAT. + * + * If successful, this must be paired with visit_end_alternate(), even + * if visiting the contents of the alternate fails. + */ +void visit_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + bool promote_int, Error **errp); + +/* + * Finish visiting an alternate type. + * + * Must be called after a successful visit_start_alternate(), even if + * an error occurred in the meantime. + * + * TODO: Should all the visit_end_* interfaces take obj parameter, so + * that dealloc visitor need not track what was passed in visit_start? + */ +void visit_end_alternate(Visitor *v); + +/** + * Check if an optional member @name of an object needs visiting. + * For input visitors, set *@present according to whether the + * corresponding visit_type_*() needs calling; for other visitors, + * leave *@present unchanged. Return *@present for convenience. + */ +bool visit_optional(Visitor *v, const char *name, bool *present); + +void visit_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp); +void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); +void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, + Error **errp); +void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, + Error **errp); +void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, + Error **errp); +void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, + Error **errp); +void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp); +void visit_type_int16(Visitor *v, const char *name, int16_t *obj, + Error **errp); +void visit_type_int32(Visitor *v, const char *name, int32_t *obj, + Error **errp); +void visit_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp); +void visit_type_size(Visitor *v, const char *name, uint64_t *obj, + Error **errp); +void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); +void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); +void visit_type_number(Visitor *v, const char *name, double *obj, + Error **errp); +void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); #endif |