mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 00:45:40 +00:00
qapi: merge QInt and QFloat in QNum
We would like to use a same QObject type to represent numbers, whether they are int, uint, or floats. Getters will allow some compatibility between the various types if the number fits other representations. Add a few more tests while at it. Backports commit 01b2ffcedd94ad7b42bc870e4c6936c87ad03429 from qemu
This commit is contained in:
parent
f1dbfe6be6
commit
dd77730d49
|
@ -34,11 +34,10 @@ void qapi_free_DummyForceArrays(DummyForceArrays *obj)
|
|||
const char *const QType_lookup[] = {
|
||||
"none",
|
||||
"qnull",
|
||||
"qint",
|
||||
"qnum",
|
||||
"qstring",
|
||||
"qdict",
|
||||
"qlist",
|
||||
"qfloat",
|
||||
"qbool",
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -26,13 +26,12 @@
|
|||
typedef enum QType {
|
||||
QTYPE_NONE = 0,
|
||||
QTYPE_QNULL = 1,
|
||||
QTYPE_QINT = 2,
|
||||
QTYPE_QNUM = 2,
|
||||
QTYPE_QSTRING = 3,
|
||||
QTYPE_QDICT = 4,
|
||||
QTYPE_QLIST = 5,
|
||||
QTYPE_QFLOAT = 6,
|
||||
QTYPE_QBOOL = 7,
|
||||
QTYPE__MAX = 8,
|
||||
QTYPE_QBOOL = 6,
|
||||
QTYPE__MAX = 7,
|
||||
} QType;
|
||||
extern const char *const QType_lookup[];
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "unicorn/platform.h"
|
||||
|
||||
|
@ -55,7 +56,7 @@ void qdict_destroy_obj(QObject *obj);
|
|||
|
||||
/* Helpers for int, bool, and string */
|
||||
#define qdict_put_int(qdict, key, value) \
|
||||
qdict_put(qdict, key, qint_from_int(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) \
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* QFloat Module
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QFLOAT_H
|
||||
#define QFLOAT_H
|
||||
|
||||
#include "unicorn/platform.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QFloat {
|
||||
QObject_HEAD;
|
||||
double value;
|
||||
} QFloat;
|
||||
|
||||
QFloat *qfloat_from_double(double value);
|
||||
double qfloat_get_double(const QFloat *qi);
|
||||
QFloat *qobject_to_qfloat(const QObject *obj);
|
||||
void qfloat_destroy_obj(QObject *obj);
|
||||
|
||||
#endif /* QFLOAT_H */
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* QInt Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QINT_H
|
||||
#define QINT_H
|
||||
|
||||
#include "unicorn/platform.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QInt {
|
||||
QObject_HEAD;
|
||||
int64_t value;
|
||||
} QInt;
|
||||
|
||||
QInt *qint_from_int(int64_t value);
|
||||
int64_t qint_get_int(const QInt *qi);
|
||||
QInt *qobject_to_qint(const QObject *obj);
|
||||
void qint_destroy_obj(QObject *obj);
|
||||
|
||||
#endif /* QINT_H */
|
|
@ -14,6 +14,7 @@
|
|||
#define QLIST_H
|
||||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef struct QListEntry {
|
||||
|
@ -31,7 +32,7 @@ typedef struct QList {
|
|||
|
||||
/* Helpers for int, bool, and string */
|
||||
#define qlist_append_int(qlist, value) \
|
||||
qlist_append(qlist, qint_from_int(value))
|
||||
qlist_append(qlist, qnum_from_int(value))
|
||||
#define qlist_append_bool(qlist, value) \
|
||||
qlist_append(qlist, qbool_from_bool(value))
|
||||
#define qlist_append_str(qlist, value) \
|
||||
|
|
46
qemu/include/qapi/qmp/qnum.h
Normal file
46
qemu/include/qapi/qmp/qnum.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* QNum Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
* Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QNUM_H
|
||||
#define QNUM_H
|
||||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef enum {
|
||||
QNUM_I64,
|
||||
QNUM_DOUBLE
|
||||
} QNumKind;
|
||||
|
||||
typedef struct QNum {
|
||||
QObject base;
|
||||
QNumKind kind;
|
||||
union {
|
||||
int64_t i64;
|
||||
double dbl;
|
||||
} u;
|
||||
} QNum;
|
||||
|
||||
QNum *qnum_from_int(int64_t value);
|
||||
QNum *qnum_from_double(double value);
|
||||
|
||||
bool qnum_get_try_int(const QNum *qn, int64_t *val);
|
||||
int64_t qnum_get_int(const QNum *qn);
|
||||
double qnum_get_double(QNum *qn);
|
||||
|
||||
char *qnum_to_string(QNum *qn);
|
||||
|
||||
QNum *qobject_to_qnum(const QObject *obj);
|
||||
void qnum_destroy_obj(QObject *obj);
|
||||
|
||||
#endif /* QNUM_H */
|
|
@ -14,8 +14,7 @@
|
|||
#define QAPI_QMP_TYPES_H
|
||||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qfloat.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
|
|
|
@ -30,9 +30,9 @@ typedef struct QObjectInputVisitor QObjectInputVisitor;
|
|||
* visit_type_FOO() creates an instance of QAPI type FOO. The visited
|
||||
* QObject must match FOO. QDict matches struct/union types, QList
|
||||
* matches list types, QString matches type 'str' and enumeration
|
||||
* types, QInt matches integer types, QFloat matches type 'number',
|
||||
* QBool matches type 'bool'. Type 'any' is matched by QObject. A
|
||||
* QAPI alternate type is matched when one of its member types is.
|
||||
* types, QNum matches integer and float types, QBool matches type
|
||||
* 'bool'. Type 'any' is matched by QObject. A QAPI alternate type
|
||||
* is matched when one of its member types is.
|
||||
*
|
||||
* visit_start_struct() ... visit_end_struct() visits a QDict and
|
||||
* creates a QAPI struct/union. Visits in between visit the
|
||||
|
|
|
@ -28,10 +28,10 @@ typedef struct QObjectOutputVisitor QObjectOutputVisitor;
|
|||
*
|
||||
* visit_type_FOO() creates a QObject for QAPI type FOO. It creates a
|
||||
* QDict for struct/union types, a QList for list types, QString for
|
||||
* type 'str' and enumeration types, QInt for integer types, QFloat
|
||||
* for type 'number', QBool for type 'bool'. For type 'any', it
|
||||
* increments the QObject's reference count. For QAPI alternate
|
||||
* types, it creates the QObject for the member that is in use.
|
||||
* type 'str' and enumeration types, QNum for integer and float
|
||||
* types, QBool for type 'bool'. For type 'any', it increments the
|
||||
* QObject's reference count. For QAPI alternate types, it creates
|
||||
* the QObject for the member that is in use.
|
||||
*
|
||||
* visit_start_struct() ... visit_end_struct() visits a QAPI
|
||||
* struct/union and creates a QDict. Visits in between visit the
|
||||
|
|
|
@ -336,9 +336,6 @@ static void qobject_input_start_alternate(Visitor *v, const char *name,
|
|||
}
|
||||
*obj = g_malloc0(size);
|
||||
(*obj)->type = qobject_type(qobj);
|
||||
if (promote_int && (*obj)->type == QTYPE_QINT) {
|
||||
(*obj)->type = QTYPE_QFLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
|
||||
|
@ -346,40 +343,36 @@ static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
|
|||
{
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QInt *qint;
|
||||
QNum *qnum;
|
||||
|
||||
if (!qobj) {
|
||||
return;
|
||||
}
|
||||
qint = qobject_to_qint(qobj);
|
||||
if (!qint) {
|
||||
qnum = qobject_to_qnum(qobj);
|
||||
if (!qnum || !qnum_get_try_int(qnum, obj)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
|
||||
full_name(qiv, name), "integer");
|
||||
return;
|
||||
}
|
||||
|
||||
*obj = qint_get_int(qint);
|
||||
}
|
||||
|
||||
static void qobject_input_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
/* FIXME: qobject_to_qint mishandles values over INT64_MAX */
|
||||
/* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QInt *qint;
|
||||
QNum *qnum;
|
||||
int64_t val;
|
||||
|
||||
if (!qobj) {
|
||||
return;
|
||||
}
|
||||
qint = qobject_to_qint(qobj);
|
||||
if (!qint) {
|
||||
qnum = qobject_to_qnum(qobj);
|
||||
if (!qnum || !qnum_get_try_int(qnum, &val)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
|
||||
full_name(qiv, name), "integer");
|
||||
return;
|
||||
}
|
||||
|
||||
*obj = qint_get_int(qint);
|
||||
*obj = val;
|
||||
}
|
||||
|
||||
static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
|
||||
|
@ -428,26 +421,19 @@ static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
|
|||
{
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
|
||||
QInt *qint;
|
||||
QFloat *qfloat;
|
||||
QNum *qnum;
|
||||
|
||||
if (!qobj) {
|
||||
return;
|
||||
}
|
||||
qint = qobject_to_qint(qobj);
|
||||
if (qint) {
|
||||
*obj = qint_get_int(qobject_to_qint(qobj));
|
||||
return;
|
||||
}
|
||||
|
||||
qfloat = qobject_to_qfloat(qobj);
|
||||
if (!qfloat) {
|
||||
qnum = qobject_to_qnum(qobj);
|
||||
if (!qnum) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
|
||||
full_name(qiv, name), "number");
|
||||
return;
|
||||
}
|
||||
|
||||
*obj = qfloat_get_double(qobject_to_qfloat(qobj));
|
||||
*obj = qnum_get_double(qnum);
|
||||
}
|
||||
|
||||
static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
|
||||
|
|
|
@ -147,7 +147,7 @@ static void qobject_output_type_int64(Visitor *v, const char *name, int64_t *obj
|
|||
Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add(qov, name, qint_from_int(*obj));
|
||||
qobject_output_add(qov, name, qnum_from_int(*obj));
|
||||
}
|
||||
|
||||
static void qobject_output_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
||||
|
@ -155,7 +155,7 @@ static void qobject_output_type_uint64(Visitor *v, const char *name, uint64_t *o
|
|||
{
|
||||
/* FIXME: QMP outputs values larger than INT64_MAX as negative */
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add(qov, name, qint_from_int(*obj));
|
||||
qobject_output_add(qov, name, qnum_from_int(*obj));
|
||||
}
|
||||
|
||||
static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
|
||||
|
@ -180,7 +180,7 @@ static void qobject_output_type_number(Visitor *v, const char *name, double *obj
|
|||
Error **errp)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
qobject_output_add(qov, name, qfloat_from_double(*obj));
|
||||
qobject_output_add(qov, name, qnum_from_double(*obj));
|
||||
}
|
||||
|
||||
static void qobject_output_type_any(Visitor *v, const char *name, QObject **obj,
|
||||
|
|
|
@ -1 +1 @@
|
|||
util-obj-y = qint.o qnull.o qobject.o qstring.o qdict.o qlist.o qfloat.o qbool.o
|
||||
util-obj-y = qnull.o qobject.o qstring.o qdict.o qlist.o qbool.o qnum.o
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qfloat.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
@ -180,37 +179,26 @@ size_t qdict_size(const QDict *qdict)
|
|||
/**
|
||||
* qdict_get_double(): Get an number mapped by 'key'
|
||||
*
|
||||
* This function assumes that 'key' exists and it stores a
|
||||
* QFloat or QInt object.
|
||||
* This function assumes that 'key' exists and it stores a QNum.
|
||||
*
|
||||
* Return number mapped by 'key'.
|
||||
*/
|
||||
double qdict_get_double(const QDict *qdict, const char *key)
|
||||
{
|
||||
QObject *obj = qdict_get(qdict, key);
|
||||
|
||||
assert(obj);
|
||||
switch (qobject_type(obj)) {
|
||||
case QTYPE_QFLOAT:
|
||||
return qfloat_get_double(qobject_to_qfloat(obj));
|
||||
case QTYPE_QINT:
|
||||
return (double)qint_get_int(qobject_to_qint(obj));
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return qnum_get_double(qobject_to_qnum(qdict_get(qdict, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* qdict_get_int(): Get an integer mapped by 'key'
|
||||
*
|
||||
* This function assumes that 'key' exists and it stores a
|
||||
* QInt object.
|
||||
* QNum representable as int.
|
||||
*
|
||||
* Return integer mapped by 'key'.
|
||||
*/
|
||||
int64_t qdict_get_int(const QDict *qdict, const char *key)
|
||||
{
|
||||
return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
|
||||
return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,16 +247,21 @@ const char *qdict_get_str(const QDict *qdict, const char *key)
|
|||
/**
|
||||
* qdict_get_try_int(): Try to get integer mapped by 'key'
|
||||
*
|
||||
* Return integer mapped by 'key', if it is not present in
|
||||
* the dictionary or if the stored object is not of QInt type
|
||||
* 'def_value' will be returned.
|
||||
* Return integer mapped by 'key', if it is not present in the
|
||||
* dictionary or if the stored object is not a QNum representing an
|
||||
* integer, 'def_value' will be returned.
|
||||
*/
|
||||
int64_t qdict_get_try_int(const QDict *qdict, const char *key,
|
||||
int64_t def_value)
|
||||
{
|
||||
QInt *qint = qobject_to_qint(qdict_get(qdict, key));
|
||||
QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
|
||||
int64_t val;
|
||||
|
||||
return qint ? qint_get_int(qint) : def_value;
|
||||
if (!qnum || !qnum_get_try_int(qnum, &val)) {
|
||||
return def_value;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* QFloat Module
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qfloat.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/**
|
||||
* qfloat_from_int(): Create a new QFloat from a float
|
||||
*
|
||||
* Return strong reference.
|
||||
*/
|
||||
QFloat *qfloat_from_double(double value)
|
||||
{
|
||||
QFloat *qf;
|
||||
|
||||
qf = g_malloc(sizeof(*qf));
|
||||
qobject_init(QOBJECT(qf), QTYPE_QFLOAT);
|
||||
qf->value = value;
|
||||
|
||||
return qf;
|
||||
}
|
||||
|
||||
/**
|
||||
* qfloat_get_double(): Get the stored float
|
||||
*/
|
||||
double qfloat_get_double(const QFloat *qf)
|
||||
{
|
||||
return qf->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_to_qfloat(): Convert a QObject into a QFloat
|
||||
*/
|
||||
QFloat *qobject_to_qfloat(const QObject *obj)
|
||||
{
|
||||
if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
|
||||
return NULL;
|
||||
}
|
||||
return container_of(obj, QFloat, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* qfloat_destroy_obj(): Free all memory allocated by a
|
||||
* QFloat object
|
||||
*/
|
||||
void qfloat_destroy_obj(QObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
g_free(qobject_to_qfloat(obj));
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* QInt Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/**
|
||||
* qint_from_int(): Create a new QInt from an int64_t
|
||||
*
|
||||
* Return strong reference.
|
||||
*/
|
||||
QInt *qint_from_int(int64_t value)
|
||||
{
|
||||
QInt *qi;
|
||||
|
||||
qi = g_malloc(sizeof(*qi));
|
||||
qobject_init(QOBJECT(qi), QTYPE_QINT);
|
||||
qi->value = value;
|
||||
|
||||
return qi;
|
||||
}
|
||||
|
||||
/**
|
||||
* qint_get_int(): Get the stored integer
|
||||
*/
|
||||
int64_t qint_get_int(const QInt *qi)
|
||||
{
|
||||
return qi->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_to_qint(): Convert a QObject into a QInt
|
||||
*/
|
||||
QInt *qobject_to_qint(const QObject *obj)
|
||||
{
|
||||
if (!obj || qobject_type(obj) != QTYPE_QINT) {
|
||||
return NULL;
|
||||
}
|
||||
return container_of(obj, QInt, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* qint_destroy_obj(): Free all memory allocated by a
|
||||
* QInt object
|
||||
*/
|
||||
void qint_destroy_obj(QObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
g_free(qobject_to_qint(obj));
|
||||
}
|
159
qemu/qobject/qnum.c
Normal file
159
qemu/qobject/qnum.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* QNum Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
* Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/**
|
||||
* qnum_from_int(): Create a new QNum from an int64_t
|
||||
*
|
||||
* Return strong reference.
|
||||
*/
|
||||
QNum *qnum_from_int(int64_t value)
|
||||
{
|
||||
QNum *qn = g_new(QNum, 1);
|
||||
|
||||
qobject_init(QOBJECT(qn), QTYPE_QNUM);
|
||||
qn->kind = QNUM_I64;
|
||||
qn->u.i64 = value;
|
||||
|
||||
return qn;
|
||||
}
|
||||
|
||||
/**
|
||||
* qnum_from_double(): Create a new QNum from a double
|
||||
*
|
||||
* Return strong reference.
|
||||
*/
|
||||
QNum *qnum_from_double(double value)
|
||||
{
|
||||
QNum *qn = g_new(QNum, 1);
|
||||
|
||||
qobject_init(QOBJECT(qn), QTYPE_QNUM);
|
||||
qn->kind = QNUM_DOUBLE;
|
||||
qn->u.dbl = value;
|
||||
|
||||
return qn;
|
||||
}
|
||||
|
||||
/**
|
||||
* qnum_get_try_int(): Get an integer representation of the number
|
||||
*
|
||||
* Return true on success.
|
||||
*/
|
||||
bool qnum_get_try_int(const QNum *qn, int64_t *val)
|
||||
{
|
||||
switch (qn->kind) {
|
||||
case QNUM_I64:
|
||||
*val = qn->u.i64;
|
||||
return true;
|
||||
case QNUM_DOUBLE:
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* qnum_get_int(): Get an integer representation of the number
|
||||
*
|
||||
* assert() on failure.
|
||||
*/
|
||||
int64_t qnum_get_int(const QNum *qn)
|
||||
{
|
||||
int64_t val;
|
||||
bool success = qnum_get_try_int(qn, &val);
|
||||
assert(success);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* qnum_get_double(): Get a float representation of the number
|
||||
*
|
||||
* qnum_get_double() loses precision for integers beyond 53 bits.
|
||||
*/
|
||||
double qnum_get_double(QNum *qn)
|
||||
{
|
||||
switch (qn->kind) {
|
||||
case QNUM_I64:
|
||||
return qn->u.i64;
|
||||
case QNUM_DOUBLE:
|
||||
return qn->u.dbl;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
char *qnum_to_string(QNum *qn)
|
||||
{
|
||||
char *buffer;
|
||||
int len;
|
||||
|
||||
switch (qn->kind) {
|
||||
case QNUM_I64:
|
||||
return g_strdup_printf("%" PRId64, qn->u.i64);
|
||||
case QNUM_DOUBLE:
|
||||
/* FIXME: snprintf() is locale dependent; but JSON requires
|
||||
* numbers to be formatted as if in the C locale. Dependence
|
||||
* on C locale is a pervasive issue in QEMU. */
|
||||
/* FIXME: This risks printing Inf or NaN, which are not valid
|
||||
* JSON values. */
|
||||
/* FIXME: the default precision of 6 for %f often causes
|
||||
* rounding errors; we should be using DBL_DECIMAL_DIG (17),
|
||||
* and only rounding to a shorter number if the result would
|
||||
* still produce the same floating point value. */
|
||||
buffer = g_strdup_printf("%f" , qn->u.dbl);
|
||||
len = strlen(buffer);
|
||||
while (len > 0 && buffer[len - 1] == '0') {
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len && buffer[len - 1] == '.') {
|
||||
buffer[len - 1] = 0;
|
||||
} else {
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_to_qnum(): Convert a QObject into a QNum
|
||||
*/
|
||||
QNum *qobject_to_qnum(const QObject *obj)
|
||||
{
|
||||
if (!obj || qobject_type(obj) != QTYPE_QNUM) {
|
||||
return NULL;
|
||||
}
|
||||
return container_of(obj, QNum, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* qnum_destroy_obj(): Free all memory allocated by a
|
||||
* QNum object
|
||||
*/
|
||||
void qnum_destroy_obj(QObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
g_free(qobject_to_qnum(obj));
|
||||
}
|
|
@ -10,19 +10,16 @@
|
|||
#include "qemu-common.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qfloat.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
static void (*qdestroy[QTYPE__MAX])(QObject *) = {
|
||||
NULL, /* No such object exists */
|
||||
NULL, /* qnull_ is indestructible */
|
||||
qint_destroy_obj,
|
||||
qnum_destroy_obj,
|
||||
qstring_destroy_obj,
|
||||
qdict_destroy_obj,
|
||||
qlist_destroy_obj,
|
||||
qfloat_destroy_obj,
|
||||
qbool_destroy_obj,
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "qom/qom-qobject.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
#include "uc_priv.h"
|
||||
|
@ -1062,38 +1062,37 @@ bool object_property_get_bool(struct uc_struct *uc, Object *obj, const char *nam
|
|||
retval = qbool_get_bool(qbool);
|
||||
}
|
||||
|
||||
QDECREF(qbool);
|
||||
qobject_decref(ret);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void object_property_set_int(struct uc_struct *uc, Object *obj, int64_t value,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
QInt *qint = qint_from_int(value);
|
||||
object_property_set_qobject(uc, obj, QOBJECT(qint), name, errp);
|
||||
QNum *qnum = qnum_from_int(value);
|
||||
object_property_set_qobject(uc, obj, QOBJECT(qnum), name, errp);
|
||||
|
||||
QDECREF(qint);
|
||||
QDECREF(qnum);
|
||||
}
|
||||
|
||||
int64_t object_property_get_int(struct uc_struct *uc, Object *obj, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
QObject *ret = object_property_get_qobject(uc, obj, name, errp);
|
||||
QInt *qint;
|
||||
QNum *qnum;
|
||||
int64_t retval;
|
||||
|
||||
if (!ret) {
|
||||
return -1;
|
||||
}
|
||||
qint = qobject_to_qint(ret);
|
||||
if (!qint) {
|
||||
|
||||
qnum = qobject_to_qnum(ret);
|
||||
if (!qnum || !qnum_get_try_int(qnum, &retval)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
|
||||
retval = -1;
|
||||
} else {
|
||||
retval = qint_get_int(qint);
|
||||
}
|
||||
|
||||
QDECREF(qint);
|
||||
qobject_decref(ret);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ def gen_visit_alternate(name, variants):
|
|||
ret = ''
|
||||
promote_int = 'true'
|
||||
for var in variants.variants:
|
||||
if var.type.alternate_qtype() == 'QTYPE_QINT':
|
||||
if var.type.alternate_qtype() == 'QTYPE_QNUM':
|
||||
promote_int = 'false'
|
||||
|
||||
ret += mcgen('''
|
||||
|
|
|
@ -21,18 +21,18 @@ import string
|
|||
|
||||
builtin_types = {
|
||||
'str': 'QTYPE_QSTRING',
|
||||
'int': 'QTYPE_QINT',
|
||||
'number': 'QTYPE_QFLOAT',
|
||||
'int': 'QTYPE_QNUM',
|
||||
'number': 'QTYPE_QNUM',
|
||||
'bool': 'QTYPE_QBOOL',
|
||||
'int8': 'QTYPE_QINT',
|
||||
'int16': 'QTYPE_QINT',
|
||||
'int32': 'QTYPE_QINT',
|
||||
'int64': 'QTYPE_QINT',
|
||||
'uint8': 'QTYPE_QINT',
|
||||
'uint16': 'QTYPE_QINT',
|
||||
'uint32': 'QTYPE_QINT',
|
||||
'uint64': 'QTYPE_QINT',
|
||||
'size': 'QTYPE_QINT',
|
||||
'int8': 'QTYPE_QNUM',
|
||||
'int16': 'QTYPE_QNUM',
|
||||
'int32': 'QTYPE_QNUM',
|
||||
'int64': 'QTYPE_QNUM',
|
||||
'uint8': 'QTYPE_QNUM',
|
||||
'uint16': 'QTYPE_QNUM',
|
||||
'uint32': 'QTYPE_QNUM',
|
||||
'uint64': 'QTYPE_QNUM',
|
||||
'size': 'QTYPE_QNUM',
|
||||
'any': None, # any QType possible, actually
|
||||
'QType': 'QTYPE_QSTRING',
|
||||
}
|
||||
|
@ -870,8 +870,8 @@ class QAPISchemaType(QAPISchemaEntity):
|
|||
def alternate_qtype(self):
|
||||
json2qtype = {
|
||||
'string': 'QTYPE_QSTRING',
|
||||
'number': 'QTYPE_QFLOAT',
|
||||
'int': 'QTYPE_QINT',
|
||||
'number': 'QTYPE_QNUM',
|
||||
'int': 'QTYPE_QNUM',
|
||||
'boolean': 'QTYPE_QBOOL',
|
||||
'object': 'QTYPE_QDICT'
|
||||
}
|
||||
|
@ -1319,9 +1319,9 @@ class QAPISchema(object):
|
|||
self.the_empty_object_type = QAPISchemaObjectType('q_empty', None,
|
||||
None, [], None)
|
||||
self._def_entity(self.the_empty_object_type)
|
||||
qtype_values = self._make_enum_members(['none', 'qnull', 'qint',
|
||||
qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
|
||||
'qstring', 'qdict', 'qlist',
|
||||
'qfloat', 'qbool'])
|
||||
'qbool'])
|
||||
self._def_entity(QAPISchemaEnumType('QType', None, qtype_values,
|
||||
'QTYPE'))
|
||||
|
||||
|
|
Loading…
Reference in a new issue