[/
    Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

    Official repository: https://github.com/cppalliance/json
]

[/-----------------------------------------------------------------------------]

[section:numbers Numbers]

JSON numbers are represented using `std::int64_t`, `std::uint64_t`, and `double`.
When a __value__ is constructed from an unsigned integer, its __kind__
will be `kind::uint64`. Likewise, a __value__ constructed from
a signed integer will have `kind::int64`, or `kind::double_` if
constructed from a floating-point type:

[doc_using_numbers_1]

When accessing a number contained within a __value__, the function
used must match the value's __kind__ exactly; no conversions will be performed.
For example if `as_double` is called on a __value__ that contains a `std::uint64_t`,
an exception is thrown. Similarly, the function `if_double` will return `nullptr`
and calling `get_double` will result in undefined behavior:

[doc_using_numbers_2]

In cases where you know that a __value__ contains a number
but don't know its __kind__, `value::to_number` can be used to convert
the __value__ to an arithmetic type:

[doc_using_numbers_3]

If the __value__ does not contain a number, or if the conversion is
to an integer type `T` and the number cannot be represented exactly
by `T`, the conversion will fail. Otherwise, the result is the number
converted to `T` as-if by `static_cast`:

[doc_using_numbers_4]

In settings where exceptions cannot be used,
an overload of `value::to_number` accepting __error_code__
can be used instead with identical semantics to its
throwing counterpart:

[doc_using_numbers_5]

When parsing a JSON document, the type used to represent a number
is not explicitly specified and must be determined from its value.
In general, the parser will choose the best type which can
accurately store the number as it appears in the document.
Integers (i.e. numbers without decimals or exponents) that
cannot be represented by `std::uint64_t` and `std::int64_t`
will be represented as `double` to preserve their magnitude:

[doc_using_numbers_6]

More formally, if the number:

* contains a decimal point, or
* contains an exponent, or
* is negative and its value is less than `INT64_MIN`, or
* is positive and its value is greater than `UINT64_MAX`,

then its type is `double`.
Otherwise, if the number is positive and its value is
greater than `INT64_MAX`, then its type is `std::uint64_t`.
All other numbers are parsed as `std::int64_t`.

[endsect]
