mirror of
https://github.com/boostorg/charconv.git
synced 2026-02-13 12:22:18 +00:00
Merge pull request #42 from mborland/system_error
Use `std::errc` as the error code instead of errno values
This commit is contained in:
@@ -13,7 +13,7 @@ https://www.boost.org/LICENSE_1_0.txt
|
||||
struct from_chars_result
|
||||
{
|
||||
const char* ptr;
|
||||
int ec;
|
||||
std::errc ec;
|
||||
|
||||
friend constexpr bool operator==(const from_chars_result& lhs, const from_chars_result& rhs) noexcept
|
||||
friend constexpr bool operator!=(const from_chars_result& lhs, const from_chars_result& rhs) noexcept
|
||||
@@ -30,10 +30,10 @@ from_chars_result from_chars(const char* first, const char* last, Real& value, c
|
||||
|
||||
== from_chars_result
|
||||
* ptr - points to the first character not matching the pattern, or has the value of last if all characters are successfully parsed.
|
||||
* ec - the error code. Valid values for <cerrno> are:
|
||||
** 0 - successful parsing
|
||||
** EINVAL - invalid argument (e.g. parsing a negative number into an unsigned type)
|
||||
** ERANGE - result out of range (e.g. overflow)
|
||||
* ec - the error code. Valid values for are:
|
||||
** std::errc() - successful parsing
|
||||
** std::errc::invalid_argument - invalid argument (e.g. parsing a negative number into an unsigned type)
|
||||
** std::errc::result_out_of_range - result out of range (e.g. overflow)
|
||||
* operator== - compares the values of ptr and ec for equality
|
||||
* operator!- - compares the value of ptr and ec for inequality
|
||||
|
||||
@@ -50,7 +50,7 @@ from_chars_result from_chars(const char* first, const char* last, Real& value, c
|
||||
** One known exception is GCC 5 which does not support constexpr comparison of `const char*`.
|
||||
|
||||
=== from_chars for floating point types
|
||||
* On ERANGE we return ±0 for small values (e.g. 1.0e-99999) or ±HUGE_VAL for large values (e.g. 1.0e+99999) to match the handling of `std::strtod`.
|
||||
* On std::errc::result_out_of_range we return ±0 for small values (e.g. 1.0e-99999) or ±HUGE_VAL for large values (e.g. 1.0e+99999) to match the handling of `std::strtod`.
|
||||
This is a divergence from the standard which states we should return the `value` argument unmodified.
|
||||
|
||||
== Examples
|
||||
@@ -62,7 +62,7 @@ This is a divergence from the standard which states we should return the `value`
|
||||
const char* buffer = "42";
|
||||
int v = 0;
|
||||
from_chars_result r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
|
||||
assert(r.ec == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(v == 42);
|
||||
----
|
||||
==== Floating Point
|
||||
@@ -71,7 +71,7 @@ assert(v == 42);
|
||||
const char* buffer = "1.2345"
|
||||
double v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
|
||||
assert(r.ec == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(v == 1.2345);
|
||||
----
|
||||
|
||||
@@ -82,7 +82,7 @@ assert(v == 1.2345);
|
||||
const char* buffer = "2a";
|
||||
unsigned v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v, 16);
|
||||
assert(r.ec == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(v == 42);
|
||||
----
|
||||
==== Floating Point
|
||||
@@ -91,34 +91,34 @@ assert(v == 42);
|
||||
const char* buffer = "1.3a2bp-10";
|
||||
double v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v, boost::charconv::chars_format::hex);
|
||||
assert(r.ec == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(v == 8.0427e-18);
|
||||
----
|
||||
|
||||
=== EINVAL
|
||||
=== std::errc::invalid_argument
|
||||
[source, c++]
|
||||
----
|
||||
const char* buffer = "-123";
|
||||
unsigned v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
|
||||
assert(r.ec == EINVAL);
|
||||
assert(r.ec == std::errc::invalid_argument);
|
||||
----
|
||||
[source, c++]
|
||||
----
|
||||
const char* buffer = "-1.573e-3";
|
||||
double v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v, boost::charconv::chars_format::fixed);
|
||||
assert(r.ec == EINVAL);
|
||||
assert(r.ec == std::errc::invalid_argument);
|
||||
----
|
||||
In the event of EINVAL v is not set by `from_chars`
|
||||
Note: In the event of std::errc::invalid_argument v is not modified by `from_chars`
|
||||
|
||||
=== ERANGE
|
||||
=== std::errc::result_out_of_range
|
||||
[source, c++]
|
||||
----
|
||||
const char* buffer = "1234";
|
||||
unsigned char v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
|
||||
assert(r.ec == ERANGE);
|
||||
assert(r.ec == std::errc::result_out_of_range);
|
||||
assert(v == 0)
|
||||
----
|
||||
In the event of ERANGE v is not set by `from_chars`
|
||||
Note: In the event of std::errc::result_out_of_range v is not modified by `from_chars`
|
||||
|
||||
@@ -22,11 +22,13 @@ This library requires a minimum of C++11.
|
||||
const char* buffer = "42";
|
||||
int v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
|
||||
assert(r == 42);
|
||||
assert(r.ec == std::errc());
|
||||
assert(v == 42);
|
||||
|
||||
char buffer[64];
|
||||
int v = 123456;
|
||||
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v);
|
||||
assert(r.ec == std::errc());
|
||||
assert(!strncmp(buffer, "123456", 6)); // Strncmp returns 0 on match
|
||||
|
||||
----
|
||||
|
||||
@@ -38,15 +38,15 @@ from_chars_result from_chars(const char* first, const char* last, Real& value, c
|
||||
struct from_chars_result
|
||||
{
|
||||
char const* ptr;
|
||||
int ec;
|
||||
std::errc ec;
|
||||
};
|
||||
----
|
||||
|
||||
`from_chars_result` is the return type of the `from_chars` family of
|
||||
overloaded functions.
|
||||
|
||||
The `ec` member is zero when the conversion was successful, `EINVAL`
|
||||
when no prefix of the passed characters form a valid value, or `ERANGE`
|
||||
The `ec` member is `std::errc()` when the conversion was successful, `std::errc::invalid_argument`
|
||||
when no prefix of the passed characters form a valid value, or `std::errc::result_out_of_range`
|
||||
when the characters form a value that would be out of range for the type.
|
||||
|
||||
The `ptr` member points to the first character not part of the matched
|
||||
@@ -66,8 +66,8 @@ Effects:;; Attempts to interpret the characters in `[first, last)` as a numeric
|
||||
consisting of an optional minus sign (only if the type is signed), and a sequence of digits. For
|
||||
bases above 10, the digit characters are `Aa` to `Zz`, as appropriate for `base`.
|
||||
|
||||
Returns:;; The `ec` member of the return value is `0` on success, `EINVAL` if
|
||||
`[first, last)` can't be interpreted as an integer of base `base`, and `ERANGE`
|
||||
Returns:;; The `ec` member of the return value is `std::errc()` on success, `std::errc::invalid_argument` if
|
||||
`[first, last)` can't be interpreted as an integer of base `base`, and `std::errc::result_out_of_range`
|
||||
if `[first, last)` when interpreted as an integer of base `base` can't be represented
|
||||
as a value of type `Integral`. The `ptr` member of the return value points to the first
|
||||
character in `[first, last)` that is not part of the matched value, or is `last` when
|
||||
@@ -84,8 +84,8 @@ Requires:;; `fmt` has the value of one of the enumerators of chars_format
|
||||
Effects:;; value is converted to a string in the style of printf in the "C" locale with the given precision. If a precision is not provided the shortest representation will be given.
|
||||
|
||||
Returns:;; The `ec` member of the return value is `0` on success.
|
||||
`EINVAL` is returned if the value can't be interpreted with the given format `fmt`.
|
||||
`ERANGE` is returned when the value can't be represented in the target floating point type.
|
||||
`std::errc::invalid_argument` is returned if the value can't be interpreted with the given format `fmt`.
|
||||
`std::errc::result_out_of_range` is returned when the value can't be represented in the target floating point type.
|
||||
The `ptr` member of the return value points to the first character in `[first, last)` that is not part of the matched value, or is `last` when all characters are matched.
|
||||
|
||||
== <boost/charconv/to_chars.hpp>
|
||||
@@ -117,18 +117,18 @@ to_chars_result to_chars(char* first, char* last, Real value, chars_format fmt =
|
||||
struct to_chars_result
|
||||
{
|
||||
char const* ptr;
|
||||
int ec;
|
||||
std::errc ec;
|
||||
};
|
||||
----
|
||||
|
||||
`to_chars_result` is the return type of the `to_chars` family of
|
||||
overloaded functions.
|
||||
|
||||
The `ec` member is zero when the conversion was successful, or `EOVERFLOW`
|
||||
The `ec` member is `std::errc()` when the conversion was successful, or `std::errc::result_out_of_range`
|
||||
when the value cannot fit into the provided buffer.
|
||||
|
||||
The `ptr` member points to the first character after the characters written,
|
||||
or `last` when `ec` is `EOVERFLOW`.
|
||||
or `last` when `ec` is `std::errc::result_out_of_range`.
|
||||
|
||||
=== to_chars
|
||||
|
||||
@@ -145,10 +145,10 @@ Effects:;; The value of `value` is converted to a string of digits in the given
|
||||
Digits in the range 10..35 (inclusive) are represented as lowercase characters
|
||||
`a`..`z`. If value is less than zero, the representation starts with a minus sign.
|
||||
|
||||
Returns:;; The `ec` member of the return value is `0` on success, and `EOVERFLOW` if
|
||||
Returns:;; The `ec` member of the return value is `std::errc()` on success, and `std::errc::result_out_of_range` if
|
||||
`[first, last)` does not contain enough space to hold the string representation of
|
||||
`value`. The `ptr` member of the return value points to the character in `[first, last]`
|
||||
that is one past the storted characters, or is `last` when `ec` is `EOVERFLOW`.
|
||||
that is one past the parsed characters, or is `last` when `ec` is `std::errc::result_out_of_range`.
|
||||
|
||||
[source, c++]
|
||||
----
|
||||
@@ -161,10 +161,10 @@ Requires:;; fmt has the value of one of the enumerators of chars_format
|
||||
Effects:;; value is converted to a string in the style of printf in the "C" locale with the given precision.
|
||||
If no precision is provided the value character string will be the shortest representation of `value`
|
||||
|
||||
Returns:;; The `ec` member of the return value is `0` on success, and `EOVERFLOW` if
|
||||
Returns:;; The `ec` member of the return value is `std::errc()` on success, and `std::errc::result_out_of_range` if
|
||||
`[first, last)` does not contain enough space to hold the string representation of
|
||||
`value`. The `ptr` member of the return value points to the character in `[first, last]`
|
||||
that is one past the storted characters, or is `last` when `ec` is `EOVERFLOW`.
|
||||
that is one past the parsed characters, or is `last` when `ec` is `std::errc::result_out_of_range`.
|
||||
|
||||
== <boost/charconv/limits.hpp>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ https://www.boost.org/LICENSE_1_0.txt
|
||||
struct to_chars_result
|
||||
{
|
||||
char* ptr;
|
||||
int ec;
|
||||
std::errc ec;
|
||||
|
||||
friend constexpr bool operator==(const to_chars_result& lhs, const to_chars_result& rhs) noexcept;
|
||||
friend constexpr bool operator!=(const to_chars_result& lhs, const to_chars_result& rhs) noexcept;
|
||||
@@ -31,16 +31,16 @@ to_chars_result(char* first, char* last, Real value, chars_format fmt = chars_fo
|
||||
|
||||
== to_chars_result
|
||||
* ptr - points to the first character
|
||||
* ec - the error code. Valid values from <cerrno> are:
|
||||
* ec - the error code. Valid values from are:
|
||||
** 0 - successful parsing
|
||||
** EINVAL - invalid argument
|
||||
** ERANGE - result out of range (e.g. overflow)
|
||||
** std::errc::invalid_argument - invalid argument
|
||||
** std::errc::result_out_of_range - result out of range (e.g. overflow)
|
||||
* operator== - compares the value of ptr and ec for equality
|
||||
* operator!= - compares the value of ptr and ec for inequality
|
||||
|
||||
== to_chars
|
||||
* first, last - pointers to the character buffer
|
||||
* value - the value to be paresed into the buffer
|
||||
* value - the value to be parsed into the buffer
|
||||
* base (integer only) - the integer base to use. Must be between 2 and 36 inclusive
|
||||
* fmt (float only) - the floating point format to use.
|
||||
See xref:chars_format.adoc[chars_format overview] for description.
|
||||
@@ -67,7 +67,7 @@ See xref:chars_format.adoc[chars_format overview] for description.
|
||||
char buffer[64] {};
|
||||
int v = 42;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v);
|
||||
assert(r.ec == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(!strcmp(buffer, "42")); // strcmp returns 0 on match
|
||||
----
|
||||
==== Floating Point
|
||||
@@ -76,7 +76,7 @@ assert(!strcmp(buffer, "42")); // strcmp returns 0 on match
|
||||
char buffer[64] {};
|
||||
double v = 1e300;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v);
|
||||
assert(r.ex == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(!strcmp(buffer, "1e+300"));
|
||||
----
|
||||
|
||||
@@ -87,7 +87,7 @@ assert(!strcmp(buffer, "1e+300"));
|
||||
char buffer[64] {};
|
||||
int v = 42;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v, 16);
|
||||
assert(r.ec == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(!strcmp(buffer, "2a")); // strcmp returns 0 on match
|
||||
----
|
||||
==== Floating Point
|
||||
@@ -96,18 +96,18 @@ assert(!strcmp(buffer, "2a")); // strcmp returns 0 on match
|
||||
char buffer[64] {};
|
||||
double v = -1.08260383390082946e+307;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v, boost::charconv::chars_format::hex);
|
||||
assert(r.ex == 0);
|
||||
assert(r.ec == std::errc());
|
||||
assert(!strcmp(buffer, "-1.ed5658af91a0fp+1019"));
|
||||
----
|
||||
|
||||
=== ERANGE
|
||||
=== std::errc::result_out_of_range
|
||||
==== Integral
|
||||
[source, c++]
|
||||
----
|
||||
char buffer[3] {};
|
||||
int v = -1234;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v, 16);
|
||||
assert(r.ec == ERANGE);
|
||||
assert(r.ec == std::errc::result_out_of_range);
|
||||
----
|
||||
==== Floating Point
|
||||
[source, c++]
|
||||
@@ -115,7 +115,7 @@ assert(r.ec == ERANGE);
|
||||
char buffer[3] {};
|
||||
double v = 1.2345;
|
||||
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v);
|
||||
assert(r.ec == ERANGE);
|
||||
assert(r.ec == std::errc::result_out_of_range);
|
||||
----
|
||||
|
||||
In the event of ERANGE to_chars_result.ptr is first
|
||||
In the event of std::errc::result_out_of_range to_chars_result.ptr is equal to first
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <boost/charconv/detail/from_chars_result.hpp>
|
||||
#include <boost/charconv/config.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <cstdlib>
|
||||
@@ -58,6 +59,10 @@ constexpr unsigned char digit_from_char(char val) noexcept
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Woverflow"
|
||||
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 9)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
|
||||
#endif
|
||||
|
||||
template <typename Integer, typename Unsigned_Integer>
|
||||
@@ -70,7 +75,7 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
|
||||
// Check pre-conditions
|
||||
if (!((first <= last) && (base >= 2 && base <= 36)))
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
Unsigned_Integer unsigned_base = static_cast<Unsigned_Integer>(base);
|
||||
@@ -95,7 +100,7 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
|
||||
}
|
||||
else if (*next == '+')
|
||||
{
|
||||
return {next, EINVAL};
|
||||
return {next, std::errc::invalid_argument};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +127,7 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
|
||||
{
|
||||
if (next != last && (*next == '-' || *next == '+'))
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
#ifdef BOOST_CHARCONV_HAS_INT128
|
||||
@@ -156,7 +161,7 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
|
||||
// If the only character was a sign abort now
|
||||
if (next == last)
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
bool overflowed = false;
|
||||
@@ -186,7 +191,7 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
|
||||
// If we have overflowed then we do not return the result
|
||||
if (overflowed)
|
||||
{
|
||||
return {next, ERANGE};
|
||||
return {next, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
value = static_cast<Integer>(result);
|
||||
@@ -202,14 +207,14 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
|
||||
}
|
||||
}
|
||||
|
||||
return {next, 0};
|
||||
return {next, std::errc()};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#elif defined(__clang__) && defined(__APPLE__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__) && (__GNUC__ < 7)
|
||||
#elif defined(__GNUC__) && (__GNUC__ < 7 || __GNUC__ >= 9)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef BOOST_CHARCONV_DETAIL_FROM_CHARS_RESULT_HPP
|
||||
#define BOOST_CHARCONV_DETAIL_FROM_CHARS_RESULT_HPP
|
||||
|
||||
#include <system_error>
|
||||
|
||||
namespace boost { namespace charconv {
|
||||
|
||||
// 22.13.3, Primitive numerical input conversion
|
||||
@@ -17,7 +19,7 @@ struct from_chars_result
|
||||
// 0 = no error
|
||||
// EINVAL = invalid_argument
|
||||
// ERANGE = result_out_of_range
|
||||
int ec;
|
||||
std::errc ec;
|
||||
|
||||
friend constexpr bool operator==(const from_chars_result& lhs, const from_chars_result& rhs) noexcept
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <boost/charconv/detail/integer_search_trees.hpp>
|
||||
#include <boost/charconv/limits.hpp>
|
||||
#include <boost/charconv/chars_format.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <cerrno>
|
||||
@@ -29,7 +30,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
{
|
||||
if (first > last)
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
auto next = first;
|
||||
@@ -43,7 +44,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
}
|
||||
else if (*next == '+')
|
||||
{
|
||||
return {next, EINVAL};
|
||||
return {next, std::errc::invalid_argument};
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -74,7 +75,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
{
|
||||
significand = 0;
|
||||
exponent = 0;
|
||||
return {next, 0};
|
||||
return {next, std::errc()};
|
||||
}
|
||||
|
||||
// Next we get the significand
|
||||
@@ -99,7 +100,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
// if fmt is chars_format::scientific the e is required
|
||||
if (fmt == chars_format::scientific)
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
exponent = 0;
|
||||
@@ -116,12 +117,12 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
}
|
||||
switch (r.ec)
|
||||
{
|
||||
case EINVAL:
|
||||
return {first, EINVAL};
|
||||
case ERANGE:
|
||||
return {next, ERANGE};
|
||||
case std::errc::invalid_argument:
|
||||
return {first, std::errc::invalid_argument};
|
||||
case std::errc::result_out_of_range:
|
||||
return {next, std::errc::result_out_of_range};
|
||||
default:
|
||||
return {next, 0};
|
||||
return {next, std::errc()};
|
||||
}
|
||||
}
|
||||
else if (*next == '.')
|
||||
@@ -148,7 +149,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
|
||||
if (next == last)
|
||||
{
|
||||
return {last, 0};
|
||||
return {last, std::errc()};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +184,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
{
|
||||
if (fmt == chars_format::scientific)
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::invalid_argument};
|
||||
}
|
||||
if (dot_position != 0 || fractional)
|
||||
{
|
||||
@@ -206,12 +207,12 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
}
|
||||
switch (r.ec)
|
||||
{
|
||||
case EINVAL:
|
||||
return {first, EINVAL};
|
||||
case ERANGE:
|
||||
return {next, ERANGE};
|
||||
case std::errc::invalid_argument:
|
||||
return {first, std::errc::invalid_argument};
|
||||
case std::errc::result_out_of_range:
|
||||
return {next, std::errc::result_out_of_range};
|
||||
default:
|
||||
return {next, 0};
|
||||
return {next, std::errc()};
|
||||
}
|
||||
}
|
||||
else if (*next == exp_char || *next == capital_exp_char)
|
||||
@@ -219,13 +220,13 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
// Would be a number without a significand e.g. e+03
|
||||
if (next == first)
|
||||
{
|
||||
return {next, EINVAL};
|
||||
return {next, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
++next;
|
||||
if (fmt == chars_format::fixed)
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
exponent = i - 1;
|
||||
@@ -249,7 +250,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
|
||||
from_chars_result r {};
|
||||
|
||||
// If the significand is 0 from chars will return EINVAL because there is nothing in the buffer,
|
||||
// If the significand is 0 from chars will return std::errc::invalid_argument because there is nothing in the buffer,
|
||||
// but it is a valid value. We need to continue parsing to get the correct value of ptr even
|
||||
// though we know we could bail now.
|
||||
//
|
||||
@@ -263,12 +264,15 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
{
|
||||
r = from_chars(significand_buffer, significand_buffer + offset, significand);
|
||||
}
|
||||
|
||||
switch (r.ec)
|
||||
{
|
||||
case EINVAL:
|
||||
return {first, EINVAL};
|
||||
case ERANGE:
|
||||
return {next, ERANGE};
|
||||
case std::errc::invalid_argument:
|
||||
return {first, std::errc::invalid_argument};
|
||||
case std::errc::result_out_of_range:
|
||||
return {next, std::errc::result_out_of_range};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (round)
|
||||
@@ -313,7 +317,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
// If the exponent can't fit in the buffer the number is not representable
|
||||
if (next != last && i == exponent_buffer_size)
|
||||
{
|
||||
return {next, ERANGE};
|
||||
return {next, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
// If the exponent was e+00 or e-00
|
||||
@@ -328,7 +332,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
exponent = extra_zeros;
|
||||
}
|
||||
|
||||
return {next, 0};
|
||||
return {next, std::errc()};
|
||||
}
|
||||
|
||||
const auto r = from_chars(exponent_buffer, exponent_buffer + i, exponent);
|
||||
@@ -337,10 +341,10 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
|
||||
switch (r.ec)
|
||||
{
|
||||
case EINVAL:
|
||||
return {first, EINVAL};
|
||||
case ERANGE:
|
||||
return {next, ERANGE};
|
||||
case std::errc::invalid_argument:
|
||||
return {first, std::errc::invalid_argument};
|
||||
case std::errc::result_out_of_range:
|
||||
return {next, std::errc::result_out_of_range};
|
||||
default:
|
||||
if (fractional)
|
||||
{
|
||||
@@ -360,7 +364,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
{
|
||||
exponent += extra_zeros;
|
||||
}
|
||||
return {next, 0};
|
||||
return {next, std::errc()};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/charconv/detail/bit_layouts.hpp>
|
||||
#include <boost/charconv/config.hpp>
|
||||
#include <boost/charconv/chars_format.hpp>
|
||||
#include <system_error>
|
||||
#include <cmath>
|
||||
|
||||
namespace boost { namespace charconv {
|
||||
@@ -108,7 +109,7 @@ from_chars_result from_chars_strtod(const char* first, const char* last, T& valu
|
||||
return_value = std::strtof(first, &str_end);
|
||||
if (return_value == HUGE_VALF)
|
||||
{
|
||||
return {last, ERANGE};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
}
|
||||
else BOOST_IF_CONSTEXPR (std::is_same<T, double>::value)
|
||||
@@ -116,7 +117,7 @@ from_chars_result from_chars_strtod(const char* first, const char* last, T& valu
|
||||
return_value = std::strtod(first, &str_end);
|
||||
if (return_value == HUGE_VAL)
|
||||
{
|
||||
return {last, ERANGE};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -124,18 +125,18 @@ from_chars_result from_chars_strtod(const char* first, const char* last, T& valu
|
||||
return_value = std::strtold(first, &str_end);
|
||||
if (return_value == HUGE_VALL)
|
||||
{
|
||||
return {last, ERANGE};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
}
|
||||
|
||||
// Since this is a fallback routine we are safe to check for 0
|
||||
if (return_value == 0 && str_end == last)
|
||||
{
|
||||
return {first, EINVAL};
|
||||
return {first, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
value = return_value;
|
||||
return {str_end, 0};
|
||||
return {str_end, std::errc()};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -146,7 +147,7 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
std::int64_t exponent {};
|
||||
|
||||
auto r = boost::charconv::detail::parser(first, last, sign, significand, exponent, fmt);
|
||||
if (r.ec != 0)
|
||||
if (r.ec != std::errc())
|
||||
{
|
||||
return r;
|
||||
}
|
||||
@@ -173,7 +174,7 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
{
|
||||
value = 1;
|
||||
r.ptr = last;
|
||||
r.ec = 0;
|
||||
r.ec = std::errc();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -182,12 +183,12 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
if (return_val == HUGE_VALF || return_val == -HUGE_VALF)
|
||||
{
|
||||
value = return_val;
|
||||
r.ec = ERANGE;
|
||||
r.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
else if (exponent < -46)
|
||||
{
|
||||
value = sign ? -0.0F : 0.0;
|
||||
r.ec = ERANGE;
|
||||
r.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -199,12 +200,12 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
if (return_val == HUGE_VAL || return_val == -HUGE_VAL)
|
||||
{
|
||||
value = return_val;
|
||||
r.ec = ERANGE;
|
||||
r.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
else if (exponent < -325)
|
||||
{
|
||||
value = sign ? -0.0 : 0.0;
|
||||
r.ec = ERANGE;
|
||||
r.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -216,7 +217,7 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
if (return_val == HUGE_VALL || return_val == -HUGE_VALL)
|
||||
{
|
||||
value = return_val;
|
||||
r.ec = ERANGE;
|
||||
r.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
#if BOOST_CHARCONV_LDBL_BITS == 64
|
||||
else if (exponent < -325)
|
||||
@@ -225,7 +226,7 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
#endif
|
||||
{
|
||||
value = sign ? -0.0L : 0.0L;
|
||||
r.ec = ERANGE;
|
||||
r.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
|
||||
else
|
||||
@@ -243,6 +244,8 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
return r;
|
||||
}
|
||||
|
||||
std::errc errno_to_errc(int errno_value) noexcept;
|
||||
|
||||
} // Namespace detail
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/charconv/detail/dragonbox.hpp>
|
||||
#include <boost/charconv/config.hpp>
|
||||
#include <boost/charconv/chars_format.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
@@ -34,12 +35,7 @@ namespace boost { namespace charconv {
|
||||
struct to_chars_result
|
||||
{
|
||||
char* ptr;
|
||||
|
||||
// Values:
|
||||
// 0 = no error
|
||||
// EINVAL = invalid_argument
|
||||
// ERANGE = result_out_of_range
|
||||
int ec;
|
||||
std::errc ec;
|
||||
|
||||
constexpr friend bool operator==(const to_chars_result& lhs, const to_chars_result& rhs) noexcept
|
||||
{
|
||||
@@ -119,7 +115,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
|
||||
|
||||
if (first > last)
|
||||
{
|
||||
return {last, EINVAL};
|
||||
return {last, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
// Strip the sign from the value and apply at the end after parsing if the type is signed
|
||||
@@ -155,7 +151,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
|
||||
|
||||
if (converted_value_digits > user_buffer_size)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
decompose32(converted_value, buffer);
|
||||
@@ -175,7 +171,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
|
||||
|
||||
if (converted_value_digits > user_buffer_size)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
if (is_negative)
|
||||
@@ -228,7 +224,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
|
||||
}
|
||||
}
|
||||
|
||||
return {first + converted_value_digits, 0};
|
||||
return {first + converted_value_digits, std::errc()};
|
||||
}
|
||||
|
||||
#ifdef BOOST_CHARCONV_HAS_INT128
|
||||
@@ -248,7 +244,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
|
||||
|
||||
if (first > last)
|
||||
{
|
||||
return {last, EINVAL};
|
||||
return {last, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
// Strip the sign from the value and apply at the end after parsing if the type is signed
|
||||
@@ -275,7 +271,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
|
||||
|
||||
if (converted_value_digits > user_buffer_size)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
if (is_negative)
|
||||
@@ -314,7 +310,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
|
||||
offset += 9;
|
||||
}
|
||||
|
||||
return {first + converted_value_digits, 0};
|
||||
return {first + converted_value_digits, std::errc()};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -327,13 +323,13 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
|
||||
|
||||
if (!((first <= last) && (base >= 2 && base <= 36)))
|
||||
{
|
||||
return {last, EINVAL};
|
||||
return {last, std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
*first++ = '0';
|
||||
return {first, 0};
|
||||
return {first, std::errc()};
|
||||
}
|
||||
|
||||
Unsigned_Integer unsigned_value {};
|
||||
@@ -418,12 +414,12 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
|
||||
|
||||
if (num_chars > output_length)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
boost::charconv::detail::memcpy(first, buffer + (buffer_size - num_chars), num_chars);
|
||||
|
||||
return {first + num_chars, 0};
|
||||
return {first + num_chars, std::errc()};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
@@ -469,7 +465,7 @@ to_chars_result to_chars_hex(char* first, char* last, Real value, int precision)
|
||||
const std::ptrdiff_t buffer_size = last - first;
|
||||
if (buffer_size < real_precision || first > last)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
// Handle edge cases first
|
||||
@@ -481,14 +477,14 @@ to_chars_result to_chars_hex(char* first, char* last, Real value, int precision)
|
||||
case FP_NAN:
|
||||
// The dragonbox impl will return the correct type of NaN
|
||||
ptr = boost::charconv::detail::to_chars(value, first, chars_format::general);
|
||||
return { ptr, 0 };
|
||||
return { ptr, std::errc() };
|
||||
case FP_ZERO:
|
||||
if (std::signbit(value))
|
||||
{
|
||||
*first++ = '-';
|
||||
}
|
||||
std::memcpy(first, "0p+0", 4);
|
||||
return {first + 4, 0};
|
||||
return {first + 4, std::errc()};
|
||||
}
|
||||
|
||||
// Extract the significand and the exponent
|
||||
@@ -552,7 +548,7 @@ to_chars_result to_chars_hex(char* first, char* last, Real value, int precision)
|
||||
const std::ptrdiff_t total_length = (value < 0) + 2 + real_precision + 2 + num_digits(abs_unbiased_exponent);
|
||||
if (total_length > buffer_size)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
return {last, std::errc::result_out_of_range};
|
||||
}
|
||||
|
||||
// Round if required
|
||||
@@ -660,7 +656,7 @@ to_chars_result to_chars_float_impl(char* first, char* last, Real value, chars_f
|
||||
}
|
||||
|
||||
auto r = to_chars_integer_impl(first, last, value_struct.significand);
|
||||
if (r.ec != 0)
|
||||
if (r.ec != std::errc())
|
||||
{
|
||||
return r;
|
||||
}
|
||||
@@ -679,7 +675,7 @@ to_chars_result to_chars_float_impl(char* first, char* last, Real value, chars_f
|
||||
abs_value /= 10;
|
||||
}
|
||||
|
||||
return { r.ptr, 0 };
|
||||
return { r.ptr, std::errc() };
|
||||
}
|
||||
else if (abs_value >= max_fractional_value && abs_value < max_value)
|
||||
{
|
||||
@@ -692,13 +688,13 @@ to_chars_result to_chars_float_impl(char* first, char* last, Real value, chars_f
|
||||
else
|
||||
{
|
||||
auto* ptr = boost::charconv::detail::to_chars(value, first, fmt);
|
||||
return { ptr, 0 };
|
||||
return { ptr, std::errc() };
|
||||
}
|
||||
}
|
||||
else if (fmt == boost::charconv::chars_format::scientific)
|
||||
{
|
||||
auto* ptr = boost::charconv::detail::to_chars(value, first, fmt);
|
||||
return { ptr, 0 };
|
||||
return { ptr, std::errc() };
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -706,7 +702,7 @@ to_chars_result to_chars_float_impl(char* first, char* last, Real value, chars_f
|
||||
if (fmt != boost::charconv::chars_format::hex)
|
||||
{
|
||||
auto* ptr = boost::charconv::detail::floff<boost::charconv::detail::main_cache_full, boost::charconv::detail::extended_cache_long>(value, precision, first, fmt);
|
||||
return { ptr, 0 };
|
||||
return { ptr, std::errc() };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <boost/charconv/from_chars.hpp>
|
||||
#include <boost/charconv/detail/bit_layouts.hpp>
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -12,6 +13,19 @@
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
std::errc boost::charconv::detail::errno_to_errc(int errno_value) noexcept
|
||||
{
|
||||
switch (errno_value)
|
||||
{
|
||||
case EINVAL:
|
||||
return std::errc::invalid_argument;
|
||||
case ERANGE:
|
||||
return std::errc::result_out_of_range;
|
||||
default:
|
||||
return std::errc();
|
||||
}
|
||||
}
|
||||
|
||||
boost::charconv::from_chars_result boost::charconv::from_chars(const char* first, const char* last, float& value, boost::charconv::chars_format fmt) noexcept
|
||||
{
|
||||
return boost::charconv::detail::from_chars_float_impl(first, last, value, fmt);
|
||||
@@ -43,7 +57,7 @@ boost::charconv::from_chars_result boost::charconv::from_chars(const char* first
|
||||
std::int64_t exponent {};
|
||||
|
||||
auto r = boost::charconv::detail::parser(first, last, sign, significand, exponent, fmt);
|
||||
if (r.ec != 0)
|
||||
if (r.ec != std::errc())
|
||||
{
|
||||
value = 0.0L;
|
||||
return r;
|
||||
@@ -54,7 +68,7 @@ boost::charconv::from_chars_result boost::charconv::from_chars(const char* first
|
||||
if (!success)
|
||||
{
|
||||
value = 0.0L;
|
||||
r.ec = ERANGE;
|
||||
r.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -107,7 +121,7 @@ boost::charconv::from_chars_result boost::charconv::from_chars(const char* first
|
||||
value = std::strtold( tmp.c_str(), &ptr );
|
||||
|
||||
r.ptr = ptr;
|
||||
r.ec = errno;
|
||||
r.ec = detail::errno_to_errc(errno);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -578,6 +578,6 @@ boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* la
|
||||
boost::charconv::to_chars_result boost::charconv::to_chars( char* first, char* last, long double value ) noexcept
|
||||
{
|
||||
std::snprintf( first, last - first, "%.*Lg", std::numeric_limits<long double>::max_digits10, value );
|
||||
return { first + std::strlen(first), 0 };
|
||||
return { first + std::strlen(first), std::errc() };
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
@@ -21,7 +22,7 @@ void test_128bit_int()
|
||||
test_value = test_value << 126;
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1);
|
||||
BOOST_TEST(r1.ec == 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST(v1 == test_value);
|
||||
BOOST_TEST(std::numeric_limits<T>::max() > static_cast<T>(std::numeric_limits<unsigned long long>::max()));
|
||||
}
|
||||
@@ -42,7 +43,7 @@ template <typename T>
|
||||
constexpr void constexpr_test()
|
||||
{
|
||||
constexpr auto results = constexpr_test_helper<T>();
|
||||
static_assert(results.second.ec == 0, "No error");
|
||||
static_assert(results.second.ec == std::errc(), "No error");
|
||||
static_assert(results.first == 42, "Value is 42");
|
||||
}
|
||||
|
||||
@@ -55,7 +56,7 @@ void base2_test()
|
||||
const char* buffer1 = "0101010";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1, 2);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, 42);
|
||||
}
|
||||
|
||||
@@ -66,13 +67,13 @@ void base16_test()
|
||||
const char* buffer1 = "2a";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1, 16);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, 42);
|
||||
|
||||
const char* buffer2 = "0";
|
||||
T v2 = 1;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2, 16);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(v2, 0);
|
||||
}
|
||||
|
||||
@@ -85,18 +86,18 @@ void overflow_test()
|
||||
|
||||
BOOST_IF_CONSTEXPR((std::numeric_limits<T>::max)() < 1234)
|
||||
{
|
||||
BOOST_TEST_EQ(r1.ec, ERANGE);
|
||||
BOOST_TEST(r1.ec == std::errc::result_out_of_range);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST_EQ(r1.ec, 0) && BOOST_TEST_EQ(v1, 1234);
|
||||
BOOST_TEST(r1.ec == std::errc()) && BOOST_TEST_EQ(v1, 1234);
|
||||
}
|
||||
|
||||
const char* buffer2 = "123456789123456789123456789";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2);
|
||||
// In the event of overflow v2 is to be returned unmodified
|
||||
BOOST_TEST_EQ(r2.ec, ERANGE) && BOOST_TEST_EQ(v2, 0);
|
||||
BOOST_TEST(r2.ec == std::errc::result_out_of_range) && BOOST_TEST_EQ(v2, 0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -105,38 +106,38 @@ void invalid_argument_test()
|
||||
const char* buffer1 = "";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, EINVAL);
|
||||
BOOST_TEST(r1.ec == std::errc::invalid_argument);
|
||||
|
||||
const char* buffer2 = "-";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2);
|
||||
BOOST_TEST_EQ(r2.ec, EINVAL);
|
||||
BOOST_TEST(r2.ec == std::errc::invalid_argument);
|
||||
|
||||
const char* buffer3 = "+";
|
||||
T v3 = 0;
|
||||
auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3);
|
||||
BOOST_TEST_EQ(r3.ec, EINVAL);
|
||||
BOOST_TEST(r3.ec == std::errc::invalid_argument);
|
||||
|
||||
BOOST_IF_CONSTEXPR(std::is_unsigned<T>::value)
|
||||
{
|
||||
const char* buffer4 = "-123";
|
||||
T v4 = 0;
|
||||
auto r4 = boost::charconv::from_chars(buffer4, buffer4 + std::strlen(buffer4), v4);
|
||||
BOOST_TEST_EQ(r4.ec, EINVAL);
|
||||
BOOST_TEST(r4.ec == std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
// Bases outside 2-36 inclusive return EINVAL
|
||||
// Bases outside 2-36 inclusive return std::errc::invalid_argument
|
||||
const char* buffer5 = "23";
|
||||
T v5 = 0;
|
||||
auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5, 1);
|
||||
BOOST_TEST_EQ(r5.ec, EINVAL);
|
||||
BOOST_TEST(r5.ec == std::errc::invalid_argument);
|
||||
auto r6 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5, 50);
|
||||
BOOST_TEST_EQ(r6.ec, EINVAL);
|
||||
BOOST_TEST(r6.ec == std::errc::invalid_argument);
|
||||
|
||||
const char* buffer7 = "+12345";
|
||||
T v7 = 3;
|
||||
auto r7 = boost::charconv::from_chars(buffer7, buffer7 + std::strlen(buffer7), v7);
|
||||
BOOST_TEST_EQ(r7.ec, EINVAL);
|
||||
BOOST_TEST(r7.ec == std::errc::invalid_argument);
|
||||
BOOST_TEST_EQ(v7, 3);
|
||||
}
|
||||
|
||||
@@ -149,17 +150,17 @@ void simple_test()
|
||||
T v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
|
||||
|
||||
BOOST_TEST_EQ( r.ec, 0 ) && BOOST_TEST_EQ(v, 34);
|
||||
BOOST_TEST( r.ec == std::errc() ) && BOOST_TEST_EQ(v, 34);
|
||||
BOOST_TEST(r == r);
|
||||
|
||||
boost::charconv::from_chars_result r2 {r.ptr, 0};
|
||||
boost::charconv::from_chars_result r2 {r.ptr, std::errc()};
|
||||
BOOST_TEST(r == r2);
|
||||
|
||||
const char* buffer2 = "12";
|
||||
T v2 = 0;
|
||||
auto r3 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer), v2);
|
||||
BOOST_TEST(r != r3);
|
||||
BOOST_TEST_EQ(r3.ec, 0) && BOOST_TEST_EQ(v2, 12);
|
||||
BOOST_TEST(r3.ec == std::errc()) && BOOST_TEST_EQ(v2, 12);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <system_error>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
@@ -17,7 +18,7 @@ void spot_value(const std::string& buffer, T expected_value, boost::charconv::ch
|
||||
{
|
||||
T v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer.c_str(), buffer.c_str() + std::strlen(buffer.c_str()), v, fmt);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
if (!BOOST_TEST_EQ(v, expected_value))
|
||||
{
|
||||
std::cerr << "Test failure for: " << buffer << " got: " << v << std::endl;
|
||||
@@ -30,7 +31,7 @@ void overflow_spot_value(const std::string& buffer, T expected_value, boost::cha
|
||||
auto v = static_cast<T>(42.L);
|
||||
auto r = boost::charconv::from_chars(buffer.c_str(), buffer.c_str() + std::strlen(buffer.c_str()), v, fmt);
|
||||
|
||||
if (!(BOOST_TEST_EQ(v, expected_value) && BOOST_TEST_EQ(r.ec, ERANGE)))
|
||||
if (!(BOOST_TEST_EQ(v, expected_value) && BOOST_TEST(r.ec == std::errc::result_out_of_range)))
|
||||
{
|
||||
std::cerr << "Test failure for: " << buffer << " got: " << v << std::endl;
|
||||
}
|
||||
@@ -55,13 +56,13 @@ void simple_integer_test()
|
||||
const char* buffer1 = "12";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, static_cast<T>(12));
|
||||
|
||||
const char* buffer2 = "1200";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(v2, static_cast<T>(1200));
|
||||
}
|
||||
|
||||
@@ -71,7 +72,7 @@ void simple_hex_integer_test()
|
||||
const char* buffer1 = "-2a";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, static_cast<T>(-42));
|
||||
}
|
||||
|
||||
@@ -81,31 +82,31 @@ void simple_scientific_test()
|
||||
const char* buffer1 = "1e1";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, static_cast<T>(1e1L));
|
||||
|
||||
const char* buffer2 = "123456789e10";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(v2, static_cast<T>(123456789e10L));
|
||||
|
||||
const char* buffer3 = "1.23456789e+10";
|
||||
T v3 = 0;
|
||||
auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_EQ(v3, static_cast<T>(1.23456789e+10L));
|
||||
|
||||
const char* buffer4 = "1234.56789e+10";
|
||||
T v4 = 0;
|
||||
auto r4 = boost::charconv::from_chars(buffer4, buffer4 + std::strlen(buffer4), v4);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_EQ(v4, static_cast<T>(1234.56789e+10L));
|
||||
|
||||
const char* buffer5 = "+1234.56789e+10";
|
||||
auto v5 = static_cast<T>(3.0L);
|
||||
auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5);
|
||||
BOOST_TEST_EQ(r5.ec, EINVAL);
|
||||
BOOST_TEST(r5.ec == std::errc::invalid_argument);
|
||||
BOOST_TEST_EQ(v5, static_cast<T>(3.0L));
|
||||
}
|
||||
|
||||
@@ -115,13 +116,13 @@ void simple_hex_scientific_test()
|
||||
const char* buffer1 = "1.3a2bp-10";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, static_cast<T>(80427e-14L));
|
||||
|
||||
const char* buffer2 = "1.234p-10";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(v2, static_cast<T>(4660e-13L));
|
||||
}
|
||||
|
||||
@@ -131,25 +132,25 @@ void dot_position_test()
|
||||
const char* buffer1 = "11.11111111";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, static_cast<T>(11.11111111L));
|
||||
|
||||
const char* buffer2 = "1111.111111";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(v2, static_cast<T>(1111.111111L));
|
||||
|
||||
const char* buffer3 = "111111.1111";
|
||||
T v3 = 0;
|
||||
auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_EQ(v3, static_cast<T>(111111.1111L));
|
||||
|
||||
const char* buffer4 = "1111111111.";
|
||||
T v4 = 0;
|
||||
auto r4 = boost::charconv::from_chars(buffer4, buffer4 + std::strlen(buffer4), v4);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_EQ(v4, static_cast<T>(1111111111.L));
|
||||
}
|
||||
|
||||
@@ -159,37 +160,37 @@ void odd_strings_test()
|
||||
const char* buffer1 = "00000000000000000000000000000000000000000005";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, static_cast<T>(5));
|
||||
|
||||
const char* buffer2 = "123456789123456789123456789";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(v2, static_cast<T>(1.23456789123456789123456789e26L));
|
||||
|
||||
const char* buffer3 = "100000000000000000000000e5";
|
||||
T v3 = 0;
|
||||
auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_EQ(v3, static_cast<T>(100000000000000000000000e5L));
|
||||
|
||||
const char* buffer4 = "1.23456789123456789123456789123456789123456789e-5";
|
||||
T v4 = 0;
|
||||
auto r4 = boost::charconv::from_chars(buffer4, buffer4 + std::strlen(buffer4), v4);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_EQ(v4, static_cast<T>(1.23456789123456789123456789123456789123456789e-5L));
|
||||
|
||||
const char* buffer5 = "1.23456789123456789123456789123456789123456789e-00000000000000000005";
|
||||
T v5 = 0;
|
||||
auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5);
|
||||
BOOST_TEST_EQ(r5.ec, 0);
|
||||
BOOST_TEST(r5.ec == std::errc());
|
||||
BOOST_TEST_EQ(v5, static_cast<T>(1.23456789123456789123456789123456789123456789e-5L));
|
||||
|
||||
const char* buffer6 = "E01";
|
||||
T v6 = 0;
|
||||
auto r6 = boost::charconv::from_chars(buffer6, buffer6 + std::strlen(buffer6), v6);
|
||||
BOOST_TEST_EQ(r6.ec, EINVAL);
|
||||
BOOST_TEST(r6.ec == std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -198,42 +199,42 @@ void zero_test()
|
||||
const char* buffer1 = "0e0";
|
||||
T v1 = 0;
|
||||
auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(v1, static_cast<T>(0));
|
||||
BOOST_TEST(!std::signbit(v1));
|
||||
|
||||
const char* buffer2 = "-0e0";
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(v2, static_cast<T>(-0));
|
||||
BOOST_TEST(std::signbit(v2));
|
||||
|
||||
const char* buffer3 = "0.0";
|
||||
T v3 = 0;
|
||||
auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_EQ(v3, static_cast<T>(0.0));
|
||||
BOOST_TEST(!std::signbit(v3));
|
||||
|
||||
const char* buffer4 = "-0.0";
|
||||
T v4 = 0;
|
||||
auto r4 = boost::charconv::from_chars(buffer4, buffer4 + std::strlen(buffer4), v4);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_EQ(v4, static_cast<T>(-0));
|
||||
BOOST_TEST(std::signbit(v4));
|
||||
|
||||
const char* buffer5 = "0";
|
||||
T v5 = 0;
|
||||
auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5);
|
||||
BOOST_TEST_EQ(r5.ec, 0);
|
||||
BOOST_TEST(r5.ec == std::errc());
|
||||
BOOST_TEST_EQ(v5, static_cast<T>(0));
|
||||
BOOST_TEST(!std::signbit(v5));
|
||||
|
||||
const char* buffer6 = "-0";
|
||||
T v6 = 0;
|
||||
auto r6 = boost::charconv::from_chars(buffer6, buffer6 + std::strlen(buffer6), v6);
|
||||
BOOST_TEST_EQ(r6.ec, 0);
|
||||
BOOST_TEST(r6.ec == std::errc());
|
||||
BOOST_TEST_EQ(v6, static_cast<T>(-0));
|
||||
BOOST_TEST(std::signbit(v6));
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ std::ostream& operator<<( std::ostream& os, boost::int128_type v )
|
||||
#include <boost/charconv/to_chars.hpp>
|
||||
#include <boost/charconv/from_chars.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <system_error>
|
||||
#include <limits>
|
||||
|
||||
void test_odr_use( int const* );
|
||||
@@ -71,24 +72,24 @@ template<typename T> void test_integral( T value )
|
||||
{
|
||||
char buffer[ boost::charconv::limits<T>::max_chars10 ];
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2 );
|
||||
|
||||
BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value );
|
||||
BOOST_TEST(r2.ec == std::errc()) && BOOST_TEST_EQ( v2, value );
|
||||
}
|
||||
|
||||
// base 10
|
||||
{
|
||||
char buffer[ boost::charconv::limits<T>::max_chars10 ];
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value, 10 );
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2, 10 );
|
||||
|
||||
BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value );
|
||||
BOOST_TEST(r2.ec == std::errc()) && BOOST_TEST_EQ( v2, value );
|
||||
}
|
||||
|
||||
// any base
|
||||
@@ -96,12 +97,12 @@ template<typename T> void test_integral( T value )
|
||||
{
|
||||
char buffer[ boost::charconv::limits<T>::max_chars ];
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value, base );
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2, base );
|
||||
|
||||
BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value );
|
||||
BOOST_TEST(r2.ec == std::errc()) && BOOST_TEST_EQ( v2, value );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,24 +124,24 @@ template<typename T> void test_floating_point( T value )
|
||||
{
|
||||
char buffer[ boost::charconv::limits<T>::max_chars10 ];
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2 );
|
||||
|
||||
BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value );
|
||||
BOOST_TEST(r2.ec == std::errc()) && BOOST_TEST_EQ( v2, value );
|
||||
}
|
||||
|
||||
// no base, max_chars
|
||||
{
|
||||
char buffer[ boost::charconv::limits<T>::max_chars ];
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2 );
|
||||
|
||||
BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value );
|
||||
BOOST_TEST(r2.ec == std::errc()) && BOOST_TEST_EQ( v2, value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ std::ostream& operator<<( std::ostream& os, boost::int128_type v )
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <system_error>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
@@ -72,18 +73,23 @@ static boost::detail::splitmix64 rng;
|
||||
|
||||
// integral types, random values
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 12)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
template<class T> void test_roundtrip( T value, int base )
|
||||
{
|
||||
char buffer[ 256 ];
|
||||
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value, base );
|
||||
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST( r.ec == std::errc() );
|
||||
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2, base );
|
||||
|
||||
if( BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value ) )
|
||||
if( BOOST_TEST( r2.ec == std::errc() ) && BOOST_TEST_EQ( v2, value ) )
|
||||
{
|
||||
}
|
||||
else
|
||||
@@ -92,6 +98,10 @@ template<class T> void test_roundtrip( T value, int base )
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 12)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
template<class T> void test_roundtrip_int8( int base )
|
||||
{
|
||||
for( int i = -256; i <= 255; ++i )
|
||||
@@ -217,12 +227,12 @@ template<class T> void test_roundtrip( T value )
|
||||
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
|
||||
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST( r.ec == std::errc() );
|
||||
|
||||
T v2 = 0;
|
||||
auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2 );
|
||||
|
||||
if( BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value ) )
|
||||
if( BOOST_TEST( r2.ec == std::errc() ) && BOOST_TEST_EQ( v2, value ) )
|
||||
{
|
||||
}
|
||||
else
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
@@ -25,7 +26,7 @@ void grind(const std::string& str, const T expected_value)
|
||||
// From string to expected value
|
||||
T v {};
|
||||
auto from_r = boost::charconv::from_chars(str.c_str(), str.c_str() + std::strlen(str.c_str()), v);
|
||||
if (!(BOOST_TEST_EQ(v, expected_value) && BOOST_TEST_EQ(from_r.ec, 0)))
|
||||
if (!(BOOST_TEST_EQ(v, expected_value) && BOOST_TEST(from_r.ec == std::errc())))
|
||||
{
|
||||
std::cerr << "Expected value: " << expected_value << "\nFrom chars value: " << v << std::endl;
|
||||
return;
|
||||
@@ -35,10 +36,10 @@ void grind(const std::string& str, const T expected_value)
|
||||
T roundtrip_v {};
|
||||
char buffer[256] {};
|
||||
auto to_r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), expected_value);
|
||||
BOOST_TEST_EQ(to_r.ec, 0);
|
||||
BOOST_TEST(to_r.ec == std::errc());
|
||||
|
||||
auto roundtrip_r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), roundtrip_v);
|
||||
if (!(BOOST_TEST_EQ(roundtrip_v, expected_value) && BOOST_TEST_EQ(roundtrip_r.ec, 0)))
|
||||
if (!(BOOST_TEST_EQ(roundtrip_v, expected_value) && BOOST_TEST(roundtrip_r.ec == std::errc())))
|
||||
{
|
||||
std::cerr << "Expected value: " << expected_value << "\nRoundtrip value: " << roundtrip_v << std::endl;
|
||||
return;
|
||||
@@ -65,7 +66,7 @@ void spot_value(const std::string& buffer, T expected_value)
|
||||
{
|
||||
T v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer.c_str(), buffer.c_str() + std::strlen(buffer.c_str()), v);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
if (!BOOST_TEST_EQ(v, expected_value))
|
||||
{
|
||||
std::cerr << "Test failure for: " << buffer << " got: " << v << std::endl;
|
||||
@@ -130,11 +131,11 @@ void issue_599_test()
|
||||
{
|
||||
char buffer[256] {};
|
||||
const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), current_ref_val);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
|
||||
double return_val {};
|
||||
const auto return_r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), return_val);
|
||||
BOOST_TEST_EQ(return_r.ec, 0);
|
||||
BOOST_TEST(return_r.ec == std::errc());
|
||||
if (!BOOST_TEST_EQ(current_ref_val, return_val))
|
||||
{
|
||||
#ifdef BOOST_CHARCONV_DEBUG
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <boost/charconv/detail/parser.hpp>
|
||||
#include <boost/charconv/chars_format.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
@@ -19,7 +20,7 @@ void test_integer()
|
||||
|
||||
const char* val1 = "12";
|
||||
auto r1 = boost::charconv::detail::parser(val1, val1 + std::strlen(val1), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(significand, 12);
|
||||
BOOST_TEST_EQ(exponent, 0);
|
||||
@@ -30,13 +31,13 @@ void test_integer()
|
||||
|
||||
const char* val2 = "123456789";
|
||||
auto r2 = boost::charconv::detail::parser(val2, val2 + std::strlen(val2), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(exponent, 0);
|
||||
BOOST_TEST_EQ(significand, 123456789);
|
||||
|
||||
auto r3 = boost::charconv::detail::parser(val2, val2 + std::strlen(val2), sign, significand, exponent, boost::charconv::chars_format::scientific);
|
||||
BOOST_TEST_EQ(r3.ec, EINVAL);
|
||||
BOOST_TEST(r3.ec == std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -48,7 +49,7 @@ void test_scientifc()
|
||||
|
||||
const char* val1 = "-1e1";
|
||||
auto r1 = boost::charconv::detail::parser(val1, val1 + std::strlen(val1), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, true);
|
||||
BOOST_TEST_EQ(significand, 1);
|
||||
BOOST_TEST_EQ(exponent, 1);
|
||||
@@ -59,7 +60,7 @@ void test_scientifc()
|
||||
|
||||
const char* val2 = "123456789e10";
|
||||
auto r2 = boost::charconv::detail::parser(val2, val2 + std::strlen(val2), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(exponent, 10);
|
||||
BOOST_TEST_EQ(significand, 123456789);
|
||||
@@ -70,31 +71,31 @@ void test_scientifc()
|
||||
|
||||
const char* val3 = "1.23456789e+10";
|
||||
auto r3 = boost::charconv::detail::parser(val3, val3 + std::strlen(val3), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(exponent, 2);
|
||||
BOOST_TEST_EQ(significand, 123456789);
|
||||
|
||||
const char* val4 = "1.23456789e-10";
|
||||
auto r4 = boost::charconv::detail::parser(val4, val4 + std::strlen(val4), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(exponent, -18);
|
||||
BOOST_TEST_EQ(significand, 123456789);
|
||||
|
||||
auto r5 = boost::charconv::detail::parser(val4, val4 + std::strlen(val4), sign, significand, exponent, boost::charconv::chars_format::fixed);
|
||||
BOOST_TEST_EQ(r5.ec, EINVAL);
|
||||
BOOST_TEST(r5.ec == std::errc::invalid_argument);
|
||||
|
||||
const char* val6 = "987654321e10";
|
||||
auto r6 = boost::charconv::detail::parser(val6, val6 + std::strlen(val6), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r6.ec, 0);
|
||||
BOOST_TEST(r6.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(exponent, 10);
|
||||
BOOST_TEST_EQ(significand, 987654321);
|
||||
|
||||
const char* val7 = "1.23456789E+10";
|
||||
auto r7 = boost::charconv::detail::parser(val7, val7 + std::strlen(val7), sign, significand, exponent);
|
||||
BOOST_TEST_EQ(r7.ec, 0);
|
||||
BOOST_TEST(r7.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(exponent, 2);
|
||||
BOOST_TEST_EQ(significand, 123456789);
|
||||
@@ -110,7 +111,7 @@ void test_hex_integer()
|
||||
|
||||
const char* val1 = "2a";
|
||||
auto r1 = boost::charconv::detail::parser(val1, val1 + std::strlen(val1), sign, significand, exponent, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(significand, 42);
|
||||
BOOST_TEST_EQ(exponent, 0);
|
||||
@@ -121,13 +122,13 @@ void test_hex_integer()
|
||||
|
||||
const char* val2 = "-1a3b5c7d9";
|
||||
auto r2 = boost::charconv::detail::parser(val2, val2 + std::strlen(val2), sign, significand, exponent, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, true);
|
||||
BOOST_TEST_EQ(exponent, 0);
|
||||
BOOST_TEST_EQ(significand, 7041566681);
|
||||
|
||||
auto r3 = boost::charconv::detail::parser(val2, val2 + std::strlen(val2), sign, significand, exponent, boost::charconv::chars_format::scientific);
|
||||
BOOST_TEST_EQ(r3.ec, EINVAL);
|
||||
BOOST_TEST(r3.ec == std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -139,7 +140,7 @@ void test_hex_scientific()
|
||||
|
||||
const char* val1 = "2ap+5";
|
||||
auto r1 = boost::charconv::detail::parser(val1, val1 + std::strlen(val1), sign, significand, exponent, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, false);
|
||||
BOOST_TEST_EQ(significand, 42);
|
||||
BOOST_TEST_EQ(exponent, 5);
|
||||
@@ -150,23 +151,23 @@ void test_hex_scientific()
|
||||
|
||||
const char* val2 = "-1.3a2bp-10";
|
||||
auto r2 = boost::charconv::detail::parser(val2, val2 + std::strlen(val2), sign, significand, exponent, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, true);
|
||||
BOOST_TEST_EQ(exponent, -14);
|
||||
BOOST_TEST_EQ(significand, 80427);
|
||||
|
||||
auto r3 = boost::charconv::detail::parser(val2, val2 + std::strlen(val2), sign, significand, exponent, boost::charconv::chars_format::scientific);
|
||||
BOOST_TEST_EQ(r3.ec, EINVAL);
|
||||
BOOST_TEST(r3.ec == std::errc::invalid_argument);
|
||||
|
||||
const char* val4 = "-1.3A2BP-10";
|
||||
auto r4 = boost::charconv::detail::parser(val4, val4 + std::strlen(val4), sign, significand, exponent, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_EQ(sign, true);
|
||||
BOOST_TEST_EQ(exponent, -14);
|
||||
BOOST_TEST_EQ(significand, 80427);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int main()
|
||||
{
|
||||
test_integer<float>();
|
||||
test_integer<double>();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
@@ -19,14 +20,14 @@ void test_128bit_int()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(1234);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "1234");
|
||||
|
||||
// Use 64-bit path
|
||||
char buffer2[64] {};
|
||||
T v2 = static_cast<T>(1234123412341234LL);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "1234123412341234");
|
||||
|
||||
// Use 128-bit path
|
||||
@@ -35,12 +36,12 @@ void test_128bit_int()
|
||||
test_value = test_value << 126;
|
||||
T v3 = 0;
|
||||
auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3);
|
||||
BOOST_TEST(r3.ec == 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST(v3 == test_value);
|
||||
|
||||
char buffer4[64] {};
|
||||
auto r4 = boost::charconv::to_chars(buffer4, buffer4 + sizeof(buffer4), v3);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer3, buffer4);
|
||||
|
||||
// Failing from roundtrip test
|
||||
@@ -50,35 +51,35 @@ void test_128bit_int()
|
||||
const char* buffer5 = "-103527168272318384816037687533325012784";
|
||||
T v5 = 0;
|
||||
auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5);
|
||||
BOOST_TEST(r5.ec == 0);
|
||||
BOOST_TEST(r5.ec == std::errc());
|
||||
BOOST_TEST(v5 < 0);
|
||||
|
||||
char buffer6[64] {};
|
||||
auto r6 = boost::charconv::to_chars(buffer6, buffer6 + sizeof(buffer6), v5);
|
||||
BOOST_TEST_EQ(r6.ec, 0);
|
||||
BOOST_TEST(r6.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer5, buffer6);
|
||||
|
||||
// And back again
|
||||
T v7 = 0;
|
||||
auto r7 = boost::charconv::from_chars(buffer6, buffer6 + std::strlen(buffer6), v7);
|
||||
BOOST_TEST(r7.ec == 0);
|
||||
BOOST_TEST(r7.ec == std::errc());
|
||||
BOOST_TEST(v5 == v7);;
|
||||
|
||||
// Second failing test
|
||||
const char* buffer10 = "-170141183460469231731687303715884105728";
|
||||
T v10 = 0;
|
||||
auto r10 = boost::charconv::from_chars(buffer10, buffer10 + std::strlen(buffer10), v10);
|
||||
BOOST_TEST(r10.ec == 0);
|
||||
BOOST_TEST(r10.ec == std::errc());
|
||||
BOOST_TEST(v10 < 0);
|
||||
|
||||
char buffer11[64] {};
|
||||
auto r11 = boost::charconv::to_chars(buffer11, buffer11 + sizeof(buffer11), v10);
|
||||
BOOST_TEST_EQ(r11.ec, 0);
|
||||
BOOST_TEST(r11.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer10, buffer11);
|
||||
|
||||
T v11 = 0;
|
||||
auto r12 = boost::charconv::from_chars(buffer11, buffer11 + std::strlen(buffer11), v11);
|
||||
BOOST_TEST(r12.ec == 0);
|
||||
BOOST_TEST(r12.ec == std::errc());
|
||||
BOOST_TEST(v10 == v11);
|
||||
}
|
||||
}
|
||||
@@ -89,7 +90,7 @@ void specific_value_tests(T value)
|
||||
{
|
||||
char buffer[64] {};
|
||||
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, value);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
std::string value_string = std::to_string(value);
|
||||
BOOST_TEST_CSTR_EQ(buffer, value_string.c_str());
|
||||
}
|
||||
@@ -98,7 +99,7 @@ void off_by_one_tests(int value)
|
||||
{
|
||||
char buffer[64] {};
|
||||
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, value);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
std::string value_string = std::to_string(value);
|
||||
BOOST_TEST_CSTR_EQ(buffer, value_string.c_str());
|
||||
}
|
||||
@@ -109,7 +110,7 @@ void base_thirtytwo_tests()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 32);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "1a");
|
||||
}
|
||||
|
||||
@@ -119,7 +120,7 @@ void base_sixteen_tests()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 16);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "2a");
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ void base_eight_tests()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 8);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "52");
|
||||
}
|
||||
|
||||
@@ -139,7 +140,7 @@ void base_four_tests()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 4);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "222");
|
||||
}
|
||||
|
||||
@@ -150,13 +151,13 @@ void base_30_tests()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(1234);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 30);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "1b4");
|
||||
|
||||
char buffer2[64] {};
|
||||
T v2 = static_cast<T>(-4321);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2, 30);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "-4o1");
|
||||
}
|
||||
|
||||
@@ -166,12 +167,12 @@ void overflow_tests()
|
||||
char buffer1[2] {};
|
||||
T v1 = static_cast<T>(250);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1);
|
||||
BOOST_TEST_EQ(r1.ec, EOVERFLOW);
|
||||
BOOST_TEST(r1.ec == std::errc::result_out_of_range);
|
||||
|
||||
char buffer2[3] {};
|
||||
T v2 = static_cast<T>(12341234);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST_EQ(r2.ec, EOVERFLOW);
|
||||
BOOST_TEST(r2.ec == std::errc::result_out_of_range);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -180,7 +181,7 @@ void base_two_tests()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 2);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "101010");
|
||||
}
|
||||
|
||||
@@ -190,13 +191,13 @@ void sixty_four_bit_tests()
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(-1234);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "-1234");
|
||||
|
||||
char buffer2[64] {};
|
||||
T v2 = static_cast<T>(1234123412341234LL);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "1234123412341234");
|
||||
}
|
||||
|
||||
@@ -206,21 +207,21 @@ void sixty_four_bit_tests<std::uint64_t>()
|
||||
char buffer1[64] {};
|
||||
std::uint64_t v1 = (std::numeric_limits<std::uint64_t>::max)();
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "18446744073709551615");
|
||||
|
||||
// Cutting this value in half would overflow a 32 bit unsigned for the back 10 digits
|
||||
char buffer2[64] {};
|
||||
std::uint64_t v2 = UINT64_C(9999999999999999999);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "9999999999999999999");
|
||||
|
||||
// Account for zeros in the back half of the split
|
||||
char buffer3[64] {};
|
||||
std::uint64_t v3 = UINT64_C(10000000000000000000);
|
||||
auto r3 = boost::charconv::to_chars(buffer3, buffer3 + sizeof(buffer3) - 1, v3);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer3, "10000000000000000000");
|
||||
}
|
||||
|
||||
@@ -230,7 +231,7 @@ void negative_vals_test()
|
||||
char buffer1[10] {};
|
||||
T v = -4321;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "-4321");
|
||||
}
|
||||
|
||||
@@ -240,7 +241,7 @@ void simple_test()
|
||||
char buffer1[64] {};
|
||||
T v = 34;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "34");
|
||||
|
||||
boost::charconv::to_chars_result r {r1.ptr, r1.ec};
|
||||
@@ -250,16 +251,16 @@ void simple_test()
|
||||
T v2 = 12;
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST(r1 != r2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "12");
|
||||
|
||||
// If the base is not 2-36 inclusive return invalid value
|
||||
char buffer3[64] {};
|
||||
T v3 = 12;
|
||||
auto r3 = boost::charconv::to_chars(buffer3, buffer3 + sizeof(buffer3) - 1, v3, -2);
|
||||
BOOST_TEST_EQ(r3.ec, EINVAL);
|
||||
BOOST_TEST(r3.ec == std::errc::invalid_argument);
|
||||
auto r4 = boost::charconv::to_chars(buffer3, buffer3 + sizeof(buffer3) - 1, v3, 90);
|
||||
BOOST_TEST_EQ(r4.ec, EINVAL);
|
||||
BOOST_TEST(r4.ec == std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
@@ -21,19 +22,19 @@ void printf_divergence()
|
||||
char buffer1[256] {};
|
||||
T v1 = 3.4;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "3.4");
|
||||
|
||||
char buffer2[256] {};
|
||||
T v2 = 3000.40;
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2), v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "3000.4");
|
||||
|
||||
char buffer3[256] {};
|
||||
T v3 = -3000000300000000.5;
|
||||
auto r3 = boost::charconv::to_chars(buffer3, buffer3 + sizeof(buffer3), v3);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer3, "-3000000300000000.5");
|
||||
}
|
||||
|
||||
@@ -43,11 +44,11 @@ void integer_general_format()
|
||||
char buffer1[256] {};
|
||||
T v1 = 1217.2772861138403;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "1217.2772861138403");
|
||||
T return_v1;
|
||||
auto r1_return = boost::charconv::from_chars(buffer1, buffer1 + strlen(buffer1), return_v1);
|
||||
BOOST_TEST_EQ(r1_return.ec, 0);
|
||||
BOOST_TEST(r1_return.ec == std::errc());
|
||||
BOOST_TEST_EQ(return_v1, v1);
|
||||
}
|
||||
|
||||
@@ -57,37 +58,37 @@ void non_finite_values(boost::charconv::chars_format fmt = boost::charconv::char
|
||||
char buffer1[256] {};
|
||||
T v1 = std::numeric_limits<T>::infinity();
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1), v1, fmt, precision);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "inf");
|
||||
|
||||
char buffer2[256] {};
|
||||
T v2 = -std::numeric_limits<T>::infinity();
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2), v2, fmt, precision);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "-inf");
|
||||
|
||||
char buffer3[256] {};
|
||||
T v3 = std::numeric_limits<T>::quiet_NaN();
|
||||
auto r3 = boost::charconv::to_chars(buffer3, buffer3 + sizeof(buffer3), v3, fmt, precision);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST(r3.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer3, "nan");
|
||||
|
||||
char buffer4[256] {};
|
||||
T v4 = -std::numeric_limits<T>::quiet_NaN();
|
||||
auto r4 = boost::charconv::to_chars(buffer4, buffer4 + sizeof(buffer4), v4, fmt, precision);
|
||||
BOOST_TEST_EQ(r4.ec, 0);
|
||||
BOOST_TEST(r4.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer4, "-nan(ind)");
|
||||
|
||||
char buffer5[256] {};
|
||||
T v5 = std::numeric_limits<T>::signaling_NaN();
|
||||
auto r5 = boost::charconv::to_chars(buffer5, buffer5 + sizeof(buffer5), v5, fmt, precision);
|
||||
BOOST_TEST_EQ(r5.ec, 0);
|
||||
BOOST_TEST(r5.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer5, "nan(snan)");
|
||||
|
||||
char buffer6[256] {};
|
||||
T v6 = -std::numeric_limits<T>::signaling_NaN();
|
||||
auto r6 = boost::charconv::to_chars(buffer6, buffer6 + sizeof(buffer6), v6, fmt, precision);
|
||||
BOOST_TEST_EQ(r6.ec, 0);
|
||||
BOOST_TEST(r6.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer6, "-nan(snan)");
|
||||
}
|
||||
|
||||
@@ -97,7 +98,7 @@ void fixed_values()
|
||||
char buffer1[256] {};
|
||||
T v1 = 61851632;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1), v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "61851632");
|
||||
}
|
||||
|
||||
@@ -107,13 +108,13 @@ void failing_ci_values()
|
||||
char buffer1[256] {};
|
||||
T v1 = -1.08260383390082946e+307;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1), v1, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST(r1.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "-1.ed5658af91a0fp+1019");
|
||||
|
||||
char buffer2[256] {};
|
||||
T v2 = -9.52743282403084637e+306;
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2), v2, boost::charconv::chars_format::hex);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST(r2.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "-1.b22914956c56fp+1019");
|
||||
}
|
||||
|
||||
@@ -122,7 +123,7 @@ void spot_check(T v, const std::string& str, boost::charconv::chars_format fmt =
|
||||
{
|
||||
char buffer[256] {};
|
||||
const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), v, fmt);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
BOOST_TEST(r.ec == std::errc());
|
||||
BOOST_TEST_CSTR_EQ(buffer, str.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ void test_spot(T val, boost::charconv::chars_format fmt = boost::charconv::chars
|
||||
r_stl = std::to_chars(buffer_stl, buffer_stl + sizeof(buffer_stl), val, stl_fmt, precision);
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ(r_boost.ec, 0);
|
||||
BOOST_TEST(r_boost.ec == std::errc());
|
||||
if (r_stl.ec != std::errc())
|
||||
{
|
||||
// STL failed
|
||||
@@ -114,16 +114,16 @@ void non_finite_test(boost::charconv::chars_format fmt = boost::charconv::chars_
|
||||
test_spot(-std::numeric_limits<T>::infinity(), fmt, i);
|
||||
test_spot(std::numeric_limits<T>::quiet_NaN(), fmt, i);
|
||||
|
||||
#if (defined(__clang__) && __clang_major__ >= 16) || defined(_MSC_VER)
|
||||
#if (defined(__clang__) && __clang_major__ >= 16 && defined(__APPLE__)) || defined(_MSC_VER)
|
||||
//
|
||||
// Newer clang and MSVC both give the following:
|
||||
// Newer apple clang and MSVC both give the following:
|
||||
//
|
||||
// -qNaN = -nan(ind)
|
||||
//
|
||||
test_spot(-std::numeric_limits<T>::quiet_NaN(), fmt, i);
|
||||
#endif
|
||||
|
||||
#if (defined(__clang__) && __clang_major__ >= 16)
|
||||
#if (defined(__clang__) && __clang_major__ >= 16 && defined(__APPLE__))
|
||||
//
|
||||
// Newer clang also gives the following:
|
||||
//
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
@@ -104,7 +105,7 @@ template<class T> void test_sprintf( T value )
|
||||
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
|
||||
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST( r.ec == std::errc() );
|
||||
|
||||
char buffer2[ 256 ];
|
||||
std::snprintf( buffer2, sizeof( buffer2 ), fmt_from_type( value ), value );
|
||||
@@ -133,7 +134,7 @@ template<class T> void test_sprintf_float( T value, boost::charconv::chars_forma
|
||||
r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value, fmt, std::numeric_limits<T>::max_digits10);
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( r.ec, 0 );
|
||||
BOOST_TEST( r.ec == std::errc() );
|
||||
|
||||
char buffer2[ 256 ];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user