qemu/qobject/qnum.c
<<
>>
Prefs
   1/*
   2 * QNum Module
   3 *
   4 * Copyright (C) 2009 Red Hat Inc.
   5 *
   6 * Authors:
   7 *  Luiz Capitulino <lcapitulino@redhat.com>
   8 *  Anthony Liguori <aliguori@us.ibm.com>
   9 *  Marc-André Lureau <marcandre.lureau@redhat.com>
  10 *
  11 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  12 * See the COPYING.LIB file in the top-level directory.
  13 */
  14
  15#include "qemu/osdep.h"
  16#include "qapi/qmp/qnum.h"
  17#include "qobject-internal.h"
  18
  19/**
  20 * qnum_from_int(): Create a new QNum from an int64_t
  21 *
  22 * Return strong reference.
  23 */
  24QNum *qnum_from_int(int64_t value)
  25{
  26    QNum *qn = g_new(QNum, 1);
  27
  28    qobject_init(QOBJECT(qn), QTYPE_QNUM);
  29    qn->kind = QNUM_I64;
  30    qn->u.i64 = value;
  31
  32    return qn;
  33}
  34
  35/**
  36 * qnum_from_uint(): Create a new QNum from an uint64_t
  37 *
  38 * Return strong reference.
  39 */
  40QNum *qnum_from_uint(uint64_t value)
  41{
  42    QNum *qn = g_new(QNum, 1);
  43
  44    qobject_init(QOBJECT(qn), QTYPE_QNUM);
  45    qn->kind = QNUM_U64;
  46    qn->u.u64 = value;
  47
  48    return qn;
  49}
  50
  51/**
  52 * qnum_from_double(): Create a new QNum from a double
  53 *
  54 * Return strong reference.
  55 */
  56QNum *qnum_from_double(double value)
  57{
  58    QNum *qn = g_new(QNum, 1);
  59
  60    qobject_init(QOBJECT(qn), QTYPE_QNUM);
  61    qn->kind = QNUM_DOUBLE;
  62    qn->u.dbl = value;
  63
  64    return qn;
  65}
  66
  67/**
  68 * qnum_get_try_int(): Get an integer representation of the number
  69 *
  70 * Return true on success.
  71 */
  72bool qnum_get_try_int(const QNum *qn, int64_t *val)
  73{
  74    switch (qn->kind) {
  75    case QNUM_I64:
  76        *val = qn->u.i64;
  77        return true;
  78    case QNUM_U64:
  79        if (qn->u.u64 > INT64_MAX) {
  80            return false;
  81        }
  82        *val = qn->u.u64;
  83        return true;
  84    case QNUM_DOUBLE:
  85        return false;
  86    }
  87
  88    assert(0);
  89    return false;
  90}
  91
  92/**
  93 * qnum_get_int(): Get an integer representation of the number
  94 *
  95 * assert() on failure.
  96 */
  97int64_t qnum_get_int(const QNum *qn)
  98{
  99    int64_t val;
 100    bool success = qnum_get_try_int(qn, &val);
 101    assert(success);
 102    return val;
 103}
 104
 105/**
 106 * qnum_get_uint(): Get an unsigned integer from the number
 107 *
 108 * Return true on success.
 109 */
 110bool qnum_get_try_uint(const QNum *qn, uint64_t *val)
 111{
 112    switch (qn->kind) {
 113    case QNUM_I64:
 114        if (qn->u.i64 < 0) {
 115            return false;
 116        }
 117        *val = qn->u.i64;
 118        return true;
 119    case QNUM_U64:
 120        *val = qn->u.u64;
 121        return true;
 122    case QNUM_DOUBLE:
 123        return false;
 124    }
 125
 126    assert(0);
 127    return false;
 128}
 129
 130/**
 131 * qnum_get_uint(): Get an unsigned integer from the number
 132 *
 133 * assert() on failure.
 134 */
 135uint64_t qnum_get_uint(const QNum *qn)
 136{
 137    uint64_t val;
 138    bool success = qnum_get_try_uint(qn, &val);
 139    assert(success);
 140    return val;
 141}
 142
 143/**
 144 * qnum_get_double(): Get a float representation of the number
 145 *
 146 * qnum_get_double() loses precision for integers beyond 53 bits.
 147 */
 148double qnum_get_double(QNum *qn)
 149{
 150    switch (qn->kind) {
 151    case QNUM_I64:
 152        return qn->u.i64;
 153    case QNUM_U64:
 154        return qn->u.u64;
 155    case QNUM_DOUBLE:
 156        return qn->u.dbl;
 157    }
 158
 159    assert(0);
 160    return 0.0;
 161}
 162
 163char *qnum_to_string(QNum *qn)
 164{
 165    switch (qn->kind) {
 166    case QNUM_I64:
 167        return g_strdup_printf("%" PRId64, qn->u.i64);
 168    case QNUM_U64:
 169        return g_strdup_printf("%" PRIu64, qn->u.u64);
 170    case QNUM_DOUBLE:
 171        /* 17 digits suffice for IEEE double */
 172        return g_strdup_printf("%.17g", qn->u.dbl);
 173    }
 174
 175    assert(0);
 176    return NULL;
 177}
 178
 179/**
 180 * qnum_is_equal(): Test whether the two QNums are equal
 181 *
 182 * Negative integers are never considered equal to unsigned integers,
 183 * but positive integers in the range [0, INT64_MAX] are considered
 184 * equal independently of whether the QNum's kind is i64 or u64.
 185 *
 186 * Doubles are never considered equal to integers.
 187 */
 188bool qnum_is_equal(const QObject *x, const QObject *y)
 189{
 190    QNum *num_x = qobject_to(QNum, x);
 191    QNum *num_y = qobject_to(QNum, y);
 192
 193    switch (num_x->kind) {
 194    case QNUM_I64:
 195        switch (num_y->kind) {
 196        case QNUM_I64:
 197            /* Comparison in native int64_t type */
 198            return num_x->u.i64 == num_y->u.i64;
 199        case QNUM_U64:
 200            /* Implicit conversion of x to uin64_t, so we have to
 201             * check its sign before */
 202            return num_x->u.i64 >= 0 && num_x->u.i64 == num_y->u.u64;
 203        case QNUM_DOUBLE:
 204            return false;
 205        }
 206        abort();
 207    case QNUM_U64:
 208        switch (num_y->kind) {
 209        case QNUM_I64:
 210            return qnum_is_equal(y, x);
 211        case QNUM_U64:
 212            /* Comparison in native uint64_t type */
 213            return num_x->u.u64 == num_y->u.u64;
 214        case QNUM_DOUBLE:
 215            return false;
 216        }
 217        abort();
 218    case QNUM_DOUBLE:
 219        switch (num_y->kind) {
 220        case QNUM_I64:
 221        case QNUM_U64:
 222            return false;
 223        case QNUM_DOUBLE:
 224            /* Comparison in native double type */
 225            return num_x->u.dbl == num_y->u.dbl;
 226        }
 227        abort();
 228    }
 229
 230    abort();
 231}
 232
 233/**
 234 * qnum_destroy_obj(): Free all memory allocated by a
 235 * QNum object
 236 */
 237void qnum_destroy_obj(QObject *obj)
 238{
 239    assert(obj != NULL);
 240    g_free(qobject_to(QNum, obj));
 241}
 242