diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2024-05-14 11:29:50 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2024-05-14 11:42:32 +0300 |
commit | fff706dcb95eba6ac76c2b678ba8d1eb80cf2f20 (patch) | |
tree | 91f73a0972902cf53fa8bef6ef509aca4fb4789d | |
parent | 0a83690b303aab06d05ef6f46158344be60075bf (diff) | |
download | ydb-fff706dcb95eba6ac76c2b678ba8d1eb80cf2f20.tar.gz |
Update contrib/restricted/boost/lexical_cast to 1.85.0
e336f3b2feb7ddb6f42cb1daea4f706c889439cf
16 files changed, 905 insertions, 1027 deletions
diff --git a/contrib/restricted/boost/lexical_cast/include/boost/detail/basic_pointerbuf.hpp b/contrib/restricted/boost/lexical_cast/include/boost/detail/basic_pointerbuf.hpp index 424dcaccb5..0a7372e033 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/detail/basic_pointerbuf.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/detail/basic_pointerbuf.hpp @@ -18,7 +18,9 @@ # pragma once #endif -#include "boost/config.hpp" +#include <boost/config.hpp> +#include <boost/integer.hpp> + #include <streambuf> namespace boost { namespace detail { diff --git a/contrib/restricted/boost/lexical_cast/include/boost/detail/lcast_precision.hpp b/contrib/restricted/boost/lexical_cast/include/boost/detail/lcast_precision.hpp index dadf9c9e22..9c4636e3b5 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/detail/lcast_precision.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/detail/lcast_precision.hpp @@ -15,12 +15,6 @@ #include <boost/config.hpp> #include <boost/integer_traits.hpp> -#ifndef BOOST_NO_IS_ABSTRACT -// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL -#include <boost/type_traits/conditional.hpp> -#include <boost/type_traits/is_abstract.hpp> -#endif - namespace boost { namespace detail { class lcast_abstract_stub {}; @@ -31,15 +25,7 @@ class lcast_abstract_stub {}; template<class T> struct lcast_precision { -#ifdef BOOST_NO_IS_ABSTRACT - typedef std::numeric_limits<T> limits; // No fix for SF:1358600. -#else - typedef typename boost::conditional< - boost::is_abstract<T>::value - , std::numeric_limits<lcast_abstract_stub> - , std::numeric_limits<T> - >::type limits; -#endif + using limits = std::numeric_limits<T>; BOOST_STATIC_CONSTANT(bool, use_default_precision = !limits::is_specialized || limits::is_exact diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast.hpp index d0b4d72986..1984e81f39 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/bad_lexical_cast.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/bad_lexical_cast.hpp index d70f54bc42..10d1b5251b 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/bad_lexical_cast.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/bad_lexical_cast.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/buffer_view.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/buffer_view.hpp index 888dd7e0ee..9b1c68271c 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/buffer_view.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/buffer_view.hpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical.hpp index fdc8f1fc53..cd9f76f542 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -35,8 +35,6 @@ #include <boost/type_traits/conditional.hpp> #include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_float.hpp> -#include <boost/type_traits/has_left_shift.hpp> -#include <boost/type_traits/has_right_shift.hpp> #include <boost/detail/lcast_precision.hpp> #include <boost/lexical_cast/detail/widest_char.hpp> @@ -44,6 +42,10 @@ #include <array> +#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW +#include <string_view> +#endif + #include <boost/lexical_cast/detail/buffer_view.hpp> #include <boost/container/container_fwd.hpp> @@ -57,6 +59,9 @@ namespace boost { template<class IteratorT> class iterator_range; + // Forward declaration of boost::basic_string_view from Utility + template<class Ch, class Tr> class basic_string_view; + namespace detail // normalize_single_byte_char<Char> { // Converts signed/unsigned char to char @@ -174,6 +179,19 @@ namespace boost { > {}; #endif +#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW + template < class Char, class Traits > + struct stream_char_common< std::basic_string_view< Char, Traits > > + { + typedef Char type; + }; +#endif + template < class Char, class Traits > + struct stream_char_common< boost::basic_string_view< Char, Traits > > + { + typedef Char type; + }; + #ifdef BOOST_HAS_INT128 template <> struct stream_char_common< boost::int128_type >: public boost::type_identity< char > {}; template <> struct stream_char_common< boost::uint128_type >: public boost::type_identity< char > {}; @@ -191,7 +209,7 @@ namespace boost { namespace detail // deduce_source_char_impl<T> { // If type T is `deduce_character_type_later` type, then tries to deduce - // character type using boost::has_left_shift<T> metafunction. + // character type using streaming metafunctions. // Otherwise supplied type T is a character type, that must be normalized // using normalize_single_byte_char<Char>. // Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>) @@ -204,20 +222,29 @@ namespace boost { template < class T > struct deduce_source_char_impl< deduce_character_type_later< T > > { - typedef boost::has_left_shift< std::basic_ostream< char >, T > result_t; + template <class U> + static auto left_shift_type(long) + -> decltype( std::declval<std::basic_ostream< char >&>() << std::declval<const U&>(), char{}); + +#if !defined(BOOST_LCAST_NO_WCHAR_T) + template <class U> + static auto left_shift_type(int) + -> decltype( std::declval<std::basic_ostream< wchar_t >&>() << std::declval<const U&>(), wchar_t{}); +#endif + template <class U> + static void left_shift_type(...); + + using type = decltype(left_shift_type<T>(1L)); + + static_assert(!std::is_same<type, void>::value, #if defined(BOOST_LCAST_NO_WCHAR_T) - static_assert(result_t::value, - "Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation"); - typedef char type; + "Source type is not std::ostream`able and std::wostream`s are " + "not supported by your STL implementation" #else - typedef typename boost::conditional< - result_t::value, char, wchar_t - >::type type; - - static_assert(result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value, - "Source type is neither std::ostream`able nor std::wostream`able"); + "Source type is neither std::ostream`able nor std::wostream`able" #endif + ); }; } @@ -237,20 +264,29 @@ namespace boost { template < class T > struct deduce_target_char_impl< deduce_character_type_later<T> > { - typedef boost::has_right_shift<std::basic_istream<char>, T > result_t; + template <class U> + static auto right_shift_type(long) + -> decltype( std::declval<std::basic_istream< char >&>() >> std::declval<U&>(), char{}); + +#if !defined(BOOST_LCAST_NO_WCHAR_T) + template <class U> + static auto right_shift_type(int) + -> decltype( std::declval<std::basic_istream< wchar_t >&>() >> std::declval<U&>(), wchar_t{}); +#endif + template <class U> + static void right_shift_type(...); + + using type = decltype(right_shift_type<T>(1L)); + + static_assert(!std::is_same<type, void>::value, #if defined(BOOST_LCAST_NO_WCHAR_T) - static_assert(result_t::value, - "Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation"); - typedef char type; + "Target type is not std::istream`able and std::wistream`s are " + "not supported by your STL implementation" #else - typedef typename boost::conditional< - result_t::value, char, wchar_t - >::type type; - - static_assert(result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value, - "Target type is neither std::istream`able nor std::wistream`able"); + "Target type is neither std::istream`able nor std::wistream`able" #endif + ); }; } @@ -275,44 +311,14 @@ namespace boost { struct deduce_target_char { typedef typename stream_char_common< T >::type stage1_type; - typedef typename deduce_target_char_impl< stage1_type >::type stage2_type; - - typedef stage2_type type; + typedef typename deduce_target_char_impl< stage1_type >::type type; }; template < class T > struct deduce_source_char { typedef typename stream_char_common< T >::type stage1_type; - typedef typename deduce_source_char_impl< stage1_type >::type stage2_type; - - typedef stage2_type type; - }; - } - - namespace detail // extract_char_traits template - { - // We are attempting to get char_traits<> from T - // template parameter. Otherwise we'll be using std::char_traits<Char> - template < class Char, class T > - struct extract_char_traits - : boost::false_type - { - typedef std::char_traits< Char > trait_t; - }; - - template < class Char, class Traits, class Alloc > - struct extract_char_traits< Char, std::basic_string< Char, Traits, Alloc > > - : boost::true_type - { - typedef Traits trait_t; - }; - - template < class Char, class Traits, class Alloc> - struct extract_char_traits< Char, boost::container::basic_string< Char, Traits, Alloc > > - : boost::true_type - { - typedef Traits trait_t; + typedef typename deduce_source_char_impl< stage1_type >::type type; }; } @@ -360,16 +366,11 @@ namespace boost { Source, typename boost::enable_if<boost::is_integral<Source> >::type > { -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_CONSTANT(std::size_t, value = std::numeric_limits<Source>::is_signed + std::numeric_limits<Source>::is_specialized + /* == 1 */ std::numeric_limits<Source>::digits10 * 2 ); -#else - BOOST_STATIC_CONSTANT(std::size_t, value = 156); - static_assert(sizeof(Source) * CHAR_BIT <= 256, ""); -#endif }; // Helper for floating point types. @@ -387,8 +388,6 @@ namespace boost { Source, typename boost::enable_if<boost::is_float<Source> >::type > { - -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION static_assert( std::numeric_limits<Source>::max_exponent10 <= 999999L && std::numeric_limits<Source>::min_exponent10 >= -999999L @@ -397,9 +396,6 @@ namespace boost { BOOST_STATIC_CONSTANT(std::size_t, value = 5 + lcast_precision<Source>::value + 6 ); -#else // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION - BOOST_STATIC_CONSTANT(std::size_t, value = 156); -#endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION }; } @@ -429,33 +425,7 @@ namespace boost { "Your compiler does not have full support for char32_t" ); #endif - typedef typename boost::conditional< - boost::detail::extract_char_traits<char_type, Target>::value, - typename boost::detail::extract_char_traits<char_type, Target>, - typename boost::detail::extract_char_traits<char_type, no_cv_src> - >::type::trait_t traits; - - typedef boost::integral_constant< - bool, - boost::is_same<char, src_char_t>::value && // source is not a wide character based type - (sizeof(char) != sizeof(target_char_t)) && // target type is based on wide character - (!(boost::detail::is_character<no_cv_src>::value)) - > is_string_widening_required_t; - - typedef boost::integral_constant< - bool, - !(boost::is_integral<no_cv_src>::value || - boost::detail::is_character< - typename deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1 - >::value // then we have no optimization for that type - ) - > is_source_input_not_optimized_t; - - // If we have an optimized conversion for - // Source, we do not need to construct stringbuf. - BOOST_STATIC_CONSTANT(bool, requires_stringbuf = - (is_string_widening_required_t::value || is_source_input_not_optimized_t::value) - ); + typedef std::char_traits<char_type> traits; typedef boost::detail::lcast_src_length<no_cv_src> len_t; }; @@ -468,29 +438,33 @@ namespace boost { { typedef lexical_cast_stream_traits<Source, Target> stream_trait; - typedef detail::lexical_istream_limited_src< + typedef detail::lcast::optimized_src_stream< typename stream_trait::char_type, typename stream_trait::traits, - stream_trait::requires_stringbuf, stream_trait::len_t::value + 1 - > i_interpreter_type; + > optimized_src_stream; + + template <class T> + static auto detect_type(int) + -> decltype(std::declval<optimized_src_stream&>().stream_in(std::declval<lcast::exact<T>>()), optimized_src_stream{}); + + template <class T> + static lcast::ios_src_stream<typename stream_trait::char_type, typename stream_trait::traits> detect_type(...); + + using from_src_stream = decltype(detect_type<Source>(1)); - typedef detail::lexical_ostream_limited_src< + typedef detail::lcast::to_target_stream< typename stream_trait::char_type, typename stream_trait::traits - > o_interpreter_type; + > to_target_stream; static inline bool try_convert(const Source& arg, Target& result) { - i_interpreter_type i_interpreter; - - // Disabling ADL, by directly specifying operators. - if (!(i_interpreter.operator <<(arg))) + from_src_stream src_stream; + if (!src_stream.stream_in(lcast::exact<Source>{arg})) return false; - o_interpreter_type out(i_interpreter.cbegin(), i_interpreter.cend()); - - // Disabling ADL, by directly specifying operators. - if(!(out.operator >>(result))) + to_target_stream out(src_stream.cbegin(), src_stream.cend()); + if (!out.stream_out(result)) return false; return true; diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical_streams.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical_streams.hpp index ad778efaaa..6398055e4b 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical_streams.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_lexical_streams.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -34,6 +34,9 @@ #include <cstdio> #include <boost/limits.hpp> #include <boost/type_traits/conditional.hpp> +#include <boost/type_traits/is_enum.hpp> +#include <boost/type_traits/is_signed.hpp> +#include <boost/type_traits/is_unsigned.hpp> #include <boost/type_traits/is_pointer.hpp> #include <boost/detail/lcast_precision.hpp> #include <boost/detail/workaround.hpp> @@ -58,8 +61,10 @@ #include <sstream> #endif +#include <boost/lexical_cast/detail/buffer_view.hpp> #include <boost/lexical_cast/detail/lcast_char_constants.hpp> #include <boost/lexical_cast/detail/lcast_unsigned_converters.hpp> +#include <boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp> #include <boost/lexical_cast/detail/inf_nan.hpp> #include <istream> @@ -69,695 +74,678 @@ #include <boost/type_traits/make_unsigned.hpp> #include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_float.hpp> -#include <boost/lexical_cast/detail/buffer_view.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/type_traits/is_reference.hpp> #include <boost/container/container_fwd.hpp> -#include <boost/integer.hpp> -#include <boost/detail/basic_pointerbuf.hpp> -#include <boost/core/noncopyable.hpp> #include <boost/core/enable_if.hpp> #ifndef BOOST_NO_CWCHAR # include <cwchar> #endif +// Forward declarations namespace boost { - - // Forward declaration template<class T, std::size_t N> class array; template<class IteratorT> class iterator_range; - namespace detail // basic_unlockedbuf - { - // acts as a stream buffer which wraps around a pair of pointers - // and gives acces to internals - template <class BufferType, class CharT> - class basic_unlockedbuf : public basic_pointerbuf<CharT, BufferType> { - public: - typedef basic_pointerbuf<CharT, BufferType> base_type; - typedef typename base_type::streamsize streamsize; - -#ifndef BOOST_NO_USING_TEMPLATE - using base_type::pptr; - using base_type::pbase; - using base_type::setbuf; -#else - charT* pptr() const { return base_type::pptr(); } - charT* pbase() const { return base_type::pbase(); } - BufferType* setbuf(char_type* s, streamsize n) { return base_type::setbuf(s, n); } -#endif - }; - } - - namespace detail - { - struct do_not_construct_out_buffer_t{}; - struct do_not_construct_out_stream_t{ - do_not_construct_out_stream_t(do_not_construct_out_buffer_t*){} - }; - - template <class CharT, class Traits> - struct out_stream_helper_trait { -#if defined(BOOST_NO_STRINGSTREAM) - typedef std::ostream out_stream_t; - typedef basic_unlockedbuf<std::strstreambuf, char> stringbuffer_t; -#elif defined(BOOST_NO_STD_LOCALE) - typedef std::ostream out_stream_t; - typedef basic_unlockedbuf<std::stringbuf, char> stringbuffer_t; - typedef basic_unlockedbuf<std::streambuf, char> buffer_t; -#else - typedef std::basic_ostream<CharT, Traits> out_stream_t; - typedef basic_unlockedbuf<std::basic_stringbuf<CharT, Traits>, CharT> stringbuffer_t; - typedef basic_unlockedbuf<std::basic_streambuf<CharT, Traits>, CharT> buffer_t; -#endif - }; - } - - namespace detail // optimized stream wrappers - { - template< class CharT // a result of widest_char transformation - , class Traits - , bool RequiresStringbuffer - , std::size_t CharacterBufferSize - > - class lexical_istream_limited_src: boost::noncopyable { - typedef typename boost::conditional< - RequiresStringbuffer, - typename out_stream_helper_trait<CharT, Traits>::out_stream_t, - do_not_construct_out_stream_t - >::type deduced_out_stream_t; - - typedef typename boost::conditional< - RequiresStringbuffer, - typename out_stream_helper_trait<CharT, Traits>::stringbuffer_t, - do_not_construct_out_buffer_t - >::type deduced_out_buffer_t; - - deduced_out_buffer_t out_buffer; - deduced_out_stream_t out_stream; - CharT buffer[CharacterBufferSize]; - - // After the `operator <<` finishes, `[start, finish)` is - // the range to output by `operator >>` - const CharT* start; - const CharT* finish; - - public: - lexical_istream_limited_src() noexcept - : out_buffer() - , out_stream(&out_buffer) - , start(buffer) - , finish(buffer + CharacterBufferSize) - {} - - const CharT* cbegin() const noexcept { - return start; - } - - const CharT* cend() const noexcept { - return finish; - } - - private: -/************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/ - bool shl_char(CharT ch) noexcept { - Traits::assign(buffer[0], ch); - finish = start + 1; - return true; - } + // forward declaration of boost::basic_string_view from Utility + template<class Ch, class Tr> class basic_string_view; +} + +namespace boost { namespace detail { namespace lcast { + + template <typename T> + struct exact { + static_assert(!boost::is_const<T>::value, ""); + static_assert(!boost::is_reference<T>::value, ""); + + const T& payload; + }; + + template< class CharT // a result of widest_char transformation + , class Traits + , std::size_t CharacterBufferSize + > + class optimized_src_stream { + CharT buffer[CharacterBufferSize]; + + // After the `stream_in(` finishes, `[start, finish)` is + // the range to output by `operator >>` + const CharT* start; + const CharT* finish; + public: + optimized_src_stream(optimized_src_stream&&) = delete; + optimized_src_stream(const optimized_src_stream&) = delete; + optimized_src_stream& operator=(optimized_src_stream&&) = delete; + optimized_src_stream& operator=(const optimized_src_stream&) = delete; + + optimized_src_stream() noexcept + : start(buffer) + , finish(buffer + CharacterBufferSize) + {} + + const CharT* cbegin() const noexcept { + return start; + } + + const CharT* cend() const noexcept { + return finish; + } + + private: + bool shl_char(CharT ch) noexcept { + Traits::assign(buffer[0], ch); + finish = start + 1; + return true; + } #ifndef BOOST_LCAST_NO_WCHAR_T - template <class T> - bool shl_char(T ch) { - static_assert(sizeof(T) <= sizeof(CharT), - "boost::lexical_cast does not support narrowing of char types." - "Use boost::locale instead" ); + template <class T> + bool shl_char(T ch) { + static_assert(sizeof(T) <= sizeof(CharT), + "boost::lexical_cast does not support narrowing of char types." + "Use boost::locale instead" ); #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - std::locale loc; - CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch); + std::locale loc; + CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch); #else - CharT const w = static_cast<CharT>(ch); + CharT const w = static_cast<CharT>(ch); #endif - Traits::assign(buffer[0], w); - finish = start + 1; - return true; - } + Traits::assign(buffer[0], w); + finish = start + 1; + return true; + } #endif - bool shl_char_array(CharT const* str_value) noexcept { - start = str_value; - finish = start + Traits::length(str_value); - return true; - } + bool shl_char_array(CharT const* str_value) noexcept { + start = str_value; + finish = start + Traits::length(str_value); + return true; + } + + bool shl_char_array_limited(CharT const* str, std::size_t max_size) noexcept { + start = str; + finish = start; + const auto zero = Traits::to_char_type(0); + while (finish < start + max_size && zero != *finish) { + ++ finish; + } + return true; + } + + template <class T> + inline bool shl_unsigned(const T n) { + CharT* tmp_finish = buffer + CharacterBufferSize; + start = lcast_put_unsigned<Traits, T, CharT>(n, tmp_finish).convert(); + finish = tmp_finish; + return true; + } + + template <class T> + inline bool shl_signed(const T n) { + CharT* tmp_finish = buffer + CharacterBufferSize; + typedef typename boost::make_unsigned<T>::type utype; + CharT* tmp_start = lcast_put_unsigned<Traits, utype, CharT>(lcast_to_unsigned(n), tmp_finish).convert(); + if (n < 0) { + --tmp_start; + CharT const minus = lcast_char_constants<CharT>::minus; + Traits::assign(*tmp_start, minus); + } + start = tmp_start; + finish = tmp_finish; + return true; + } + + bool shl_real_type(float val, char* begin) { + using namespace std; + const double val_as_double = val; + finish = start + + boost::core::snprintf(begin, CharacterBufferSize, + "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double); + return finish > start; + } + + bool shl_real_type(double val, char* begin) { + using namespace std; + finish = start + + boost::core::snprintf(begin, CharacterBufferSize, + "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val); + return finish > start; + } - template <class T> - bool shl_char_array(T const* str_value) { - static_assert(sizeof(T) <= sizeof(CharT), - "boost::lexical_cast does not support narrowing of char types." - "Use boost::locale instead" ); - return shl_input_streamable(str_value); - } +#ifndef __MINGW32__ + bool shl_real_type(long double val, char* begin) { + using namespace std; + finish = start + + boost::core::snprintf(begin, CharacterBufferSize, + "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val ); + return finish > start; + } +#else + bool shl_real_type(long double val, char* begin) { + return shl_real_type(static_cast<double>(val), begin); + } +#endif - bool shl_char_array_limited(CharT const* str, std::size_t max_size) noexcept { - start = str; - finish = start; - const auto zero = Traits::to_char_type(0); - while (finish < start + max_size && zero != *finish) { - ++ finish; - } +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) + bool shl_real_type(float val, wchar_t* begin) { + using namespace std; + const double val_as_double = val; + finish = start + swprintf(begin, CharacterBufferSize, + L"%.*g", + static_cast<int>(boost::detail::lcast_get_precision<float >()), + val_as_double ); + return finish > start; + } + + bool shl_real_type(double val, wchar_t* begin) { + using namespace std; + finish = start + swprintf(begin, CharacterBufferSize, + L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val ); + return finish > start; + } + + bool shl_real_type(long double val, wchar_t* begin) { + using namespace std; + finish = start + swprintf(begin, CharacterBufferSize, + L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val ); + return finish > start; + } +#endif + public: + template <class C> + using enable_if_compatible_char_t = typename boost::enable_if_c< + boost::is_same<const C, const CharT>::value || ( + boost::is_same<const char, const CharT>::value && ( + boost::is_same<const C, const unsigned char>::value || + boost::is_same<const C, const signed char>::value + ) + ), bool + >::type; + + template<class CharTraits, class Alloc> + bool stream_in(lcast::exact<std::basic_string<CharT,CharTraits,Alloc>> x) noexcept { + start = x.payload.data(); + finish = start + x.payload.length(); + return true; + } + + template<class CharTraits, class Alloc> + bool stream_in(lcast::exact<boost::container::basic_string<CharT,CharTraits,Alloc>> x) noexcept { + start = x.payload.data(); + finish = start + x.payload.length(); + return true; + } + + bool stream_in(lcast::exact<bool> x) noexcept { + CharT const czero = lcast_char_constants<CharT>::zero; + Traits::assign(buffer[0], Traits::to_char_type(czero + x.payload)); + finish = start + 1; + return true; + } + + bool stream_in(lcast::exact<boost::conversion::detail::buffer_view<CharT>> x) noexcept { + start = x.payload.begin; + finish = x.payload.end; + return true; + } + + template <class C> + enable_if_compatible_char_t<C> + stream_in(lcast::exact<boost::iterator_range<C*>> x) noexcept { + auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end()); + return stream_in(lcast::exact<decltype(buf)>{buf}); + } + + bool stream_in(lcast::exact<char> x) { return shl_char(x.payload); } + bool stream_in(lcast::exact<unsigned char> x) { return shl_char(static_cast<char>(x.payload)); } + bool stream_in(lcast::exact<signed char> x) { return shl_char(static_cast<char>(x.payload)); } + + template <class C> + typename boost::enable_if_c<boost::detail::is_character<C>::value, bool>::type + stream_in(lcast::exact<C> x) { return shl_char(x.payload); } + + template <class Type> + enable_if_compatible_char_t<Type> + stream_in(lcast::exact<Type*> x) { return shl_char_array(reinterpret_cast<CharT const*>(x.payload)); } + + template <class Type> + typename boost::enable_if_c<boost::is_signed<Type>::value && !boost::is_enum<Type>::value, bool>::type + stream_in(lcast::exact<Type> x) { return shl_signed(x.payload); } + + template <class Type> + typename boost::enable_if_c<boost::is_unsigned<Type>::value && !boost::is_enum<Type>::value, bool>::type + stream_in(lcast::exact<Type> x) { return shl_unsigned(x.payload); } + + template <class Type> + auto stream_in(lcast::exact<Type> x) -> decltype(shl_real_type(x.payload, buffer)) { + const CharT* inf_nan = detail::get_inf_nan(x.payload, CharT()); + if (inf_nan) { + start = inf_nan; + finish = start + Traits::length(inf_nan); return true; } - - template<typename InputStreamable> - bool shl_input_streamable(InputStreamable& input) { + return shl_real_type(x.payload, buffer); + } + + template <class C, std::size_t N> + enable_if_compatible_char_t<C> + stream_in(lcast::exact<boost::array<C, N>> x) noexcept { + return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N); + } + + template <class C, std::size_t N> + enable_if_compatible_char_t<C> + stream_in(lcast::exact<std::array<C, N>> x) noexcept { + return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N); + } + +#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW + template <class C, class CharTraits> + enable_if_compatible_char_t<C> + stream_in(lcast::exact<std::basic_string_view<C, CharTraits>> x) noexcept { + return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), x.payload.size()); + } +#endif + template <class C, class CharTraits> + enable_if_compatible_char_t<C> + stream_in(lcast::exact<boost::basic_string_view<C, CharTraits>> x) noexcept { + return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), x.payload.size()); + } + }; + + + template <class CharT, class Traits> + class ios_src_stream { + typedef detail::lcast::out_stream_t<CharT, Traits> deduced_out_stream_t; + typedef detail::lcast::stringbuffer_t<CharT, Traits> deduced_out_buffer_t; + + deduced_out_buffer_t out_buffer; + deduced_out_stream_t out_stream; + + const CharT* start = nullptr; + const CharT* finish = nullptr; + public: + ios_src_stream(ios_src_stream&&) = delete; + ios_src_stream(const ios_src_stream&) = delete; + ios_src_stream& operator=(ios_src_stream&&) = delete; + ios_src_stream& operator=(const ios_src_stream&) = delete; + + ios_src_stream(): out_buffer(), out_stream(&out_buffer) {} + + const CharT* cbegin() const noexcept { + return start; + } + + const CharT* cend() const noexcept { + return finish; + } + private: + const deduced_out_buffer_t* get_rdbuf() const { + return static_cast<deduced_out_buffer_t*>( + out_stream.rdbuf() + ); + } + + template<typename InputStreamable> + bool shl_input_streamable(InputStreamable& input) { #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) - // If you have compilation error at this point, than your STL library - // does not support such conversions. Try updating it. - static_assert(boost::is_same<char, CharT>::value, ""); + // If you have compilation error at this point, than your STL library + // does not support such conversions. Try updating it. + static_assert(boost::is_same<char, CharT>::value, ""); #endif #ifndef BOOST_NO_EXCEPTIONS - out_stream.exceptions(std::ios::badbit); - try { + out_stream.exceptions(std::ios::badbit); + try { #endif - bool const result = !(out_stream << input).fail(); - const deduced_out_buffer_t* const p = static_cast<deduced_out_buffer_t*>( - out_stream.rdbuf() - ); - start = p->pbase(); - finish = p->pptr(); - return result; + bool const result = !(out_stream << input).fail(); + const auto* const p = get_rdbuf(); + start = p->pbase(); + finish = p->pptr(); + return result; #ifndef BOOST_NO_EXCEPTIONS - } catch (const ::std::ios_base::failure& /*f*/) { - return false; - } -#endif - } - - template <class T> - inline bool shl_unsigned(const T n) { - CharT* tmp_finish = buffer + CharacterBufferSize; - start = lcast_put_unsigned<Traits, T, CharT>(n, tmp_finish).convert(); - finish = tmp_finish; - return true; - } - - template <class T> - inline bool shl_signed(const T n) { - CharT* tmp_finish = buffer + CharacterBufferSize; - typedef typename boost::make_unsigned<T>::type utype; - CharT* tmp_start = lcast_put_unsigned<Traits, utype, CharT>(lcast_to_unsigned(n), tmp_finish).convert(); - if (n < 0) { - --tmp_start; - CharT const minus = lcast_char_constants<CharT>::minus; - Traits::assign(*tmp_start, minus); - } - start = tmp_start; - finish = tmp_finish; - return true; - } - - template <class T, class SomeCharT> - bool shl_real_type(const T& val, SomeCharT* /*begin*/) { - lcast_set_precision(out_stream, &val); - return shl_input_streamable(val); - } - - bool shl_real_type(float val, char* begin) { - using namespace std; - const double val_as_double = val; - finish = start + - boost::core::snprintf(begin, CharacterBufferSize, - "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double); - return finish > start; - } - - bool shl_real_type(double val, char* begin) { - using namespace std; - finish = start + - boost::core::snprintf(begin, CharacterBufferSize, - "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val); - return finish > start; - } - -#ifndef __MINGW32__ - bool shl_real_type(long double val, char* begin) { - using namespace std; - finish = start + - boost::core::snprintf(begin, CharacterBufferSize, - "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val ); - return finish > start; + } catch (const ::std::ios_base::failure& /*f*/) { + return false; } #endif - - -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) - bool shl_real_type(float val, wchar_t* begin) { - using namespace std; - const double val_as_double = val; - finish = start + swprintf(begin, CharacterBufferSize, - L"%.*g", - static_cast<int>(boost::detail::lcast_get_precision<float >()), - val_as_double ); - return finish > start; - } - - bool shl_real_type(double val, wchar_t* begin) { - using namespace std; - finish = start + swprintf(begin, CharacterBufferSize, - L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val ); - return finish > start; - } - - bool shl_real_type(long double val, wchar_t* begin) { - using namespace std; - finish = start + swprintf(begin, CharacterBufferSize, - L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val ); - return finish > start; - } -#endif - template <class T> - bool shl_real(T val) { - CharT* tmp_finish = buffer + CharacterBufferSize; - if (put_inf_nan(buffer, tmp_finish, val)) { - finish = tmp_finish; - return true; - } - - return shl_real_type(val, static_cast<CharT*>(buffer)); - } - -/************************************ OPERATORS << ( ... ) ********************************/ - public: - template<class Alloc> - bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) noexcept { - start = str.data(); - finish = start + str.length(); - return true; - } - - template<class Alloc> - bool operator<<(boost::container::basic_string<CharT,Traits,Alloc> const& str) noexcept { - start = str.data(); - finish = start + str.length(); - return true; - } - - bool operator<<(bool value) noexcept { - CharT const czero = lcast_char_constants<CharT>::zero; - Traits::assign(buffer[0], Traits::to_char_type(czero + value)); - finish = start + 1; - return true; - } - - bool operator<<(boost::conversion::detail::buffer_view<CharT> rng) noexcept { - start = rng.begin; - finish = rng.end; + } + + template <class T> + bool shl_char_array(T const* str_value) { + static_assert(sizeof(T) <= sizeof(CharT), + "boost::lexical_cast does not support narrowing of char types." + "Use boost::locale instead" ); + return shl_input_streamable(str_value); + } + + template <class T> + bool shl_real(T val) { + const CharT* inf_nan = detail::get_inf_nan(val, CharT()); + if (inf_nan) { + start = inf_nan; + finish = start + Traits::length(inf_nan); return true; } - template <class C> - bool operator<<(const iterator_range<C*>& rng) noexcept { - return (*this) << boost::conversion::detail::make_buffer_view(rng.begin(), rng.end()); - } + lcast_set_precision(out_stream, &val); + return shl_input_streamable(val); + } - bool operator<<(char ch) { return shl_char(ch); } - bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); } - bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); } -#if !defined(BOOST_LCAST_NO_WCHAR_T) - bool operator<<(wchar_t const* str) { return shl_char_array(str); } - bool operator<<(wchar_t * str) { return shl_char_array(str); } -#ifndef BOOST_NO_INTRINSIC_WCHAR_T - bool operator<<(wchar_t ch) { return shl_char(ch); } -#endif -#endif -#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator<<(char16_t ch) { return shl_char(ch); } - bool operator<<(char16_t * str) { return shl_char_array(str); } - bool operator<<(char16_t const * str) { return shl_char_array(str); } -#endif -#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator<<(char32_t ch) { return shl_char(ch); } - bool operator<<(char32_t * str) { return shl_char_array(str); } - bool operator<<(char32_t const * str) { return shl_char_array(str); } -#endif - bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); } - bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); } - bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); } - bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); } - bool operator<<(char const* str_value) { return shl_char_array(str_value); } - bool operator<<(char* str_value) { return shl_char_array(str_value); } - bool operator<<(short n) { return shl_signed(n); } - bool operator<<(int n) { return shl_signed(n); } - bool operator<<(long n) { return shl_signed(n); } - bool operator<<(unsigned short n) { return shl_unsigned(n); } - bool operator<<(unsigned int n) { return shl_unsigned(n); } - bool operator<<(unsigned long n) { return shl_unsigned(n); } + public: + template <class Type> + typename boost::enable_if_c<boost::detail::is_character<Type>::value && sizeof(char) == sizeof(Type), bool>::type + stream_in(lcast::exact<const Type*> x) { return shl_char_array(reinterpret_cast<char const*>(x.payload)); } -#if defined(BOOST_HAS_LONG_LONG) - bool operator<<(boost::ulong_long_type n) { return shl_unsigned(n); } - bool operator<<(boost::long_long_type n) { return shl_signed(n); } -#elif defined(BOOST_HAS_MS_INT64) - bool operator<<(unsigned __int64 n) { return shl_unsigned(n); } - bool operator<<( __int64 n) { return shl_signed(n); } -#endif + template <class Type> + typename boost::enable_if_c<boost::detail::is_character<Type>::value && sizeof(char) != sizeof(Type), bool>::type + stream_in(lcast::exact<const Type*> x) { return shl_char_array(x.payload); } -#ifdef BOOST_HAS_INT128 - bool operator<<(const boost::uint128_type& n) { return shl_unsigned(n); } - bool operator<<(const boost::int128_type& n) { return shl_signed(n); } -#endif - bool operator<<(float val) { return shl_real(val); } - bool operator<<(double val) { return shl_real(val); } - bool operator<<(long double val) { + bool stream_in(lcast::exact<float> x) { return shl_real(x.payload); } + bool stream_in(lcast::exact<double> x) { return shl_real(x.payload); } + bool stream_in(lcast::exact<long double> x) { #ifndef __MINGW32__ - return shl_real(val); + return shl_real(x.payload); #else - return shl_real(static_cast<double>(val)); + return shl_real(static_cast<double>(x.payload)); #endif - } + } + + template <class C> + typename boost::enable_if_c<boost::detail::is_character<C>::value, bool>::type + stream_in(lcast::exact<iterator_range<C*>> x) noexcept { + auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end()); + return stream_in(lcast::exact<decltype(buf)>{buf}); + } + + template <class C> + typename boost::enable_if_c<boost::detail::is_character<C>::value, bool>::type + stream_in(lcast::exact<iterator_range<const C*>> x) noexcept { + auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end()); + return stream_in(lcast::exact<decltype(buf)>{buf}); + } + + template <class InStreamable> + bool stream_in(lcast::exact<InStreamable> x) { return shl_input_streamable(x.payload); } + }; + + + template <class CharT, class Traits> + class to_target_stream { + //`[start, finish)` is the range to output by `operator >>` + const CharT* start; + const CharT* const finish; + + public: + to_target_stream(to_target_stream&&) = delete; + to_target_stream(const to_target_stream&) = delete; + to_target_stream& operator=(to_target_stream&&) = delete; + to_target_stream& operator=(const to_target_stream&) = delete; + + to_target_stream(const CharT* begin, const CharT* end) noexcept + : start(begin) + , finish(end) + {} + + private: + template <typename Type> +#if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif + bool shr_unsigned(Type& output) { + if (start == finish) return false; + CharT const minus = lcast_char_constants<CharT>::minus; + CharT const plus = lcast_char_constants<CharT>::plus; + bool const has_minus = Traits::eq(minus, *start); - // Adding constness to characters. Constness does not change layout - template <class C, std::size_t N> - typename boost::disable_if<boost::is_const<C>, bool>::type - operator<<(boost::array<C, N> const& input) noexcept { - static_assert( - sizeof(boost::array<const C, N>) == sizeof(boost::array<C, N>), - "boost::array<C, N> and boost::array<const C, N> must have exactly the same layout." - ); - return ((*this) << reinterpret_cast<boost::array<const C, N> const& >(input)); + /* We won`t use `start' any more, so no need in decrementing it after */ + if (has_minus || Traits::eq(plus, *start)) { + ++start; } - template <std::size_t N> - bool operator<<(boost::array<const CharT, N> const& input) noexcept { - return shl_char_array_limited(input.data(), N); - } + bool const succeed = lcast_ret_unsigned<Traits, Type, CharT>(output, start, finish).convert(); - template <std::size_t N> - bool operator<<(boost::array<const unsigned char, N> const& input) noexcept { - return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); + if (has_minus) { + output = static_cast<Type>(0u - output); } - template <std::size_t N> - bool operator<<(boost::array<const signed char, N> const& input) noexcept { - return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); - } + return succeed; + } -#ifndef BOOST_NO_CXX11_HDR_ARRAY - // Making a Boost.Array from std::array - template <class C, std::size_t N> - bool operator<<(std::array<C, N> const& input) noexcept { - static_assert( - sizeof(std::array<C, N>) == sizeof(boost::array<C, N>), - "std::array and boost::array must have exactly the same layout. " - "Bug in implementation of std::array or boost::array." - ); - return ((*this) << reinterpret_cast<boost::array<C, N> const& >(input)); - } + template <typename Type> +#if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) + __attribute__((no_sanitize("unsigned-integer-overflow"))) #endif - template <class InStreamable> - bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } - }; - - - template <class CharT, class Traits> - class lexical_ostream_limited_src: boost::noncopyable { - //`[start, finish)` is the range to output by `operator >>` - const CharT* start; - const CharT* const finish; - - public: - lexical_ostream_limited_src(const CharT* begin, const CharT* end) noexcept - : start(begin) - , finish(end) - {} - -/************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ - private: - template <typename Type> - bool shr_unsigned(Type& output) { - if (start == finish) return false; - CharT const minus = lcast_char_constants<CharT>::minus; - CharT const plus = lcast_char_constants<CharT>::plus; - bool const has_minus = Traits::eq(minus, *start); - - /* We won`t use `start' any more, so no need in decrementing it after */ - if (has_minus || Traits::eq(plus, *start)) { - ++start; - } - - bool const succeed = lcast_ret_unsigned<Traits, Type, CharT>(output, start, finish).convert(); - - if (has_minus) { - output = static_cast<Type>(0u - output); - } - - return succeed; - } - - template <typename Type> - bool shr_signed(Type& output) { - if (start == finish) return false; - CharT const minus = lcast_char_constants<CharT>::minus; - CharT const plus = lcast_char_constants<CharT>::plus; - typedef typename make_unsigned<Type>::type utype; - utype out_tmp = 0; - bool const has_minus = Traits::eq(minus, *start); - - /* We won`t use `start' any more, so no need in decrementing it after */ - if (has_minus || Traits::eq(plus, *start)) { - ++start; - } - - bool succeed = lcast_ret_unsigned<Traits, utype, CharT>(out_tmp, start, finish).convert(); - if (has_minus) { - utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits); - succeed = succeed && out_tmp<=comp_val; - output = static_cast<Type>(0u - out_tmp); - } else { - utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)()); - succeed = succeed && out_tmp<=comp_val; - output = static_cast<Type>(out_tmp); - } - return succeed; - } - - template<typename InputStreamable> - bool shr_using_base_class(InputStreamable& output) - { - static_assert( - !boost::is_pointer<InputStreamable>::value, - "boost::lexical_cast can not convert to pointers" - ); + bool shr_signed(Type& output) { + if (start == finish) return false; + CharT const minus = lcast_char_constants<CharT>::minus; + CharT const plus = lcast_char_constants<CharT>::plus; + typedef typename make_unsigned<Type>::type utype; + utype out_tmp = 0; + bool const has_minus = Traits::eq(minus, *start); + + /* We won`t use `start' any more, so no need in decrementing it after */ + if (has_minus || Traits::eq(plus, *start)) { + ++start; + } + + bool succeed = lcast_ret_unsigned<Traits, utype, CharT>(out_tmp, start, finish).convert(); + if (has_minus) { + utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits); + succeed = succeed && out_tmp<=comp_val; + output = static_cast<Type>(0u - out_tmp); + } else { + utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)()); + succeed = succeed && out_tmp<=comp_val; + output = static_cast<Type>(out_tmp); + } + return succeed; + } + + template<typename InputStreamable> + bool shr_using_base_class(InputStreamable& output) + { + static_assert( + !boost::is_pointer<InputStreamable>::value, + "boost::lexical_cast can not convert to pointers" + ); #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) - static_assert(boost::is_same<char, CharT>::value, - "boost::lexical_cast can not convert, because your STL library does not " - "support such conversions. Try updating it." - ); + static_assert(boost::is_same<char, CharT>::value, + "boost::lexical_cast can not convert, because your STL library does not " + "support such conversions. Try updating it." + ); #endif #if defined(BOOST_NO_STRINGSTREAM) - std::istrstream stream(start, static_cast<std::istrstream::streamsize>(finish - start)); + std::istrstream stream(start, static_cast<std::istrstream::streamsize>(finish - start)); #else - typedef typename out_stream_helper_trait<CharT, Traits>::buffer_t buffer_t; - buffer_t buf; - // Usually `istream` and `basic_istream` do not modify - // content of buffer; `buffer_t` assures that this is true - buf.setbuf(const_cast<CharT*>(start), static_cast<typename buffer_t::streamsize>(finish - start)); + typedef detail::lcast::buffer_t<CharT, Traits> buffer_t; + buffer_t buf; + // Usually `istream` and `basic_istream` do not modify + // content of buffer; `buffer_t` assures that this is true + buf.setbuf(const_cast<CharT*>(start), static_cast<typename buffer_t::streamsize>(finish - start)); #if defined(BOOST_NO_STD_LOCALE) - std::istream stream(&buf); + std::istream stream(&buf); #else - std::basic_istream<CharT, Traits> stream(&buf); + std::basic_istream<CharT, Traits> stream(&buf); #endif // BOOST_NO_STD_LOCALE #endif // BOOST_NO_STRINGSTREAM #ifndef BOOST_NO_EXCEPTIONS - stream.exceptions(std::ios::badbit); - try { + stream.exceptions(std::ios::badbit); + try { #endif - stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, static_cast<InputStreamable*>(0)); + stream.unsetf(std::ios::skipws); + lcast_set_precision(stream, static_cast<InputStreamable*>(0)); - return (stream >> output) - && (stream.get() == Traits::eof()); + return (stream >> output) + && (stream.get() == Traits::eof()); #ifndef BOOST_NO_EXCEPTIONS - } catch (const ::std::ios_base::failure& /*f*/) { - return false; - } -#endif - } - - template<class T> - inline bool shr_xchar(T& output) noexcept { - static_assert(sizeof(CharT) == sizeof(T), - "boost::lexical_cast does not support narrowing of character types." - "Use boost::locale instead" ); - bool const ok = (finish - start == 1); - if (ok) { - CharT out; - Traits::assign(out, *start); - output = static_cast<T>(out); - } - return ok; - } - - template <std::size_t N, class ArrayT> - bool shr_std_array(ArrayT& output) noexcept { - using namespace std; - const std::size_t size = static_cast<std::size_t>(finish - start); - if (size > N - 1) { // `-1` because we need to store \0 at the end - return false; - } - - memcpy(&output[0], start, size * sizeof(CharT)); - output[size] = Traits::to_char_type(0); - return true; + } catch (const ::std::ios_base::failure& /*f*/) { + return false; } - -/************************************ OPERATORS >> ( ... ) ********************************/ - public: - bool operator>>(unsigned short& output) { return shr_unsigned(output); } - bool operator>>(unsigned int& output) { return shr_unsigned(output); } - bool operator>>(unsigned long int& output) { return shr_unsigned(output); } - bool operator>>(short& output) { return shr_signed(output); } - bool operator>>(int& output) { return shr_signed(output); } - bool operator>>(long int& output) { return shr_signed(output); } +#endif + } + + template<class T> + inline bool shr_xchar(T& output) noexcept { + static_assert(sizeof(CharT) == sizeof(T), + "boost::lexical_cast does not support narrowing of character types." + "Use boost::locale instead" ); + bool const ok = (finish - start == 1); + if (ok) { + CharT out; + Traits::assign(out, *start); + output = static_cast<T>(out); + } + return ok; + } + + template <std::size_t N, class ArrayT> + bool shr_std_array(ArrayT& output) noexcept { + const std::size_t size = static_cast<std::size_t>(finish - start); + if (size > N - 1) { // `-1` because we need to store \0 at the end + return false; + } + + std::memcpy(&output[0], start, size * sizeof(CharT)); + output[size] = Traits::to_char_type(0); + return true; + } + + public: + bool stream_out(unsigned short& output) { return shr_unsigned(output); } + bool stream_out(unsigned int& output) { return shr_unsigned(output); } + bool stream_out(unsigned long int& output) { return shr_unsigned(output); } + bool stream_out(short& output) { return shr_signed(output); } + bool stream_out(int& output) { return shr_signed(output); } + bool stream_out(long int& output) { return shr_signed(output); } #if defined(BOOST_HAS_LONG_LONG) - bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); } - bool operator>>(boost::long_long_type& output) { return shr_signed(output); } + bool stream_out(boost::ulong_long_type& output) { return shr_unsigned(output); } + bool stream_out(boost::long_long_type& output) { return shr_signed(output); } #elif defined(BOOST_HAS_MS_INT64) - bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } - bool operator>>(__int64& output) { return shr_signed(output); } + bool stream_out(unsigned __int64& output) { return shr_unsigned(output); } + bool stream_out(__int64& output) { return shr_signed(output); } #endif #ifdef BOOST_HAS_INT128 - bool operator>>(boost::uint128_type& output) { return shr_unsigned(output); } - bool operator>>(boost::int128_type& output) { return shr_signed(output); } + bool stream_out(boost::uint128_type& output) { return shr_unsigned(output); } + bool stream_out(boost::int128_type& output) { return shr_signed(output); } #endif - bool operator>>(char& output) { return shr_xchar(output); } - bool operator>>(unsigned char& output) { return shr_xchar(output); } - bool operator>>(signed char& output) { return shr_xchar(output); } + bool stream_out(char& output) { return shr_xchar(output); } + bool stream_out(unsigned char& output) { return shr_xchar(output); } + bool stream_out(signed char& output) { return shr_xchar(output); } #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - bool operator>>(wchar_t& output) { return shr_xchar(output); } + bool stream_out(wchar_t& output) { return shr_xchar(output); } #endif #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator>>(char16_t& output) { return shr_xchar(output); } + bool stream_out(char16_t& output) { return shr_xchar(output); } #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator>>(char32_t& output) { return shr_xchar(output); } + bool stream_out(char32_t& output) { return shr_xchar(output); } #endif - template<class Alloc> - bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { - str.assign(start, finish); return true; - } + template<class CharTraits, class Alloc> + bool stream_out(std::basic_string<CharT,CharTraits,Alloc>& str) { + str.assign(start, finish); return true; + } - template<class Alloc> - bool operator>>(boost::container::basic_string<CharT,Traits,Alloc>& str) { - str.assign(start, finish); return true; - } + template<class CharTraits, class Alloc> + bool stream_out(boost::container::basic_string<CharT,CharTraits,Alloc>& str) { + str.assign(start, finish); return true; + } - template <std::size_t N> - bool operator>>(std::array<CharT, N>& output) noexcept { - return shr_std_array<N>(output); - } + template <class C, std::size_t N> + bool stream_out(std::array<C, N>& output) noexcept { + static_assert(sizeof(C) == sizeof(CharT), ""); + return shr_std_array<N>(output); + } - template <std::size_t N> - bool operator>>(std::array<unsigned char, N>& output) noexcept { - return ((*this) >> reinterpret_cast<std::array<char, N>& >(output)); - } + template <class C, std::size_t N> + bool stream_out(boost::array<C, N>& output) noexcept { + static_assert(sizeof(C) == sizeof(CharT), ""); + return shr_std_array<N>(output); + } - template <std::size_t N> - bool operator>>(std::array<signed char, N>& output) noexcept { - return ((*this) >> reinterpret_cast<std::array<char, N>& >(output)); - } + bool stream_out(bool& output) noexcept { + output = false; // Suppress warning about uninitalized variable - template <class C, std::size_t N> - bool operator>>(boost::array<C, N>& output) noexcept { - static_assert( - sizeof(std::array<C, N>) == sizeof(boost::array<C, N>), - "std::array<C, N> and boost::array<C, N> must have exactly the same layout." - ); - return ((*this) >> reinterpret_cast<std::array<C, N>& >(output)); - } + if (start == finish) return false; + CharT const zero = lcast_char_constants<CharT>::zero; + CharT const plus = lcast_char_constants<CharT>::plus; + CharT const minus = lcast_char_constants<CharT>::minus; - bool operator>>(bool& output) noexcept { - output = false; // Suppress warning about uninitalized variable - - if (start == finish) return false; - CharT const zero = lcast_char_constants<CharT>::zero; - CharT const plus = lcast_char_constants<CharT>::plus; - CharT const minus = lcast_char_constants<CharT>::minus; - - const CharT* const dec_finish = finish - 1; - output = Traits::eq(*dec_finish, zero + 1); - if (!output && !Traits::eq(*dec_finish, zero)) { - return false; // Does not ends on '0' or '1' - } - - if (start == dec_finish) return true; - - // We may have sign at the beginning - if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) { - ++ start; - } - - // Skipping zeros - while (start != dec_finish) { - if (!Traits::eq(zero, *start)) { - return false; // Not a zero => error - } - - ++ start; - } - - return true; + const CharT* const dec_finish = finish - 1; + output = Traits::eq(*dec_finish, zero + 1); + if (!output && !Traits::eq(*dec_finish, zero)) { + return false; // Does not ends on '0' or '1' } - private: - // Not optimised converter - template <class T> - bool float_types_converter_internal(T& output) { - if (parse_inf_nan(start, finish, output)) return true; - bool const return_value = shr_using_base_class(output); - - /* Some compilers and libraries successfully - * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... - * We are trying to provide a unified behaviour, - * so we just forbid such conversions (as some - * of the most popular compilers/libraries do) - * */ - CharT const minus = lcast_char_constants<CharT>::minus; - CharT const plus = lcast_char_constants<CharT>::plus; - CharT const capital_e = lcast_char_constants<CharT>::capital_e; - CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e; - if ( return_value && - ( - Traits::eq(*(finish-1), lowercase_e) // 1.0e - || Traits::eq(*(finish-1), capital_e) // 1.0E - || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E- - || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+ - ) - ) return false; - - return return_value; + if (start == dec_finish) return true; + + // We may have sign at the beginning + if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) { + ++ start; } - public: - bool operator>>(float& output) { return float_types_converter_internal(output); } - bool operator>>(double& output) { return float_types_converter_internal(output); } - bool operator>>(long double& output) { return float_types_converter_internal(output); } + // Skipping zeros + while (start != dec_finish) { + if (!Traits::eq(zero, *start)) { + return false; // Not a zero => error + } - // Generic istream-based algorithm. - // lcast_streambuf_for_target<InputStreamable>::value is true. - template <typename InputStreamable> - bool operator>>(InputStreamable& output) { - return shr_using_base_class(output); - } - }; - } -} // namespace boost + ++ start; + } + + return true; + } + + private: + // Not optimised converter + template <class T> + bool float_types_converter_internal(T& output) { + if (parse_inf_nan(start, finish, output)) return true; + bool const return_value = shr_using_base_class(output); + + /* Some compilers and libraries successfully + * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... + * We are trying to provide a unified behaviour, + * so we just forbid such conversions (as some + * of the most popular compilers/libraries do) + * */ + CharT const minus = lcast_char_constants<CharT>::minus; + CharT const plus = lcast_char_constants<CharT>::plus; + CharT const capital_e = lcast_char_constants<CharT>::capital_e; + CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e; + if ( return_value && + ( + Traits::eq(*(finish-1), lowercase_e) // 1.0e + || Traits::eq(*(finish-1), capital_e) // 1.0E + || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E- + || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+ + ) + ) return false; + + return return_value; + } + + public: + bool stream_out(float& output) { return float_types_converter_internal(output); } + bool stream_out(double& output) { return float_types_converter_internal(output); } + bool stream_out(long double& output) { return float_types_converter_internal(output); } + + // Generic istream-based algorithm. + // lcast_streambuf_for_target<InputStreamable>::value is true. + template <typename InputStreamable> + bool stream_out(InputStreamable& output) { + return shr_using_base_class(output); + } + }; + +}}} // namespace boost::detail::lcast #undef BOOST_LCAST_NO_WCHAR_T diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_numeric.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_numeric.hpp index a2c992db53..167473b363 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_numeric.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/converter_numeric.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -23,101 +23,107 @@ # pragma once #endif +#include <boost/core/cmath.hpp> +#include <boost/core/enable_if.hpp> #include <boost/limits.hpp> #include <boost/type_traits/type_identity.hpp> #include <boost/type_traits/conditional.hpp> #include <boost/type_traits/make_unsigned.hpp> #include <boost/type_traits/is_signed.hpp> -#include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_arithmetic.hpp> -#include <boost/type_traits/is_base_of.hpp> #include <boost/type_traits/is_float.hpp> -#include <boost/type_traits/remove_volatile.hpp> - -#include <boost/numeric/conversion/cast.hpp> namespace boost { namespace detail { -template <class Source > -struct detect_precision_loss -{ - typedef Source source_type; - typedef boost::numeric::Trunc<Source> Rounder; - typedef typename conditional< - boost::is_arithmetic<Source>::value, Source, Source const& - >::type argument_type ; - - static inline source_type nearbyint(argument_type s, bool& is_ok) noexcept { - const source_type near_int = Rounder::nearbyint(s); - if (near_int && is_ok) { - const source_type orig_div_round = s / near_int; - const source_type eps = std::numeric_limits<source_type>::epsilon(); - - is_ok = !((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps); - } +template <class Source, class Target> +bool ios_numeric_comparer_float(Source x, Source y) noexcept { + return x == y + || (boost::core::isnan(x) && boost::core::isnan(y)) + || (x < (std::numeric_limits<Target>::min)()) + ; +} + +template <class RangeType, class T> +constexpr bool is_out_of_range_for(T value) noexcept { + return value > static_cast<T>((std::numeric_limits<RangeType>::max)()) + || value < static_cast<T>((std::numeric_limits<RangeType>::min)()); +} + - return s; +// integral -> integral +template <typename Target, typename Source> +typename boost::enable_if_c< + !boost::is_floating_point<Source>::value && !boost::is_floating_point<Target>::value, bool +>::type noexcept_numeric_convert(Source arg, Target& result) noexcept { + const Target target_tmp = static_cast<Target>(arg); + const Source arg_restored = static_cast<Source>(target_tmp); + if (arg == arg_restored) { + result = target_tmp; + return true; } + return false; +} - typedef typename Rounder::round_style round_style; -}; +// integral -> floating point +template <typename Target, typename Source> +typename boost::enable_if_c< + !boost::is_floating_point<Source>::value && boost::is_floating_point<Target>::value, bool +>::type noexcept_numeric_convert(Source arg, Target& result) noexcept { + const Target target_tmp = static_cast<Target>(arg); + result = target_tmp; + return true; +} -template <typename Base, class Source> -struct fake_precision_loss: public Base -{ - typedef Source source_type ; - typedef typename conditional< - boost::is_arithmetic<Source>::value, Source, Source const& - >::type argument_type ; - static inline source_type nearbyint(argument_type s, bool& /*is_ok*/) noexcept { - return s; +// floating point -> floating point +template <typename Target, typename Source> +typename boost::enable_if_c< + boost::is_floating_point<Source>::value && boost::is_floating_point<Target>::value, bool +>::type noexcept_numeric_convert(Source arg, Target& result) noexcept { + const Target target_tmp = static_cast<Target>(arg); + const Source arg_restored = static_cast<Source>(target_tmp); + if (detail::ios_numeric_comparer_float<Source, Target>(arg, arg_restored)) { + result = target_tmp; + return true; } -}; -struct nothrow_overflow_handler -{ - inline bool operator() ( boost::numeric::range_check_result r ) const noexcept { - return (r == boost::numeric::cInRange); - } -}; + return false; +} +// floating point -> integral template <typename Target, typename Source> -inline bool noexcept_numeric_convert(const Source& arg, Target& result) noexcept { - typedef boost::numeric::converter< - Target, - Source, - boost::numeric::conversion_traits<Target, Source >, - nothrow_overflow_handler, - detect_precision_loss<Source > - > converter_orig_t; - - typedef typename boost::conditional< - boost::is_base_of< detect_precision_loss<Source >, converter_orig_t >::value, - converter_orig_t, - fake_precision_loss<converter_orig_t, Source> - >::type converter_t; - - bool res = nothrow_overflow_handler()(converter_t::out_of_range(arg)); - if (res) { - result = converter_t::low_level_convert(converter_t::nearbyint(arg, res)); +typename boost::enable_if_c< + boost::is_floating_point<Source>::value && !boost::is_floating_point<Target>::value, bool +>::type noexcept_numeric_convert(Source arg, Target& result) noexcept { + if (detail::is_out_of_range_for<Target>(arg)) { + return false; } - return res; + const Target target_tmp = static_cast<Target>(arg); + const Source arg_restored = static_cast<Source>(target_tmp); + if (detail::ios_numeric_comparer_float<Source, Target>(arg, arg_restored)) { + result = target_tmp; + return true; + } + + return false; } -template <typename Target, typename Source> struct lexical_cast_dynamic_num_not_ignoring_minus { - static inline bool try_convert(const Source &arg, Target& result) noexcept { - return noexcept_numeric_convert<Target, Source >(arg, result); + template <typename Target, typename Source> + static inline bool try_convert(Source arg, Target& result) noexcept { + return boost::detail::noexcept_numeric_convert<Target, Source >(arg, result); } }; -template <typename Target, typename Source> struct lexical_cast_dynamic_num_ignoring_minus { - static inline bool try_convert(const Source &arg, Target& result) noexcept { + template <typename Target, typename Source> +#if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif + static inline bool try_convert(Source arg, Target& result) noexcept { typedef typename boost::conditional< boost::is_float<Source>::value, boost::type_identity<Source>, @@ -126,17 +132,19 @@ struct lexical_cast_dynamic_num_ignoring_minus typedef typename usource_lazy_t::type usource_t; if (arg < 0) { - const bool res = noexcept_numeric_convert<Target, usource_t>(0u - arg, result); + const bool res = boost::detail::noexcept_numeric_convert<Target, usource_t>( + static_cast<usource_t>(0u - static_cast<usource_t>(arg)), result + ); result = static_cast<Target>(0u - result); return res; } else { - return noexcept_numeric_convert<Target, usource_t>(arg, result); + return boost::detail::noexcept_numeric_convert<Target, usource_t>(arg, result); } } }; /* - * lexical_cast_dynamic_num follows the rules: + * dynamic_num_converter_impl follows the rules: * 1) If Source can be converted to Target without precision loss and * without overflows, then assign Source to Target and return * @@ -156,16 +164,14 @@ struct lexical_cast_dynamic_num_ignoring_minus template <typename Target, typename Source> struct dynamic_num_converter_impl { - typedef typename boost::remove_volatile<Source>::type source_type; - - static inline bool try_convert(source_type arg, Target& result) noexcept { + static inline bool try_convert(Source arg, Target& result) noexcept { typedef typename boost::conditional< boost::is_unsigned<Target>::value && - (boost::is_signed<source_type>::value || boost::is_float<source_type>::value) && - !(boost::is_same<source_type, bool>::value) && + (boost::is_signed<Source>::value || boost::is_float<Source>::value) && + !(boost::is_same<Source, bool>::value) && !(boost::is_same<Target, bool>::value), - lexical_cast_dynamic_num_ignoring_minus<Target, source_type>, - lexical_cast_dynamic_num_not_ignoring_minus<Target, source_type> + lexical_cast_dynamic_num_ignoring_minus, + lexical_cast_dynamic_num_not_ignoring_minus >::type caster_type; return caster_type::try_convert(arg, result); diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/inf_nan.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/inf_nan.hpp index a9f92b2d1c..df01d3f975 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/inf_nan.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/inf_nan.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -100,32 +100,25 @@ namespace boost { } template <class CharT, class T> - bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value + const CharT* get_inf_nan_impl(T value , const CharT* lc_nan - , const CharT* lc_infinity) noexcept + , const CharT* lc_minus_nan + , const CharT* lc_infinity + , const CharT* lc_minus_infinity) noexcept { - const CharT minus = lcast_char_constants<CharT>::minus; if (boost::core::isnan(value)) { if (boost::core::signbit(value)) { - *begin = minus; - ++ begin; + return lc_minus_nan; } - - std::memcpy(begin, lc_nan, 3 * sizeof(CharT)); - end = begin + 3; - return true; + return lc_nan; } else if (boost::core::isinf(value)) { if (boost::core::signbit(value)) { - *begin = minus; - ++ begin; + return lc_minus_infinity; } - - std::memcpy(begin, lc_infinity, 3 * sizeof(CharT)); - end = begin + 3; - return true; + return lc_infinity; } - return false; + return nullptr; } @@ -139,8 +132,8 @@ namespace boost { } template <class T> - bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) noexcept { - return put_inf_nan_impl(begin, end, value, L"nan", L"infinity"); + const wchar_t* get_inf_nan(T value, wchar_t) noexcept { + return detail::get_inf_nan_impl(value, L"nan", L"-nan", L"inf", L"-inf"); } #endif @@ -154,8 +147,8 @@ namespace boost { } template <class T> - bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) noexcept { - return put_inf_nan_impl(begin, end, value, u"nan", u"infinity"); + const char16_t* get_inf_nan(T value, char16_t) noexcept { + return detail::get_inf_nan_impl(value, u"nan", u"-nan", u"inf", u"-inf"); } #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) @@ -168,8 +161,8 @@ namespace boost { } template <class T> - bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) noexcept { - return put_inf_nan_impl(begin, end, value, U"nan", U"infinity"); + const char32_t* get_inf_nan(T value, char32_t) noexcept { + return detail::get_inf_nan_impl(value, U"nan", U"-nan", U"inf", U"-inf"); } #endif @@ -181,9 +174,9 @@ namespace boost { , '(', ')'); } - template <class CharT, class T> - bool put_inf_nan(CharT* begin, CharT*& end, const T& value) noexcept { - return put_inf_nan_impl(begin, end, value, "nan", "infinity"); + template <class T> + const char* get_inf_nan(T value, char) noexcept { + return detail::get_inf_nan_impl(value, "nan", "-nan", "inf", "-inf"); } } } // namespace boost diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/is_character.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/is_character.hpp index c0e4929567..f9b2234566 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/is_character.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/is_character.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -26,34 +26,27 @@ #include <boost/type_traits/integral_constant.hpp> #include <boost/type_traits/is_same.hpp> -namespace boost { - - namespace detail // is_character<...> - { - // returns true, if T is one of the character types - template < typename T > - struct is_character - { - typedef typename boost::integral_constant< - bool, - boost::is_same< T, char >::value || - #if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) - boost::is_same< T, wchar_t >::value || - #endif - #ifndef BOOST_NO_CXX11_CHAR16_T - boost::is_same< T, char16_t >::value || - #endif - #ifndef BOOST_NO_CXX11_CHAR32_T - boost::is_same< T, char32_t >::value || - #endif - boost::is_same< T, unsigned char >::value || - boost::is_same< T, signed char >::value - > type; - - BOOST_STATIC_CONSTANT(bool, value = (type::value) ); - }; - } -} +namespace boost { namespace detail { + +// returns true, if T is one of the character types +template < typename T > +using is_character = boost::integral_constant< + bool, + boost::is_same< T, char >::value || +#if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) + boost::is_same< T, wchar_t >::value || +#endif +#ifndef BOOST_NO_CXX11_CHAR16_T + boost::is_same< T, char16_t >::value || +#endif +#ifndef BOOST_NO_CXX11_CHAR32_T + boost::is_same< T, char32_t >::value || +#endif + boost::is_same< T, unsigned char >::value || + boost::is_same< T, signed char >::value +>; + +}} #endif // BOOST_LEXICAL_CAST_DETAIL_IS_CHARACTER_HPP diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp new file mode 100644 index 0000000000..18168c5dbd --- /dev/null +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp @@ -0,0 +1,73 @@ +// Copyright Kevlin Henney, 2000-2005. +// Copyright Alexander Nasonov, 2006-2010. +// Copyright Antony Polukhin, 2011-2024. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_BASIC_UNLOCKEDBUF_HPP +#define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_BASIC_UNLOCKEDBUF_HPP + +#include <boost/config.hpp> +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + + +#ifdef BOOST_NO_STRINGSTREAM +#include <strstream> +#else +#include <sstream> +#endif + +#include <boost/detail/basic_pointerbuf.hpp> +#ifndef BOOST_NO_CWCHAR +# include <cwchar> +#endif + +namespace boost { namespace detail { namespace lcast { + + // acts as a stream buffer which wraps around a pair of pointers + // and gives acces to internals + template <class BufferType, class CharT> + class basic_unlockedbuf : public basic_pointerbuf<CharT, BufferType> { + public: + typedef basic_pointerbuf<CharT, BufferType> base_type; + typedef typename base_type::streamsize streamsize; + + using base_type::pptr; + using base_type::pbase; + using base_type::setbuf; + }; + +#if defined(BOOST_NO_STRINGSTREAM) + template <class CharT, class Traits> + using out_stream_t = std::ostream; + + template <class CharT, class Traits> + using stringbuffer_t = basic_unlockedbuf<std::strstreambuf, char>; +#elif defined(BOOST_NO_STD_LOCALE) + template <class CharT, class Traits> + using out_stream_t = std::ostream; + + template <class CharT, class Traits> + using stringbuffer_t = basic_unlockedbuf<std::stringbuf, char>; + + template <class CharT, class Traits> + using buffer_t = basic_unlockedbuf<std::streambuf, char>; +#else + template <class CharT, class Traits> + using out_stream_t = std::basic_ostream<CharT, Traits>; + + template <class CharT, class Traits> + using stringbuffer_t = basic_unlockedbuf<std::basic_stringbuf<CharT, Traits>, CharT>; + + template <class CharT, class Traits> + using buffer_t = basic_unlockedbuf<std::basic_streambuf<CharT, Traits>, CharT>; +#endif + +}}} // namespace boost::detail::lcast + +#endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_BASIC_UNLOCKEDBUF_HPP + diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_char_constants.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_char_constants.hpp index e2069a56b3..8be09dc3e2 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_char_constants.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_char_constants.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_unsigned_converters.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_unsigned_converters.hpp index cfb0c2e321..21656e8466 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_unsigned_converters.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/lcast_unsigned_converters.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -56,6 +56,9 @@ namespace boost namespace detail // lcast_to_unsigned { template<class T> +#if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif inline typename boost::make_unsigned<T>::type lcast_to_unsigned(const T value) noexcept { typedef typename boost::make_unsigned<T>::type result_type; @@ -251,6 +254,9 @@ namespace boost private: // Iteration that does not care about grouping/separators and assumes that all // input characters are digits +#if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif inline bool main_convert_iteration() noexcept { CharT const czero = lcast_char_constants<CharT>::zero; T const maxv = (std::numeric_limits<T>::max)(); diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/widest_char.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/widest_char.hpp index f7a36fab27..2db928c5d2 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/widest_char.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/detail/widest_char.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -28,14 +28,12 @@ namespace boost { namespace detail { - template <typename TargetChar, typename SourceChar> - struct widest_char { - typedef typename boost::conditional< - (sizeof(TargetChar) > sizeof(SourceChar)) - , TargetChar - , SourceChar - >::type type; - }; +template <typename TargetChar, typename SourceChar> +using widest_char = boost::conditional< + (sizeof(TargetChar) > sizeof(SourceChar)) + , TargetChar + , SourceChar +>; }} // namespace boost::detail diff --git a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/try_lexical_convert.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/try_lexical_convert.hpp index 962d950eb3..35cc68703e 100644 --- a/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/try_lexical_convert.hpp +++ b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/try_lexical_convert.hpp @@ -1,6 +1,6 @@ // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. +// Copyright Antony Polukhin, 2011-2024. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -23,20 +23,7 @@ # pragma once #endif -#if defined(__clang__) || (defined(__GNUC__) && \ - !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#endif - - -#include <string> -#include <boost/type_traits/is_integral.hpp> -#include <boost/type_traits/type_identity.hpp> #include <boost/type_traits/conditional.hpp> -#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_arithmetic.hpp> #include <boost/lexical_cast/detail/buffer_view.hpp> @@ -44,119 +31,17 @@ #include <boost/lexical_cast/detail/converter_numeric.hpp> #include <boost/lexical_cast/detail/converter_lexical.hpp> -#include <boost/container/container_fwd.hpp> - namespace boost { namespace detail { - template<typename T> - struct is_stdstring - : boost::false_type - {}; - - template<typename CharT, typename Traits, typename Alloc> - struct is_stdstring< std::basic_string<CharT, Traits, Alloc> > - : boost::true_type - {}; - - // Sun Studio has problem with partial specialization of templates differing only in namespace. - // We workaround that by making `is_booststring` trait, instead of specializing `is_stdstring` for `boost::container::basic_string`. - template<typename T> - struct is_booststring - : boost::false_type - {}; - - template<typename CharT, typename Traits, typename Alloc> - struct is_booststring< boost::container::basic_string<CharT, Traits, Alloc> > - : boost::true_type - {}; - - template<typename Target, typename Source> - struct is_arithmetic_and_not_xchars - { - typedef boost::integral_constant< - bool, - !(boost::detail::is_character<Target>::value) && - !(boost::detail::is_character<Source>::value) && - boost::is_arithmetic<Source>::value && - boost::is_arithmetic<Target>::value - > type; - - BOOST_STATIC_CONSTANT(bool, value = ( - type::value - )); - }; - - /* - * is_xchar_to_xchar<Target, Source>::value is true, - * Target and Souce are char types of the same size 1 (char, signed char, unsigned char). - */ - template<typename Target, typename Source> - struct is_xchar_to_xchar - { - typedef boost::integral_constant< - bool, - sizeof(Source) == sizeof(Target) && - sizeof(Source) == sizeof(char) && - boost::detail::is_character<Target>::value && - boost::detail::is_character<Source>::value - > type; - - BOOST_STATIC_CONSTANT(bool, value = ( - type::value - )); - }; - - template<typename Target, typename Source> - struct is_char_array_to_stdstring - : boost::false_type - {}; - - template<typename CharT, typename Traits, typename Alloc> - struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* > - : boost::true_type - {}; - - template<typename CharT, typename Traits, typename Alloc> - struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* > - : boost::true_type - {}; - - // Sun Studio has problem with partial specialization of templates differing only in namespace. - // We workaround that by making `is_char_array_to_booststring` trait, instead of specializing `is_char_array_to_stdstring` for `boost::container::basic_string`. template<typename Target, typename Source> - struct is_char_array_to_booststring - : boost::false_type - {}; - - template<typename CharT, typename Traits, typename Alloc> - struct is_char_array_to_booststring< boost::container::basic_string<CharT, Traits, Alloc>, CharT* > - : boost::true_type - {}; - - template<typename CharT, typename Traits, typename Alloc> - struct is_char_array_to_booststring< boost::container::basic_string<CharT, Traits, Alloc>, const CharT* > - : boost::true_type - {}; - - template <typename Target, typename Source> - struct copy_converter_impl - { -// MSVC fail to forward an array (DevDiv#555157 "SILENT BAD CODEGEN triggered by perfect forwarding", -// fixed in 2013 RTM). -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined(BOOST_MSVC) || BOOST_MSVC >= 1800) - template <class T> - static inline bool try_convert(T&& arg, Target& result) { - result = static_cast<T&&>(arg); // eqaul to `result = std::forward<T>(arg);` - return true; - } -#else - static inline bool try_convert(const Source& arg, Target& result) { - result = arg; - return true; - } -#endif - }; + using is_arithmetic_and_not_xchars = boost::integral_constant< + bool, + !(boost::detail::is_character<Target>::value) && + !(boost::detail::is_character<Source>::value) && + boost::is_arithmetic<Source>::value && + boost::is_arithmetic<Target>::value + >; } namespace conversion { namespace detail { @@ -164,39 +49,20 @@ namespace boost { template <typename Target, typename Source> inline bool try_lexical_convert(const Source& arg, Target& result) { - typedef typename boost::detail::array_to_pointer_decay<Source>::type src; + static_assert( + !boost::is_volatile<Source>::value, + "Boost.LexicalCast does not support volatile input"); - typedef boost::integral_constant< - bool, - boost::detail::is_xchar_to_xchar<Target, src >::value || - boost::detail::is_char_array_to_stdstring<Target, src >::value || - boost::detail::is_char_array_to_booststring<Target, src >::value || - ( - boost::is_same<Target, src >::value && - (boost::detail::is_stdstring<Target >::value || boost::detail::is_booststring<Target >::value) - ) || - ( - boost::is_same<Target, src >::value && - boost::detail::is_character<Target >::value - ) - > shall_we_copy_t; + typedef typename boost::detail::array_to_pointer_decay<Source>::type src; typedef boost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t; - // We do evaluate second `if_` lazily to avoid unnecessary instantiations - // of `shall_we_copy_with_dynamic_check_t` and improve compilation times. typedef typename boost::conditional< - shall_we_copy_t::value, - boost::type_identity<boost::detail::copy_converter_impl<Target, src > >, - boost::conditional< - shall_we_copy_with_dynamic_check_t::value, - boost::detail::dynamic_num_converter_impl<Target, src >, - boost::detail::lexical_converter_impl<Target, src > - > - >::type caster_type_lazy; - - typedef typename caster_type_lazy::type caster_type; + shall_we_copy_with_dynamic_check_t::value, + boost::detail::dynamic_num_converter_impl<Target, src >, + boost::detail::lexical_converter_impl<Target, src > + >::type caster_type; return caster_type::try_convert(arg, result); } @@ -223,11 +89,5 @@ namespace boost { } // namespace boost -#if defined(__clang__) || (defined(__GNUC__) && \ - !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) -#pragma GCC diagnostic pop -#endif - #endif // BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP diff --git a/contrib/restricted/boost/lexical_cast/ya.make b/contrib/restricted/boost/lexical_cast/ya.make index 6de1c1e592..53582e1aad 100644 --- a/contrib/restricted/boost/lexical_cast/ya.make +++ b/contrib/restricted/boost/lexical_cast/ya.make @@ -6,16 +6,15 @@ LICENSE(BSL-1.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(1.84.0) +VERSION(1.85.0) -ORIGINAL_SOURCE(https://github.com/boostorg/lexical_cast/archive/boost-1.84.0.tar.gz) +ORIGINAL_SOURCE(https://github.com/boostorg/lexical_cast/archive/boost-1.85.0.tar.gz) PEERDIR( contrib/restricted/boost/config contrib/restricted/boost/container contrib/restricted/boost/core contrib/restricted/boost/integer - contrib/restricted/boost/numeric_conversion contrib/restricted/boost/throw_exception contrib/restricted/boost/type_traits ) |