Merge pull request #17 from mborland/drop_gnu

Drop GNU requirement for 128-bit integers
This commit is contained in:
Matt Borland
2023-02-14 11:44:21 -08:00
committed by GitHub
9 changed files with 299 additions and 97 deletions

View File

@@ -7,6 +7,7 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <climits>
// This header implements separate compilation features as described in
// http://www.boost.org/more/separate_compilation.html
@@ -46,8 +47,23 @@
#endif
// Use 128 bit integers and supress warnings for using extensions
#if defined(BOOST_HAS_INT128) && !defined(__STRICT_ANSI__)
#if defined(BOOST_HAS_INT128)
# define BOOST_CHARCONV_HAS_INT128
# define BOOST_CHARCONV_INT128_MAX (boost::int128_type)(((boost::uint128_type) 1 << 127) - 1)
# define BOOST_CHARCONV_INT128_MIN (-BOOST_CHARCONV_INT128_MAX - 1)
# define BOOST_CHARCONV_UINT128_MAX ((2 * (boost::uint128_type) BOOST_CHARCONV_INT128_MAX) + 1)
#endif
#ifndef BOOST_NO_CXX14_CONSTEXPR
# define BOOST_CHARCONV_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
#else
# define BOOST_CHARCONV_CXX14_CONSTEXPR inline
#endif
#if defined(__GNUC__) && __GNUC__ == 5
# define BOOST_CHARCONV_GCC5_CONSTEXPR inline
#else
# define BOOST_CHARCONV_GCC5_CONSTEXPR BOOST_CHARCONV_CXX14_CONSTEXPR
#endif
#endif // BOOST_CHARCONV_CONFIG_HPP_INCLUDED

View File

