xref: /qemu/qobject/qnum.c (revision f917eed3069640f6fa15f07cc5a61ecf4270e6a3)
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"
1701b2ffceSMarc-André Lureau 
1801b2ffceSMarc-André Lureau /**
1901b2ffceSMarc-André Lureau  * qnum_from_int(): Create a new QNum from an int64_t
2001b2ffceSMarc-André Lureau  *
2101b2ffceSMarc-André Lureau  * Return strong reference.
2201b2ffceSMarc-André Lureau  */
2301b2ffceSMarc-André Lureau QNum *qnum_from_int(int64_t value)
2401b2ffceSMarc-André Lureau {
2501b2ffceSMarc-André Lureau     QNum *qn = g_new(QNum, 1);
2601b2ffceSMarc-André Lureau 
2701b2ffceSMarc-André Lureau     qobject_init(QOBJECT(qn), QTYPE_QNUM);
2801b2ffceSMarc-André Lureau     qn->kind = QNUM_I64;
2901b2ffceSMarc-André Lureau     qn->u.i64 = value;
3001b2ffceSMarc-André Lureau 
3101b2ffceSMarc-André Lureau     return qn;
3201b2ffceSMarc-André Lureau }
3301b2ffceSMarc-André Lureau 
3401b2ffceSMarc-André Lureau /**
3561a8f418SMarc-André Lureau  * qnum_from_uint(): Create a new QNum from an uint64_t
3661a8f418SMarc-André Lureau  *
3761a8f418SMarc-André Lureau  * Return strong reference.
3861a8f418SMarc-André Lureau  */
3961a8f418SMarc-André Lureau QNum *qnum_from_uint(uint64_t value)
4061a8f418SMarc-André Lureau {
4161a8f418SMarc-André Lureau     QNum *qn = g_new(QNum, 1);
4261a8f418SMarc-André Lureau 
4361a8f418SMarc-André Lureau     qobject_init(QOBJECT(qn), QTYPE_QNUM);
4461a8f418SMarc-André Lureau     qn->kind = QNUM_U64;
4561a8f418SMarc-André Lureau     qn->u.u64 = value;
4661a8f418SMarc-André Lureau 
4761a8f418SMarc-André Lureau     return qn;
4861a8f418SMarc-André Lureau }
4961a8f418SMarc-André Lureau 
5061a8f418SMarc-André Lureau /**
5101b2ffceSMarc-André Lureau  * qnum_from_double(): Create a new QNum from a double
5201b2ffceSMarc-André Lureau  *
5301b2ffceSMarc-André Lureau  * Return strong reference.
5401b2ffceSMarc-André Lureau  */
5501b2ffceSMarc-André Lureau QNum *qnum_from_double(double value)
5601b2ffceSMarc-André Lureau {
5701b2ffceSMarc-André Lureau     QNum *qn = g_new(QNum, 1);
5801b2ffceSMarc-André Lureau 
5901b2ffceSMarc-André Lureau     qobject_init(QOBJECT(qn), QTYPE_QNUM);
6001b2ffceSMarc-André Lureau     qn->kind = QNUM_DOUBLE;
6101b2ffceSMarc-André Lureau     qn->u.dbl = value;
6201b2ffceSMarc-André Lureau 
6301b2ffceSMarc-André Lureau     return qn;
6401b2ffceSMarc-André Lureau }
6501b2ffceSMarc-André Lureau 
6601b2ffceSMarc-André Lureau /**
6701b2ffceSMarc-André Lureau  * qnum_get_try_int(): Get an integer representation of the number
6801b2ffceSMarc-André Lureau  *
6901b2ffceSMarc-André Lureau  * Return true on success.
7001b2ffceSMarc-André Lureau  */
7101b2ffceSMarc-André Lureau bool qnum_get_try_int(const QNum *qn, int64_t *val)
7201b2ffceSMarc-André Lureau {
7301b2ffceSMarc-André Lureau     switch (qn->kind) {
7401b2ffceSMarc-André Lureau     case QNUM_I64:
7501b2ffceSMarc-André Lureau         *val = qn->u.i64;
7601b2ffceSMarc-André Lureau         return true;
7761a8f418SMarc-André Lureau     case QNUM_U64:
7861a8f418SMarc-André Lureau         if (qn->u.u64 > INT64_MAX) {
7961a8f418SMarc-André Lureau             return false;
8061a8f418SMarc-André Lureau         }
8161a8f418SMarc-André Lureau         *val = qn->u.u64;
8261a8f418SMarc-André Lureau         return true;
8301b2ffceSMarc-André Lureau     case QNUM_DOUBLE:
8401b2ffceSMarc-André Lureau         return false;
8501b2ffceSMarc-André Lureau     }
8601b2ffceSMarc-André Lureau 
8701b2ffceSMarc-André Lureau     assert(0);
8801b2ffceSMarc-André Lureau     return false;
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  */
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  */
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 
12561a8f418SMarc-André Lureau     assert(0);
12661a8f418SMarc-André Lureau     return false;
12761a8f418SMarc-André Lureau }
12861a8f418SMarc-André Lureau 
12961a8f418SMarc-André Lureau /**
13061a8f418SMarc-André Lureau  * qnum_get_uint(): Get an unsigned integer from the number
13161a8f418SMarc-André Lureau  *
13261a8f418SMarc-André Lureau  * assert() on failure.
13361a8f418SMarc-André Lureau  */
13461a8f418SMarc-André Lureau uint64_t qnum_get_uint(const QNum *qn)
13561a8f418SMarc-André Lureau {
13661a8f418SMarc-André Lureau     uint64_t val;
13761a8f418SMarc-André Lureau     bool success = qnum_get_try_uint(qn, &val);
13861a8f418SMarc-André Lureau     assert(success);
13961a8f418SMarc-André Lureau     return val;
14061a8f418SMarc-André Lureau }
14161a8f418SMarc-André Lureau 
14261a8f418SMarc-André Lureau /**
14301b2ffceSMarc-André Lureau  * qnum_get_double(): Get a float representation of the number
14401b2ffceSMarc-André Lureau  *
14501b2ffceSMarc-André Lureau  * qnum_get_double() loses precision for integers beyond 53 bits.
14601b2ffceSMarc-André Lureau  */
14701b2ffceSMarc-André Lureau double qnum_get_double(QNum *qn)
14801b2ffceSMarc-André Lureau {
14901b2ffceSMarc-André Lureau     switch (qn->kind) {
15001b2ffceSMarc-André Lureau     case QNUM_I64:
15101b2ffceSMarc-André Lureau         return qn->u.i64;
15261a8f418SMarc-André Lureau     case QNUM_U64:
15361a8f418SMarc-André Lureau         return qn->u.u64;
15401b2ffceSMarc-André Lureau     case QNUM_DOUBLE:
15501b2ffceSMarc-André Lureau         return qn->u.dbl;
15601b2ffceSMarc-André Lureau     }
15701b2ffceSMarc-André Lureau 
15801b2ffceSMarc-André Lureau     assert(0);
15901b2ffceSMarc-André Lureau     return 0.0;
16001b2ffceSMarc-André Lureau }
16101b2ffceSMarc-André Lureau 
16201b2ffceSMarc-André Lureau char *qnum_to_string(QNum *qn)
16301b2ffceSMarc-André Lureau {
16401b2ffceSMarc-André Lureau     switch (qn->kind) {
16501b2ffceSMarc-André Lureau     case QNUM_I64:
16601b2ffceSMarc-André Lureau         return g_strdup_printf("%" PRId64, qn->u.i64);
16761a8f418SMarc-André Lureau     case QNUM_U64:
16861a8f418SMarc-André Lureau         return g_strdup_printf("%" PRIu64, qn->u.u64);
16901b2ffceSMarc-André Lureau     case QNUM_DOUBLE:
170*f917eed3SMarkus Armbruster         /* FIXME: g_strdup_printf() is locale dependent; but JSON requires
17101b2ffceSMarc-André Lureau          * numbers to be formatted as if in the C locale. Dependence
17201b2ffceSMarc-André Lureau          * on C locale is a pervasive issue in QEMU. */
17301b2ffceSMarc-André Lureau         /* FIXME: This risks printing Inf or NaN, which are not valid
17401b2ffceSMarc-André Lureau          * JSON values. */
175*f917eed3SMarkus Armbruster         /* 17 digits suffice for IEEE double */
176*f917eed3SMarkus Armbruster         return g_strdup_printf("%.17g", qn->u.dbl);
17701b2ffceSMarc-André Lureau     }
17801b2ffceSMarc-André Lureau 
17901b2ffceSMarc-André Lureau     assert(0);
18001b2ffceSMarc-André Lureau     return NULL;
18101b2ffceSMarc-André Lureau }
18201b2ffceSMarc-André Lureau 
18301b2ffceSMarc-André Lureau /**
184b38dd678SMax Reitz  * qnum_is_equal(): Test whether the two QNums are equal
185b38dd678SMax Reitz  *
186b38dd678SMax Reitz  * Negative integers are never considered equal to unsigned integers,
187b38dd678SMax Reitz  * but positive integers in the range [0, INT64_MAX] are considered
188b38dd678SMax Reitz  * equal independently of whether the QNum's kind is i64 or u64.
189b38dd678SMax Reitz  *
190b38dd678SMax Reitz  * Doubles are never considered equal to integers.
191b38dd678SMax Reitz  */
192b38dd678SMax Reitz bool qnum_is_equal(const QObject *x, const QObject *y)
193b38dd678SMax Reitz {
1947dc847ebSMax Reitz     QNum *num_x = qobject_to(QNum, x);
1957dc847ebSMax Reitz     QNum *num_y = qobject_to(QNum, y);
196b38dd678SMax Reitz 
197b38dd678SMax Reitz     switch (num_x->kind) {
198b38dd678SMax Reitz     case QNUM_I64:
199b38dd678SMax Reitz         switch (num_y->kind) {
200b38dd678SMax Reitz         case QNUM_I64:
201b38dd678SMax Reitz             /* Comparison in native int64_t type */
202b38dd678SMax Reitz             return num_x->u.i64 == num_y->u.i64;
203b38dd678SMax Reitz         case QNUM_U64:
204b38dd678SMax Reitz             /* Implicit conversion of x to uin64_t, so we have to
205b38dd678SMax Reitz              * check its sign before */
206b38dd678SMax Reitz             return num_x->u.i64 >= 0 && num_x->u.i64 == num_y->u.u64;
207b38dd678SMax Reitz         case QNUM_DOUBLE:
208b38dd678SMax Reitz             return false;
209b38dd678SMax Reitz         }
210b38dd678SMax Reitz         abort();
211b38dd678SMax Reitz     case QNUM_U64:
212b38dd678SMax Reitz         switch (num_y->kind) {
213b38dd678SMax Reitz         case QNUM_I64:
214b38dd678SMax Reitz             return qnum_is_equal(y, x);
215b38dd678SMax Reitz         case QNUM_U64:
216b38dd678SMax Reitz             /* Comparison in native uint64_t type */
217b38dd678SMax Reitz             return num_x->u.u64 == num_y->u.u64;
218b38dd678SMax Reitz         case QNUM_DOUBLE:
219b38dd678SMax Reitz             return false;
220b38dd678SMax Reitz         }
221b38dd678SMax Reitz         abort();
222b38dd678SMax Reitz     case QNUM_DOUBLE:
223b38dd678SMax Reitz         switch (num_y->kind) {
224b38dd678SMax Reitz         case QNUM_I64:
225b38dd678SMax Reitz         case QNUM_U64:
226b38dd678SMax Reitz             return false;
227b38dd678SMax Reitz         case QNUM_DOUBLE:
228b38dd678SMax Reitz             /* Comparison in native double type */
229b38dd678SMax Reitz             return num_x->u.dbl == num_y->u.dbl;
230b38dd678SMax Reitz         }
231b38dd678SMax Reitz         abort();
232b38dd678SMax Reitz     }
233b38dd678SMax Reitz 
234b38dd678SMax Reitz     abort();
235b38dd678SMax Reitz }
236b38dd678SMax Reitz 
237b38dd678SMax Reitz /**
23801b2ffceSMarc-André Lureau  * qnum_destroy_obj(): Free all memory allocated by a
23901b2ffceSMarc-André Lureau  * QNum object
24001b2ffceSMarc-André Lureau  */
24101b2ffceSMarc-André Lureau void qnum_destroy_obj(QObject *obj)
24201b2ffceSMarc-André Lureau {
24301b2ffceSMarc-André Lureau     assert(obj != NULL);
2447dc847ebSMax Reitz     g_free(qobject_to(QNum, obj));
24501b2ffceSMarc-André Lureau }
246