101b2ffceSMarc-André Lureau /*
201b2ffceSMarc-André Lureau * QNum Module
301b2ffceSMarc-André Lureau *
401b2ffceSMarc-André Lureau * Copyright (C) 2009 Red Hat Inc.
501b2ffceSMarc-André Lureau *
601b2ffceSMarc-André Lureau * Authors:
701b2ffceSMarc-André Lureau * Luiz Capitulino <lcapitulino@redhat.com>
801b2ffceSMarc-André Lureau * Anthony Liguori <aliguori@us.ibm.com>
901b2ffceSMarc-André Lureau * Marc-André Lureau <marcandre.lureau@redhat.com>
1001b2ffceSMarc-André Lureau *
1101b2ffceSMarc-André Lureau * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
1201b2ffceSMarc-André Lureau * See the COPYING.LIB file in the top-level directory.
1301b2ffceSMarc-André Lureau */
1401b2ffceSMarc-André Lureau
1501b2ffceSMarc-André Lureau #include "qemu/osdep.h"
1601b2ffceSMarc-André Lureau #include "qapi/qmp/qnum.h"
1780d71121SMarkus Armbruster #include "qobject-internal.h"
1801b2ffceSMarc-André Lureau
1901b2ffceSMarc-André Lureau /**
2001b2ffceSMarc-André Lureau * qnum_from_int(): Create a new QNum from an int64_t
2101b2ffceSMarc-André Lureau *
2201b2ffceSMarc-André Lureau * Return strong reference.
2301b2ffceSMarc-André Lureau */
qnum_from_int(int64_t value)2401b2ffceSMarc-André Lureau QNum *qnum_from_int(int64_t value)
2501b2ffceSMarc-André Lureau {
2601b2ffceSMarc-André Lureau QNum *qn = g_new(QNum, 1);
2701b2ffceSMarc-André Lureau
2801b2ffceSMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM);
2901b2ffceSMarc-André Lureau qn->kind = QNUM_I64;
3001b2ffceSMarc-André Lureau qn->u.i64 = value;
3101b2ffceSMarc-André Lureau
3201b2ffceSMarc-André Lureau return qn;
3301b2ffceSMarc-André Lureau }
3401b2ffceSMarc-André Lureau
3501b2ffceSMarc-André Lureau /**
3661a8f418SMarc-André Lureau * qnum_from_uint(): Create a new QNum from an uint64_t
3761a8f418SMarc-André Lureau *
3861a8f418SMarc-André Lureau * Return strong reference.
3961a8f418SMarc-André Lureau */
qnum_from_uint(uint64_t value)4061a8f418SMarc-André Lureau QNum *qnum_from_uint(uint64_t value)
4161a8f418SMarc-André Lureau {
4261a8f418SMarc-André Lureau QNum *qn = g_new(QNum, 1);
4361a8f418SMarc-André Lureau
4461a8f418SMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM);
4561a8f418SMarc-André Lureau qn->kind = QNUM_U64;
4661a8f418SMarc-André Lureau qn->u.u64 = value;
4761a8f418SMarc-André Lureau
4861a8f418SMarc-André Lureau return qn;
4961a8f418SMarc-André Lureau }
5061a8f418SMarc-André Lureau
5161a8f418SMarc-André Lureau /**
5201b2ffceSMarc-André Lureau * qnum_from_double(): Create a new QNum from a double
5301b2ffceSMarc-André Lureau *
5401b2ffceSMarc-André Lureau * Return strong reference.
5501b2ffceSMarc-André Lureau */
qnum_from_double(double value)5601b2ffceSMarc-André Lureau QNum *qnum_from_double(double value)
5701b2ffceSMarc-André Lureau {
5801b2ffceSMarc-André Lureau QNum *qn = g_new(QNum, 1);
5901b2ffceSMarc-André Lureau
6001b2ffceSMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM);
6101b2ffceSMarc-André Lureau qn->kind = QNUM_DOUBLE;
6201b2ffceSMarc-André Lureau qn->u.dbl = value;
6301b2ffceSMarc-André Lureau
6401b2ffceSMarc-André Lureau return qn;
6501b2ffceSMarc-André Lureau }
6601b2ffceSMarc-André Lureau
6701b2ffceSMarc-André Lureau /**
6801b2ffceSMarc-André Lureau * qnum_get_try_int(): Get an integer representation of the number
6901b2ffceSMarc-André Lureau *
7001b2ffceSMarc-André Lureau * Return true on success.
7101b2ffceSMarc-André Lureau */
qnum_get_try_int(const QNum * qn,int64_t * val)7201b2ffceSMarc-André Lureau bool qnum_get_try_int(const QNum *qn, int64_t *val)
7301b2ffceSMarc-André Lureau {
7401b2ffceSMarc-André Lureau switch (qn->kind) {
7501b2ffceSMarc-André Lureau case QNUM_I64:
7601b2ffceSMarc-André Lureau *val = qn->u.i64;
7701b2ffceSMarc-André Lureau return true;
7861a8f418SMarc-André Lureau case QNUM_U64:
7961a8f418SMarc-André Lureau if (qn->u.u64 > INT64_MAX) {
8061a8f418SMarc-André Lureau return false;
8161a8f418SMarc-André Lureau }
8261a8f418SMarc-André Lureau *val = qn->u.u64;
8361a8f418SMarc-André Lureau return true;
8401b2ffceSMarc-André Lureau case QNUM_DOUBLE:
8501b2ffceSMarc-André Lureau return false;
8601b2ffceSMarc-André Lureau }
8701b2ffceSMarc-André Lureau
88*890000ddSPierrick Bouvier g_assert_not_reached();
8901b2ffceSMarc-André Lureau }
9001b2ffceSMarc-André Lureau
9101b2ffceSMarc-André Lureau /**
9201b2ffceSMarc-André Lureau * qnum_get_int(): Get an integer representation of the number
9301b2ffceSMarc-André Lureau *
9401b2ffceSMarc-André Lureau * assert() on failure.
9501b2ffceSMarc-André Lureau */
qnum_get_int(const QNum * qn)9601b2ffceSMarc-André Lureau int64_t qnum_get_int(const QNum *qn)
9701b2ffceSMarc-André Lureau {
9801b2ffceSMarc-André Lureau int64_t val;
9901b2ffceSMarc-André Lureau bool success = qnum_get_try_int(qn, &val);
10001b2ffceSMarc-André Lureau assert(success);
10101b2ffceSMarc-André Lureau return val;
10201b2ffceSMarc-André Lureau }
10301b2ffceSMarc-André Lureau
10401b2ffceSMarc-André Lureau /**
10561a8f418SMarc-André Lureau * qnum_get_uint(): Get an unsigned integer from the number
10661a8f418SMarc-André Lureau *
10761a8f418SMarc-André Lureau * Return true on success.
10861a8f418SMarc-André Lureau */
qnum_get_try_uint(const QNum * qn,uint64_t * val)10961a8f418SMarc-André Lureau bool qnum_get_try_uint(const QNum *qn, uint64_t *val)
11061a8f418SMarc-André Lureau {
11161a8f418SMarc-André Lureau switch (qn->kind) {
11261a8f418SMarc-André Lureau case QNUM_I64:
11361a8f418SMarc-André Lureau if (qn->u.i64 < 0) {
11461a8f418SMarc-André Lureau return false;
11561a8f418SMarc-André Lureau }
11661a8f418SMarc-André Lureau *val = qn->u.i64;
11761a8f418SMarc-André Lureau return true;
11861a8f418SMarc-André Lureau case QNUM_U64:
11961a8f418SMarc-André Lureau *val = qn->u.u64;
12061a8f418SMarc-André Lureau return true;
12161a8f418SMarc-André Lureau case QNUM_DOUBLE:
12261a8f418SMarc-André Lureau return false;
12361a8f418SMarc-André Lureau }
12461a8f418SMarc-André Lureau
125*890000ddSPierrick Bouvier g_assert_not_reached();
12661a8f418SMarc-André Lureau }
12761a8f418SMarc-André Lureau
12861a8f418SMarc-André Lureau /**
12961a8f418SMarc-André Lureau * qnum_get_uint(): Get an unsigned integer from the number
13061a8f418SMarc-André Lureau *
13161a8f418SMarc-André Lureau * assert() on failure.
13261a8f418SMarc-André Lureau */
qnum_get_uint(const QNum * qn)13361a8f418SMarc-André Lureau uint64_t qnum_get_uint(const QNum *qn)
13461a8f418SMarc-André Lureau {
13561a8f418SMarc-André Lureau uint64_t val;
13661a8f418SMarc-André Lureau bool success = qnum_get_try_uint(qn, &val);
13761a8f418SMarc-André Lureau assert(success);
13861a8f418SMarc-André Lureau return val;
13961a8f418SMarc-André Lureau }
14061a8f418SMarc-André Lureau
14161a8f418SMarc-André Lureau /**
14201b2ffceSMarc-André Lureau * qnum_get_double(): Get a float representation of the number
14301b2ffceSMarc-André Lureau *
14401b2ffceSMarc-André Lureau * qnum_get_double() loses precision for integers beyond 53 bits.
14501b2ffceSMarc-André Lureau */
qnum_get_double(QNum * qn)14601b2ffceSMarc-André Lureau double qnum_get_double(QNum *qn)
14701b2ffceSMarc-André Lureau {
14801b2ffceSMarc-André Lureau switch (qn->kind) {
14901b2ffceSMarc-André Lureau case QNUM_I64:
15001b2ffceSMarc-André Lureau return qn->u.i64;
15161a8f418SMarc-André Lureau case QNUM_U64:
15261a8f418SMarc-André Lureau return qn->u.u64;
15301b2ffceSMarc-André Lureau case QNUM_DOUBLE:
15401b2ffceSMarc-André Lureau return qn->u.dbl;
15501b2ffceSMarc-André Lureau }
15601b2ffceSMarc-André Lureau
157*890000ddSPierrick Bouvier g_assert_not_reached();
15801b2ffceSMarc-André Lureau }
15901b2ffceSMarc-André Lureau
qnum_to_string(QNum * qn)16001b2ffceSMarc-André Lureau char *qnum_to_string(QNum *qn)
16101b2ffceSMarc-André Lureau {
16201b2ffceSMarc-André Lureau switch (qn->kind) {
16301b2ffceSMarc-André Lureau case QNUM_I64:
16401b2ffceSMarc-André Lureau return g_strdup_printf("%" PRId64, qn->u.i64);
16561a8f418SMarc-André Lureau case QNUM_U64:
16661a8f418SMarc-André Lureau return g_strdup_printf("%" PRIu64, qn->u.u64);
16701b2ffceSMarc-André Lureau case QNUM_DOUBLE:
168f917eed3SMarkus Armbruster /* 17 digits suffice for IEEE double */
169f917eed3SMarkus Armbruster return g_strdup_printf("%.17g", qn->u.dbl);
17001b2ffceSMarc-André Lureau }
17101b2ffceSMarc-André Lureau
172*890000ddSPierrick Bouvier g_assert_not_reached();
17301b2ffceSMarc-André Lureau }
17401b2ffceSMarc-André Lureau
17501b2ffceSMarc-André Lureau /**
176b38dd678SMax Reitz * qnum_is_equal(): Test whether the two QNums are equal
177b38dd678SMax Reitz *
178b38dd678SMax Reitz * Negative integers are never considered equal to unsigned integers,
179b38dd678SMax Reitz * but positive integers in the range [0, INT64_MAX] are considered
180b38dd678SMax Reitz * equal independently of whether the QNum's kind is i64 or u64.
181b38dd678SMax Reitz *
182b38dd678SMax Reitz * Doubles are never considered equal to integers.
183b38dd678SMax Reitz */
qnum_is_equal(const QObject * x,const QObject * y)184b38dd678SMax Reitz bool qnum_is_equal(const QObject *x, const QObject *y)
185b38dd678SMax Reitz {
1867dc847ebSMax Reitz QNum *num_x = qobject_to(QNum, x);
1877dc847ebSMax Reitz QNum *num_y = qobject_to(QNum, y);
188b38dd678SMax Reitz
189b38dd678SMax Reitz switch (num_x->kind) {
190b38dd678SMax Reitz case QNUM_I64:
191b38dd678SMax Reitz switch (num_y->kind) {
192b38dd678SMax Reitz case QNUM_I64:
193b38dd678SMax Reitz /* Comparison in native int64_t type */
194b38dd678SMax Reitz return num_x->u.i64 == num_y->u.i64;
195b38dd678SMax Reitz case QNUM_U64:
196b38dd678SMax Reitz /* Implicit conversion of x to uin64_t, so we have to
197b38dd678SMax Reitz * check its sign before */
198b38dd678SMax Reitz return num_x->u.i64 >= 0 && num_x->u.i64 == num_y->u.u64;
199b38dd678SMax Reitz case QNUM_DOUBLE:
200b38dd678SMax Reitz return false;
201b38dd678SMax Reitz }
202b38dd678SMax Reitz abort();
203b38dd678SMax Reitz case QNUM_U64:
204b38dd678SMax Reitz switch (num_y->kind) {
205b38dd678SMax Reitz case QNUM_I64:
206b38dd678SMax Reitz return qnum_is_equal(y, x);
207b38dd678SMax Reitz case QNUM_U64:
208b38dd678SMax Reitz /* Comparison in native uint64_t type */
209b38dd678SMax Reitz return num_x->u.u64 == num_y->u.u64;
210b38dd678SMax Reitz case QNUM_DOUBLE:
211b38dd678SMax Reitz return false;
212b38dd678SMax Reitz }
213b38dd678SMax Reitz abort();
214b38dd678SMax Reitz case QNUM_DOUBLE:
215b38dd678SMax Reitz switch (num_y->kind) {
216b38dd678SMax Reitz case QNUM_I64:
217b38dd678SMax Reitz case QNUM_U64:
218b38dd678SMax Reitz return false;
219b38dd678SMax Reitz case QNUM_DOUBLE:
220b38dd678SMax Reitz /* Comparison in native double type */
221b38dd678SMax Reitz return num_x->u.dbl == num_y->u.dbl;
222b38dd678SMax Reitz }
223b38dd678SMax Reitz abort();
224b38dd678SMax Reitz }
225b38dd678SMax Reitz
226b38dd678SMax Reitz abort();
227b38dd678SMax Reitz }
228b38dd678SMax Reitz
229b38dd678SMax Reitz /**
23001b2ffceSMarc-André Lureau * qnum_destroy_obj(): Free all memory allocated by a
23101b2ffceSMarc-André Lureau * QNum object
23201b2ffceSMarc-André Lureau */
qnum_destroy_obj(QObject * obj)23301b2ffceSMarc-André Lureau void qnum_destroy_obj(QObject *obj)
23401b2ffceSMarc-André Lureau {
23501b2ffceSMarc-André Lureau assert(obj != NULL);
2367dc847ebSMax Reitz g_free(qobject_to(QNum, obj));
23701b2ffceSMarc-André Lureau }
238d709bbf3SMarc-André Lureau
qnum_unref(QNum * q)239d709bbf3SMarc-André Lureau void qnum_unref(QNum *q)
240d709bbf3SMarc-André Lureau {
241d709bbf3SMarc-André Lureau qobject_unref(q);
242d709bbf3SMarc-André Lureau }
243