@@ -167,30 +167,30 @@ static constexpr std::array<std::uint64_t, 20> powers_of_10 =
// Assume that if someone is using 128 bit ints they are favoring the top end of the range
// Max value is 340,282,366,920,938,463,463,374,607,431,768,211,455 (39 digits)
BOOST_CXX14_CONSTEXPR inline int num_digits(unsigned __int128 x) noexcept
BOOST_CXX14_CONSTEXPR inline int num_digits(boost::uint128_type x) noexcept
{
// There is not literal for unsigned __int128 so we need to calculate them using the max value of the
// There is not literal for boost::uint128_type 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_38 = digits_39 / 10;
constexpr unsigned __int128 digits_37 = digits_38 / 10;
constexpr unsigned __int128 digits_36 = digits_37 / 10;
constexpr unsigned __int128 digits_35 = digits_36 / 10;
constexpr unsigned __int128 digits_34 = digits_35 / 10;
constexpr unsigned __int128 digits_33 = digits_34 / 10;
constexpr unsigned __int128 digits_32 = digits_33 / 10;
constexpr unsigned __int128 digits_31 = digits_32 / 10;
constexpr unsigned __int128 digits_30 = digits_31 / 10;
constexpr unsigned __int128 digits_29 = digits_30 / 10;
constexpr unsigned __int128 digits_28 = digits_29 / 10;
constexpr unsigned __int128 digits_27 = digits_28 / 10;
constexpr unsigned __int128 digits_26 = digits_27 / 10;
constexpr unsigned __int128 digits_25 = digits_26 / 10;
constexpr unsigned __int128 digits_24 = digits_25 / 10;
constexpr unsigned __int128 digits_23 = digits_24 / 10;
constexpr unsigned __int128 digits_22 = digits_23 / 10;
constexpr unsigned __int128 digits_21 = digits_22 / 10;
constexpr boost::uint128_type digits_39 = static_cast<boost::uint128_type>(UINT64_C(10000000000000000000)) *
static_cast<boost::uint128_type>(UINT64_C(1000000000000000000));
constexpr boost::uint128_type digits_38 = digits_39 / 10;
constexpr boost::uint128_type digits_37 = digits_38 / 10;
constexpr boost::uint128_type digits_36 = digits_37 / 10;
constexpr boost::uint128_type digits_35 = digits_36 / 10;
constexpr boost::uint128_type digits_34 = digits_35 / 10;
constexpr boost::uint128_type digits_33 = digits_34 / 10;
constexpr boost::uint128_type digits_32 = digits_33 / 10;
constexpr boost::uint128_type digits_31 = digits_32 / 10;
constexpr boost::uint128_type digits_30 = digits_31 / 10;
constexpr boost::uint128_type digits_29 = digits_30 / 10;
constexpr boost::uint128_type digits_28 = digits_29 / 10;
constexpr boost::uint128_type digits_27 = digits_28 / 10;
constexpr boost::uint128_type digits_26 = digits_27 / 10;
constexpr boost::uint128_type digits_25 = digits_26 / 10;
constexpr boost::uint128_type digits_24 = digits_25 / 10;
constexpr boost::uint128_type digits_23 = digits_24 / 10;
constexpr boost::uint128_type digits_22 = digits_23 / 10;
constexpr boost::uint128_type digits_21 = digits_22 / 10;
return (x > digits_39) ? 39 :
(x > digits_38) ? 38 :

View File

@@ -60,7 +60,7 @@ constexpr char* memcpy(char* dest, const char* src, std::size_t count)
#else // Either not C++14 or no way of telling if we are in a constexpr context
#define BOOST_CHARCONV_CONSTEXPR
#define BOOST_CHARCONV_CONSTEXPR inline
inline void* memcpy(void* dest, const void* src, std::size_t count)
{

View File

@@ -68,10 +68,17 @@ constexpr unsigned char digit_from_char(char val) noexcept
return uchar_values[static_cast<std::size_t>(val)];
}
template <typename Integer>
BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4146)
#elif defined(__GNUC__) && (__GNUC__ == 5 || __GNUC__ == 6)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Woverflow"
#endif
template <typename Integer, typename Unsigned_Integer>
BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept
{
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
Unsigned_Integer result = 0;
Unsigned_Integer overflow_value = 0;
Unsigned_Integer max_digit = 0;
@@ -83,11 +90,18 @@ BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl
return {first, EINVAL};
}
Unsigned_Integer unsigned_base = static_cast<Unsigned_Integer>(base);
// Strip sign if the type is signed
// Negative sign will be appended at the end of parsing
BOOST_ATTRIBUTE_UNUSED bool is_negative = false;
auto next = first;
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::int128_type>::value || std::is_signed<Integer>::value)
#else
BOOST_IF_CONSTEXPR (std::is_signed<Integer>::value)
#endif
{
if (next != last)
{
@@ -102,8 +116,18 @@ BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl
}
}
overflow_value = (std::numeric_limits<Integer>::max)();
max_digit = (std::numeric_limits<Integer>::max)();
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::int128_type>::value)
{
overflow_value = BOOST_CHARCONV_INT128_MAX;
max_digit = BOOST_CHARCONV_INT128_MAX;
}
else
#endif
{
overflow_value = (std::numeric_limits<Integer>::max)();
max_digit = (std::numeric_limits<Integer>::max)();
}
if (is_negative)
{
@@ -125,12 +149,33 @@ BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl
}
}
overflow_value = (std::numeric_limits<Unsigned_Integer>::max)();
max_digit = (std::numeric_limits<Unsigned_Integer>::max)();
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::uint128_type>::value)
{
overflow_value = BOOST_CHARCONV_UINT128_MAX;
max_digit = BOOST_CHARCONV_UINT128_MAX;
}
else
#endif
{
overflow_value = (std::numeric_limits<Unsigned_Integer>::max)();
max_digit = (std::numeric_limits<Unsigned_Integer>::max)();
}
}
overflow_value /= static_cast<Unsigned_Integer>(base);
max_digit %= base;
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::int128_type>::value)
{
overflow_value /= unsigned_base;
max_digit %= unsigned_base;
overflow_value *= 2; // Overflow value would cause INT128_MIN in non-base10 to fail
}
else
#endif
{
overflow_value /= unsigned_base;
max_digit %= unsigned_base;
}
// If the only character was a sign abort now
if (next == last)
@@ -141,16 +186,16 @@ BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl
bool overflowed = false;
while (next != last)
{
auto current_digit = digit_from_char(*next);
const unsigned char current_digit = digit_from_char(*next);
if (current_digit >= base)
if (current_digit >= unsigned_base)
{
break;
}
if (result < overflow_value || (result == overflow_value && current_digit <= max_digit))
{
result = static_cast<Unsigned_Integer>(result * base + current_digit);
result = static_cast<Unsigned_Integer>(result * unsigned_base + current_digit);
}
else
{
@@ -169,43 +214,104 @@ BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl
}
value = static_cast<Integer>(result);
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::int128_type>::value || std::is_signed<Integer>::value)
#else
BOOST_IF_CONSTEXPR (std::is_signed<Integer>::value)
#endif
{
if (is_negative)
{
value = apply_sign(value);
value = -(static_cast<Unsigned_Integer>(value));
}
}
return {next, 0};
}
} // Namespace detail
// GCC 5 does not support constexpr comparison of const char*
#if defined(__GNUC__) && __GNUC__ == 5
template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, bool>::type = true>
inline from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept
{
return detail::from_chars_integer_impl(first, last, value, base);
}
template<>
inline from_chars_result from_chars<bool>(const char* first, const char* last, bool& value, int base) noexcept = delete;
#else
#ifdef BOOST_MSVC
# pragma warning(pop)
#elif defined(__GNUC__) && (__GNUC__ == 5 || __GNUC__ == 6)
# pragma GCC diagnostic pop
#endif
// Only from_chars for integer types is constexpr (as of C++23)
template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, bool>::type = true>
BOOST_CXX14_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept
template <typename Integer>
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept
{
return detail::from_chars_integer_impl(first, last, value, base);
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
return detail::from_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
}
template <>
BOOST_CXX14_CONSTEXPR from_chars_result from_chars<bool>(const char* first, const char* last, bool& value, int base) noexcept = delete;
#ifdef BOOST_HAS_INT128
template <typename Integer>
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars128(const char* first, const char* last, Integer& value, int base = 10) noexcept
{
using Unsigned_Integer = boost::uint128_type;
return detail::from_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
}
#endif
#endif // GCC5 workarounds
} // Namespace detail
// integer overloads
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, bool& value, int base = 10) noexcept = delete;
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, char& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, signed char& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned char& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, short& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned short& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned int& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::int128_type& value, int base = 10) noexcept
{
return detail::from_chars_integer_impl<boost::int128_type, boost::uint128_type>(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::uint128_type& value, int base = 10) noexcept
{
return detail::from_chars_integer_impl<boost::uint128_type, boost::uint128_type>(first, last, value, base);
}
#endif
// floating point overloads

View File

@@ -57,7 +57,7 @@ template<> struct limits<boost::uint128_type>
#endif // #if defined(BOOST_HAS_INT128)
#if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) || (defined(__clang__) && __clang_major__ <= 5)
// Definitions of in-class constexpr members are allowed but deprecated in C++17

View File

@@ -81,7 +81,7 @@ namespace detail {
// See: https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/
// https://arxiv.org/abs/2101.11408
BOOST_CHARCONV_CONSTEXPR inline char* decompose32(std::uint32_t value, char* buffer) noexcept
BOOST_CHARCONV_CONSTEXPR char* decompose32(std::uint32_t value, char* buffer) noexcept
{
constexpr auto mask = (std::uint64_t(1) << 57) - 1;
auto y = value * std::uint64_t(1441151881);
@@ -98,7 +98,7 @@ BOOST_CHARCONV_CONSTEXPR inline char* decompose32(std::uint32_t value, char* buf
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4127)
# pragma warning(disable: 4127 4146)
#endif
template <typename Integer>
@@ -251,12 +251,12 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
}
// Strip the sign from the value and apply at the end after parsing if the type is signed
BOOST_IF_CONSTEXPR (std::is_signed<Integer>::value)
BOOST_IF_CONSTEXPR (std::is_same<boost::int128_type, Integer>::value)
{
if (value < 0)
{
is_negative = true;
unsigned_value = apply_sign(value);
unsigned_value = -(static_cast<Unsigned_Integer>(value));
}
else
{
@@ -270,12 +270,6 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
auto converted_value = static_cast<boost::uint128_type>(unsigned_value);
// If the value fits into 64 bits use the other method of processing
if (converted_value < (std::numeric_limits<std::uint64_t>::max)())
{
return to_chars_integer_impl(first, last, value);
}
const int converted_value_digits = num_digits(converted_value);
if (converted_value_digits > user_buffer_size)
@@ -288,6 +282,12 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
*first++ = '-';
}
// If the value fits into 64 bits use the other method of processing
if (converted_value < (std::numeric_limits<std::uint64_t>::max)())
{
return to_chars_integer_impl(first, last, static_cast<std::uint64_t>(value));
}
constexpr std::uint32_t ten_9 = UINT32_C(1000000000);
char buffer[5][10] {};
int num_chars[5] {};
@@ -317,19 +317,13 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
}
#endif
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// All other bases
// Use a simple lookup table to put together the Integer in character form
template <typename Integer>
template <typename Integer, typename Unsigned_Integer>
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* last, Integer value, int base) noexcept
{
BOOST_CHARCONV_ASSERT_MSG(base >= 2 && base <= 36, "Base must be between 2 and 36 (inclusive)");
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
const std::ptrdiff_t output_length = last - first;
if (!(first <= last))
@@ -351,7 +345,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
if (value < 0)
{
*first++ = '-';
unsigned_value = apply_sign(value);
unsigned_value = -(static_cast<Unsigned_Integer>(value));
}
else
{
@@ -433,31 +427,94 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
return {first + num_chars, 0};
}
} // Namespace detail
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, bool>::type = true>
template <typename Integer>
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, Integer value, int base = 10) noexcept
{
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
if (base == 10)
{
return detail::to_chars_integer_impl(first, last, value);
}
return detail::to_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
}
#ifdef BOOST_CHARCONV_HAS_INT128
template <typename Integer>
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars128(char* first, char* last, Integer value, int base = 10) noexcept
{
if (base == 10)
{
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_IF_CONSTEXPR(std::is_same<Integer, boost::int128_type>::value || std::is_same<Integer, boost::uint128_type>::value)
{
return detail::to_chars_128integer_impl(first, last, value);
}
else
#endif
{
return detail::to_chars_integer_impl(first, last, value);
}
return to_chars_128integer_impl(first, last, value);
}
return detail::to_chars_integer_impl(first, last, value, base);
return to_chars_integer_impl<Integer, boost::uint128_type>(first, last, value, base);
}
#endif
} // Namespace detail
// integer overloads
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, bool value, int base) noexcept = delete;
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, char value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, signed char value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned char value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, short value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned short value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned int value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, long value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned long value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, long long value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned long long value, int base = 10) noexcept
{
return detail::to_chars(first, last, value, base);
}
template <>
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars<bool>(char* first, char* last, bool value, int base) noexcept = delete;
#ifdef BOOST_CHARCONV_HAS_INT128
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, boost::int128_type value, int base = 10) noexcept
{
return detail::to_chars128(first, last, value, base);
}
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, boost::uint128_type value, int base = 10) noexcept
{
return detail::to_chars128(first, last, value, base);
}
#endif
// floating point overloads
BOOST_CHARCONV_DECL to_chars_result to_chars( char* first, char* last, float value ) noexcept;

