Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix to_chars errc value for overflow #167

Merged
merged 2 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions doc/charconv/to_chars.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ https://www.boost.org/LICENSE_1_0.txt
== to_chars overview

`to_chars` is a set of functions that attempts to convert `value` into a character buffer specified by `[first, last)`.
The result of `to_chars` is `to_chars_result` which on success returns `ptr` equal to one-past-the-end of the characters written and `ec == std::errc()` and on failure returns `std::errc::result_out_of_range` and `ptr == last`.
The result of `to_chars` is `to_chars_result` which on success returns `ptr` equal to one-past-the-end of the characters written and `ec == std::errc()` and on failure returns `std::errc::value_too_large` and `ptr == last`.
`to_chars` does not null-terminate the returned characters.

== Definitions
Expand Down Expand Up @@ -55,7 +55,7 @@ See <<chars_format overview>> for description.
|===
|Return Value | Description
|`std::errc()` | Successful Parsing
| `std::errc::result_out_of_range` | 1) Overflow
| `std::errc::value_too_large` | 1) Overflow

2) Underflow
|===
Expand Down Expand Up @@ -138,14 +138,14 @@ std::cout << "U: " << buffer_u << "\nV: " << buffer_v << std::endl;

----

=== std::errc::result_out_of_range
=== std::errc::value_too_large
==== 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 == std::errc::result_out_of_range);
assert(r.ec == std::errc::value_too_large);
assert(!r); // Same as above but less verbose. Added in C++26.
----
==== Floating Point
Expand All @@ -154,8 +154,8 @@ assert(!r); // Same as above but less verbose. Added in C++26.
char buffer[3] {};
double v = 1.2345;
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v);
assert(r.ec == std::errc::result_out_of_range);
assert(r.ec == std::errc::value_too_large);
assert(!r); // Same as above but less verbose. Added in C++26.
----

In the event of `std::errc::result_out_of_range`, to_chars_result.ptr is equal to `last`
In the event of `std::errc::value_too_large`, to_chars_result.ptr is equal to `last`
10 changes: 5 additions & 5 deletions include/boost/charconv/detail/dragonbox/dragonbox.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2605,7 +2605,7 @@
}
else
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 2608 in include/boost/charconv/detail/dragonbox/dragonbox.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/dragonbox/dragonbox.hpp#L2608

Added line #L2608 was not covered by tests
}
}
}
Expand All @@ -2628,7 +2628,7 @@
}
else
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}
}
else
Expand Down Expand Up @@ -2677,7 +2677,7 @@
}
else
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}
}
else
Expand All @@ -2689,7 +2689,7 @@
}
else
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}
}
}
Expand All @@ -2702,7 +2702,7 @@
}
else
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions include/boost/charconv/detail/dragonbox/floff.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,7 @@
{
if (first >= last)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 1311 in include/boost/charconv/detail/dragonbox/floff.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/dragonbox/floff.hpp#L1311

Added line #L1311 was not covered by tests
}

auto buffer_size = static_cast<std::size_t>(last - first);
Expand Down Expand Up @@ -1339,7 +1339,7 @@

if (buffer_size < inf_chars)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}

std::memcpy(buffer, "inf", inf_chars); // NOLINT : Specifically not null-terminating
Expand All @@ -1359,7 +1359,7 @@

if (buffer_size < nan_chars)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}

std::memcpy(buffer, "nan", nan_chars); // NOLINT : Specifically not null-terminating
Expand All @@ -1371,7 +1371,7 @@

if (buffer_size < neg_nan_chars)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}

std::memcpy(buffer, "nan(ind)", neg_nan_chars); // NOLINT : Specifically not null-terminating
Expand All @@ -1384,7 +1384,7 @@

if (buffer_size < snan_chars)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}

std::memcpy(buffer, "nan(snan)", snan_chars); // NOLINT : Specifically not null-terminating
Expand Down Expand Up @@ -1419,7 +1419,7 @@

if (buffer_size < zero_chars)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 1422 in include/boost/charconv/detail/dragonbox/floff.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/dragonbox/floff.hpp#L1422

Added line #L1422 was not covered by tests
}

std::memcpy(buffer, "0e+00", zero_chars);
Expand All @@ -1429,7 +1429,7 @@
{
if (buffer_size < static_cast<std::size_t>(precision) + 6U)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 1432 in include/boost/charconv/detail/dragonbox/floff.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/dragonbox/floff.hpp#L1432

Added line #L1432 was not covered by tests
}

