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" 16*407bc4bfSDaniel P. Berrangé #include "qobject/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 */ 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 */ 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 */ 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 */ 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 88890000ddSPierrick 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 */ 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 125890000ddSPierrick 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 */ 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 */ 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 157890000ddSPierrick Bouvier g_assert_not_reached(); 15801b2ffceSMarc-André Lureau } 15901b2ffceSMarc-André Lureau 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 172890000ddSPierrick 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 */ 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 */ 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 239d709bbf3SMarc-André Lureau void qnum_unref(QNum *q) 240d709bbf3SMarc-André Lureau { 241d709bbf3SMarc-André Lureau qobject_unref(q); 242d709bbf3SMarc-André Lureau } 243