View File

@@ -6,7 +6,7 @@
int main()
{
char buffer[ 32 ];
char buffer[ 32 ] {};
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), 1048576 );
int v = 0;

View File

@@ -82,7 +82,15 @@ template<class T> void test_roundtrip( T value, int base )
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_EQ( r2.ec, 0 );
if (BOOST_TEST_EQ( v2, value ))
{
}
else
{
std::cerr << "Original Value: " << value << "\nBase:" << base << "\nConverted Value: " << buffer << "\nRoundtriped Value: " << v2 << std::endl;
}
}
template<class T> void test_roundtrip_int8( int base )
@@ -253,7 +261,6 @@ int main()
test_roundtrip_int64<std::int64_t>( base );
test_roundtrip_uint64<std::uint64_t>( base );
#ifdef BOOST_CHARCONV_HAS_INT128
test_roundtrip_int128<boost::int128_type>( base );
@@ -281,7 +288,6 @@ int main()
test_roundtrip_bv<long long>( base );
test_roundtrip_bv<unsigned long long>( base );
#ifdef BOOST_CHARCONV_HAS_INT128
test_roundtrip_bv<boost::int128_type>( base );

View File

@@ -37,7 +37,6 @@ void test_128bit_int()
auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3);
BOOST_TEST(r3.ec == 0);
BOOST_TEST(v3 == test_value);
BOOST_TEST(std::numeric_limits<T>::max() > static_cast<T>(std::numeric_limits<unsigned long long>::max()));
char buffer4[64] {};
auto r4 = boost::charconv::to_chars(buffer4, buffer4 + sizeof(buffer4), v3);
@@ -52,6 +51,7 @@ void test_128bit_int()
T v5 = 0;
auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5);
BOOST_TEST(r5.ec == 0);
BOOST_TEST(v5 < 0);
char buffer6[64] {};
auto r6 = boost::charconv::to_chars(buffer6, buffer6 + sizeof(buffer6), v5);
@@ -63,6 +63,23 @@ void test_128bit_int()
auto r7 = boost::charconv::from_chars(buffer6, buffer6 + std::strlen(buffer6), v7);
BOOST_TEST(r7.ec == 0);
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(v10 < 0);
char buffer11[64] {};
auto r11 = boost::charconv::to_chars(buffer11, buffer11 + sizeof(buffer11), v10);
BOOST_TEST_EQ(r11.ec, 0);
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(v10 == v11);
}
}
#endif