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/error.h" 1701b2ffceSMarc-André Lureau #include "qapi/qmp/qnum.h" 1801b2ffceSMarc-André Lureau #include "qapi/qmp/qobject.h" 1901b2ffceSMarc-André Lureau #include "qemu-common.h" 2001b2ffceSMarc-André Lureau 2101b2ffceSMarc-André Lureau /** 2201b2ffceSMarc-André Lureau * qnum_from_int(): Create a new QNum from an int64_t 2301b2ffceSMarc-André Lureau * 2401b2ffceSMarc-André Lureau * Return strong reference. 2501b2ffceSMarc-André Lureau */ 2601b2ffceSMarc-André Lureau QNum *qnum_from_int(int64_t value) 2701b2ffceSMarc-André Lureau { 2801b2ffceSMarc-André Lureau QNum *qn = g_new(QNum, 1); 2901b2ffceSMarc-André Lureau 3001b2ffceSMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM); 3101b2ffceSMarc-André Lureau qn->kind = QNUM_I64; 3201b2ffceSMarc-André Lureau qn->u.i64 = value; 3301b2ffceSMarc-André Lureau 3401b2ffceSMarc-André Lureau return qn; 3501b2ffceSMarc-André Lureau } 3601b2ffceSMarc-André Lureau 3701b2ffceSMarc-André Lureau /** 38*61a8f418SMarc-André Lureau * qnum_from_uint(): Create a new QNum from an uint64_t 39*61a8f418SMarc-André Lureau * 40*61a8f418SMarc-André Lureau * Return strong reference. 41*61a8f418SMarc-André Lureau */ 42*61a8f418SMarc-André Lureau QNum *qnum_from_uint(uint64_t value) 43*61a8f418SMarc-André Lureau { 44*61a8f418SMarc-André Lureau QNum *qn = g_new(QNum, 1); 45*61a8f418SMarc-André Lureau 46*61a8f418SMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM); 47*61a8f418SMarc-André Lureau qn->kind = QNUM_U64; 48*61a8f418SMarc-André Lureau qn->u.u64 = value; 49*61a8f418SMarc-André Lureau 50*61a8f418SMarc-André Lureau return qn; 51*61a8f418SMarc-André Lureau } 52*61a8f418SMarc-André Lureau 53*61a8f418SMarc-André Lureau /** 5401b2ffceSMarc-André Lureau * qnum_from_double(): Create a new QNum from a double 5501b2ffceSMarc-André Lureau * 5601b2ffceSMarc-André Lureau * Return strong reference. 5701b2ffceSMarc-André Lureau */ 5801b2ffceSMarc-André Lureau QNum *qnum_from_double(double value) 5901b2ffceSMarc-André Lureau { 6001b2ffceSMarc-André Lureau QNum *qn = g_new(QNum, 1); 6101b2ffceSMarc-André Lureau 6201b2ffceSMarc-André Lureau qobject_init(QOBJECT(qn), QTYPE_QNUM); 6301b2ffceSMarc-André Lureau qn->kind = QNUM_DOUBLE; 6401b2ffceSMarc-André Lureau qn->u.dbl = value; 6501b2ffceSMarc-André Lureau 6601b2ffceSMarc-André Lureau return qn; 6701b2ffceSMarc-André Lureau } 6801b2ffceSMarc-André Lureau 6901b2ffceSMarc-André Lureau /** 7001b2ffceSMarc-André Lureau * qnum_get_try_int(): Get an integer representation of the number 7101b2ffceSMarc-André Lureau * 7201b2ffceSMarc-André Lureau * Return true on success. 7301b2ffceSMarc-André Lureau */ 7401b2ffceSMarc-André Lureau bool qnum_get_try_int(const QNum *qn, int64_t *val) 7501b2ffceSMarc-André Lureau { 7601b2ffceSMarc-André Lureau switch (qn->kind) { 7701b2ffceSMarc-André Lureau case QNUM_I64: 7801b2ffceSMarc-André Lureau *val = qn->u.i64; 7901b2ffceSMarc-André Lureau return true; 80*61a8f418SMarc-André Lureau case QNUM_U64: 81*61a8f418SMarc-André Lureau if (qn->u.u64 > INT64_MAX) { 82*61a8f418SMarc-André Lureau return false; 83*61a8f418SMarc-André Lureau } 84*61a8f418SMarc-André Lureau *val = qn->u.u64; 85*61a8f418SMarc-André Lureau return true; 8601b2ffceSMarc-André Lureau case QNUM_DOUBLE: 8701b2ffceSMarc-André Lureau return false; 8801b2ffceSMarc-André Lureau } 8901b2ffceSMarc-André Lureau 9001b2ffceSMarc-André Lureau assert(0); 9101b2ffceSMarc-André Lureau return false; 9201b2ffceSMarc-André Lureau } 9301b2ffceSMarc-André Lureau 9401b2ffceSMarc-André Lureau /** 9501b2ffceSMarc-André Lureau * qnum_get_int(): Get an integer representation of the number 9601b2ffceSMarc-André Lureau * 9701b2ffceSMarc-André Lureau * assert() on failure. 9801b2ffceSMarc-André Lureau */ 9901b2ffceSMarc-André Lureau int64_t qnum_get_int(const QNum *qn) 10001b2ffceSMarc-André Lureau { 10101b2ffceSMarc-André Lureau int64_t val; 10201b2ffceSMarc-André Lureau bool success = qnum_get_try_int(qn, &val); 10301b2ffceSMarc-André Lureau assert(success); 10401b2ffceSMarc-André Lureau return val; 10501b2ffceSMarc-André Lureau } 10601b2ffceSMarc-André Lureau 10701b2ffceSMarc-André Lureau /** 108*61a8f418SMarc-André Lureau * qnum_get_uint(): Get an unsigned integer from the number 109*61a8f418SMarc-André Lureau * 110*61a8f418SMarc-André Lureau * Return true on success. 111*61a8f418SMarc-André Lureau */ 112*61a8f418SMarc-André Lureau bool qnum_get_try_uint(const QNum *qn, uint64_t *val) 113*61a8f418SMarc-André Lureau { 114*61a8f418SMarc-André Lureau switch (qn->kind) { 115*61a8f418SMarc-André Lureau case QNUM_I64: 116*61a8f418SMarc-André Lureau if (qn->u.i64 < 0) { 117*61a8f418SMarc-André Lureau return false; 118*61a8f418SMarc-André Lureau } 119*61a8f418SMarc-André Lureau *val = qn->u.i64; 120*61a8f418SMarc-André Lureau return true; 121*61a8f418SMarc-André Lureau case QNUM_U64: 122*61a8f418SMarc-André Lureau *val = qn->u.u64; 123*61a8f418SMarc-André Lureau return true; 124*61a8f418SMarc-André Lureau case QNUM_DOUBLE: 125*61a8f418SMarc-André Lureau return false; 126*61a8f418SMarc-André Lureau } 127*61a8f418SMarc-André Lureau 128*61a8f418SMarc-André Lureau assert(0); 129*61a8f418SMarc-André Lureau return false; 130*61a8f418SMarc-André Lureau } 131*61a8f418SMarc-André Lureau 132*61a8f418SMarc-André Lureau /** 133*61a8f418SMarc-André Lureau * qnum_get_uint(): Get an unsigned integer from the number 134*61a8f418SMarc-André Lureau * 135*61a8f418SMarc-André Lureau * assert() on failure. 136*61a8f418SMarc-André Lureau */ 137*61a8f418SMarc-André Lureau uint64_t qnum_get_uint(const QNum *qn) 138*61a8f418SMarc-André Lureau { 139*61a8f418SMarc-André Lureau uint64_t val; 140*61a8f418SMarc-André Lureau bool success = qnum_get_try_uint(qn, &val); 141*61a8f418SMarc-André Lureau assert(success); 142*61a8f418SMarc-André Lureau return val; 143*61a8f418SMarc-André Lureau } 144*61a8f418SMarc-André Lureau 145*61a8f418SMarc-André Lureau /** 14601b2ffceSMarc-André Lureau * qnum_get_double(): Get a float representation of the number 14701b2ffceSMarc-André Lureau * 14801b2ffceSMarc-André Lureau * qnum_get_double() loses precision for integers beyond 53 bits. 14901b2ffceSMarc-André Lureau */ 15001b2ffceSMarc-André Lureau double qnum_get_double(QNum *qn) 15101b2ffceSMarc-André Lureau { 15201b2ffceSMarc-André Lureau switch (qn->kind) { 15301b2ffceSMarc-André Lureau case QNUM_I64: 15401b2ffceSMarc-André Lureau return qn->u.i64; 155*61a8f418SMarc-André Lureau case QNUM_U64: 156*61a8f418SMarc-André Lureau return qn->u.u64; 15701b2ffceSMarc-André Lureau case QNUM_DOUBLE: 15801b2ffceSMarc-André Lureau return qn->u.dbl; 15901b2ffceSMarc-André Lureau } 16001b2ffceSMarc-André Lureau 16101b2ffceSMarc-André Lureau assert(0); 16201b2ffceSMarc-André Lureau return 0.0; 16301b2ffceSMarc-André Lureau } 16401b2ffceSMarc-André Lureau 16501b2ffceSMarc-André Lureau char *qnum_to_string(QNum *qn) 16601b2ffceSMarc-André Lureau { 16701b2ffceSMarc-André Lureau char *buffer; 16801b2ffceSMarc-André Lureau int len; 16901b2ffceSMarc-André Lureau 17001b2ffceSMarc-André Lureau switch (qn->kind) { 17101b2ffceSMarc-André Lureau case QNUM_I64: 17201b2ffceSMarc-André Lureau return g_strdup_printf("%" PRId64, qn->u.i64); 173*61a8f418SMarc-André Lureau case QNUM_U64: 174*61a8f418SMarc-André Lureau return g_strdup_printf("%" PRIu64, qn->u.u64); 17501b2ffceSMarc-André Lureau case QNUM_DOUBLE: 17601b2ffceSMarc-André Lureau /* FIXME: snprintf() is locale dependent; but JSON requires 17701b2ffceSMarc-André Lureau * numbers to be formatted as if in the C locale. Dependence 17801b2ffceSMarc-André Lureau * on C locale is a pervasive issue in QEMU. */ 17901b2ffceSMarc-André Lureau /* FIXME: This risks printing Inf or NaN, which are not valid 18001b2ffceSMarc-André Lureau * JSON values. */ 18101b2ffceSMarc-André Lureau /* FIXME: the default precision of 6 for %f often causes 18201b2ffceSMarc-André Lureau * rounding errors; we should be using DBL_DECIMAL_DIG (17), 18301b2ffceSMarc-André Lureau * and only rounding to a shorter number if the result would 18401b2ffceSMarc-André Lureau * still produce the same floating point value. */ 18501b2ffceSMarc-André Lureau buffer = g_strdup_printf("%f" , qn->u.dbl); 18601b2ffceSMarc-André Lureau len = strlen(buffer); 18701b2ffceSMarc-André Lureau while (len > 0 && buffer[len - 1] == '0') { 18801b2ffceSMarc-André Lureau len--; 18901b2ffceSMarc-André Lureau } 19001b2ffceSMarc-André Lureau 19101b2ffceSMarc-André Lureau if (len && buffer[len - 1] == '.') { 19201b2ffceSMarc-André Lureau buffer[len - 1] = 0; 19301b2ffceSMarc-André Lureau } else { 19401b2ffceSMarc-André Lureau buffer[len] = 0; 19501b2ffceSMarc-André Lureau } 19601b2ffceSMarc-André Lureau 19701b2ffceSMarc-André Lureau return buffer; 19801b2ffceSMarc-André Lureau } 19901b2ffceSMarc-André Lureau 20001b2ffceSMarc-André Lureau assert(0); 20101b2ffceSMarc-André Lureau return NULL; 20201b2ffceSMarc-André Lureau } 20301b2ffceSMarc-André Lureau 20401b2ffceSMarc-André Lureau /** 20501b2ffceSMarc-André Lureau * qobject_to_qnum(): Convert a QObject into a QNum 20601b2ffceSMarc-André Lureau */ 20701b2ffceSMarc-André Lureau QNum *qobject_to_qnum(const QObject *obj) 20801b2ffceSMarc-André Lureau { 20901b2ffceSMarc-André Lureau if (!obj || qobject_type(obj) != QTYPE_QNUM) { 21001b2ffceSMarc-André Lureau return NULL; 21101b2ffceSMarc-André Lureau } 21201b2ffceSMarc-André Lureau return container_of(obj, QNum, base); 21301b2ffceSMarc-André Lureau } 21401b2ffceSMarc-André Lureau 21501b2ffceSMarc-André Lureau /** 21601b2ffceSMarc-André Lureau * qnum_destroy_obj(): Free all memory allocated by a 21701b2ffceSMarc-André Lureau * QNum object 21801b2ffceSMarc-André Lureau */ 21901b2ffceSMarc-André Lureau void qnum_destroy_obj(QObject *obj) 22001b2ffceSMarc-André Lureau { 22101b2ffceSMarc-André Lureau assert(obj != NULL); 22201b2ffceSMarc-André Lureau g_free(qobject_to_qnum(obj)); 22301b2ffceSMarc-André Lureau } 224