1*01b2ffceSMarc-André Lureau /* 2*01b2ffceSMarc-André Lureau * QNum Module 3*01b2ffceSMarc-André Lureau * 4*01b2ffceSMarc-André Lureau * Copyright (C) 2009 Red Hat Inc. 5*01b2ffceSMarc-André Lureau * 6*01b2ffceSMarc-André Lureau * Authors: 7*01b2ffceSMarc-André Lureau * Luiz Capitulino <lcapitulino@redhat.com> 8*01b2ffceSMarc-André Lureau * Anthony Liguori <aliguori@us.ibm.com> 9*01b2ffceSMarc-André Lureau * Marc-André Lureau <marcandre.lureau@redhat.com> 10*01b2ffceSMarc-André Lureau * 11*01b2ffceSMarc-André Lureau * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 12*01b2ffceSMarc-André Lureau * See the COPYING.LIB file in the top-level directory. 13*01b2ffceSMarc-André Lureau */ 14*01b2ffceSMarc-André Lureau 15*01b2ffceSMarc-André Lureau #include "qemu/osdep.h" 16*01b2ffceSMarc-André Lureau #include "qapi/error.h" 17*01b2ffceSMarc-André Lureau #include "qapi/qmp/qnum.h" 18*01b2ffceSMarc-André Lureau #include "qapi/qmp/qobject.h" 19*01b2ffceSMarc-André Lureau #include "qemu-common.h" 20*01b2ffceSMarc-André Lureau 21*01b2ffceSMarc-André Lureau /** 22*01b2ffceSMarc-André Lureau * qnum_from_int(): Create a new QNum from an int64_t 23*01b2ffceSMarc-André Lureau * 24*01b2ffceSMarc-André Lureau * Return strong reference. 25*01b2ffceSMarc-André Lureau */ 26*01b2ffceSMarc-André Lureau QNum *qnum_from_int(int64_t value) 27*01b2ffceSMarc-André Lureau { 28*01b2ffceSMarc-André Lureau QNum *qn = g_new(QNum, 1); 29*01b2ffceSMarc-André Lureau 30*01b2ffceSMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM); 31*01b2ffceSMarc-André Lureau qn->kind = QNUM_I64; 32*01b2ffceSMarc-André Lureau qn->u.i64 = value; 33*01b2ffceSMarc-André Lureau 34*01b2ffceSMarc-André Lureau return qn; 35*01b2ffceSMarc-André Lureau } 36*01b2ffceSMarc-André Lureau 37*01b2ffceSMarc-André Lureau /** 38*01b2ffceSMarc-André Lureau * qnum_from_double(): Create a new QNum from a double 39*01b2ffceSMarc-André Lureau * 40*01b2ffceSMarc-André Lureau * Return strong reference. 41*01b2ffceSMarc-André Lureau */ 42*01b2ffceSMarc-André Lureau QNum *qnum_from_double(double value) 43*01b2ffceSMarc-André Lureau { 44*01b2ffceSMarc-André Lureau QNum *qn = g_new(QNum, 1); 45*01b2ffceSMarc-André Lureau 46*01b2ffceSMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM); 47*01b2ffceSMarc-André Lureau qn->kind = QNUM_DOUBLE; 48*01b2ffceSMarc-André Lureau qn->u.dbl = value; 49*01b2ffceSMarc-André Lureau 50*01b2ffceSMarc-André Lureau return qn; 51*01b2ffceSMarc-André Lureau } 52*01b2ffceSMarc-André Lureau 53*01b2ffceSMarc-André Lureau /** 54*01b2ffceSMarc-André Lureau * qnum_get_try_int(): Get an integer representation of the number 55*01b2ffceSMarc-André Lureau * 56*01b2ffceSMarc-André Lureau * Return true on success. 57*01b2ffceSMarc-André Lureau */ 58*01b2ffceSMarc-André Lureau bool qnum_get_try_int(const QNum *qn, int64_t *val) 59*01b2ffceSMarc-André Lureau { 60*01b2ffceSMarc-André Lureau switch (qn->kind) { 61*01b2ffceSMarc-André Lureau case QNUM_I64: 62*01b2ffceSMarc-André Lureau *val = qn->u.i64; 63*01b2ffceSMarc-André Lureau return true; 64*01b2ffceSMarc-André Lureau case QNUM_DOUBLE: 65*01b2ffceSMarc-André Lureau return false; 66*01b2ffceSMarc-André Lureau } 67*01b2ffceSMarc-André Lureau 68*01b2ffceSMarc-André Lureau assert(0); 69*01b2ffceSMarc-André Lureau return false; 70*01b2ffceSMarc-André Lureau } 71*01b2ffceSMarc-André Lureau 72*01b2ffceSMarc-André Lureau /** 73*01b2ffceSMarc-André Lureau * qnum_get_int(): Get an integer representation of the number 74*01b2ffceSMarc-André Lureau * 75*01b2ffceSMarc-André Lureau * assert() on failure. 76*01b2ffceSMarc-André Lureau */ 77*01b2ffceSMarc-André Lureau int64_t qnum_get_int(const QNum *qn) 78*01b2ffceSMarc-André Lureau { 79*01b2ffceSMarc-André Lureau int64_t val; 80*01b2ffceSMarc-André Lureau bool success = qnum_get_try_int(qn, &val); 81*01b2ffceSMarc-André Lureau assert(success); 82*01b2ffceSMarc-André Lureau return val; 83*01b2ffceSMarc-André Lureau } 84*01b2ffceSMarc-André Lureau 85*01b2ffceSMarc-André Lureau /** 86*01b2ffceSMarc-André Lureau * qnum_get_double(): Get a float representation of the number 87*01b2ffceSMarc-André Lureau * 88*01b2ffceSMarc-André Lureau * qnum_get_double() loses precision for integers beyond 53 bits. 89*01b2ffceSMarc-André Lureau */ 90*01b2ffceSMarc-André Lureau double qnum_get_double(QNum *qn) 91*01b2ffceSMarc-André Lureau { 92*01b2ffceSMarc-André Lureau switch (qn->kind) { 93*01b2ffceSMarc-André Lureau case QNUM_I64: 94*01b2ffceSMarc-André Lureau return qn->u.i64; 95*01b2ffceSMarc-André Lureau case QNUM_DOUBLE: 96*01b2ffceSMarc-André Lureau return qn->u.dbl; 97*01b2ffceSMarc-André Lureau } 98*01b2ffceSMarc-André Lureau 99*01b2ffceSMarc-André Lureau assert(0); 100*01b2ffceSMarc-André Lureau return 0.0; 101*01b2ffceSMarc-André Lureau } 102*01b2ffceSMarc-André Lureau 103*01b2ffceSMarc-André Lureau char *qnum_to_string(QNum *qn) 104*01b2ffceSMarc-André Lureau { 105*01b2ffceSMarc-André Lureau char *buffer; 106*01b2ffceSMarc-André Lureau int len; 107*01b2ffceSMarc-André Lureau 108*01b2ffceSMarc-André Lureau switch (qn->kind) { 109*01b2ffceSMarc-André Lureau case QNUM_I64: 110*01b2ffceSMarc-André Lureau return g_strdup_printf("%" PRId64, qn->u.i64); 111*01b2ffceSMarc-André Lureau case QNUM_DOUBLE: 112*01b2ffceSMarc-André Lureau /* FIXME: snprintf() is locale dependent; but JSON requires 113*01b2ffceSMarc-André Lureau * numbers to be formatted as if in the C locale. Dependence 114*01b2ffceSMarc-André Lureau * on C locale is a pervasive issue in QEMU. */ 115*01b2ffceSMarc-André Lureau /* FIXME: This risks printing Inf or NaN, which are not valid 116*01b2ffceSMarc-André Lureau * JSON values. */ 117*01b2ffceSMarc-André Lureau /* FIXME: the default precision of 6 for %f often causes 118*01b2ffceSMarc-André Lureau * rounding errors; we should be using DBL_DECIMAL_DIG (17), 119*01b2ffceSMarc-André Lureau * and only rounding to a shorter number if the result would 120*01b2ffceSMarc-André Lureau * still produce the same floating point value. */ 121*01b2ffceSMarc-André Lureau buffer = g_strdup_printf("%f" , qn->u.dbl); 122*01b2ffceSMarc-André Lureau len = strlen(buffer); 123*01b2ffceSMarc-André Lureau while (len > 0 && buffer[len - 1] == '0') { 124*01b2ffceSMarc-André Lureau len--; 125*01b2ffceSMarc-André Lureau } 126*01b2ffceSMarc-André Lureau 127*01b2ffceSMarc-André Lureau if (len && buffer[len - 1] == '.') { 128*01b2ffceSMarc-André Lureau buffer[len - 1] = 0; 129*01b2ffceSMarc-André Lureau } else { 130*01b2ffceSMarc-André Lureau buffer[len] = 0; 131*01b2ffceSMarc-André Lureau } 132*01b2ffceSMarc-André Lureau 133*01b2ffceSMarc-André Lureau return buffer; 134*01b2ffceSMarc-André Lureau } 135*01b2ffceSMarc-André Lureau 136*01b2ffceSMarc-André Lureau assert(0); 137*01b2ffceSMarc-André Lureau return NULL; 138*01b2ffceSMarc-André Lureau } 139*01b2ffceSMarc-André Lureau 140*01b2ffceSMarc-André Lureau /** 141*01b2ffceSMarc-André Lureau * qobject_to_qnum(): Convert a QObject into a QNum 142*01b2ffceSMarc-André Lureau */ 143*01b2ffceSMarc-André Lureau QNum *qobject_to_qnum(const QObject *obj) 144*01b2ffceSMarc-André Lureau { 145*01b2ffceSMarc-André Lureau if (!obj || qobject_type(obj) != QTYPE_QNUM) { 146*01b2ffceSMarc-André Lureau return NULL; 147*01b2ffceSMarc-André Lureau } 148*01b2ffceSMarc-André Lureau return container_of(obj, QNum, base); 149*01b2ffceSMarc-André Lureau } 150*01b2ffceSMarc-André Lureau 151*01b2ffceSMarc-André Lureau /** 152*01b2ffceSMarc-André Lureau * qnum_destroy_obj(): Free all memory allocated by a 153*01b2ffceSMarc-André Lureau * QNum object 154*01b2ffceSMarc-André Lureau */ 155*01b2ffceSMarc-André Lureau void qnum_destroy_obj(QObject *obj) 156*01b2ffceSMarc-André Lureau { 157*01b2ffceSMarc-André Lureau assert(obj != NULL); 158*01b2ffceSMarc-André Lureau g_free(qobject_to_qnum(obj)); 159*01b2ffceSMarc-André Lureau } 160