qnum.c 5.1 KB

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