diff options
author | Max Reitz <mreitz@redhat.com> | 2018-02-24 16:40:28 +0100 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2018-03-19 14:49:04 -0500 |
commit | 1a56b1e2ab5e9d6d89386ca953b4afb419e15abe (patch) | |
tree | 63b90fb88991f9bfa449be1c7d0b4385ea7c834b /include/qapi/qmp | |
parent | 9139b5672360aaa263da1d96cdfdbe16accb6e3b (diff) | |
download | qemu-1a56b1e2ab5e9d6d89386ca953b4afb419e15abe.zip qemu-1a56b1e2ab5e9d6d89386ca953b4afb419e15abe.tar.gz qemu-1a56b1e2ab5e9d6d89386ca953b4afb419e15abe.tar.bz2 |
qapi: Add qobject_to()
This is a dynamic casting macro that, given a QObject type, returns an
object as that type or NULL if the object is of a different type (or
NULL itself).
The macro uses lower-case letters because:
1. There does not seem to be a hard rule on whether qemu macros have to
be upper-cased,
2. The current situation in qapi/qmp is inconsistent (compare e.g.
QINCREF() vs. qdict_put()),
3. qobject_to() will evaluate its @obj parameter only once, thus it is
generally not important to the caller whether it is a macro or not,
4. I prefer it aesthetically.
The macro parameter order is chosen with typename first for
consistency with other QAPI macros like QAPI_CLONE(), as well as
for legibility (read it as "qobject to" type "applied to" obj).
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20180224154033.29559-3-mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
[eblake: swap parameter order to list type first, avoid clang ubsan
warning on QOBJECT(NULL) and container_of(NULL,type,base)]
Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'include/qapi/qmp')
-rw-r--r-- | include/qapi/qmp/qobject.h | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 012439a..e022707 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -50,6 +50,21 @@ struct QObject { #define QDECREF(obj) \ qobject_decref(obj ? QOBJECT(obj) : 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) ({ \ + QObject *_tmp = qobject_check_type(obj, glue(QTYPE_CAST_TO_, type)); \ + _tmp ? container_of(_tmp, type, base) : (type *)NULL; }) + /* Initialize an object to default values */ static inline void qobject_init(QObject *obj, QType type) { @@ -102,4 +117,18 @@ static inline QType qobject_type(const QObject *obj) return obj->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 */ |