Skip to content

Commit

Permalink
Merge pull request #111 from cppalliance/110
Browse files Browse the repository at this point in the history
Add macro to change ERANGE handling.
  • Loading branch information
mborland authored Jan 5, 2024
2 parents 1927ac9 + 070c83b commit 59b61b1
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .drone.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
windows_pipeline(
"Windows VS2015 msvc-14.0",
"cppalliance/dronevs2015",
{ TOOLSET: 'msvc-14.0', CXXSTD: '14,latest' },
{ TOOLSET: 'msvc-14.0', CXXSTD: '14,latest', B2_DONT_EMBED_MANIFEST: '1' },
),

windows_pipeline(
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ jobs:
os: ubuntu-22.04
install:
- g++-12-multilib
- toolset: gcc-12
cxxstd: "03,11,14,17,20,23"
address_model: 32,64
os: ubuntu-22.04
install:
- g++-12-multilib
define: "BOOST_CHARCONV_STD_ERANGE"
- toolset: gcc-12
cxxstd: "03-gnu,11-gnu,14-gnu,17-gnu,20-gnu,23-gnu"
address_model: 32,64
Expand Down Expand Up @@ -454,6 +461,10 @@ jobs:
then
B2_ARGS+=("address-model=${{matrix.address_model}}")
fi
if [ -n "${{matrix.define}}" ]
then
B2_ARGS+=("define=${{matrix.define}}")
fi
B2_ARGS+=("libs/$LIBRARY/test")
./b2 "${B2_ARGS[@]}"
Expand Down
1 change: 1 addition & 0 deletions doc/charconv/from_chars.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ from_chars_result from_chars(const char* first, const char* last, Real& value, c
=== from_chars for floating point types
* 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.
** If you want the behavior from the standard, compile the library with `BOOST_CHARCONV_STD_ERANGE` defined.
* These functions have been tested to support all built-in floating-point types and those from C++23's `<stdfloat>`
** Long doubles can be 64, 80, or 128-bit, but must be IEEE 754 compliant. An example of a non-compliant, and therefore unsupported, format is `__ibm128`.
** Use of `__float128` or `std::float128_t` requires compiling with `-std=gnu++xx` and linking GCC's `libquadmath`.
Expand Down
40 changes: 40 additions & 0 deletions src/from_chars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,52 @@

boost::charconv::from_chars_result boost::charconv::from_chars(const char* first, const char* last, float& value, boost::charconv::chars_format fmt) noexcept
{
#ifdef BOOST_CHARCONV_STD_ERANGE

float temp_value;
const auto r = fmt != boost::charconv::chars_format::hex ? boost::charconv::detail::fast_float::from_chars(first, last, temp_value, fmt) :
boost::charconv::detail::from_chars_float_impl(first, last, temp_value, fmt);
if (r)
{
value = temp_value;
}

return r;

#else

if (fmt != boost::charconv::chars_format::hex)
{
return boost::charconv::detail::fast_float::from_chars(first, last, value, fmt);
}
return boost::charconv::detail::from_chars_float_impl(first, last, value, fmt);

#endif
}

boost::charconv::from_chars_result boost::charconv::from_chars(const char* first, const char* last, double& value, boost::charconv::chars_format fmt) noexcept
{
#ifdef BOOST_CHARCONV_STD_ERANGE

double temp_value;
const auto r = fmt != boost::charconv::chars_format::hex ? boost::charconv::detail::fast_float::from_chars(first, last, temp_value, fmt) :
boost::charconv::detail::from_chars_float_impl(first, last, temp_value, fmt);
if (r)
{
value = temp_value;
}

return r;

#else

if (fmt != boost::charconv::chars_format::hex)
{
return boost::charconv::detail::fast_float::from_chars(first, last, value, fmt);
}
return boost::charconv::detail::from_chars_float_impl(first, last, value, fmt);

#endif
}

#ifdef BOOST_CHARCONV_HAS_FLOAT128
Expand Down Expand Up @@ -79,7 +111,11 @@ boost::charconv::from_chars_result boost::charconv::from_chars(const char* first
auto return_val = boost::charconv::detail::compute_float128(exponent, significand, sign, success);
r.ec = static_cast<std::errc>(success);

#ifdef BOOST_CHARCONV_STD_ERANGE
if (r.ec == std::errc())
#else
if (r.ec == std::errc() || r.ec == std::errc::result_out_of_range)
#endif
{
value = return_val;
}
Expand Down Expand Up @@ -202,7 +238,11 @@ boost::charconv::from_chars_result boost::charconv::from_chars(const char* first
auto return_val = boost::charconv::detail::compute_float80<long double>(exponent, significand, sign, success);
r.ec = success;

#ifdef BOOST_CHARCONV_STD_ERANGE
if (r.ec == std::errc())
#else
if (r.ec == std::errc() || r.ec == std::errc::result_out_of_range)
#endif
{
value = return_val;
}
Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ run from_chars_float2.cpp ;
run-fail STL_benchmark.cpp : : : [ requires cxx17_hdr_charconv ] [ check-target-builds ../config//has_double_conversion "Google double-coversion support" : <library>"double-conversion" ] ;
run test_float128.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : <library>"quadmath" ] ;
run P2497.cpp ;
run github_issue_110.cpp ;
10 changes: 10 additions & 0 deletions test/from_chars_float.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,14 @@ void boost_json_test()
fc("6372891218502368041059e064");
}

// Issue 37 conflicts with handling from 110
#ifdef BOOST_CHARCONV_STD_ERANGE

template <typename T>
void test_issue_37() {}

#else

template <typename T>
void test_issue_37()
{
Expand Down Expand Up @@ -422,6 +430,8 @@ void test_issue_37()
overflow_spot_value("-1.0e-99999", static_cast<T>(-0.0L));
}

#endif

template <typename T>
void test_issue_45(T v, const std::string& full_buffer, const std::ptrdiff_t ptr, boost::charconv::chars_format fmt = boost::charconv::chars_format::general)
{
Expand Down
66 changes: 66 additions & 0 deletions test/github_issue_110.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2024 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/charconv.hpp>
#include <boost/core/lightweight_test.hpp>

#ifdef BOOST_CHARCONV_STD_ERANGE

template <typename T>
void overflow_spot_value(const std::string& buffer, boost::charconv::chars_format fmt = boost::charconv::chars_format::general)
{
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, static_cast<T>(42.L)) && BOOST_TEST(r.ec == std::errc::result_out_of_range)))
{
std::cerr << "Test failure for: " << buffer << " got: " << v << std::endl;
}
}

template <typename T>
void test()
{
const auto format_list = {boost::charconv::chars_format::general, boost::charconv::chars_format::scientific, boost::charconv::chars_format::hex};

for (const auto format : format_list)
{
if (format != boost::charconv::chars_format::hex)
{
overflow_spot_value<T>("1e99999", format);
overflow_spot_value<T>("-1e99999", format);
overflow_spot_value<T>("1e-99999", format);
overflow_spot_value<T>("-1.0e-99999", format);
}
else
{
overflow_spot_value<T>("1p99999", format);
overflow_spot_value<T>("-1p99999", format);
overflow_spot_value<T>("1p-99999", format);
overflow_spot_value<T>("-1.0p-99999", format);
}
}
}

int main()
{
test<float>();
test<double>();
test<long double>();

#ifdef BOOST_CHARCONV_HAS_FLOAT128
test<__float128>();
#endif

return boost::report_errors();
}

#else

int main()
{
return 0;
}

#endif
12 changes: 12 additions & 0 deletions test/test_boost_json_values.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,16 @@ void test_within_ulp()
}
};

// Directly conflicts with the expected outcomes
#ifdef BOOST_CHARCONV_STD_ERANGE

int main()
{
return 0;
}

#else

int main()
{
issue_599_test();
Expand Down Expand Up @@ -479,3 +489,5 @@ int main()

return boost::report_errors();
}

#endif

0 comments on commit 59b61b1

Please sign in to comment.