Simplify 32-bit impl and improve logic

This commit is contained in:
Matt Borland
2023-01-18 13:34:33 -08:00
parent 0e5fa4c26b
commit 9b350bcdcb
2 changed files with 16 additions and 12 deletions

View File

@@ -13,6 +13,8 @@
#include <array>
#include <cstdint>
namespace boost { namespace charconv { namespace detail {
// Generic solution
template <typename T>
BOOST_CXX14_CONSTEXPR int num_digits(T x) noexcept
@@ -169,7 +171,8 @@ BOOST_CXX14_CONSTEXPR int num_digits(unsigned __int128 x) noexcept
{
// There is not literal for unsigned __int128 so we need to calculate them using the max value of the
// std::uint64_t powers of 10
constexpr unsigned __int128 digits_39 = static_cast<unsigned __int128>(UINT64_C(10000000000000000000)) * static_cast<unsigned __int128>(UINT64_C(1000000000000000000));
constexpr unsigned __int128 digits_39 = static_cast<unsigned __int128>(UINT64_C(10000000000000000000)) *
static_cast<unsigned __int128>(UINT64_C(1000000000000000000));
constexpr unsigned __int128 digits_38 = digits_39 / 10;
constexpr unsigned __int128 digits_37 = digits_38 / 10;
constexpr unsigned __int128 digits_36 = digits_37 / 10;
@@ -231,4 +234,6 @@ BOOST_CXX14_CONSTEXPR int num_digits(unsigned __int128 x) noexcept
}
#endif // 128-bit support
}}} // Namespace boost::charconv::detail
#endif // BOOST_CHARCONV_DETAIL_INTEGER_SEARCH_TREES_HPP

View File

@@ -90,10 +90,7 @@ BOOST_CXX14_CONSTEXPR char* decompose32(std::uint32_t value, char* buffer)
template <typename Integer>
BOOST_CXX14_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* last, Integer value)
{
// decompose32 will always return 10 digits (including leading 0s)
char buffer[10] {};
{
if (!(first <= last))
{
return {last, EINVAL};
@@ -103,16 +100,18 @@ BOOST_CXX14_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* l
// If the type is greater than 32 bits we use a binary search tree to figure out how many digits
// are present and then decompose the value into two (or more) std::uint32_t of known length so that we
// don't have the issue of removing leading zeros from the least significant digits
if (static_cast<std::uint32_t>(value) <= (std::numeric_limits<std::uint32_t>::max)())
// TODO: fix this logic for types that could contain values greater than std::uint32_t but don't
// and types smaller than which would overflow on casting
if (std::numeric_limits<Integer>::digits <= std::numeric_limits<std::uint32_t>::digits ||
value <= static_cast<Integer>((std::numeric_limits<std::uint32_t>::max)()))
{
char buffer[10] {};
const auto num_sig_chars = num_digits(value);
decompose32(value, buffer);
std::size_t i {};
while (buffer[i] == '0')
{
++i;
}
std::memcpy(first, buffer + i, sizeof(buffer) - i);
std::memcpy(first, buffer + (sizeof(buffer) - num_sig_chars), num_sig_chars);
}
else if (static_cast<std::uint64_t>(value) <= (std::numeric_limits<std::uint64_t>::max)())
{