std::memcpy(buffer, "0.", 2); // NOLINT : Specifically not null-terminating
Expand Down Expand Up @@ -1460,7 +1460,7 @@

if (buffer_size < static_cast<std::size_t>(remaining_digits))
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 1463 in include/boost/charconv/detail/dragonbox/floff.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/dragonbox/floff.hpp#L1463

Added line #L1463 was not covered by tests
}

/////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
6 changes: 3 additions & 3 deletions include/boost/charconv/detail/ryu/ryu_generic_128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@
// Option 2: Append 0s to the end of the number until we get the proper output
if (current_len + v.exponent > result_size)
{
return -static_cast<int>(std::errc::result_out_of_range);
return -static_cast<int>(std::errc::value_too_large);

Check warning on line 404 in include/boost/charconv/detail/ryu/ryu_generic_128.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/ryu/ryu_generic_128.hpp#L404

Added line #L404 was not covered by tests
}

memset(r.ptr, '0', static_cast<std::size_t>(v.exponent));
Expand All @@ -419,7 +419,7 @@
// Option 4: Leading 0s
if (-v.exponent + 2 > result_size)
{
return -static_cast<int>(std::errc::result_out_of_range);
return -static_cast<int>(std::errc::value_too_large);

Check warning on line 422 in include/boost/charconv/detail/ryu/ryu_generic_128.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/ryu/ryu_generic_128.hpp#L422

Added line #L422 was not covered by tests
}

memmove(result - v.exponent - current_len + 2, result, static_cast<std::size_t>(current_len));
Expand Down Expand Up @@ -480,7 +480,7 @@

if (index + olength > static_cast<size_t>(result_size))
{
return -static_cast<int>(std::errc::result_out_of_range);
return -static_cast<int>(std::errc::value_too_large);

Check warning on line 483 in include/boost/charconv/detail/ryu/ryu_generic_128.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/ryu/ryu_generic_128.hpp#L483

Added line #L483 was not covered by tests
}
else if (olength == 0)
{
Expand Down
8 changes: 4 additions & 4 deletions include/boost/charconv/detail/to_chars_integer_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@

if (converted_value_digits > user_buffer_size)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}

decompose32(converted_value, buffer);
Expand All @@ -151,7 +151,7 @@

if (converted_value_digits > user_buffer_size)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 154 in include/boost/charconv/detail/to_chars_integer_impl.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/to_chars_integer_impl.hpp#L154

Added line #L154 was not covered by tests
}

if (is_negative)
Expand Down Expand Up @@ -258,7 +258,7 @@

if (converted_value_digits > user_buffer_size)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 261 in include/boost/charconv/detail/to_chars_integer_impl.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/to_chars_integer_impl.hpp#L261

Added line #L261 was not covered by tests
}

if (is_negative)
Expand Down Expand Up @@ -409,7 +409,7 @@

if (num_chars > output_length)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 412 in include/boost/charconv/detail/to_chars_integer_impl.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/charconv/detail/to_chars_integer_impl.hpp#L412

Added line #L412 was not covered by tests
}

boost::charconv::detail::memcpy(first, buffer + (buffer_size - static_cast<unsigned long>(num_chars)),
Expand Down
22 changes: 11 additions & 11 deletions src/to_chars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@
const std::ptrdiff_t total_length = total_buffer_length(9, exponent, false);
if (total_length > (last - first))
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 275 in src/to_chars.cpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars.cpp#L275

Added line #L275 was not covered by tests
}

// Print significand.
Expand Down Expand Up @@ -315,7 +315,7 @@
const std::ptrdiff_t total_length = total_buffer_length(17, exponent, false);
if (total_length > (last - first))
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 318 in src/to_chars.cpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars.cpp#L318

Added line #L318 was not covered by tests
}

// Print significand by decomposing it into a 9-digit block and a 8-digit block.
Expand Down Expand Up @@ -593,7 +593,7 @@
}
else
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}
}
#endif
Expand All @@ -603,7 +603,7 @@
auto real_precision = boost::charconv::detail::get_real_precision<long double>(precision);
if (buffer_size < real_precision || first > last)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 606 in src/to_chars.cpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars.cpp#L606

