* [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection
@ 2017-08-25 10:58 Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper Marc-André Lureau
` (14 more replies)
0 siblings, 15 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:58 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Hi,
This series is based on patches 2-5 from "[PATCH v2 00/54] qapi: add #if
pre-processor conditions to generated code". Generating a literal qobject
will allow to easily introduce #if conditionals from the original series.
v2:
- use QLIST_FOREACH_ENTRY for list comparison
- update qdict comparison to check for the size instead of doing a
qdict copy
- commit message update
- add r-b tags
Marc-André Lureau (14):
qdict: add qdict_put_null() helper
qlit: move qlit from check-qjson to qobject/
qlit: use QLit prefix consistently
qlit: remove compound literals
qlit: rename compare_litqobj_to_qobj() to qlit_equal_qobject()
qlit: make qlit_equal_qobject return a bool
qlit: make qlit_equal_qobject() take const arguments
qlit: add QLIT_QNULL and QLIT_BOOL
qlit: Replace open-coded qnum_get_int() by call
tests: add qlit tests
qlit: improve QLit dict vs qdict comparison
qlit: improve QLit list vs qlist comparison
qlit: add qobject_form_qlit()
qapi: generate a literal qobject for introspection
scripts/qapi-introspect.py | 87 ++++++++++++---------
include/qapi/qmp/qdict.h | 4 +-
include/qapi/qmp/qlit.h | 56 ++++++++++++++
monitor.c | 2 +-
qobject/qlit.c | 121 ++++++++++++++++++++++++++++++
target/i386/cpu.c | 4 +-
tests/check-qjson.c | 150 +++++++------------------------------
tests/check-qlit.c | 100 +++++++++++++++++++++++++
tests/test-qobject-input-visitor.c | 11 ++-
docs/devel/qapi-code-gen.txt | 29 ++++---
qobject/Makefile.objs | 2 +-
tests/Makefile.include | 5 +-
12 files changed, 393 insertions(+), 178 deletions(-)
create mode 100644 include/qapi/qmp/qlit.h
create mode 100644 qobject/qlit.c
create mode 100644 tests/check-qlit.c
--
2.14.1.146.gd35faa819
^ permalink raw reply [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 12:58 ` Eduardo Habkost
2017-08-25 15:31 ` Eric Blake
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 02/14] qlit: move qlit from check-qjson to qobject/ Marc-André Lureau
` (13 subsequent siblings)
14 siblings, 2 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel
Cc: armbru, Marc-André Lureau, Paolo Bonzini, Richard Henderson,
Eduardo Habkost
A step towards completeness.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/qmp/qdict.h | 4 +++-
target/i386/cpu.c | 4 ++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 363e431106..6588c7f0c8 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -53,13 +53,15 @@ void qdict_destroy_obj(QObject *obj);
#define qdict_put(qdict, key, obj) \
qdict_put_obj(qdict, key, QOBJECT(obj))
-/* Helpers for int, bool, and string */
+/* Helpers for int, bool, null, and string */
#define qdict_put_int(qdict, key, value) \
qdict_put(qdict, key, qnum_from_int(value))
#define qdict_put_bool(qdict, key, value) \
qdict_put(qdict, key, qbool_from_bool(value))
#define qdict_put_str(qdict, key, value) \
qdict_put(qdict, key, qstring_from_str(value))
+#define qdict_put_null(qdict, key) \
+ qdict_put(qdict, key, qnull())
/* High level helpers */
double qdict_get_double(const QDict *qdict, const char *key);
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ddc45abd70..bec2009a9c 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2454,7 +2454,7 @@ static QDict *x86_cpu_static_props(void)
d = qdict_new();
for (i = 0; props[i]; i++) {
- qdict_put(d, props[i], qnull());
+ qdict_put_null(d, props[i]);
}
for (w = 0; w < FEATURE_WORDS; w++) {
@@ -2464,7 +2464,7 @@ static QDict *x86_cpu_static_props(void)
if (!fi->feat_names[bit]) {
continue;
}
- qdict_put(d, fi->feat_names[bit], qnull());
+ qdict_put_null(d, fi->feat_names[bit]);
}
}
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 02/14] qlit: move qlit from check-qjson to qobject/
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 03/14] qlit: use QLit prefix consistently Marc-André Lureau
` (12 subsequent siblings)
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Fix code style issues while at it, to please checkpatch.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/qmp/qlit.h | 49 +++++++++++++++++++++++++
qobject/qlit.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
tests/check-qjson.c | 96 +------------------------------------------------
qobject/Makefile.objs | 2 +-
4 files changed, 140 insertions(+), 96 deletions(-)
create mode 100644 include/qapi/qmp/qlit.h
create mode 100644 qobject/qlit.c
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
new file mode 100644
index 0000000000..280db5064a
--- /dev/null
+++ b/include/qapi/qmp/qlit.h
@@ -0,0 +1,49 @@
+/*
+ * 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 "qapi-types.h"
+#include "qobject.h"
+
+typedef struct LiteralQDictEntry LiteralQDictEntry;
+typedef struct LiteralQObject LiteralQObject;
+
+struct LiteralQObject {
+ int type;
+ union {
+ int64_t qnum;
+ const char *qstr;
+ LiteralQDictEntry *qdict;
+ LiteralQObject *qlist;
+ } value;
+};
+
+struct LiteralQDictEntry {
+ const char *key;
+ LiteralQObject value;
+};
+
+#define QLIT_QNUM(val) \
+ (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
+#define QLIT_QSTR(val) \
+ (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
+#define QLIT_QDICT(val) \
+ (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
+#define QLIT_QLIST(val) \
+ (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
+
+int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
+
+#endif /* QLIT_H */
diff --git a/qobject/qlit.c b/qobject/qlit.c
new file mode 100644
index 0000000000..5917c3584e
--- /dev/null
+++ b/qobject/qlit.c
@@ -0,0 +1,89 @@
+/*
+ * QLit literal qobject
+ *
+ * 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.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/qmp/qlit.h"
+#include "qapi/qmp/types.h"
+
+typedef struct QListCompareHelper {
+ int index;
+ LiteralQObject *objs;
+ int result;
+} QListCompareHelper;
+
+static void compare_helper(QObject *obj, void *opaque)
+{
+ QListCompareHelper *helper = opaque;
+
+ if (helper->result == 0) {
+ return;
+ }
+
+ if (helper->objs[helper->index].type == QTYPE_NONE) {
+ helper->result = 0;
+ return;
+ }
+
+ helper->result =
+ compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
+}
+
+int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
+{
+ int64_t val;
+
+ if (!rhs || lhs->type != qobject_type(rhs)) {
+ return 0;
+ }
+
+ switch (lhs->type) {
+ case QTYPE_QNUM:
+ g_assert(qnum_get_try_int(qobject_to_qnum(rhs), &val));
+ return lhs->value.qnum == val;
+ case QTYPE_QSTRING:
+ return (strcmp(lhs->value.qstr,
+ qstring_get_str(qobject_to_qstring(rhs))) == 0);
+ case QTYPE_QDICT: {
+ int i;
+
+ for (i = 0; lhs->value.qdict[i].key; i++) {
+ QObject *obj = qdict_get(qobject_to_qdict(rhs),
+ lhs->value.qdict[i].key);
+
+ if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+ case QTYPE_QLIST: {
+ QListCompareHelper helper;
+
+ helper.index = 0;
+ helper.objs = lhs->value.qlist;
+ helper.result = 1;
+
+ qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
+
+ return helper.result;
+ }
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index a3a97b0d99..525f79e60b 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -16,6 +16,7 @@
#include "qapi/error.h"
#include "qapi/qmp/types.h"
#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qlit.h"
#include "qemu-common.h"
static void escaped_string(void)
@@ -1059,101 +1060,6 @@ static void keyword_literal(void)
QDECREF(null);
}
-typedef struct LiteralQDictEntry LiteralQDictEntry;
-typedef struct LiteralQObject LiteralQObject;
-
-struct LiteralQObject
-{
- int type;
- union {
- int64_t qnum;
- const char *qstr;
- LiteralQDictEntry *qdict;
- LiteralQObject *qlist;
- } value;
-};
-
-struct LiteralQDictEntry
-{
- const char *key;
- LiteralQObject value;
-};
-
-#define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
-#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
-#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
-#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
-
-typedef struct QListCompareHelper
-{
- int index;
- LiteralQObject *objs;
- int result;
-} QListCompareHelper;
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
-
-static void compare_helper(QObject *obj, void *opaque)
-{
- QListCompareHelper *helper = opaque;
-
- if (helper->result == 0) {
- return;
- }
-
- if (helper->objs[helper->index].type == QTYPE_NONE) {
- helper->result = 0;
- return;
- }
-
- helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
-}
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
-{
- int64_t val;
-
- if (!rhs || lhs->type != qobject_type(rhs)) {
- return 0;
- }
-
- switch (lhs->type) {
- case QTYPE_QNUM:
- g_assert(qnum_get_try_int(qobject_to_qnum(rhs), &val));
- return lhs->value.qnum == val;
- case QTYPE_QSTRING:
- return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
- case QTYPE_QDICT: {
- int i;
-
- for (i = 0; lhs->value.qdict[i].key; i++) {
- QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
-
- if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
- return 0;
- }
- }
-
- return 1;
- }
- case QTYPE_QLIST: {
- QListCompareHelper helper;
-
- helper.index = 0;
- helper.objs = lhs->value.qlist;
- helper.result = 1;
-
- qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
-
- return helper.result;
- }
- default:
- break;
- }
-
- return 0;
-}
-
static void simple_dict(void)
{
int i;
diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs
index fc8885c9a4..002d25873a 100644
--- a/qobject/Makefile.objs
+++ b/qobject/Makefile.objs
@@ -1,2 +1,2 @@
-util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o
+util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o qlit.o
util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 03/14] qlit: use QLit prefix consistently
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 02/14] qlit: move qlit from check-qjson to qobject/ Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals Marc-André Lureau
` (11 subsequent siblings)
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Rename from LiteralQ to QLit.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/qmp/qlit.h | 24 ++++++++++++------------
qobject/qlit.c | 4 ++--
tests/check-qjson.c | 40 ++++++++++++++++++++--------------------
3 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index 280db5064a..a4ad91321b 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -17,33 +17,33 @@
#include "qapi-types.h"
#include "qobject.h"
-typedef struct LiteralQDictEntry LiteralQDictEntry;
-typedef struct LiteralQObject LiteralQObject;
+typedef struct QLitDictEntry QLitDictEntry;
+typedef struct QLitObject QLitObject;
-struct LiteralQObject {
+struct QLitObject {
int type;
union {
int64_t qnum;
const char *qstr;
- LiteralQDictEntry *qdict;
- LiteralQObject *qlist;
+ QLitDictEntry *qdict;
+ QLitObject *qlist;
} value;
};
-struct LiteralQDictEntry {
+struct QLitDictEntry {
const char *key;
- LiteralQObject value;
+ QLitObject value;
};
#define QLIT_QNUM(val) \
- (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
+ (QLitObject){.type = QTYPE_QNUM, .value.qnum = (val)}
#define QLIT_QSTR(val) \
- (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
+ (QLitObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
#define QLIT_QDICT(val) \
- (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
+ (QLitObject){.type = QTYPE_QDICT, .value.qdict = (val)}
#define QLIT_QLIST(val) \
- (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
+ (QLitObject){.type = QTYPE_QLIST, .value.qlist = (val)}
-int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
+int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs);
#endif /* QLIT_H */
diff --git a/qobject/qlit.c b/qobject/qlit.c
index 5917c3584e..262d64988d 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -20,7 +20,7 @@
typedef struct QListCompareHelper {
int index;
- LiteralQObject *objs;
+ QLitObject *objs;
int result;
} QListCompareHelper;
@@ -41,7 +41,7 @@ static void compare_helper(QObject *obj, void *opaque)
compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
}
-int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
+int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs)
{
int64_t val;
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 525f79e60b..82b3681327 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -1065,23 +1065,23 @@ static void simple_dict(void)
int i;
struct {
const char *encoded;
- LiteralQObject decoded;
+ QLitObject decoded;
} test_cases[] = {
{
.encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
- .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+ .decoded = QLIT_QDICT(((QLitDictEntry[]){
{ "foo", QLIT_QNUM(42) },
{ "bar", QLIT_QSTR("hello world") },
{ }
})),
}, {
.encoded = "{}",
- .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+ .decoded = QLIT_QDICT(((QLitDictEntry[]){
{ }
})),
}, {
.encoded = "{\"foo\": 43}",
- .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+ .decoded = QLIT_QDICT(((QLitDictEntry[]){
{ "foo", QLIT_QNUM(43) },
{ }
})),
@@ -1163,11 +1163,11 @@ static void simple_list(void)
int i;
struct {
const char *encoded;
- LiteralQObject decoded;
+ QLitObject decoded;
} test_cases[] = {
{
.encoded = "[43,42]",
- .decoded = QLIT_QLIST(((LiteralQObject[]){
+ .decoded = QLIT_QLIST(((QLitObject[]){
QLIT_QNUM(43),
QLIT_QNUM(42),
{ }
@@ -1175,21 +1175,21 @@ static void simple_list(void)
},
{
.encoded = "[43]",
- .decoded = QLIT_QLIST(((LiteralQObject[]){
+ .decoded = QLIT_QLIST(((QLitObject[]){
QLIT_QNUM(43),
{ }
})),
},
{
.encoded = "[]",
- .decoded = QLIT_QLIST(((LiteralQObject[]){
+ .decoded = QLIT_QLIST(((QLitObject[]){
{ }
})),
},
{
.encoded = "[{}]",
- .decoded = QLIT_QLIST(((LiteralQObject[]){
- QLIT_QDICT(((LiteralQDictEntry[]){
+ .decoded = QLIT_QLIST(((QLitObject[]){
+ QLIT_QDICT(((QLitDictEntry[]){
{},
})),
{},
@@ -1220,11 +1220,11 @@ static void simple_whitespace(void)
int i;
struct {
const char *encoded;
- LiteralQObject decoded;
+ QLitObject decoded;
} test_cases[] = {
{
.encoded = " [ 43 , 42 ]",
- .decoded = QLIT_QLIST(((LiteralQObject[]){
+ .decoded = QLIT_QLIST(((QLitObject[]){
QLIT_QNUM(43),
QLIT_QNUM(42),
{ }
@@ -1232,12 +1232,12 @@ static void simple_whitespace(void)
},
{
.encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
- .decoded = QLIT_QLIST(((LiteralQObject[]){
+ .decoded = QLIT_QLIST(((QLitObject[]){
QLIT_QNUM(43),
- QLIT_QDICT(((LiteralQDictEntry[]){
+ QLIT_QDICT(((QLitDictEntry[]){
{ "h", QLIT_QSTR("b") },
{ }})),
- QLIT_QLIST(((LiteralQObject[]){
+ QLIT_QLIST(((QLitObject[]){
{ }})),
QLIT_QNUM(42),
{ }
@@ -1245,13 +1245,13 @@ static void simple_whitespace(void)
},
{
.encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
- .decoded = QLIT_QLIST(((LiteralQObject[]){
+ .decoded = QLIT_QLIST(((QLitObject[]){
QLIT_QNUM(43),
- QLIT_QDICT(((LiteralQDictEntry[]){
+ QLIT_QDICT(((QLitDictEntry[]){
{ "h", QLIT_QSTR("b") },
{ "a", QLIT_QNUM(32) },
{ }})),
- QLIT_QLIST(((LiteralQObject[]){
+ QLIT_QLIST(((QLitObject[]){
{ }})),
QLIT_QNUM(42),
{ }
@@ -1282,10 +1282,10 @@ static void simple_varargs(void)
{
QObject *embedded_obj;
QObject *obj;
- LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
+ QLitObject decoded = QLIT_QLIST(((QLitObject[]){
QLIT_QNUM(1),
QLIT_QNUM(2),
- QLIT_QLIST(((LiteralQObject[]){
+ QLIT_QLIST(((QLitObject[]){
QLIT_QNUM(32),
QLIT_QNUM(42),
{}})),
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (2 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 03/14] qlit: use QLit prefix consistently Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-30 12:00 ` Markus Armbruster
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 05/14] qlit: rename compare_litqobj_to_qobj() to qlit_equal_qobject() Marc-André Lureau
` (10 subsequent siblings)
14 siblings, 1 reply; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
They are not considered constant expressions in C, producing an error
when compiling a const QLit.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/qapi/qmp/qlit.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index a4ad91321b..f1d6eed317 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -36,13 +36,13 @@ struct QLitDictEntry {
};
#define QLIT_QNUM(val) \
- (QLitObject){.type = QTYPE_QNUM, .value.qnum = (val)}
+ { .type = QTYPE_QNUM, .value.qnum = (val) }
#define QLIT_QSTR(val) \
- (QLitObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
+ { .type = QTYPE_QSTRING, .value.qstr = (val) }
#define QLIT_QDICT(val) \
- (QLitObject){.type = QTYPE_QDICT, .value.qdict = (val)}
+ { .type = QTYPE_QDICT, .value.qdict = (val) }
#define QLIT_QLIST(val) \
- (QLitObject){.type = QTYPE_QLIST, .value.qlist = (val)}
+ { .type = QTYPE_QLIST, .value.qlist = (val) }
int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs);
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 05/14] qlit: rename compare_litqobj_to_qobj() to qlit_equal_qobject()
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (3 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 06/14] qlit: make qlit_equal_qobject return a bool Marc-André Lureau
` (9 subsequent siblings)
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
compare_litqobj_to_qobj() lacks a qlit_ prefix. Moreover, "compare"
suggests -1, 0, +1 for less than, equal and greater than. The
function actually returns non-zero for equal, zero for unequal.
Rename to qlit_equal_qobject().
Its return type will be cleaned up in the next patch.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/qmp/qlit.h | 2 +-
qobject/qlit.c | 6 +++---
tests/check-qjson.c | 14 +++++++-------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index f1d6eed317..5a180477c8 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -44,6 +44,6 @@ struct QLitDictEntry {
#define QLIT_QLIST(val) \
{ .type = QTYPE_QLIST, .value.qlist = (val) }
-int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs);
+int qlit_equal_qobject(QLitObject *lhs, QObject *rhs);
#endif /* QLIT_H */
diff --git a/qobject/qlit.c b/qobject/qlit.c
index 262d64988d..0c4101898d 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -38,10 +38,10 @@ static void compare_helper(QObject *obj, void *opaque)
}
helper->result =
- compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
+ qlit_equal_qobject(&helper->objs[helper->index++], obj);
}
-int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs)
+int qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
{
int64_t val;
@@ -63,7 +63,7 @@ int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs)
QObject *obj = qdict_get(qobject_to_qdict(rhs),
lhs->value.qdict[i].key);
- if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
+ if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
return 0;
}
}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 82b3681327..e5ca273cbc 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -1094,13 +1094,13 @@ static void simple_dict(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
str = qobject_to_json(obj);
qobject_decref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort);
- g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
qobject_decref(obj);
QDECREF(str);
}
@@ -1203,13 +1203,13 @@ static void simple_list(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
str = qobject_to_json(obj);
qobject_decref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort);
- g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
qobject_decref(obj);
QDECREF(str);
}
@@ -1265,13 +1265,13 @@ static void simple_whitespace(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
str = qobject_to_json(obj);
qobject_decref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort);
- g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
qobject_decref(obj);
QDECREF(str);
@@ -1295,7 +1295,7 @@ static void simple_varargs(void)
g_assert(embedded_obj != NULL);
obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
- g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&decoded, obj) == 1);
qobject_decref(obj);
}
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 06/14] qlit: make qlit_equal_qobject return a bool
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (4 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 05/14] qlit: rename compare_litqobj_to_qobj() to qlit_equal_qobject() Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 07/14] qlit: make qlit_equal_qobject() take const arguments Marc-André Lureau
` (8 subsequent siblings)
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Make it more obvious about the expected return values.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/qmp/qlit.h | 2 +-
qobject/qlit.c | 18 +++++++++---------
tests/check-qjson.c | 14 +++++++-------
3 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index 5a180477c8..35aabbdc9f 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -44,6 +44,6 @@ struct QLitDictEntry {
#define QLIT_QLIST(val) \
{ .type = QTYPE_QLIST, .value.qlist = (val) }
-int qlit_equal_qobject(QLitObject *lhs, QObject *rhs);
+bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs);
#endif /* QLIT_H */
diff --git a/qobject/qlit.c b/qobject/qlit.c
index 0c4101898d..a2975bef3f 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -21,19 +21,19 @@
typedef struct QListCompareHelper {
int index;
QLitObject *objs;
- int result;
+ bool result;
} QListCompareHelper;
static void compare_helper(QObject *obj, void *opaque)
{
QListCompareHelper *helper = opaque;
- if (helper->result == 0) {
+ if (!helper->result) {
return;
}
if (helper->objs[helper->index].type == QTYPE_NONE) {
- helper->result = 0;
+ helper->result = false;
return;
}
@@ -41,12 +41,12 @@ static void compare_helper(QObject *obj, void *opaque)
qlit_equal_qobject(&helper->objs[helper->index++], obj);
}
-int qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
+bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
{
int64_t val;
if (!rhs || lhs->type != qobject_type(rhs)) {
- return 0;
+ return false;
}
switch (lhs->type) {
@@ -64,18 +64,18 @@ int qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
lhs->value.qdict[i].key);
if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
case QTYPE_QLIST: {
QListCompareHelper helper;
helper.index = 0;
helper.objs = lhs->value.qlist;
- helper.result = 1;
+ helper.result = true;
qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
@@ -85,5 +85,5 @@ int qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
break;
}
- return 0;
+ return false;
}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index e5ca273cbc..59227934ce 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -1094,13 +1094,13 @@ static void simple_dict(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
str = qobject_to_json(obj);
qobject_decref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort);
- g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_decref(obj);
QDECREF(str);
}
@@ -1203,13 +1203,13 @@ static void simple_list(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
str = qobject_to_json(obj);
qobject_decref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort);
- g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_decref(obj);
QDECREF(str);
}
@@ -1265,13 +1265,13 @@ static void simple_whitespace(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
str = qobject_to_json(obj);
qobject_decref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort);
- g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_decref(obj);
QDECREF(str);
@@ -1295,7 +1295,7 @@ static void simple_varargs(void)
g_assert(embedded_obj != NULL);
obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
- g_assert(qlit_equal_qobject(&decoded, obj) == 1);
+ g_assert(qlit_equal_qobject(&decoded, obj));
qobject_decref(obj);
}
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 07/14] qlit: make qlit_equal_qobject() take const arguments
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (5 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 06/14] qlit: make qlit_equal_qobject return a bool Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 08/14] qlit: add QLIT_QNULL and QLIT_BOOL Marc-André Lureau
` (7 subsequent siblings)
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/qmp/qlit.h | 2 +-
qobject/qlit.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index 35aabbdc9f..fc1a2d845d 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -44,6 +44,6 @@ struct QLitDictEntry {
#define QLIT_QLIST(val) \
{ .type = QTYPE_QLIST, .value.qlist = (val) }
-bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs);
+bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs);
#endif /* QLIT_H */
diff --git a/qobject/qlit.c b/qobject/qlit.c
index a2975bef3f..ae2787ef35 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -41,7 +41,7 @@ static void compare_helper(QObject *obj, void *opaque)
qlit_equal_qobject(&helper->objs[helper->index++], obj);
}
-bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
+bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
{
int64_t val;
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 08/14] qlit: add QLIT_QNULL and QLIT_BOOL
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (6 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 07/14] qlit: make qlit_equal_qobject() take const arguments Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 09/14] qlit: Replace open-coded qnum_get_int() by call Marc-André Lureau
` (6 subsequent siblings)
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
As they are going to be used in the following patches.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/qmp/qlit.h | 5 +++++
qobject/qlit.c | 4 ++++
2 files changed, 9 insertions(+)
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index fc1a2d845d..b18406bce9 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -23,6 +23,7 @@ typedef struct QLitObject QLitObject;
struct QLitObject {
int type;
union {
+ bool qbool;
int64_t qnum;
const char *qstr;
QLitDictEntry *qdict;
@@ -35,6 +36,10 @@ struct QLitDictEntry {
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) \
diff --git a/qobject/qlit.c b/qobject/qlit.c
index ae2787ef35..07ad6b05e8 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -50,6 +50,8 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
}
switch (lhs->type) {
+ case QTYPE_QBOOL:
+ return lhs->value.qbool == qbool_get_bool(qobject_to_qbool(rhs));
case QTYPE_QNUM:
g_assert(qnum_get_try_int(qobject_to_qnum(rhs), &val));
return lhs->value.qnum == val;
@@ -81,6 +83,8 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
return helper.result;
}
+ case QTYPE_QNULL:
+ return true;
default:
break;
}
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 09/14] qlit: Replace open-coded qnum_get_int() by call
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (7 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 08/14] qlit: add QLIT_QNULL and QLIT_BOOL Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 10/14] tests: add qlit tests Marc-André Lureau
` (5 subsequent siblings)
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Bonus: rids us of a side effect in an assertion.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
qobject/qlit.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/qobject/qlit.c b/qobject/qlit.c
index 07ad6b05e8..b1d9146220 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -43,8 +43,6 @@ static void compare_helper(QObject *obj, void *opaque)
bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
{
- int64_t val;
-
if (!rhs || lhs->type != qobject_type(rhs)) {
return false;
}
@@ -53,8 +51,7 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
case QTYPE_QBOOL:
return lhs->value.qbool == qbool_get_bool(qobject_to_qbool(rhs));
case QTYPE_QNUM:
- g_assert(qnum_get_try_int(qobject_to_qnum(rhs), &val));
- return lhs->value.qnum == val;
+ return lhs->value.qnum == qnum_get_int(qobject_to_qnum(rhs));
case QTYPE_QSTRING:
return (strcmp(lhs->value.qstr,
qstring_get_str(qobject_to_qstring(rhs))) == 0);
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 10/14] tests: add qlit tests
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (8 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 09/14] qlit: Replace open-coded qnum_get_int() by call Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-30 12:15 ` Markus Armbruster
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 11/14] qlit: improve QLit dict vs qdict comparison Marc-André Lureau
` (4 subsequent siblings)
14 siblings, 1 reply; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/check-qlit.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
tests/Makefile.include | 5 +++-
2 files changed, 68 insertions(+), 1 deletion(-)
create mode 100644 tests/check-qlit.c
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
new file mode 100644
index 0000000000..47fde92a46
--- /dev/null
+++ b/tests/check-qlit.c
@@ -0,0 +1,64 @@
+/*
+ * QLit unit-tests.
+ *
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ * 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 "qemu/osdep.h"
+
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qlit.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qstring.h"
+
+static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
+ { "foo", QLIT_QNUM(42) },
+ { "bar", QLIT_QSTR("hello world") },
+ { "baz", QLIT_QNULL },
+ { "bee", QLIT_QLIST(((QLitObject[]) {
+ QLIT_QNUM(43),
+ QLIT_QNUM(44),
+ QLIT_QBOOL(true),
+ { },
+ }))},
+ { },
+}));
+
+static QObject *make_qobject(void)
+{
+ QDict *qdict = qdict_new();
+ QList *list = qlist_new();
+
+ qdict_put_int(qdict, "foo", 42);
+ qdict_put_str(qdict, "bar", "hello world");
+ qdict_put_null(qdict, "baz");
+
+ qlist_append_int(list, 43);
+ qlist_append_int(list, 44);
+ qlist_append_bool(list, true);
+ qdict_put(qdict, "bee", list);
+
+ return QOBJECT(qdict);
+}
+
+static void qlit_equal_qobject_test(void)
+{
+ QObject *qobj = make_qobject();
+
+ g_assert(qlit_equal_qobject(&qlit, qobj));
+
+ qobject_decref(qobj);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
+
+ return g_test_run();
+}
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 37c1bed683..3653c7b40a 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -43,6 +43,8 @@ check-unit-y += tests/check-qnull$(EXESUF)
gcov-files-check-qnull-y = qobject/qnull.c
check-unit-y += tests/check-qjson$(EXESUF)
gcov-files-check-qjson-y = qobject/qjson.c
+check-unit-y += tests/check-qlit$(EXESUF)
+gcov-files-check-qlit-y = qobject/qlit.c
check-unit-y += tests/test-qobject-output-visitor$(EXESUF)
gcov-files-test-qobject-output-visitor-y = qapi/qobject-output-visitor.c
check-unit-y += tests/test-clone-visitor$(EXESUF)
@@ -535,7 +537,7 @@ GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
tests/check-qlist.o tests/check-qnull.o \
- tests/check-qjson.o \
+ tests/check-qjson.o tests/check-qlit.o \
tests/test-coroutine.o tests/test-string-output-visitor.o \
tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
tests/test-clone-visitor.o \
@@ -569,6 +571,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
+tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y)
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 11/14] qlit: improve QLit dict vs qdict comparison
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (9 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 10/14] tests: add qlit tests Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-30 12:35 ` Markus Armbruster
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison Marc-André Lureau
` (3 subsequent siblings)
14 siblings, 1 reply; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Verify that all qdict values are covered.
(a previous iteration of this patch created a copy of qdict to remove
all checked elements, verifying no duplicates exist in the literal
qdict, however this is a programming error, and a size comparison
should be enough)
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qobject/qlit.c | 37 +++++++++++++++++++++++--------------
tests/check-qlit.c | 7 +++++++
2 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/qobject/qlit.c b/qobject/qlit.c
index b1d9146220..dc0015f76c 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -41,6 +41,27 @@ static void compare_helper(QObject *obj, void *opaque)
qlit_equal_qobject(&helper->objs[helper->index++], obj);
}
+static bool qlit_equal_qdict(const QLitObject *lhs, const QDict *qdict)
+{
+ int i;
+
+ for (i = 0; lhs->value.qdict[i].key; i++) {
+ QObject *obj = qdict_get(qdict, lhs->value.qdict[i].key);
+
+ if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
+ return false;
+ }
+ }
+
+ /* Note: the literal qdict must not contain duplicates, this is
+ * considered a programming error and it isn't checked here. */
+ if (qdict_size(qdict) != i) {
+ return false;
+ }
+
+ return true;
+}
+
bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
{
if (!rhs || lhs->type != qobject_type(rhs)) {
@@ -55,20 +76,8 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
case QTYPE_QSTRING:
return (strcmp(lhs->value.qstr,
qstring_get_str(qobject_to_qstring(rhs))) == 0);
- case QTYPE_QDICT: {
- int i;
-
- for (i = 0; lhs->value.qdict[i].key; i++) {
- QObject *obj = qdict_get(qobject_to_qdict(rhs),
- lhs->value.qdict[i].key);
-
- if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
- return false;
- }
- }
-
- return true;
- }
+ case QTYPE_QDICT:
+ return qlit_equal_qdict(lhs, qobject_to_qdict(rhs));
case QTYPE_QLIST: {
QListCompareHelper helper;
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
index 47fde92a46..5d9558dfd9 100644
--- a/tests/check-qlit.c
+++ b/tests/check-qlit.c
@@ -28,6 +28,11 @@ static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
{ },
}));
+static QLitObject qlit_foo = QLIT_QDICT(((QLitDictEntry[]) {
+ { "foo", QLIT_QNUM(42) },
+ { },
+}));
+
static QObject *make_qobject(void)
{
QDict *qdict = qdict_new();
@@ -51,6 +56,8 @@ static void qlit_equal_qobject_test(void)
g_assert(qlit_equal_qobject(&qlit, qobj));
+ g_assert(!qlit_equal_qobject(&qlit_foo, qobj));
+
qobject_decref(qobj);
}
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (10 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 11/14] qlit: improve QLit dict vs qdict comparison Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-30 12:36 ` Markus Armbruster
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit() Marc-André Lureau
` (2 subsequent siblings)
14 siblings, 1 reply; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Use QLIST_FOREACH_ENTRY() to simplify the code and break earlier.
Check that the QLit list has the same size as the qlist, this should
ensure that we have an exact match when iterating over qlist for
comparing the elements.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qobject/qlit.c | 53 +++++++++++++++++++----------------------------------
tests/check-qlit.c | 3 +++
2 files changed, 22 insertions(+), 34 deletions(-)
diff --git a/qobject/qlit.c b/qobject/qlit.c
index dc0015f76c..3c4882c784 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -18,29 +18,6 @@
#include "qapi/qmp/qlit.h"
#include "qapi/qmp/types.h"
-typedef struct QListCompareHelper {
- int index;
- QLitObject *objs;
- bool result;
-} QListCompareHelper;
-
-static void compare_helper(QObject *obj, void *opaque)
-{
- QListCompareHelper *helper = opaque;
-
- if (!helper->result) {
- return;
- }
-
- if (helper->objs[helper->index].type == QTYPE_NONE) {
- helper->result = false;
- return;
- }
-
- helper->result =
- qlit_equal_qobject(&helper->objs[helper->index++], obj);
-}
-
static bool qlit_equal_qdict(const QLitObject *lhs, const QDict *qdict)
{
int i;
@@ -62,6 +39,23 @@ static bool qlit_equal_qdict(const QLitObject *lhs, const QDict *qdict)
return true;
}
+static bool qlit_equal_qlist(const QLitObject *lhs, const QList *qlist)
+{
+ QListEntry *e;
+ int i = 0;
+
+ QLIST_FOREACH_ENTRY(qlist, e) {
+ QObject *obj = qlist_entry_obj(e);
+
+ if (!qlit_equal_qobject(&lhs->value.qlist[i], obj)) {
+ return false;
+ }
+ i++;
+ }
+
+ return !e && lhs->value.qlist[i].type == QTYPE_NONE;
+}
+
bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
{
if (!rhs || lhs->type != qobject_type(rhs)) {
@@ -78,17 +72,8 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
qstring_get_str(qobject_to_qstring(rhs))) == 0);
case QTYPE_QDICT:
return qlit_equal_qdict(lhs, qobject_to_qdict(rhs));
- case QTYPE_QLIST: {
- QListCompareHelper helper;
-
- helper.index = 0;
- helper.objs = lhs->value.qlist;
- helper.result = true;
-
- qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
-
- return helper.result;
- }
+ case QTYPE_QLIST:
+ return qlit_equal_qlist(lhs, qobject_to_qlist(rhs));
case QTYPE_QNULL:
return true;
default:
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
index 5d9558dfd9..ae74bfcb83 100644
--- a/tests/check-qlit.c
+++ b/tests/check-qlit.c
@@ -58,6 +58,9 @@ static void qlit_equal_qobject_test(void)
g_assert(!qlit_equal_qobject(&qlit_foo, qobj));
+ qdict_put(qobject_to_qdict(qobj), "bee", qlist_new());
+ g_assert(!qlit_equal_qobject(&qlit, qobj));
+
qobject_decref(qobj);
}
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit()
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (11 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-08-25 15:35 ` Eric Blake
2017-08-30 12:53 ` Markus Armbruster
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 14/14] qapi: generate a literal qobject for introspection Marc-André Lureau
2017-09-01 12:06 ` [Qemu-devel] [PATCH v2 00/14] Generate " Markus Armbruster
14 siblings, 2 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/qapi/qmp/qlit.h | 2 ++
qobject/qlit.c | 37 +++++++++++++++++++++++++++++++++++++
tests/check-qlit.c | 26 ++++++++++++++++++++++++++
3 files changed, 65 insertions(+)
diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index b18406bce9..56feb25e04 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -51,4 +51,6 @@ struct QLitDictEntry {
bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs);
+QObject *qobject_from_qlit(const QLitObject *qlit);
+
#endif /* QLIT_H */
diff --git a/qobject/qlit.c b/qobject/qlit.c
index 3c4882c784..e44c09e9eb 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -82,3 +82,40 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
return false;
}
+
+QObject *qobject_from_qlit(const QLitObject *qlit)
+{
+ int i;
+
+ switch (qlit->type) {
+ case QTYPE_QNULL:
+ return QOBJECT(qnull());
+ case QTYPE_QNUM:
+ return QOBJECT(qnum_from_int(qlit->value.qnum));
+ case QTYPE_QSTRING:
+ return QOBJECT(qstring_from_str(qlit->value.qstr));
+ case QTYPE_QDICT: {
+ QDict *qdict = qdict_new();
+ for (i = 0; qlit->value.qdict[i].value.type != QTYPE_NONE; i++) {
+ QLitDictEntry *e = &qlit->value.qdict[i];
+
+ qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value));
+ }
+ return QOBJECT(qdict);
+ }
+ case QTYPE_QLIST: {
+ QList *qlist = qlist_new();
+
+ for (i = 0; qlit->value.qlist[i].type != QTYPE_NONE; i++) {
+ qlist_append_obj(qlist, qobject_from_qlit(&qlit->value.qlist[i]));
+ }
+ return QOBJECT(qlist);
+ }
+ case QTYPE_QBOOL:
+ return QOBJECT(qbool_from_bool(qlit->value.qbool));
+ case QTYPE_NONE:
+ assert(0);
+ }
+
+ return NULL;
+}
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
index ae74bfcb83..135a399c6d 100644
--- a/tests/check-qlit.c
+++ b/tests/check-qlit.c
@@ -64,11 +64,37 @@ static void qlit_equal_qobject_test(void)
qobject_decref(qobj);
}
+static void qobject_from_qlit_test(void)
+{
+ QObject *obj, *qobj = qobject_from_qlit(&qlit);
+ QDict *qdict;
+ QList *bee;
+
+ qdict = qobject_to_qdict(qobj);
+ g_assert_cmpint(qdict_get_int(qdict, "foo"), ==, 42);
+ g_assert_cmpstr(qdict_get_str(qdict, "bar"), ==, "hello world");
+ g_assert(qobject_type(qdict_get(qdict, "baz")) == QTYPE_QNULL);
+
+ bee = qdict_get_qlist(qdict, "bee");
+ obj = qlist_pop(bee);
+ g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 43);
+ qobject_decref(obj);
+ obj = qlist_pop(bee);
+ g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 44);
+ qobject_decref(obj);
+ obj = qlist_pop(bee);
+ g_assert(qbool_get_bool(qobject_to_qbool(obj)));
+ qobject_decref(obj);
+
+ qobject_decref(qobj);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
+ g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test);
return g_test_run();
}
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH v2 14/14] qapi: generate a literal qobject for introspection
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (12 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit() Marc-André Lureau
@ 2017-08-25 10:59 ` Marc-André Lureau
2017-09-01 12:06 ` [Qemu-devel] [PATCH v2 00/14] Generate " Markus Armbruster
14 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-25 10:59 UTC (permalink / raw)
To: qemu-devel
Cc: armbru, Marc-André Lureau, Dr. David Alan Gilbert, Michael Roth
Replace the generated json string with a literal qobject. The later is
easier to deal with, at run time as well as compile time: adding #if
conditionals will be easier than in a json string.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi-introspect.py | 87 ++++++++++++++++++++++----------------
monitor.c | 2 +-
tests/test-qobject-input-visitor.c | 11 +++--
docs/devel/qapi-code-gen.txt | 29 ++++++++-----
4 files changed, 78 insertions(+), 51 deletions(-)
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 032bcea491..a157a5f91c 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -12,31 +12,41 @@
from qapi import *
-# Caveman's json.dumps() replacement (we're stuck at Python 2.4)
-# TODO try to use json.dumps() once we get unstuck
-def to_json(obj, level=0):
+def to_qlit(obj, level=0, suppress_first_indent=False):
+
+ def indent(level):
+ return level * 4 * ' '
+
+ ret = ''
+ if not suppress_first_indent:
+ ret += indent(level)
if obj is None:
- ret = 'null'
+ ret += 'QLIT_QNULL'
elif isinstance(obj, str):
- ret = '"' + obj.replace('"', r'\"') + '"'
+ ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
elif isinstance(obj, list):
- elts = [to_json(elt, level + 1)
+ elts = [to_qlit(elt, level + 1)
for elt in obj]
- ret = '[' + ', '.join(elts) + ']'
+ elts.append(indent(level + 1) + "{}")
+ ret += 'QLIT_QLIST(((QLitObject[]) {\n'
+ ret += ',\n'.join(elts) + '\n'
+ ret += indent(level) + '}))'
elif isinstance(obj, dict):
- elts = ['"%s": %s' % (key.replace('"', r'\"'),
- to_json(obj[key], level + 1))
- for key in sorted(obj.keys())]
- ret = '{' + ', '.join(elts) + '}'
+ elts = []
+ for key, value in sorted(obj.iteritems()):
+ elts.append(indent(level + 1) + '{ %s, %s }' %
+ (to_c_string(key), to_qlit(value, level + 1, False)))
+ elts.append(indent(level + 1) + '{}')
+ ret += 'QLIT_QDICT(((QLitDictEntry[]) {\n'
+ ret += ',\n'.join(elts) + '\n'
+ ret += indent(level) + '}))'
else:
assert False # not implemented
- if level == 1:
- ret = '\n' + ret
return ret
-def to_c_string(string):
- return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'
+def to_c_string(s):
+ return '"' + s.replace('\\', r'\\').replace('"', r'\"') + '"'
class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
@@ -45,39 +55,37 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
self.defn = None
self.decl = None
self._schema = None
- self._jsons = None
+ self._qlits = None
self._used_types = None
self._name_map = None
def visit_begin(self, schema):
self._schema = schema
- self._jsons = []
+ self._qlits = []
self._used_types = []
self._name_map = {}
def visit_end(self):
# visit the types that are actually used
- jsons = self._jsons
- self._jsons = []
+ qlits = self._qlits
+ self._qlits = []
for typ in self._used_types:
typ.visit(self)
# generate C
# TODO can generate awfully long lines
- jsons.extend(self._jsons)
- name = c_name(prefix, protect=False) + 'qmp_schema_json'
+ qlits.extend(self._qlits)
+ name = c_name(prefix, protect=False) + 'qmp_schema_qlit'
self.decl = mcgen('''
-extern const char %(c_name)s[];
+extern const QLitObject %(c_name)s;
''',
c_name=c_name(name))
- lines = to_json(jsons).split('\n')
- c_string = '\n '.join([to_c_string(line) for line in lines])
self.defn = mcgen('''
-const char %(c_name)s[] = %(c_string)s;
+const QLitObject %(c_name)s = %(c_string)s;
''',
c_name=c_name(name),
- c_string=c_string)
+ c_string=to_qlit(qlits))
self._schema = None
- self._jsons = None
+ self._qlits = None
self._used_types = None
self._name_map = None
@@ -111,12 +119,12 @@ const char %(c_name)s[] = %(c_string)s;
return '[' + self._use_type(typ.element_type) + ']'
return self._name(typ.name)
- def _gen_json(self, name, mtype, obj):
+ def _gen_qlit(self, name, mtype, obj):
if mtype not in ('command', 'event', 'builtin', 'array'):
name = self._name(name)
obj['name'] = name
obj['meta-type'] = mtype
- self._jsons.append(obj)
+ self._qlits.append(obj)
def _gen_member(self, member):
ret = {'name': member.name, 'type': self._use_type(member.type)}
@@ -132,24 +140,24 @@ const char %(c_name)s[] = %(c_string)s;
return {'case': variant.name, 'type': self._use_type(variant.type)}
def visit_builtin_type(self, name, info, json_type):
- self._gen_json(name, 'builtin', {'json-type': json_type})
+ self._gen_qlit(name, 'builtin', {'json-type': json_type})
def visit_enum_type(self, name, info, values, prefix):
- self._gen_json(name, 'enum', {'values': values})
+ self._gen_qlit(name, 'enum', {'values': values})
def visit_array_type(self, name, info, element_type):
element = self._use_type(element_type)
- self._gen_json('[' + element + ']', 'array', {'element-type': element})
+ self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
def visit_object_type_flat(self, name, info, members, variants):
obj = {'members': [self._gen_member(m) for m in members]}
if variants:
obj.update(self._gen_variants(variants.tag_member.name,
variants.variants))
- self._gen_json(name, 'object', obj)
+ self._gen_qlit(name, 'object', obj)
def visit_alternate_type(self, name, info, variants):
- self._gen_json(name, 'alternate',
+ self._gen_qlit(name, 'alternate',
{'members': [{'type': self._use_type(m.type)}
for m in variants.variants]})
@@ -157,13 +165,13 @@ const char %(c_name)s[] = %(c_string)s;
gen, success_response, boxed):
arg_type = arg_type or self._schema.the_empty_object_type
ret_type = ret_type or self._schema.the_empty_object_type
- self._gen_json(name, 'command',
+ self._gen_qlit(name, 'command',
{'arg-type': self._use_type(arg_type),
'ret-type': self._use_type(ret_type)})
def visit_event(self, name, info, arg_type, boxed):
arg_type = arg_type or self._schema.the_empty_object_type
- self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
+ self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
# Debugging aid: unmask QAPI schema's type names
# We normally mask them, because they're not QMP wire ABI
@@ -205,11 +213,18 @@ h_comment = '''
fdef.write(mcgen('''
#include "qemu/osdep.h"
+#include "qapi/qmp/qlit.h"
#include "%(prefix)sqmp-introspect.h"
''',
prefix=prefix))
+fdecl.write(mcgen('''
+#include "qemu/osdep.h"
+#include "qapi/qmp/qlit.h"
+
+'''))
+
schema = QAPISchema(input_file)
gen = QAPISchemaGenIntrospectVisitor(opt_unmask)
schema.visit(gen)
diff --git a/monitor.c b/monitor.c
index e0f880107f..14c27d4b6f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -953,7 +953,7 @@ EventInfoList *qmp_query_events(Error **errp)
static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
Error **errp)
{
- *ret_data = qobject_from_json(qmp_schema_json, &error_abort);
+ *ret_data = qobject_from_qlit(&qmp_schema_qlit);
}
/*
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index bcf02617dc..bdd00f6bd8 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -1247,24 +1247,27 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
}
static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
- const char *schema_json)
+ const QLitObject *qlit)
{
SchemaInfoList *schema = NULL;
+ QObject *obj = qobject_from_qlit(qlit);
Visitor *v;
- v = visitor_input_test_init_raw(data, schema_json);
+ v = qobject_input_visitor_new(obj);
visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
g_assert(schema);
qapi_free_SchemaInfoList(schema);
+ qobject_decref(obj);
+ visit_free(v);
}
static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
const void *unused)
{
- do_test_visitor_in_qmp_introspect(data, test_qmp_schema_json);
- do_test_visitor_in_qmp_introspect(data, qmp_schema_json);
+ do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit);
+ do_test_visitor_in_qmp_introspect(data, &qmp_schema_qlit);
}
int main(int argc, char **argv)
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 9903ac4c19..b653e86bff 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -1295,18 +1295,27 @@ Example:
#ifndef EXAMPLE_QMP_INTROSPECT_H
#define EXAMPLE_QMP_INTROSPECT_H
- extern const char example_qmp_schema_json[];
+ extern const QLitObject qmp_schema_qlit;
#endif
$ cat qapi-generated/example-qmp-introspect.c
[Uninteresting stuff omitted...]
- const char example_qmp_schema_json[] = "["
- "{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
- "{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, "
- "{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
- "{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
- "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
- "{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[2]\"}, "
- "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
- "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]";
+ const QLitObject example_qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
+ QLIT_QDICT(((QLitDictEntry[]) {
+ { "arg-type", QLIT_QSTR("0") },
+ { "meta-type", QLIT_QSTR("event") },
+ { "name", QLIT_QSTR("Event") },
+ { }
+ })),
+ QLIT_QDICT(((QLitDictEntry[]) {
+ { "members", QLIT_QLIST(((QLitObject[]) {
+ { }
+ })) },
+ { "meta-type", QLIT_QSTR("object") },
+ { "name", QLIT_QSTR("0") },
+ { }
+ })),
+ ...
+ { }
+ }));
--
2.14.1.146.gd35faa819
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper Marc-André Lureau
@ 2017-08-25 12:58 ` Eduardo Habkost
2017-08-25 15:31 ` Eric Blake
1 sibling, 0 replies; 40+ messages in thread
From: Eduardo Habkost @ 2017-08-25 12:58 UTC (permalink / raw)
To: Marc-André Lureau
Cc: qemu-devel, armbru, Paolo Bonzini, Richard Henderson
On Fri, Aug 25, 2017 at 12:59:00PM +0200, Marc-André Lureau wrote:
> A step towards completeness.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
Now replying to the latest version:
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
--
Eduardo
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper Marc-André Lureau
2017-08-25 12:58 ` Eduardo Habkost
@ 2017-08-25 15:31 ` Eric Blake
2017-08-30 12:01 ` Markus Armbruster
1 sibling, 1 reply; 40+ messages in thread
From: Eric Blake @ 2017-08-25 15:31 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
Cc: Richard Henderson, armbru, Eduardo Habkost, Paolo Bonzini
[-- Attachment #1: Type: text/plain, Size: 616 bytes --]
On 08/25/2017 05:59 AM, Marc-André Lureau wrote:
> A step towards completeness.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
> ---
> include/qapi/qmp/qdict.h | 4 +++-
> target/i386/cpu.c | 4 ++--
> 2 files changed, 5 insertions(+), 3 deletions(-)
Is it worth touching up scripts/coccinelle/qobject.cocci at the same time?
I guess we don't care about a qlist_append_null() variant?
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit()
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit() Marc-André Lureau
@ 2017-08-25 15:35 ` Eric Blake
2017-08-30 12:53 ` Markus Armbruster
1 sibling, 0 replies; 40+ messages in thread
From: Eric Blake @ 2017-08-25 15:35 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: armbru
[-- Attachment #1: Type: text/plain, Size: 499 bytes --]
On 08/25/2017 05:59 AM, Marc-André Lureau wrote:
s/form/from/ in the subject
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/qapi/qmp/qlit.h | 2 ++
> qobject/qlit.c | 37 +++++++++++++++++++++++++++++++++++++
> tests/check-qlit.c | 26 ++++++++++++++++++++++++++
> 3 files changed, 65 insertions(+)
>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals Marc-André Lureau
@ 2017-08-30 12:00 ` Markus Armbruster
2017-08-30 12:11 ` Marc-André Lureau
0 siblings, 1 reply; 40+ messages in thread
From: Markus Armbruster @ 2017-08-30 12:00 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> They are not considered constant expressions in C, producing an error
> when compiling a const QLit.
A const QLit? Do you mean a non-const one?
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/qapi/qmp/qlit.h | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
> index a4ad91321b..f1d6eed317 100644
> --- a/include/qapi/qmp/qlit.h
> +++ b/include/qapi/qmp/qlit.h
> @@ -36,13 +36,13 @@ struct QLitDictEntry {
> };
>
> #define QLIT_QNUM(val) \
> - (QLitObject){.type = QTYPE_QNUM, .value.qnum = (val)}
> + { .type = QTYPE_QNUM, .value.qnum = (val) }
> #define QLIT_QSTR(val) \
> - (QLitObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
> + { .type = QTYPE_QSTRING, .value.qstr = (val) }
> #define QLIT_QDICT(val) \
> - (QLitObject){.type = QTYPE_QDICT, .value.qdict = (val)}
> + { .type = QTYPE_QDICT, .value.qdict = (val) }
> #define QLIT_QLIST(val) \
> - (QLitObject){.type = QTYPE_QLIST, .value.qlist = (val)}
> + { .type = QTYPE_QLIST, .value.qlist = (val) }
>
> int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs);
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper
2017-08-25 15:31 ` Eric Blake
@ 2017-08-30 12:01 ` Markus Armbruster
2017-08-30 13:54 ` Eric Blake
2017-08-31 13:58 ` Markus Armbruster
0 siblings, 2 replies; 40+ messages in thread
From: Markus Armbruster @ 2017-08-30 12:01 UTC (permalink / raw)
To: Eric Blake
Cc: Marc-André Lureau, qemu-devel, Paolo Bonzini,
Eduardo Habkost, Richard Henderson
Eric Blake <eblake@redhat.com> writes:
> On 08/25/2017 05:59 AM, Marc-André Lureau wrote:
>> A step towards completeness.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>> ---
>> include/qapi/qmp/qdict.h | 4 +++-
>> target/i386/cpu.c | 4 ++--
>> 2 files changed, 5 insertions(+), 3 deletions(-)
>
> Is it worth touching up scripts/coccinelle/qobject.cocci at the same time?
Let's keep it up-to-date. I can do it when I apply.
> I guess we don't care about a qlist_append_null() variant?
Only if we have users.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-30 12:00 ` Markus Armbruster
@ 2017-08-30 12:11 ` Marc-André Lureau
2017-08-30 13:02 ` Markus Armbruster
0 siblings, 1 reply; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-30 12:11 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
Hi
----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > They are not considered constant expressions in C, producing an error
> > when compiling a const QLit.
>
> A const QLit? Do you mean a non-const one?
Really a const QLitObject:
const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
QLIT_QNULL,
{}
}));
qmp-introspect.c:17:63: error: initializer element is not constant
const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
^
Removing the "compound literals" fixes this error.
We may want to include it in the commit message, but I think it lacks a bit of "C standard" explanation. I think it is something like "compound literals" are not const. But then why does it work with (QLitObject[]) ? :)
>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > include/qapi/qmp/qlit.h | 8 ++++----
> > 1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
> > index a4ad91321b..f1d6eed317 100644
> > --- a/include/qapi/qmp/qlit.h
> > +++ b/include/qapi/qmp/qlit.h
> > @@ -36,13 +36,13 @@ struct QLitDictEntry {
> > };
> >
> > #define QLIT_QNUM(val) \
> > - (QLitObject){.type = QTYPE_QNUM, .value.qnum = (val)}
> > + { .type = QTYPE_QNUM, .value.qnum = (val) }
> > #define QLIT_QSTR(val) \
> > - (QLitObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
> > + { .type = QTYPE_QSTRING, .value.qstr = (val) }
> > #define QLIT_QDICT(val) \
> > - (QLitObject){.type = QTYPE_QDICT, .value.qdict = (val)}
> > + { .type = QTYPE_QDICT, .value.qdict = (val) }
> > #define QLIT_QLIST(val) \
> > - (QLitObject){.type = QTYPE_QLIST, .value.qlist = (val)}
> > + { .type = QTYPE_QLIST, .value.qlist = (val) }
> >
> > int compare_litqobj_to_qobj(QLitObject *lhs, QObject *rhs);
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 10/14] tests: add qlit tests
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 10/14] tests: add qlit tests Marc-André Lureau
@ 2017-08-30 12:15 ` Markus Armbruster
2017-08-30 12:23 ` Marc-André Lureau
0 siblings, 1 reply; 40+ messages in thread
From: Markus Armbruster @ 2017-08-30 12:15 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> tests/check-qlit.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
> tests/Makefile.include | 5 +++-
> 2 files changed, 68 insertions(+), 1 deletion(-)
> create mode 100644 tests/check-qlit.c
>
> diff --git a/tests/check-qlit.c b/tests/check-qlit.c
> new file mode 100644
> index 0000000000..47fde92a46
> --- /dev/null
> +++ b/tests/check-qlit.c
> @@ -0,0 +1,64 @@
> +/*
> + * QLit unit-tests.
> + *
> + * Copyright (C) 2017 Red Hat Inc.
> + *
> + * 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.
Please use GPLv2+ unless you have a specific reason for something else.
In that case, explain your reason in the commit message.
May I change the copyright notice to GPLv2+ for you?
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qapi/qmp/qbool.h"
> +#include "qapi/qmp/qdict.h"
> +#include "qapi/qmp/qlit.h"
> +#include "qapi/qmp/qnum.h"
> +#include "qapi/qmp/qstring.h"
> +
> +static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
> + { "foo", QLIT_QNUM(42) },
> + { "bar", QLIT_QSTR("hello world") },
> + { "baz", QLIT_QNULL },
> + { "bee", QLIT_QLIST(((QLitObject[]) {
> + QLIT_QNUM(43),
> + QLIT_QNUM(44),
> + QLIT_QBOOL(true),
> + { },
> + }))},
> + { },
> +}));
> +
> +static QObject *make_qobject(void)
> +{
> + QDict *qdict = qdict_new();
> + QList *list = qlist_new();
> +
> + qdict_put_int(qdict, "foo", 42);
> + qdict_put_str(qdict, "bar", "hello world");
> + qdict_put_null(qdict, "baz");
> +
> + qlist_append_int(list, 43);
> + qlist_append_int(list, 44);
> + qlist_append_bool(list, true);
> + qdict_put(qdict, "bee", list);
> +
> + return QOBJECT(qdict);
> +}
> +
> +static void qlit_equal_qobject_test(void)
> +{
> + QObject *qobj = make_qobject();
> +
> + g_assert(qlit_equal_qobject(&qlit, qobj));
> +
> + qobject_decref(qobj);
> +}
> +
> +int main(int argc, char **argv)
> +{
> + g_test_init(&argc, &argv, NULL);
> +
> + g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
> +
> + return g_test_run();
> +}
We also need negative tests. Could be done as follow-up patch.
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 37c1bed683..3653c7b40a 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -43,6 +43,8 @@ check-unit-y += tests/check-qnull$(EXESUF)
> gcov-files-check-qnull-y = qobject/qnull.c
> check-unit-y += tests/check-qjson$(EXESUF)
> gcov-files-check-qjson-y = qobject/qjson.c
> +check-unit-y += tests/check-qlit$(EXESUF)
> +gcov-files-check-qlit-y = qobject/qlit.c
> check-unit-y += tests/test-qobject-output-visitor$(EXESUF)
> gcov-files-test-qobject-output-visitor-y = qapi/qobject-output-visitor.c
> check-unit-y += tests/test-clone-visitor$(EXESUF)
> @@ -535,7 +537,7 @@ GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
>
> test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
> tests/check-qlist.o tests/check-qnull.o \
> - tests/check-qjson.o \
> + tests/check-qjson.o tests/check-qlit.o \
> tests/test-coroutine.o tests/test-string-output-visitor.o \
> tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
> tests/test-clone-visitor.o \
> @@ -569,6 +571,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
> tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
> tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
> tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
> +tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y)
> tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
> tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 10/14] tests: add qlit tests
2017-08-30 12:15 ` Markus Armbruster
@ 2017-08-30 12:23 ` Marc-André Lureau
0 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-30 12:23 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
Hi
----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > tests/check-qlit.c | 64
> > ++++++++++++++++++++++++++++++++++++++++++++++++++
> > tests/Makefile.include | 5 +++-
> > 2 files changed, 68 insertions(+), 1 deletion(-)
> > create mode 100644 tests/check-qlit.c
> >
> > diff --git a/tests/check-qlit.c b/tests/check-qlit.c
> > new file mode 100644
> > index 0000000000..47fde92a46
> > --- /dev/null
> > +++ b/tests/check-qlit.c
> > @@ -0,0 +1,64 @@
> > +/*
> > + * QLit unit-tests.
> > + *
> > + * Copyright (C) 2017 Red Hat Inc.
> > + *
> > + * 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.
>
> Please use GPLv2+ unless you have a specific reason for something else.
> In that case, explain your reason in the commit message.
>
> May I change the copyright notice to GPLv2+ for you?
I copied that header from some other files. Sure, feel free (although I like LGPL better in general, so we can easily move the code to a shared library)
>
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +
> > +#include "qapi/qmp/qbool.h"
> > +#include "qapi/qmp/qdict.h"
> > +#include "qapi/qmp/qlit.h"
> > +#include "qapi/qmp/qnum.h"
> > +#include "qapi/qmp/qstring.h"
> > +
> > +static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
> > + { "foo", QLIT_QNUM(42) },
> > + { "bar", QLIT_QSTR("hello world") },
> > + { "baz", QLIT_QNULL },
> > + { "bee", QLIT_QLIST(((QLitObject[]) {
> > + QLIT_QNUM(43),
> > + QLIT_QNUM(44),
> > + QLIT_QBOOL(true),
> > + { },
> > + }))},
> > + { },
> > +}));
> > +
> > +static QObject *make_qobject(void)
> > +{
> > + QDict *qdict = qdict_new();
> > + QList *list = qlist_new();
> > +
> > + qdict_put_int(qdict, "foo", 42);
> > + qdict_put_str(qdict, "bar", "hello world");
> > + qdict_put_null(qdict, "baz");
> > +
> > + qlist_append_int(list, 43);
> > + qlist_append_int(list, 44);
> > + qlist_append_bool(list, true);
> > + qdict_put(qdict, "bee", list);
> > +
> > + return QOBJECT(qdict);
> > +}
> > +
> > +static void qlit_equal_qobject_test(void)
> > +{
> > + QObject *qobj = make_qobject();
> > +
> > + g_assert(qlit_equal_qobject(&qlit, qobj));
> > +
> > + qobject_decref(qobj);
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > + g_test_init(&argc, &argv, NULL);
> > +
> > + g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
> > +
> > + return g_test_run();
> > +}
>
> We also need negative tests. Could be done as follow-up patch.
There are a few in following patches iirc, more is always welcome.
Thanks
>
> > diff --git a/tests/Makefile.include b/tests/Makefile.include
> > index 37c1bed683..3653c7b40a 100644
> > --- a/tests/Makefile.include
> > +++ b/tests/Makefile.include
> > @@ -43,6 +43,8 @@ check-unit-y += tests/check-qnull$(EXESUF)
> > gcov-files-check-qnull-y = qobject/qnull.c
> > check-unit-y += tests/check-qjson$(EXESUF)
> > gcov-files-check-qjson-y = qobject/qjson.c
> > +check-unit-y += tests/check-qlit$(EXESUF)
> > +gcov-files-check-qlit-y = qobject/qlit.c
> > check-unit-y += tests/test-qobject-output-visitor$(EXESUF)
> > gcov-files-test-qobject-output-visitor-y = qapi/qobject-output-visitor.c
> > check-unit-y += tests/test-clone-visitor$(EXESUF)
> > @@ -535,7 +537,7 @@ GENERATED_FILES += tests/test-qapi-types.h
> > tests/test-qapi-visit.h \
> >
> > test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o
> > \
> > tests/check-qlist.o tests/check-qnull.o \
> > - tests/check-qjson.o \
> > + tests/check-qjson.o tests/check-qlit.o \
> > tests/test-coroutine.o tests/test-string-output-visitor.o \
> > tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
> > tests/test-clone-visitor.o \
> > @@ -569,6 +571,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o
> > $(test-util-obj-y)
> > tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
> > tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
> > tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
> > +tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y)
> > tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o
> > $(test-qom-obj-y)
> > tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o
> > $(test-qom-obj-y)
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/14] qlit: improve QLit dict vs qdict comparison
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 11/14] qlit: improve QLit dict vs qdict comparison Marc-André Lureau
@ 2017-08-30 12:35 ` Markus Armbruster
2017-08-30 13:05 ` Marc-André Lureau
0 siblings, 1 reply; 40+ messages in thread
From: Markus Armbruster @ 2017-08-30 12:35 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Verify that all qdict values are covered.
>
> (a previous iteration of this patch created a copy of qdict to remove
> all checked elements, verifying no duplicates exist in the literal
> qdict, however this is a programming error, and a size comparison
> should be enough)
The parenthesis confused me, because I wasn't sure about the exact
meaning of "a previous iteration of this patch". I tried to find a
prior commit, but it looks like you're really talking about v1.
Confused me, because I don't expect commit messages discussing previous
iterations.
What about:
qlit: Tighten QLit dict vs qdict comparison
We check that all members of the QLit dictionary are also in the
QDict. We neglect to check the other direction.
Comparing the number of members suffices, because QDict can't
contain duplicate members, and putting duplicates in a QLit is a
programming error.
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> qobject/qlit.c | 37 +++++++++++++++++++++++--------------
> tests/check-qlit.c | 7 +++++++
> 2 files changed, 30 insertions(+), 14 deletions(-)
>
> diff --git a/qobject/qlit.c b/qobject/qlit.c
> index b1d9146220..dc0015f76c 100644
> --- a/qobject/qlit.c
> +++ b/qobject/qlit.c
> @@ -41,6 +41,27 @@ static void compare_helper(QObject *obj, void *opaque)
> qlit_equal_qobject(&helper->objs[helper->index++], obj);
> }
>
> +static bool qlit_equal_qdict(const QLitObject *lhs, const QDict *qdict)
> +{
> + int i;
> +
> + for (i = 0; lhs->value.qdict[i].key; i++) {
> + QObject *obj = qdict_get(qdict, lhs->value.qdict[i].key);
> +
> + if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
> + return false;
> + }
> + }
> +
> + /* Note: the literal qdict must not contain duplicates, this is
> + * considered a programming error and it isn't checked here. */
> + if (qdict_size(qdict) != i) {
> + return false;
> + }
> +
> + return true;
> +}
> +
> bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
> {
> if (!rhs || lhs->type != qobject_type(rhs)) {
> @@ -55,20 +76,8 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
> case QTYPE_QSTRING:
> return (strcmp(lhs->value.qstr,
> qstring_get_str(qobject_to_qstring(rhs))) == 0);
> - case QTYPE_QDICT: {
> - int i;
> -
> - for (i = 0; lhs->value.qdict[i].key; i++) {
> - QObject *obj = qdict_get(qobject_to_qdict(rhs),
> - lhs->value.qdict[i].key);
> -
> - if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
> - return false;
> - }
> - }
> -
> - return true;
> - }
> + case QTYPE_QDICT:
> + return qlit_equal_qdict(lhs, qobject_to_qdict(rhs));
> case QTYPE_QLIST: {
> QListCompareHelper helper;
>
> diff --git a/tests/check-qlit.c b/tests/check-qlit.c
> index 47fde92a46..5d9558dfd9 100644
> --- a/tests/check-qlit.c
> +++ b/tests/check-qlit.c
> @@ -28,6 +28,11 @@ static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
> { },
> }));
>
> +static QLitObject qlit_foo = QLIT_QDICT(((QLitDictEntry[]) {
> + { "foo", QLIT_QNUM(42) },
> + { },
> +}));
> +
> static QObject *make_qobject(void)
> {
> QDict *qdict = qdict_new();
> @@ -51,6 +56,8 @@ static void qlit_equal_qobject_test(void)
>
> g_assert(qlit_equal_qobject(&qlit, qobj));
>
> + g_assert(!qlit_equal_qobject(&qlit_foo, qobj));
> +
> qobject_decref(qobj);
> }
Ah, you do have negative test cases, just not in the patch creating the
test.
When you leave gaps in that will be filled in later patches, I recomend
pointing out the gaps in the commit message, with a promise they'll be
filled shortly. Your reviewers will thank you.
With am improved commit message,
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison Marc-André Lureau
@ 2017-08-30 12:36 ` Markus Armbruster
2017-08-31 14:20 ` Markus Armbruster
0 siblings, 1 reply; 40+ messages in thread
From: Markus Armbruster @ 2017-08-30 12:36 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Use QLIST_FOREACH_ENTRY() to simplify the code and break earlier.
>
> Check that the QLit list has the same size as the qlist, this should
> ensure that we have an exact match when iterating over qlist for
> comparing the elements.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit()
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit() Marc-André Lureau
2017-08-25 15:35 ` Eric Blake
@ 2017-08-30 12:53 ` Markus Armbruster
2017-08-30 13:00 ` Marc-André Lureau
1 sibling, 1 reply; 40+ messages in thread
From: Markus Armbruster @ 2017-08-30 12:53 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Eric already pointed out the typo in the title.
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/qapi/qmp/qlit.h | 2 ++
> qobject/qlit.c | 37 +++++++++++++++++++++++++++++++++++++
> tests/check-qlit.c | 26 ++++++++++++++++++++++++++
> 3 files changed, 65 insertions(+)
>
> diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
> index b18406bce9..56feb25e04 100644
> --- a/include/qapi/qmp/qlit.h
> +++ b/include/qapi/qmp/qlit.h
> @@ -51,4 +51,6 @@ struct QLitDictEntry {
>
> bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs);
>
> +QObject *qobject_from_qlit(const QLitObject *qlit);
> +
> #endif /* QLIT_H */
> diff --git a/qobject/qlit.c b/qobject/qlit.c
> index 3c4882c784..e44c09e9eb 100644
> --- a/qobject/qlit.c
> +++ b/qobject/qlit.c
> @@ -82,3 +82,40 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
>
> return false;
> }
> +
> +QObject *qobject_from_qlit(const QLitObject *qlit)
> +{
> + int i;
> +
> + switch (qlit->type) {
> + case QTYPE_QNULL:
> + return QOBJECT(qnull());
> + case QTYPE_QNUM:
> + return QOBJECT(qnum_from_int(qlit->value.qnum));
This line shows that QLitObject member value.qnum should really be named
value.qint. Let's not worry about that now.
> + case QTYPE_QSTRING:
> + return QOBJECT(qstring_from_str(qlit->value.qstr));
> + case QTYPE_QDICT: {
> + QDict *qdict = qdict_new();
Blank line here. Can touch up when I apply.
> + for (i = 0; qlit->value.qdict[i].value.type != QTYPE_NONE; i++) {
> + QLitDictEntry *e = &qlit->value.qdict[i];
I'd prefer the laconic
QDict *qdict = qdict_new();
QLitDictEntry *e;
for (e = qlit->value.qdict; e->key; e++) {
qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value));
}
return QOBJECT(qdict);
Can slot that in when I apply.
> +
> + qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value));
> + }
> + return QOBJECT(qdict);
> + }
> + case QTYPE_QLIST: {
> + QList *qlist = qlist_new();
> +
> + for (i = 0; qlit->value.qlist[i].type != QTYPE_NONE; i++) {
> + qlist_append_obj(qlist, qobject_from_qlit(&qlit->value.qlist[i]));
> + }
> + return QOBJECT(qlist);
Likewise
QList *qlist = qlist_new();
QLitObject *e;
for (e = qlit->value.qlist; e->type != QTYPE_NONE; e++) {
qlist_append_obj(qlist, qobject_from_qlit(e));
}
return QOBJECT(qlist);
> + }
> + case QTYPE_QBOOL:
> + return QOBJECT(qbool_from_bool(qlit->value.qbool));
> + case QTYPE_NONE:
> + assert(0);
> + }
> +
> + return NULL;
> +}
> diff --git a/tests/check-qlit.c b/tests/check-qlit.c
> index ae74bfcb83..135a399c6d 100644
> --- a/tests/check-qlit.c
> +++ b/tests/check-qlit.c
> @@ -64,11 +64,37 @@ static void qlit_equal_qobject_test(void)
> qobject_decref(qobj);
> }
>
> +static void qobject_from_qlit_test(void)
> +{
> + QObject *obj, *qobj = qobject_from_qlit(&qlit);
> + QDict *qdict;
> + QList *bee;
> +
> + qdict = qobject_to_qdict(qobj);
> + g_assert_cmpint(qdict_get_int(qdict, "foo"), ==, 42);
> + g_assert_cmpstr(qdict_get_str(qdict, "bar"), ==, "hello world");
> + g_assert(qobject_type(qdict_get(qdict, "baz")) == QTYPE_QNULL);
> +
> + bee = qdict_get_qlist(qdict, "bee");
> + obj = qlist_pop(bee);
> + g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 43);
> + qobject_decref(obj);
> + obj = qlist_pop(bee);
> + g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 44);
> + qobject_decref(obj);
> + obj = qlist_pop(bee);
> + g_assert(qbool_get_bool(qobject_to_qbool(obj)));
> + qobject_decref(obj);
> +
> + qobject_decref(qobj);
> +}
> +
> int main(int argc, char **argv)
> {
> g_test_init(&argc, &argv, NULL);
>
> g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
> + g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test);
>
> return g_test_run();
> }
With the typo fixed and preferably with the improvements I suggested:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit()
2017-08-30 12:53 ` Markus Armbruster
@ 2017-08-30 13:00 ` Marc-André Lureau
0 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-30 13:00 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
Hi
----- Original Message -----
> Eric already pointed out the typo in the title.
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > include/qapi/qmp/qlit.h | 2 ++
> > qobject/qlit.c | 37 +++++++++++++++++++++++++++++++++++++
> > tests/check-qlit.c | 26 ++++++++++++++++++++++++++
> > 3 files changed, 65 insertions(+)
> >
> > diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
> > index b18406bce9..56feb25e04 100644
> > --- a/include/qapi/qmp/qlit.h
> > +++ b/include/qapi/qmp/qlit.h
> > @@ -51,4 +51,6 @@ struct QLitDictEntry {
> >
> > bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs);
> >
> > +QObject *qobject_from_qlit(const QLitObject *qlit);
> > +
> > #endif /* QLIT_H */
> > diff --git a/qobject/qlit.c b/qobject/qlit.c
> > index 3c4882c784..e44c09e9eb 100644
> > --- a/qobject/qlit.c
> > +++ b/qobject/qlit.c
> > @@ -82,3 +82,40 @@ bool qlit_equal_qobject(const QLitObject *lhs, const
> > QObject *rhs)
> >
> > return false;
> > }
> > +
> > +QObject *qobject_from_qlit(const QLitObject *qlit)
> > +{
> > + int i;
> > +
> > + switch (qlit->type) {
> > + case QTYPE_QNULL:
> > + return QOBJECT(qnull());
> > + case QTYPE_QNUM:
> > + return QOBJECT(qnum_from_int(qlit->value.qnum));
>
> This line shows that QLitObject member value.qnum should really be named
> value.qint. Let's not worry about that now.
>
> > + case QTYPE_QSTRING:
> > + return QOBJECT(qstring_from_str(qlit->value.qstr));
> > + case QTYPE_QDICT: {
> > + QDict *qdict = qdict_new();
>
> Blank line here. Can touch up when I apply.
>
> > + for (i = 0; qlit->value.qdict[i].value.type != QTYPE_NONE; i++) {
> > + QLitDictEntry *e = &qlit->value.qdict[i];
>
> I'd prefer the laconic
>
> QDict *qdict = qdict_new();
> QLitDictEntry *e;
>
> for (e = qlit->value.qdict; e->key; e++) {
> qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value));
> }
> return QOBJECT(qdict);
>
> Can slot that in when I apply.
>
Indeed!
> > +
> > + qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value));
> > + }
> > + return QOBJECT(qdict);
> > + }
> > + case QTYPE_QLIST: {
> > + QList *qlist = qlist_new();
> > +
> > + for (i = 0; qlit->value.qlist[i].type != QTYPE_NONE; i++) {
> > + qlist_append_obj(qlist,
> > qobject_from_qlit(&qlit->value.qlist[i]));
> > + }
> > + return QOBJECT(qlist);
>
> Likewise
>
> QList *qlist = qlist_new();
> QLitObject *e;
>
> for (e = qlit->value.qlist; e->type != QTYPE_NONE; e++) {
> qlist_append_obj(qlist, qobject_from_qlit(e));
> }
> return QOBJECT(qlist);
>
> > + }
> > + case QTYPE_QBOOL:
> > + return QOBJECT(qbool_from_bool(qlit->value.qbool));
> > + case QTYPE_NONE:
> > + assert(0);
> > + }
> > +
> > + return NULL;
> > +}
> > diff --git a/tests/check-qlit.c b/tests/check-qlit.c
> > index ae74bfcb83..135a399c6d 100644
> > --- a/tests/check-qlit.c
> > +++ b/tests/check-qlit.c
> > @@ -64,11 +64,37 @@ static void qlit_equal_qobject_test(void)
> > qobject_decref(qobj);
> > }
> >
> > +static void qobject_from_qlit_test(void)
> > +{
> > + QObject *obj, *qobj = qobject_from_qlit(&qlit);
> > + QDict *qdict;
> > + QList *bee;
> > +
> > + qdict = qobject_to_qdict(qobj);
> > + g_assert_cmpint(qdict_get_int(qdict, "foo"), ==, 42);
> > + g_assert_cmpstr(qdict_get_str(qdict, "bar"), ==, "hello world");
> > + g_assert(qobject_type(qdict_get(qdict, "baz")) == QTYPE_QNULL);
> > +
> > + bee = qdict_get_qlist(qdict, "bee");
> > + obj = qlist_pop(bee);
> > + g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 43);
> > + qobject_decref(obj);
> > + obj = qlist_pop(bee);
> > + g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 44);
> > + qobject_decref(obj);
> > + obj = qlist_pop(bee);
> > + g_assert(qbool_get_bool(qobject_to_qbool(obj)));
> > + qobject_decref(obj);
> > +
> > + qobject_decref(qobj);
> > +}
> > +
> > int main(int argc, char **argv)
> > {
> > g_test_init(&argc, &argv, NULL);
> >
> > g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
> > + g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test);
> >
> > return g_test_run();
> > }
>
> With the typo fixed and preferably with the improvements I suggested:
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
Thanks
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-30 12:11 ` Marc-André Lureau
@ 2017-08-30 13:02 ` Markus Armbruster
2017-08-30 13:19 ` Marc-André Lureau
0 siblings, 1 reply; 40+ messages in thread
From: Markus Armbruster @ 2017-08-30 13:02 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Hi
>
> ----- Original Message -----
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > They are not considered constant expressions in C, producing an error
>> > when compiling a const QLit.
>>
>> A const QLit? Do you mean a non-const one?
>
> Really a const QLitObject:
>
>
> const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
> QLIT_QNULL,
> {}
> }));
>
> qmp-introspect.c:17:63: error: initializer element is not constant
> const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
> ^
> Removing the "compound literals" fixes this error.
Does QLIT_QLIST(((const QLitObject[]) { ... } work?
> We may want to include it in the commit message, but I think it lacks a bit of "C standard" explanation. I think it is something like "compound literals" are not const. But then why does it work with (QLitObject[]) ? :)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/14] qlit: improve QLit dict vs qdict comparison
2017-08-30 12:35 ` Markus Armbruster
@ 2017-08-30 13:05 ` Marc-André Lureau
0 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-30 13:05 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
Hi
----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Verify that all qdict values are covered.
> >
> > (a previous iteration of this patch created a copy of qdict to remove
> > all checked elements, verifying no duplicates exist in the literal
> > qdict, however this is a programming error, and a size comparison
> > should be enough)
>
> The parenthesis confused me, because I wasn't sure about the exact
> meaning of "a previous iteration of this patch". I tried to find a
> prior commit, but it looks like you're really talking about v1.
> Confused me, because I don't expect commit messages discussing previous
> iterations.
>
> What about:
>
> qlit: Tighten QLit dict vs qdict comparison
>
> We check that all members of the QLit dictionary are also in the
> QDict. We neglect to check the other direction.
>
> Comparing the number of members suffices, because QDict can't
> contain duplicate members, and putting duplicates in a QLit is a
> programming error.
Looks good to me
>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > qobject/qlit.c | 37 +++++++++++++++++++++++--------------
> > tests/check-qlit.c | 7 +++++++
> > 2 files changed, 30 insertions(+), 14 deletions(-)
> >
> > diff --git a/qobject/qlit.c b/qobject/qlit.c
> > index b1d9146220..dc0015f76c 100644
> > --- a/qobject/qlit.c
> > +++ b/qobject/qlit.c
> > @@ -41,6 +41,27 @@ static void compare_helper(QObject *obj, void *opaque)
> > qlit_equal_qobject(&helper->objs[helper->index++], obj);
> > }
> >
> > +static bool qlit_equal_qdict(const QLitObject *lhs, const QDict *qdict)
> > +{
> > + int i;
> > +
> > + for (i = 0; lhs->value.qdict[i].key; i++) {
> > + QObject *obj = qdict_get(qdict, lhs->value.qdict[i].key);
> > +
> > + if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
> > + return false;
> > + }
> > + }
> > +
> > + /* Note: the literal qdict must not contain duplicates, this is
> > + * considered a programming error and it isn't checked here. */
> > + if (qdict_size(qdict) != i) {
> > + return false;
> > + }
> > +
> > + return true;
> > +}
> > +
> > bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
> > {
> > if (!rhs || lhs->type != qobject_type(rhs)) {
> > @@ -55,20 +76,8 @@ bool qlit_equal_qobject(const QLitObject *lhs, const
> > QObject *rhs)
> > case QTYPE_QSTRING:
> > return (strcmp(lhs->value.qstr,
> > qstring_get_str(qobject_to_qstring(rhs))) == 0);
> > - case QTYPE_QDICT: {
> > - int i;
> > -
> > - for (i = 0; lhs->value.qdict[i].key; i++) {
> > - QObject *obj = qdict_get(qobject_to_qdict(rhs),
> > - lhs->value.qdict[i].key);
> > -
> > - if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
> > - return false;
> > - }
> > - }
> > -
> > - return true;
> > - }
> > + case QTYPE_QDICT:
> > + return qlit_equal_qdict(lhs, qobject_to_qdict(rhs));
> > case QTYPE_QLIST: {
> > QListCompareHelper helper;
> >
> > diff --git a/tests/check-qlit.c b/tests/check-qlit.c
> > index 47fde92a46..5d9558dfd9 100644
> > --- a/tests/check-qlit.c
> > +++ b/tests/check-qlit.c
> > @@ -28,6 +28,11 @@ static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
> > { },
> > }));
> >
> > +static QLitObject qlit_foo = QLIT_QDICT(((QLitDictEntry[]) {
> > + { "foo", QLIT_QNUM(42) },
> > + { },
> > +}));
> > +
> > static QObject *make_qobject(void)
> > {
> > QDict *qdict = qdict_new();
> > @@ -51,6 +56,8 @@ static void qlit_equal_qobject_test(void)
> >
> > g_assert(qlit_equal_qobject(&qlit, qobj));
> >
> > + g_assert(!qlit_equal_qobject(&qlit_foo, qobj));
> > +
> > qobject_decref(qobj);
> > }
>
> Ah, you do have negative test cases, just not in the patch creating the
> test.
>
> When you leave gaps in that will be filled in later patches, I recomend
> pointing out the gaps in the commit message, with a promise they'll be
> filled shortly. Your reviewers will thank you.
>
> With am improved commit message,
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
Thanks
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-30 13:02 ` Markus Armbruster
@ 2017-08-30 13:19 ` Marc-André Lureau
2017-08-31 8:42 ` Markus Armbruster
0 siblings, 1 reply; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-30 13:19 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
Hi
----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Hi
> >
> > ----- Original Message -----
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >> > They are not considered constant expressions in C, producing an error
> >> > when compiling a const QLit.
> >>
> >> A const QLit? Do you mean a non-const one?
> >
> > Really a const QLitObject:
> >
> >
> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
> > QLIT_QNULL,
> > {}
> > }));
> >
> > qmp-introspect.c:17:63: error: initializer element is not constant
> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
> > ^
> > Removing the "compound literals" fixes this error.
>
> Does QLIT_QLIST(((const QLitObject[]) { ... } work?
No. Even if I put "const" all over the place (in member, in compound type etc).
Give it a try, see if you can make it const, I am out of luck.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper
2017-08-30 12:01 ` Markus Armbruster
@ 2017-08-30 13:54 ` Eric Blake
2017-08-31 13:58 ` Markus Armbruster
1 sibling, 0 replies; 40+ messages in thread
From: Eric Blake @ 2017-08-30 13:54 UTC (permalink / raw)
To: Markus Armbruster
Cc: Marc-André Lureau, qemu-devel, Paolo Bonzini,
Eduardo Habkost, Richard Henderson
[-- Attachment #1: Type: text/plain, Size: 1200 bytes --]
On 08/30/2017 07:01 AM, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
>
>> On 08/25/2017 05:59 AM, Marc-André Lureau wrote:
>>> A step towards completeness.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>>> ---
>>> include/qapi/qmp/qdict.h | 4 +++-
>>> target/i386/cpu.c | 4 ++--
>>> 2 files changed, 5 insertions(+), 3 deletions(-)
>>
>> Is it worth touching up scripts/coccinelle/qobject.cocci at the same time?
>
> Let's keep it up-to-date. I can do it when I apply.
>
>> I guess we don't care about a qlist_append_null() variant?
>
> Only if we have users.
Most (all?) of our qlist_ users tend to be heterogenous; we insert list
members that have the same type. I don't see anyone wanting a list of
all null objects any time soon; about the only reason to support it
would be if we wanted a list of the StrOrNull alternate type, where some
list elements can be null. But you're right that we don't have to add
it now.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-30 13:19 ` Marc-André Lureau
@ 2017-08-31 8:42 ` Markus Armbruster
2017-08-31 9:14 ` Marc-André Lureau
2017-08-31 15:28 ` Laszlo Ersek
0 siblings, 2 replies; 40+ messages in thread
From: Markus Armbruster @ 2017-08-31 8:42 UTC (permalink / raw)
To: Marc-André Lureau
Cc: qemu-devel, Eric Blake, László Érsek
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Hi
>
> ----- Original Message -----
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Hi
>> >
>> > ----- Original Message -----
>> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> >>
>> >> > They are not considered constant expressions in C, producing an error
>> >> > when compiling a const QLit.
>> >>
>> >> A const QLit? Do you mean a non-const one?
>> >
>> > Really a const QLitObject:
>> >
>> >
>> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>> > QLIT_QNULL,
>> > {}
>> > }));
>> >
>> > qmp-introspect.c:17:63: error: initializer element is not constant
>> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>> > ^
>> > Removing the "compound literals" fixes this error.
>>
>> Does QLIT_QLIST(((const QLitObject[]) { ... } work?
>
> No. Even if I put "const" all over the place (in member, in compound type etc).
>
> Give it a try, see if you can make it const, I am out of luck.
The commit message's explanation is wrong. This isn't about const at
all, it's about "constant expressions", which are something else
entirely.
For what it's worth, clang is cool with the compound literals. On
Fedora 26 with a minimized test case (appended):
$ clang -c -g -O -Wall compound-lit.c
$ gcc -c -g -O -Wall compound-lit.c
compound-lit.c:30:37: error: initializer element is not constant
.value.qdict = (QLitDictEntry[]){
^
compound-lit.c:30:37: note: (near initialization for ‘(anonymous).value’)
GCC bug or not? A search of the GCC Bugzilla finds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713
Copying a few notorious language lawyers^W^W^Wtrusted advisers.
Even if this turns out to be a gcc bug, we'll have to work around it.
But the work-around needs a comment then.
In any case, the commit message needs fixing.
enum {
QTYPE_NONE, QTYPE_QSTRING, QTYPE_QDICT,
};
typedef struct QLitDictEntry QLitDictEntry;
typedef struct QLitObject QLitObject;
struct QLitObject {
int type;
union {
const char *qstr;
QLitDictEntry *qdict;
} value;
};
struct QLitDictEntry {
const char *key;
QLitObject value;
};
QLitObject qlit1 = (QLitObject){
.type = QTYPE_QDICT,
.value.qdict = (QLitDictEntry[]){
{ "foo", {} },
{}
}};
QLitObject qlit2 = (QLitObject){
.type = QTYPE_QDICT,
.value.qdict = (QLitDictEntry[]){
{ "foo", (QLitObject){} },
{}
}};
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-31 8:42 ` Markus Armbruster
@ 2017-08-31 9:14 ` Marc-André Lureau
2017-08-31 13:50 ` Markus Armbruster
2017-08-31 15:28 ` Laszlo Ersek
1 sibling, 1 reply; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-31 9:14 UTC (permalink / raw)
To: Markus Armbruster; +Cc: László Érsek, qemu-devel
Hi
On Thu, Aug 31, 2017 at 10:43 AM Markus Armbruster <armbru@redhat.com>
wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Hi
> >
> > ----- Original Message -----
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >> > Hi
> >> >
> >> > ----- Original Message -----
> >> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >> >>
> >> >> > They are not considered constant expressions in C, producing an
> error
> >> >> > when compiling a const QLit.
> >> >>
> >> >> A const QLit? Do you mean a non-const one?
> >> >
> >> > Really a const QLitObject:
> >> >
> >> >
> >> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
> >> > QLIT_QNULL,
> >> > {}
> >> > }));
> >> >
> >> > qmp-introspect.c:17:63: error: initializer element is not constant
> >> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
> >> > ^
> >> > Removing the "compound literals" fixes this error.
> >>
> >> Does QLIT_QLIST(((const QLitObject[]) { ... } work?
> >
> > No. Even if I put "const" all over the place (in member, in compound
> type etc).
> >
> > Give it a try, see if you can make it const, I am out of luck.
>
> The commit message's explanation is wrong. This isn't about const at
> all, it's about "constant expressions", which are something else
> entirely.
>
The point was that declaring a non const QLit with those "compound
literals" worked vs with const.
> For what it's worth, clang is cool with the compound literals. On
> Fedora 26 with a minimized test case (appended):
>
> $ clang -c -g -O -Wall compound-lit.c
> $ gcc -c -g -O -Wall compound-lit.c
> compound-lit.c:30:37: error: initializer element is not constant
> .value.qdict = (QLitDictEntry[]){
> ^
> compound-lit.c:30:37: note: (near initialization for
> ‘(anonymous).value’)
>
> GCC bug or not? A search of the GCC Bugzilla finds
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713
>
> Copying a few notorious language lawyers^W^W^Wtrusted advisers.
>
> Even if this turns out to be a gcc bug, we'll have to work around it.
> But the work-around needs a comment then.
>
> In any case, the commit message needs fixing.
>
What about adapting the bug comment:
qlit: remove compound literals
A compound literal (i.e., "(struct Str1){1}"), is not a constant
expression, and so it cannot be used to initialize an object with static
storage duration.
$ gcc -c -g -O -Wall compound-lit.c
compound-lit.c:30:37: error: initializer element is not constant
.value.qdict = (QLitDictEntry[]){
^
compound-lit.c:30:37: note: (near initialization for
‘(anonymous).value’)
clang accepts it. In some cases, gcc accepts compound literals as
initializer, but not in this nested case. There is a gcc bug about it:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713.
Feel free to adapt on commit
thanks
>
>
> enum {
> QTYPE_NONE, QTYPE_QSTRING, QTYPE_QDICT,
> };
>
> typedef struct QLitDictEntry QLitDictEntry;
> typedef struct QLitObject QLitObject;
>
> struct QLitObject {
> int type;
> union {
> const char *qstr;
> QLitDictEntry *qdict;
> } value;
> };
>
> struct QLitDictEntry {
> const char *key;
> QLitObject value;
> };
>
> QLitObject qlit1 = (QLitObject){
> .type = QTYPE_QDICT,
> .value.qdict = (QLitDictEntry[]){
> { "foo", {} },
> {}
> }};
>
> QLitObject qlit2 = (QLitObject){
> .type = QTYPE_QDICT,
> .value.qdict = (QLitDictEntry[]){
> { "foo", (QLitObject){} },
> {}
> }};
>
> --
Marc-André Lureau
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-31 9:14 ` Marc-André Lureau
@ 2017-08-31 13:50 ` Markus Armbruster
0 siblings, 0 replies; 40+ messages in thread
From: Markus Armbruster @ 2017-08-31 13:50 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: László Érsek, qemu-devel
Marc-André Lureau <marcandre.lureau@gmail.com> writes:
> Hi
>
> On Thu, Aug 31, 2017 at 10:43 AM Markus Armbruster <armbru@redhat.com>
> wrote:
>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Hi
>> >
>> > ----- Original Message -----
>> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> >>
>> >> > Hi
>> >> >
>> >> > ----- Original Message -----
>> >> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> >> >>
>> >> >> > They are not considered constant expressions in C, producing an
>> error
>> >> >> > when compiling a const QLit.
>> >> >>
>> >> >> A const QLit? Do you mean a non-const one?
>> >> >
>> >> > Really a const QLitObject:
>> >> >
>> >> >
>> >> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>> >> > QLIT_QNULL,
>> >> > {}
>> >> > }));
>> >> >
>> >> > qmp-introspect.c:17:63: error: initializer element is not constant
>> >> > const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>> >> > ^
>> >> > Removing the "compound literals" fixes this error.
>> >>
>> >> Does QLIT_QLIST(((const QLitObject[]) { ... } work?
>> >
>> > No. Even if I put "const" all over the place (in member, in compound
>> type etc).
>> >
>> > Give it a try, see if you can make it const, I am out of luck.
>>
>> The commit message's explanation is wrong. This isn't about const at
>> all, it's about "constant expressions", which are something else
>> entirely.
>>
>
> The point was that declaring a non const QLit with those "compound
> literals" worked vs with const.
The keyword const is a red herring here, and that's precisely what's
wrong with the commit message. The minimized test case demonstrates the
problem without const.
>> For what it's worth, clang is cool with the compound literals. On
>> Fedora 26 with a minimized test case (appended):
>>
>> $ clang -c -g -O -Wall compound-lit.c
>> $ gcc -c -g -O -Wall compound-lit.c
>> compound-lit.c:30:37: error: initializer element is not constant
>> .value.qdict = (QLitDictEntry[]){
>> ^
>> compound-lit.c:30:37: note: (near initialization for
>> ‘(anonymous).value’)
>>
>> GCC bug or not? A search of the GCC Bugzilla finds
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713
>>
>> Copying a few notorious language lawyers^W^W^Wtrusted advisers.
>>
>> Even if this turns out to be a gcc bug, we'll have to work around it.
>> But the work-around needs a comment then.
>>
>> In any case, the commit message needs fixing.
>>
>
> What about adapting the bug comment:
>
> qlit: remove compound literals
>
> A compound literal (i.e., "(struct Str1){1}"), is not a constant
> expression, and so it cannot be used to initialize an object with static
> storage duration.
That's better.
It's weird that a compound literal isn't a constant expression, but
arguing about it here won't make gcc treat it as one.
> $ gcc -c -g -O -Wall compound-lit.c
> compound-lit.c:30:37: error: initializer element is not constant
> .value.qdict = (QLitDictEntry[]){
> ^
> compound-lit.c:30:37: note: (near initialization for
> ‘(anonymous).value’)
>
> clang accepts it. In some cases, gcc accepts compound literals as
> initializer, but not in this nested case. There is a gcc bug about it:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713.
>
> Feel free to adapt on commit
Using this:
qlit: Change compound literals to initializers
The QLIT_QFOO() macros expand into compound literals. Sadly, gcc
doesn't recognizes these as constant expressions (clang does), which
makes the macros useless for initializing objects with static storage
duration.
There is a gcc bug about it:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713
Change the macros to expand into initializers.
Avoids passing judgement on "bug or no bug", and avoids referring to the
compount-lit.c example without actually including it.
I might still add a comment.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper
2017-08-30 12:01 ` Markus Armbruster
2017-08-30 13:54 ` Eric Blake
@ 2017-08-31 13:58 ` Markus Armbruster
1 sibling, 0 replies; 40+ messages in thread
From: Markus Armbruster @ 2017-08-31 13:58 UTC (permalink / raw)
To: Eric Blake
Cc: Marc-André Lureau, qemu-devel, Paolo Bonzini,
Eduardo Habkost, Richard Henderson
Markus Armbruster <armbru@redhat.com> writes:
> Eric Blake <eblake@redhat.com> writes:
>
>> On 08/25/2017 05:59 AM, Marc-André Lureau wrote:
>>> A step towards completeness.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>>> ---
>>> include/qapi/qmp/qdict.h | 4 +++-
>>> target/i386/cpu.c | 4 ++--
>>> 2 files changed, 5 insertions(+), 3 deletions(-)
>>
>> Is it worth touching up scripts/coccinelle/qobject.cocci at the same time?
>
> Let's keep it up-to-date. I can do it when I apply.
Squashing in the appended patch. I verified it produces exactly the
change to target/i386/cpu.c Marc-André did manually, and no others.
diff --git a/scripts/coccinelle/qobject.cocci b/scripts/coccinelle/qobject.cocci
index c518caf7b1..1120eb1a42 100644
--- a/scripts/coccinelle/qobject.cocci
+++ b/scripts/coccinelle/qobject.cocci
@@ -20,6 +20,9 @@ expression Obj, Key, E;
|
- qdict_put(Obj, Key, qstring_from_str(E));
+ qdict_put_str(Obj, Key, E);
+|
+- qdict_put(Obj, Key, qnull());
++ qdict_put_null(Obj, Key);
)
// Use QList macros where they make sense
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison
2017-08-30 12:36 ` Markus Armbruster
@ 2017-08-31 14:20 ` Markus Armbruster
2017-08-31 14:37 ` Marc-André Lureau
0 siblings, 1 reply; 40+ messages in thread
From: Markus Armbruster @ 2017-08-31 14:20 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Markus Armbruster <armbru@redhat.com> writes:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Use QLIST_FOREACH_ENTRY() to simplify the code and break earlier.
>>
>> Check that the QLit list has the same size as the qlist, this should
>> ensure that we have an exact match when iterating over qlist for
>> comparing the elements.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
I'm updating the commit message so it continues to match the previous
commit's message:
qlit: Tighten QLit list vs QList comparison
We check that all members of the QLit list are also in the QList. We
neglect to check the other direction. Fix that.
While there, use QLIST_FOREACH_ENTRY() to simplify the code and break
the loop on the first mismatch.
Hope that's okay with you.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison
2017-08-31 14:20 ` Markus Armbruster
@ 2017-08-31 14:37 ` Marc-André Lureau
0 siblings, 0 replies; 40+ messages in thread
From: Marc-André Lureau @ 2017-08-31 14:37 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
Hi
----- Original Message -----
> Markus Armbruster <armbru@redhat.com> writes:
>
> > Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >
> >> Use QLIST_FOREACH_ENTRY() to simplify the code and break earlier.
> >>
> >> Check that the QLit list has the same size as the qlist, this should
> >> ensure that we have an exact match when iterating over qlist for
> >> comparing the elements.
> >>
> >> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
> I'm updating the commit message so it continues to match the previous
> commit's message:
>
> qlit: Tighten QLit list vs QList comparison
>
> We check that all members of the QLit list are also in the QList. We
> neglect to check the other direction. Fix that.
>
> While there, use QLIST_FOREACH_ENTRY() to simplify the code and break
> the loop on the first mismatch.
>
> Hope that's okay with you.
Works for me, thanks a lot.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-31 8:42 ` Markus Armbruster
2017-08-31 9:14 ` Marc-André Lureau
@ 2017-08-31 15:28 ` Laszlo Ersek
2017-09-01 9:51 ` Markus Armbruster
1 sibling, 1 reply; 40+ messages in thread
From: Laszlo Ersek @ 2017-08-31 15:28 UTC (permalink / raw)
To: Markus Armbruster, Marc-André Lureau; +Cc: qemu-devel, Eric Blake
On 08/31/17 10:42, Markus Armbruster wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Hi
>>
>> ----- Original Message -----
>>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>>
>>>> Hi
>>>>
>>>> ----- Original Message -----
>>>>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>>>>
>>>>>> They are not considered constant expressions in C, producing an error
>>>>>> when compiling a const QLit.
>>>>>
>>>>> A const QLit? Do you mean a non-const one?
>>>>
>>>> Really a const QLitObject:
>>>>
>>>>
>>>> const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>>>> QLIT_QNULL,
>>>> {}
>>>> }));
>>>>
>>>> qmp-introspect.c:17:63: error: initializer element is not constant
>>>> const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>>>> ^
>>>> Removing the "compound literals" fixes this error.
>>>
>>> Does QLIT_QLIST(((const QLitObject[]) { ... } work?
>>
>> No. Even if I put "const" all over the place (in member, in compound type etc).
>>
>> Give it a try, see if you can make it const, I am out of luck.
>
> The commit message's explanation is wrong. This isn't about const at
> all, it's about "constant expressions", which are something else
> entirely.
>
> For what it's worth, clang is cool with the compound literals. On
> Fedora 26 with a minimized test case (appended):
>
> $ clang -c -g -O -Wall compound-lit.c
> $ gcc -c -g -O -Wall compound-lit.c
> compound-lit.c:30:37: error: initializer element is not constant
> .value.qdict = (QLitDictEntry[]){
> ^
> compound-lit.c:30:37: note: (near initialization for ‘(anonymous).value’)
>
> GCC bug or not? A search of the GCC Bugzilla finds
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713
>
> Copying a few notorious language lawyers^W^W^Wtrusted advisers.
>
> Even if this turns out to be a gcc bug, we'll have to work around it.
> But the work-around needs a comment then.
>
> In any case, the commit message needs fixing.
>
>
>
> enum {
> QTYPE_NONE, QTYPE_QSTRING, QTYPE_QDICT,
> };
>
> typedef struct QLitDictEntry QLitDictEntry;
> typedef struct QLitObject QLitObject;
>
> struct QLitObject {
> int type;
> union {
> const char *qstr;
> QLitDictEntry *qdict;
> } value;
> };
>
> struct QLitDictEntry {
> const char *key;
> QLitObject value;
> };
>
> QLitObject qlit1 = (QLitObject){
> .type = QTYPE_QDICT,
> .value.qdict = (QLitDictEntry[]){
> { "foo", {} },
> {}
> }};
>
> QLitObject qlit2 = (QLitObject){
> .type = QTYPE_QDICT,
> .value.qdict = (QLitDictEntry[]){
> { "foo", (QLitObject){} },
> {}
> }};
>
(1) When discussing standards conformance, please drop the {} construct;
it is a GNUism. Replacing it with { 0 } works in all contexts, and
conforms to the standard. (Not trying to be pedantic here, but it does
elicit extra warnings from my gcc command line
gcc -std=c99 -pedantic -Wall -Wextra -fsyntax-only
(2) Let's see what the standard says:
6.5.2.5 Compound literals
Constraints
3 If the compound literal occurs outside the body of a function, the
initializer list shall consist of constant expressions.
In the initialization of "qlit1", one element of the initializer list
(namely for .value.qdict) is
[1] (QLitDictEntry[]) {
{ "foo", { 0 } },
{ 0 }
}
Is this a constant expression?
6.6 Constant expressions
7 More latitude is permitted for constant expressions in initializers.
Such a constant expression shall be, or evaluate to, one of the
following:
- an arithmetic constant expression,
- a null pointer constant,
- an address constant, or
- an address constant for an object type plus or minus an integer
constant expression.
Now, is [1] an address constant?
6.6 Constant expressions
9 An address constant is a null pointer, a pointer to an lvalue
designating an object of static storage duration, or a pointer to a
function designator; it shall be created explicitly using the unary
& operator or an integer constant cast to pointer type, or
implicitly by the use of an expression of array or function type.
The array-subscript [] and member-access . and -> operators, the
address & and indirection * unary operators, and pointer casts may
be used in the creation of an address constant, but the value of an
object shall not be accessed by use of these operators.
"expression of array [...] type" applies; question is:
- is [1] an lvalue designating an object of static storage duration?
6.5.2.5 Compound literals
Semantics
5 If the type name specifies an array of unknown size, the size is
determined by the initializer list as specified in 6.7.8, and the
type of the compound literal is that of the completed array type.
Otherwise (when the type name specifies an object type), the type
of the compound literal is that specified by the type name. In
either case, the result is an lvalue.
So, an lvalue [1] is.
6 The value of the compound literal is that of an unnamed object
initialized by the initializer list. If the compound literal occurs
outside the body of a function, the object has static storage
duration; otherwise, it has automatic storage duration associated
with the enclosing block.
Static storage duration is therefore also proven; the initializer [1]
that we provide for ".value.qdict" *is* a constant expression.
(3) However, on my side at least -- RHEL-7.4 --, the initializer for
".value.qdict" is not what gcc complains about, in the initialization of
"qlit1"!
The problem is the *outer* compound literal. *That* is indeed not a
constant expression; if you review 6.6p7 above, it does not fit any of
the allowed cases.
However, the outer compound literal doesn't buy us anything! If you
change the code like this, it compiles without a hitch:
--- xx.c 2017-08-31 17:23:05.145481557 +0200
+++ yy.c 2017-08-31 17:25:14.839088894 +0200
@@ -18,7 +18,7 @@
QLitObject value;
};
-QLitObject qlit1 = (QLitObject){
+QLitObject qlit1 = {
.type = QTYPE_QDICT,
.value.qdict = (QLitDictEntry[]){
{ "foo", { 0 } },
(I ignored "qlit2" for this discussion.)
Thanks
Laszlo
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals
2017-08-31 15:28 ` Laszlo Ersek
@ 2017-09-01 9:51 ` Markus Armbruster
0 siblings, 0 replies; 40+ messages in thread
From: Markus Armbruster @ 2017-09-01 9:51 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: Marc-André Lureau, qemu-devel
Laszlo Ersek <lersek@redhat.com> writes:
> On 08/31/17 10:42, Markus Armbruster wrote:
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>> Hi
>>>
>>> ----- Original Message -----
>>>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>>>
>>>>> Hi
>>>>>
>>>>> ----- Original Message -----
>>>>>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>>>>>
>>>>>>> They are not considered constant expressions in C, producing an error
>>>>>>> when compiling a const QLit.
>>>>>>
>>>>>> A const QLit? Do you mean a non-const one?
>>>>>
>>>>> Really a const QLitObject:
>>>>>
>>>>>
>>>>> const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>>>>> QLIT_QNULL,
>>>>> {}
>>>>> }));
>>>>>
>>>>> qmp-introspect.c:17:63: error: initializer element is not constant
>>>>> const QLitObject qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
>>>>> ^
>>>>> Removing the "compound literals" fixes this error.
>>>>
>>>> Does QLIT_QLIST(((const QLitObject[]) { ... } work?
>>>
>>> No. Even if I put "const" all over the place (in member, in compound type etc).
>>>
>>> Give it a try, see if you can make it const, I am out of luck.
>>
>> The commit message's explanation is wrong. This isn't about const at
>> all, it's about "constant expressions", which are something else
>> entirely.
>>
>> For what it's worth, clang is cool with the compound literals. On
>> Fedora 26 with a minimized test case (appended):
>>
>> $ clang -c -g -O -Wall compound-lit.c
>> $ gcc -c -g -O -Wall compound-lit.c
>> compound-lit.c:30:37: error: initializer element is not constant
>> .value.qdict = (QLitDictEntry[]){
>> ^
>> compound-lit.c:30:37: note: (near initialization for ‘(anonymous).value’)
>>
>> GCC bug or not? A search of the GCC Bugzilla finds
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713
>>
>> Copying a few notorious language lawyers^W^W^Wtrusted advisers.
>>
>> Even if this turns out to be a gcc bug, we'll have to work around it.
>> But the work-around needs a comment then.
>>
>> In any case, the commit message needs fixing.
>>
>>
>>
>> enum {
>> QTYPE_NONE, QTYPE_QSTRING, QTYPE_QDICT,
>> };
>>
>> typedef struct QLitDictEntry QLitDictEntry;
>> typedef struct QLitObject QLitObject;
>>
>> struct QLitObject {
>> int type;
>> union {
>> const char *qstr;
>> QLitDictEntry *qdict;
>> } value;
>> };
>>
>> struct QLitDictEntry {
>> const char *key;
>> QLitObject value;
>> };
>>
>> QLitObject qlit1 = (QLitObject){
>> .type = QTYPE_QDICT,
>> .value.qdict = (QLitDictEntry[]){
>> { "foo", {} },
>> {}
>> }};
>>
>> QLitObject qlit2 = (QLitObject){
>> .type = QTYPE_QDICT,
>> .value.qdict = (QLitDictEntry[]){
>> { "foo", (QLitObject){} },
>> {}
>> }};
>>
>
> (1) When discussing standards conformance, please drop the {} construct;
> it is a GNUism. Replacing it with { 0 } works in all contexts, and
> conforms to the standard. (Not trying to be pedantic here, but it does
> elicit extra warnings from my gcc command line
>
> gcc -std=c99 -pedantic -Wall -Wextra -fsyntax-only
>
>
> (2) Let's see what the standard says:
>
> 6.5.2.5 Compound literals
> Constraints
> 3 If the compound literal occurs outside the body of a function, the
> initializer list shall consist of constant expressions.
>
> In the initialization of "qlit1", one element of the initializer list
> (namely for .value.qdict) is
>
> [1] (QLitDictEntry[]) {
> { "foo", { 0 } },
> { 0 }
> }
>
> Is this a constant expression?
>
> 6.6 Constant expressions
> 7 More latitude is permitted for constant expressions in initializers.
> Such a constant expression shall be, or evaluate to, one of the
> following:
> - an arithmetic constant expression,
> - a null pointer constant,
> - an address constant, or
> - an address constant for an object type plus or minus an integer
> constant expression.
>
> Now, is [1] an address constant?
>
> 6.6 Constant expressions
> 9 An address constant is a null pointer, a pointer to an lvalue
> designating an object of static storage duration, or a pointer to a
> function designator; it shall be created explicitly using the unary
> & operator or an integer constant cast to pointer type, or
> implicitly by the use of an expression of array or function type.
> The array-subscript [] and member-access . and -> operators, the
> address & and indirection * unary operators, and pointer casts may
> be used in the creation of an address constant, but the value of an
> object shall not be accessed by use of these operators.
>
> "expression of array [...] type" applies; question is:
> - is [1] an lvalue designating an object of static storage duration?
>
> 6.5.2.5 Compound literals
> Semantics
> 5 If the type name specifies an array of unknown size, the size is
> determined by the initializer list as specified in 6.7.8, and the
> type of the compound literal is that of the completed array type.
> Otherwise (when the type name specifies an object type), the type
> of the compound literal is that specified by the type name. In
> either case, the result is an lvalue.
>
> So, an lvalue [1] is.
>
> 6 The value of the compound literal is that of an unnamed object
> initialized by the initializer list. If the compound literal occurs
> outside the body of a function, the object has static storage
> duration; otherwise, it has automatic storage duration associated
> with the enclosing block.
>
> Static storage duration is therefore also proven; the initializer [1]
> that we provide for ".value.qdict" *is* a constant expression.
>
>
> (3) However, on my side at least -- RHEL-7.4 --, the initializer for
> ".value.qdict" is not what gcc complains about, in the initialization of
> "qlit1"!
>
> The problem is the *outer* compound literal. *That* is indeed not a
> constant expression; if you review 6.6p7 above, it does not fit any of
> the allowed cases.
In other words, you can have constant expressions of arithmetic and
pointer type (which includes arrays), but not of struct or union type.
Sad.
> However, the outer compound literal doesn't buy us anything! If you
> change the code like this, it compiles without a hitch:
>
> --- xx.c 2017-08-31 17:23:05.145481557 +0200
> +++ yy.c 2017-08-31 17:25:14.839088894 +0200
> @@ -18,7 +18,7 @@
> QLitObject value;
> };
>
> -QLitObject qlit1 = (QLitObject){
> +QLitObject qlit1 = {
> .type = QTYPE_QDICT,
> .value.qdict = (QLitDictEntry[]){
> { "foo", { 0 } },
>
>
> (I ignored "qlit2" for this discussion.)
Yes.
I figure the original author chose compound literals over traditional
initializers for their nicely explicit typing. Sadly, they turn out to
be useless for initializing struct and union types of static storage
duration. To make the macros usable there, we have to give up the
explicit typing. While that's sad for the C lanaguage, it's no biggie
for us. But I wanted to *understand* what we're doing, so I can fix up
the commit message without making a fool out of myself :)
Thanks for your help, László!
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
` (13 preceding siblings ...)
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 14/14] qapi: generate a literal qobject for introspection Marc-André Lureau
@ 2017-09-01 12:06 ` Markus Armbruster
14 siblings, 0 replies; 40+ messages in thread
From: Markus Armbruster @ 2017-09-01 12:06 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Hi,
>
> This series is based on patches 2-5 from "[PATCH v2 00/54] qapi: add #if
> pre-processor conditions to generated code". Generating a literal qobject
> will allow to easily introduce #if conditionals from the original series.
>
> v2:
> - use QLIST_FOREACH_ENTRY for list comparison
> - update qdict comparison to check for the size instead of doing a
> qdict copy
> - commit message update
> - add r-b tags
>
> Marc-André Lureau (14):
> qdict: add qdict_put_null() helper
> qlit: move qlit from check-qjson to qobject/
> qlit: use QLit prefix consistently
> qlit: remove compound literals
> qlit: rename compare_litqobj_to_qobj() to qlit_equal_qobject()
> qlit: make qlit_equal_qobject return a bool
> qlit: make qlit_equal_qobject() take const arguments
> qlit: add QLIT_QNULL and QLIT_BOOL
> qlit: Replace open-coded qnum_get_int() by call
> tests: add qlit tests
> qlit: improve QLit dict vs qdict comparison
> qlit: improve QLit list vs qlist comparison
> qlit: add qobject_form_qlit()
> qapi: generate a literal qobject for introspection
PATCH 14 makes sense only together with work mentioned in its commit
message. Without PATCH 14, PATCH 13 is left without a user.
Fortunately, PATCH 01-12 make sense on their own: applied to qapi-next.
PATCH 13-14 applied to qapi-not-next, to give you a suitable base for
respins of the remainder of "qapi: add #if pre-processor conditions to
generated code".
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2017-09-01 12:06 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-25 10:58 [Qemu-devel] [PATCH v2 00/14] Generate a literal qobject for introspection Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 01/14] qdict: add qdict_put_null() helper Marc-André Lureau
2017-08-25 12:58 ` Eduardo Habkost
2017-08-25 15:31 ` Eric Blake
2017-08-30 12:01 ` Markus Armbruster
2017-08-30 13:54 ` Eric Blake
2017-08-31 13:58 ` Markus Armbruster
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 02/14] qlit: move qlit from check-qjson to qobject/ Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 03/14] qlit: use QLit prefix consistently Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 04/14] qlit: remove compound literals Marc-André Lureau
2017-08-30 12:00 ` Markus Armbruster
2017-08-30 12:11 ` Marc-André Lureau
2017-08-30 13:02 ` Markus Armbruster
2017-08-30 13:19 ` Marc-André Lureau
2017-08-31 8:42 ` Markus Armbruster
2017-08-31 9:14 ` Marc-André Lureau
2017-08-31 13:50 ` Markus Armbruster
2017-08-31 15:28 ` Laszlo Ersek
2017-09-01 9:51 ` Markus Armbruster
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 05/14] qlit: rename compare_litqobj_to_qobj() to qlit_equal_qobject() Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 06/14] qlit: make qlit_equal_qobject return a bool Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 07/14] qlit: make qlit_equal_qobject() take const arguments Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 08/14] qlit: add QLIT_QNULL and QLIT_BOOL Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 09/14] qlit: Replace open-coded qnum_get_int() by call Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 10/14] tests: add qlit tests Marc-André Lureau
2017-08-30 12:15 ` Markus Armbruster
2017-08-30 12:23 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 11/14] qlit: improve QLit dict vs qdict comparison Marc-André Lureau
2017-08-30 12:35 ` Markus Armbruster
2017-08-30 13:05 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 12/14] qlit: improve QLit list vs qlist comparison Marc-André Lureau
2017-08-30 12:36 ` Markus Armbruster
2017-08-31 14:20 ` Markus Armbruster
2017-08-31 14:37 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 13/14] qlit: add qobject_form_qlit() Marc-André Lureau
2017-08-25 15:35 ` Eric Blake
2017-08-30 12:53 ` Markus Armbruster
2017-08-30 13:00 ` Marc-André Lureau
2017-08-25 10:59 ` [Qemu-devel] [PATCH v2 14/14] qapi: generate a literal qobject for introspection Marc-André Lureau
2017-09-01 12:06 ` [Qemu-devel] [PATCH v2 00/14] Generate " Markus Armbruster
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.