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 #ifndef QNUM_H 1601b2ffceSMarc-André Lureau #define QNUM_H 1701b2ffceSMarc-André Lureau 18*407bc4bfSDaniel P. Berrangé #include "qobject/qobject.h" 1901b2ffceSMarc-André Lureau 2001b2ffceSMarc-André Lureau typedef enum { 2101b2ffceSMarc-André Lureau QNUM_I64, 2261a8f418SMarc-André Lureau QNUM_U64, 2301b2ffceSMarc-André Lureau QNUM_DOUBLE 2401b2ffceSMarc-André Lureau } QNumKind; 2501b2ffceSMarc-André Lureau 26f90cb284SMarkus Armbruster /* 27f90cb284SMarkus Armbruster * QNum encapsulates how our dialect of JSON fills in the blanks left 2837aded92SMarkus Armbruster * by the JSON specification (RFC 8259) regarding numbers. 29f90cb284SMarkus Armbruster * 30f90cb284SMarkus Armbruster * Conceptually, we treat number as an abstract type with three 31f90cb284SMarkus Armbruster * concrete subtypes: floating-point, signed integer, unsigned 32f90cb284SMarkus Armbruster * integer. QNum implements this as a discriminated union of double, 33f90cb284SMarkus Armbruster * int64_t, uint64_t. 34f90cb284SMarkus Armbruster * 35f90cb284SMarkus Armbruster * The JSON parser picks the subtype as follows. If the number has a 36f90cb284SMarkus Armbruster * decimal point or an exponent, it is floating-point. Else if it 37f90cb284SMarkus Armbruster * fits into int64_t, it's signed integer. Else if it fits into 38f90cb284SMarkus Armbruster * uint64_t, it's unsigned integer. Else it's floating-point. 39f90cb284SMarkus Armbruster * 40f90cb284SMarkus Armbruster * Any number can serve as double: qnum_get_double() converts under 41f90cb284SMarkus Armbruster * the hood. 42f90cb284SMarkus Armbruster * 43f90cb284SMarkus Armbruster * An integer can serve as signed / unsigned integer as long as it is 44f90cb284SMarkus Armbruster * in range: qnum_get_try_int() / qnum_get_try_uint() check range and 45f90cb284SMarkus Armbruster * convert under the hood. 46f90cb284SMarkus Armbruster */ 479f5c734dSMarkus Armbruster struct QNum { 483d3eacaeSMarc-André Lureau struct QObjectBase_ base; 4901b2ffceSMarc-André Lureau QNumKind kind; 5001b2ffceSMarc-André Lureau union { 5101b2ffceSMarc-André Lureau int64_t i64; 5261a8f418SMarc-André Lureau uint64_t u64; 5301b2ffceSMarc-André Lureau double dbl; 5401b2ffceSMarc-André Lureau } u; 559f5c734dSMarkus Armbruster }; 5601b2ffceSMarc-André Lureau 57d709bbf3SMarc-André Lureau void qnum_unref(QNum *q); 58d709bbf3SMarc-André Lureau 59d709bbf3SMarc-André Lureau G_DEFINE_AUTOPTR_CLEANUP_FUNC(QNum, qnum_unref) 60d709bbf3SMarc-André Lureau 6101b2ffceSMarc-André Lureau QNum *qnum_from_int(int64_t value); 6261a8f418SMarc-André Lureau QNum *qnum_from_uint(uint64_t value); 6301b2ffceSMarc-André Lureau QNum *qnum_from_double(double value); 6401b2ffceSMarc-André Lureau 6501b2ffceSMarc-André Lureau bool qnum_get_try_int(const QNum *qn, int64_t *val); 6601b2ffceSMarc-André Lureau int64_t qnum_get_int(const QNum *qn); 6761a8f418SMarc-André Lureau 6861a8f418SMarc-André Lureau bool qnum_get_try_uint(const QNum *qn, uint64_t *val); 6961a8f418SMarc-André Lureau uint64_t qnum_get_uint(const QNum *qn); 7061a8f418SMarc-André Lureau 7101b2ffceSMarc-André Lureau double qnum_get_double(QNum *qn); 7201b2ffceSMarc-André Lureau 7301b2ffceSMarc-André Lureau char *qnum_to_string(QNum *qn); 7401b2ffceSMarc-André Lureau 7501b2ffceSMarc-André Lureau #endif /* QNUM_H */ 76