Added line #L606 was not covered by tests
}

if (fmt == boost::charconv::chars_format::general || fmt == boost::charconv::chars_format::scientific)
Expand All @@ -629,9 +629,9 @@
{
return { first + num_chars, std::errc() };
}
else if (num_chars == -static_cast<int>(std::errc::result_out_of_range))
else if (num_chars == -static_cast<int>(std::errc::value_too_large))

Check warning on line 632 in src/to_chars.cpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars.cpp#L632

Added line #L632 was not covered by tests
{
return { last, std::errc::result_out_of_range };
return { last, std::errc::value_too_large };

Check warning on line 634 in src/to_chars.cpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars.cpp#L634

Added line #L634 was not covered by tests
}
}

Expand Down Expand Up @@ -686,7 +686,7 @@
// Sanity check our bounds
if (first >= last)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}

char* const original_first = first;
Expand All @@ -705,7 +705,7 @@
auto real_precision = boost::charconv::detail::get_real_precision<__float128>(precision);
if (buffer_size < real_precision || first > last)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}

if ((fmt == boost::charconv::chars_format::general || fmt == boost::charconv::chars_format::scientific))
Expand All @@ -719,7 +719,7 @@
}
else if (num_chars == -1)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};
}
}
else if (fmt == boost::charconv::chars_format::hex)
Expand All @@ -735,9 +735,9 @@
{
return { first + num_chars, std::errc() };
}
else if (num_chars == -static_cast<int>(std::errc::result_out_of_range))
else if (num_chars == -static_cast<int>(std::errc::value_too_large))
{
return { last, std::errc::result_out_of_range };
return { last, std::errc::value_too_large };
}
}

Expand Down
18 changes: 9 additions & 9 deletions src/to_chars_float_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
else
{
// Avoid buffer overflow
return { first, std::errc::result_out_of_range };
return { first, std::errc::value_too_large };
}

}
Expand All @@ -107,7 +107,7 @@
else
{
// Avoid buffer overflow
return { first, std::errc::result_out_of_range };
return { first, std::errc::value_too_large };
}
}
else
Expand Down Expand Up @@ -165,7 +165,7 @@
else
{
// Avoid buffer overflow
return { first, std::errc::result_out_of_range };
return { first, std::errc::value_too_large };
}

}
Expand All @@ -184,7 +184,7 @@
else
{
// Avoid buffer overflow
return { first, std::errc::result_out_of_range };
return { first, std::errc::value_too_large };
}
}
else
Expand Down Expand Up @@ -258,7 +258,7 @@

if (buffer_size < real_precision || first > last)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 261 in src/to_chars_float_impl.hpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars_float_impl.hpp#L261

Added line #L261 was not covered by tests
}

// Extract the significand and the exponent
Expand Down Expand Up @@ -374,7 +374,7 @@
const std::ptrdiff_t total_length = total_buffer_length(real_precision, abs_unbiased_exponent, (value < 0));
if (total_length > buffer_size)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 377 in src/to_chars_float_impl.hpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars_float_impl.hpp#L377

Added line #L377 was not covered by tests
}

// Round if required
Expand Down Expand Up @@ -483,7 +483,7 @@
auto real_precision = get_real_precision<Real>(precision);
if (buffer_size < real_precision || first > last)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 486 in src/to_chars_float_impl.hpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars_float_impl.hpp#L486

Added line #L486 was not covered by tests
}

auto abs_value = std::abs(value);
Expand Down Expand Up @@ -534,7 +534,7 @@
const std::ptrdiff_t total_length = total_buffer_length(num_dig, value_struct.exponent, (value < 0));
if (total_length > buffer_size)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 537 in src/to_chars_float_impl.hpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars_float_impl.hpp#L537

Added line #L537 was not covered by tests
}

auto r = to_chars_integer_impl(first, last, value_struct.significand);
Expand Down Expand Up @@ -598,7 +598,7 @@
// Sanity check our bounds
if (first >= last)
{
return {last, std::errc::result_out_of_range};
return {last, std::errc::value_too_large};

Check warning on line 601 in src/to_chars_float_impl.hpp

View check run for this annotation

Codecov / codecov/patch

src/to_chars_float_impl.hpp#L601

Added line #L601 was not covered by tests
}

auto abs_value = std::abs(value);
Expand Down
Loading
Loading