@@ -15,6 +15,7 @@
#define QLIT_H
#include "qobject.h"
+#include "qnum.h"
typedef struct QLitDictEntry QLitDictEntry;
typedef struct QLitObject QLitObject;
@@ -23,7 +24,7 @@ struct QLitObject {
QType type;
union {
bool qbool;
- int64_t qnum;
+ QNumValue qnum;
const char *qstr;
QLitDictEntry *qdict;
QLitObject *qlist;
@@ -39,8 +40,14 @@ struct QLitDictEntry {
{ .type = QTYPE_QNULL }
#define QLIT_QBOOL(val) \
{ .type = QTYPE_QBOOL, .value.qbool = (val) }
+#define QLIT_QNUM_INT(val) \
+ { .type = QTYPE_QNUM, .value.qnum = QNUM_VAL_INT(val) }
+#define QLIT_QNUM_UINT(val) \
+ { .type = QTYPE_QNUM, .value.qnum = QNUM_VAL_UINT(val) }
+#define QLIT_QNUM_DOUBLE(val) \
+ { .type = QTYPE_QNUM, .value.qnum = QNUM_VAL_DOUBLE(val) }
#define QLIT_QNUM(val) \
- { .type = QTYPE_QNUM, .value.qnum = (val) }
+ QLIT_QNUM_INT(val)
#define QLIT_QSTR(val) \
{ .type = QTYPE_QSTRING, .value.qstr = (val) }
#define QLIT_QDICT(val) \
@@ -71,7 +71,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:
- return lhs->value.qnum == qnum_get_int(qobject_to(QNum, rhs));
+ return qnum_value_is_equal(&lhs->value.qnum, qnum_get_value(qobject_to(QNum, rhs)));
case QTYPE_QSTRING:
return (strcmp(lhs->value.qstr,
qstring_get_str(qobject_to(QString, rhs))) == 0);
@@ -94,7 +94,7 @@ QObject *qobject_from_qlit(const QLitObject *qlit)
case QTYPE_QNULL:
return QOBJECT(qnull());
case QTYPE_QNUM:
- return QOBJECT(qnum_from_int(qlit->value.qnum));
+ return QOBJECT(qnum_from_value(qlit->value.qnum));
case QTYPE_QSTRING:
return QOBJECT(qstring_from_str(qlit->value.qstr));
case QTYPE_QDICT: {
@@ -796,20 +796,23 @@ static void simple_number(void)
int i;
struct {
const char *encoded;
+ QLitObject qlit;
int64_t decoded;
int skip;
} test_cases[] = {
- { "0", 0 },
- { "1234", 1234 },
- { "1", 1 },
- { "-32", -32 },
- { "-0", 0, .skip = 1 },
+ { "0", QLIT_QNUM(0), 0, },
+ { "1234", QLIT_QNUM(1234), 1234, },
+ { "1", QLIT_QNUM(1), 1, },
+ { "-32", QLIT_QNUM(-32), -32, },
+ { "-0", QLIT_QNUM(0), 0, .skip = 1 },
{ },
};
for (i = 0; test_cases[i].encoded; i++) {
QNum *qnum;
int64_t val;
+ QNum *qlit_num;
+ int64_t qlit_val;
qnum = qobject_to(QNum,
qobject_from_json(test_cases[i].encoded,
@@ -817,6 +820,7 @@ static void simple_number(void)
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, test_cases[i].decoded);
+
if (test_cases[i].skip == 0) {
QString *str;
@@ -826,9 +830,66 @@ static void simple_number(void)
}
qobject_unref(qnum);
+
+ qlit_num = qobject_to(QNum,
+ qobject_from_qlit(&test_cases[i].qlit));
+ g_assert(qlit_num);
+ g_assert(qnum_get_try_int(qlit_num, &qlit_val));
+ g_assert_cmpint(qlit_val, ==, test_cases[i].decoded);
+
+ qobject_unref(qlit_num);
}
}
+static void qlit_large_number(void)
+{
+ QLitObject maxu64 = QLIT_QNUM_UINT(UINT64_MAX);
+ QLitObject maxi64 = QLIT_QNUM(INT64_MAX);
+ QLitObject mini64 = QLIT_QNUM(INT64_MIN);
+ QLitObject gtu64 = QLIT_QNUM_DOUBLE(18446744073709552e3);
+ QLitObject lti64 = QLIT_QNUM_DOUBLE(-92233720368547758e2);
+ QNum *qnum;
+ uint64_t val;
+ int64_t ival;
+
+ qnum = qobject_to(QNum, qobject_from_qlit(&maxu64));
+ g_assert(qnum);
+ g_assert_cmpuint(qnum_get_uint(qnum), ==, UINT64_MAX);
+ g_assert(!qnum_get_try_int(qnum, &ival));
+
+ qobject_unref(qnum);
+
+ qnum = qobject_to(QNum, qobject_from_qlit(&maxi64));
+ g_assert(qnum);
+ g_assert_cmpuint(qnum_get_uint(qnum), ==, INT64_MAX);
+ g_assert_cmpint(qnum_get_int(qnum), ==, INT64_MAX);
+
+ qobject_unref(qnum);
+
+ qnum = qobject_to(QNum, qobject_from_qlit(&mini64));
+ g_assert(qnum);
+ g_assert(!qnum_get_try_uint(qnum, &val));
+ g_assert_cmpuint(qnum_get_int(qnum), ==, INT64_MIN);
+
+ qobject_unref(qnum);
+
+ qnum = qobject_to(QNum, qobject_from_qlit(>u64));
+ g_assert(qnum);
+ g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
+ g_assert(!qnum_get_try_uint(qnum, &val));
+ g_assert(!qnum_get_try_int(qnum, &ival));
+
+ qobject_unref(qnum);
+
+ qnum = qobject_to(QNum, qobject_from_qlit(<i64));
+ g_assert(qnum);
+ g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
+ g_assert(!qnum_get_try_uint(qnum, &val));
+ g_assert(!qnum_get_try_int(qnum, &ival));
+
+ qobject_unref(qnum);
+}
+
static void large_number(void)
{
const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
@@ -1472,6 +1533,7 @@ int main(int argc, char **argv)
g_test_add_func("/literals/string/utf8", utf8_string);
g_test_add_func("/literals/number/simple", simple_number);
+ g_test_add_func("/literals/number/qlit_large", qlit_large_number);
g_test_add_func("/literals/number/large", large_number);
g_test_add_func("/literals/number/float", float_number);
Use QNumValue to represent QNums, so we can also support uint64_t and double QNum values. Add new QLIT_QNUM_(INT|UINT|DOUBLE) macros for each case. The QLIT_QNUM() macro is being kept for compatibility with existing code, but becomes just a wrapper for QLIT_QNUM_INT(). Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- include/qapi/qmp/qlit.h | 11 +++++-- qobject/qlit.c | 4 +-- tests/check-qjson.c | 72 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 78 insertions(+), 9 deletions(-)