qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qnum.c (5217B)


      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  */
     24 QNum *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  */
     40 QNum *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  */
     56 QNum *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  */
     72 bool 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  */
     97 int64_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  */
    110 bool 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  */
    135 uint64_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  */
    148 double 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 
    163 char *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  */
    188 bool 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  */
    237 void qnum_destroy_obj(QObject *obj)
    238 {
    239     assert(obj != NULL);
    240     g_free(qobject_to(QNum, obj));
    241 }
    242 
    243 void qnum_unref(QNum *q)
    244 {
    245     qobject_unref(q);
    246 }