diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-07-02 16:05:55 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-07-02 16:16:39 +0300 |
commit | aa7cbf9b8c72570a3ceddf7f74338761fe2faf1c (patch) | |
tree | 66523e5ba47a93dd523916721eacf5e3f7b83cf7 /contrib/restricted | |
parent | 3336f268eb26aa0318cd3fa3f97116c43545f87b (diff) | |
download | ydb-aa7cbf9b8c72570a3ceddf7f74338761fe2faf1c.tar.gz |
Revert boost/lexical_cast to pre-PR#70 version to fix tests
This PR has broken the tests:
https://github.com/boostorg/lexical_cast/pull/70
as can be seen here:
https://a.yandex-team.ru/arcadia/commit/rXXXXXX/checks
8c9b2a7490283d0744d97fc6213a503d27fc7e73
Diffstat (limited to 'contrib/restricted')
6 files changed, 281 insertions, 175 deletions
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 cd9f76f542..0347d54e2d 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 @@ -42,10 +42,6 @@ #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> @@ -59,9 +55,6 @@ 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 @@ -179,19 +172,6 @@ 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 > {}; @@ -322,6 +302,32 @@ namespace boost { }; } + 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; + }; + } + namespace detail // array_to_pointer_decay<T> { template<class T> @@ -425,7 +431,11 @@ namespace boost { "Your compiler does not have full support for char32_t" ); #endif - typedef std::char_traits<char_type> traits; + 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::detail::lcast_src_length<no_cv_src> len_t; }; @@ -464,7 +474,7 @@ namespace boost { return false; to_target_stream out(src_stream.cbegin(), src_stream.cend()); - if (!out.stream_out(result)) + 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 6398055e4b..e7cabef760 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 @@ -77,6 +77,7 @@ #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_reference.hpp> #include <boost/container/container_fwd.hpp> +#include <boost/core/noncopyable.hpp> #include <boost/core/enable_if.hpp> #ifndef BOOST_NO_CWCHAR # include <cwchar> @@ -88,9 +89,6 @@ namespace boost { class array; 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 boost { namespace detail { namespace lcast { @@ -107,7 +105,7 @@ namespace boost { namespace detail { namespace lcast { , class Traits , std::size_t CharacterBufferSize > - class optimized_src_stream { + class optimized_src_stream: boost::noncopyable { CharT buffer[CharacterBufferSize]; // After the `stream_in(` finishes, `[start, finish)` is @@ -115,11 +113,6 @@ namespace boost { namespace detail { namespace lcast { 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) @@ -254,25 +247,15 @@ namespace boost { namespace detail { namespace lcast { } #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 { + template<class Alloc> + bool stream_in(lcast::exact<std::basic_string<CharT,Traits,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 { + template<class Alloc> + bool stream_in(lcast::exact<boost::container::basic_string<CharT,Traits,Alloc>> x) noexcept { start = x.payload.data(); finish = start + x.payload.length(); return true; @@ -292,12 +275,19 @@ namespace boost { namespace detail { namespace lcast { } template <class C> - enable_if_compatible_char_t<C> + typename boost::enable_if_c<boost::detail::is_character<C>::value && sizeof(CharT) == sizeof(C), bool>::type 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}); } + template <class C> + typename boost::enable_if_c<boost::detail::is_character<C>::value && sizeof(CharT) == sizeof(C), bool>::type + stream_in(lcast::exact<boost::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}); + } + 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)); } @@ -307,8 +297,12 @@ namespace boost { namespace detail { namespace lcast { 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)); } + typename boost::enable_if_c<boost::detail::is_character<Type>::value && sizeof(CharT) == sizeof(Type), bool>::type + stream_in(lcast::exact<const Type*> x) { return shl_char_array(reinterpret_cast<CharT const*>(x.payload)); } + + template <class Type> + typename boost::enable_if_c<boost::detail::is_character<Type>::value && sizeof(CharT) == sizeof(Type), bool>::type + stream_in(lcast::exact<Type*> x) { return shl_char_array(reinterpret_cast<CharT*>(x.payload)); } template <class Type> typename boost::enable_if_c<boost::is_signed<Type>::value && !boost::is_enum<Type>::value, bool>::type @@ -330,28 +324,27 @@ namespace boost { namespace detail { namespace lcast { } template <class C, std::size_t N> - enable_if_compatible_char_t<C> + typename boost::enable_if_c<boost::detail::is_character<C>::value && sizeof(CharT) == sizeof(C), bool>::type 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 { + typename boost::enable_if_c<boost::detail::is_character<C>::value && sizeof(CharT) == sizeof(C), bool>::type + stream_in(lcast::exact<boost::array<const 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()); + template <class C, std::size_t N> + typename boost::enable_if_c<boost::detail::is_character<C>::value && sizeof(CharT) == sizeof(C), bool>::type + stream_in(lcast::exact<std::array<C, N>> x) noexcept { + return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N); } -#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 C, std::size_t N> + typename boost::enable_if_c<boost::detail::is_character<C>::value && sizeof(CharT) == sizeof(C), bool>::type + stream_in(lcast::exact<std::array<const C, N>> x) noexcept { + return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N); } }; @@ -367,11 +360,6 @@ namespace boost { namespace detail { namespace lcast { 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 { @@ -472,17 +460,12 @@ namespace boost { namespace detail { namespace lcast { template <class CharT, class Traits> - class to_target_stream { + class to_target_stream: boost::noncopyable { //`[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) @@ -490,9 +473,6 @@ namespace boost { namespace detail { namespace lcast { 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; @@ -514,9 +494,6 @@ namespace boost { namespace detail { namespace lcast { } template <typename Type> -#if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) - __attribute__((no_sanitize("unsigned-integer-overflow"))) -#endif bool shr_signed(Type& output) { if (start == finish) return false; CharT const minus = lcast_char_constants<CharT>::minus; @@ -648,13 +625,13 @@ namespace boost { namespace detail { namespace lcast { #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) bool stream_out(char32_t& output) { return shr_xchar(output); } #endif - template<class CharTraits, class Alloc> - bool stream_out(std::basic_string<CharT,CharTraits,Alloc>& str) { + template<class Alloc> + bool stream_out(std::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) { + template<class Alloc> + bool stream_out(boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; } 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 167473b363..95b0334a9f 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 @@ -23,107 +23,101 @@ # 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> -namespace boost { namespace detail { - -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)()) - ; -} +#include <boost/numeric/conversion/cast.hpp> -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)()); -} +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); + } -// 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 s; } - return false; -} -// 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; -} + typedef typename Rounder::round_style round_style; +}; +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 ; -// 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; + static inline source_type nearbyint(argument_type s, bool& /*is_ok*/) noexcept { + return s; } +}; - return false; -} - -// floating point -> 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 { - if (detail::is_out_of_range_for<Target>(arg)) { - return false; +struct nothrow_overflow_handler +{ + inline bool operator() ( boost::numeric::range_check_result r ) const noexcept { + return (r == boost::numeric::cInRange); } +}; - 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; +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)); } - return false; + return res; } +template <typename Target, typename Source> struct lexical_cast_dynamic_num_not_ignoring_minus { - 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); + static inline bool try_convert(const Source &arg, Target& result) noexcept { + return noexcept_numeric_convert<Target, Source >(arg, result); } }; +template <typename Target, typename Source> struct lexical_cast_dynamic_num_ignoring_minus { - 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 { + static inline bool try_convert(const Source &arg, Target& result) noexcept { typedef typename boost::conditional< boost::is_float<Source>::value, boost::type_identity<Source>, @@ -132,19 +126,17 @@ struct lexical_cast_dynamic_num_ignoring_minus typedef typename usource_lazy_t::type usource_t; if (arg < 0) { - const bool res = boost::detail::noexcept_numeric_convert<Target, usource_t>( - static_cast<usource_t>(0u - static_cast<usource_t>(arg)), result - ); + const bool res = noexcept_numeric_convert<Target, usource_t>(0u - arg, result); result = static_cast<Target>(0u - result); return res; } else { - return boost::detail::noexcept_numeric_convert<Target, usource_t>(arg, result); + return noexcept_numeric_convert<Target, usource_t>(arg, result); } } }; /* - * dynamic_num_converter_impl follows the rules: + * lexical_cast_dynamic_num follows the rules: * 1) If Source can be converted to Target without precision loss and * without overflows, then assign Source to Target and return * @@ -164,14 +156,16 @@ struct lexical_cast_dynamic_num_ignoring_minus template <typename Target, typename Source> struct dynamic_num_converter_impl { - static inline bool try_convert(Source arg, Target& result) noexcept { + typedef typename boost::remove_volatile<Source>::type source_type; + + static inline bool try_convert(source_type arg, Target& result) noexcept { typedef typename boost::conditional< boost::is_unsigned<Target>::value && - (boost::is_signed<Source>::value || boost::is_float<Source>::value) && - !(boost::is_same<Source, bool>::value) && + (boost::is_signed<source_type>::value || boost::is_float<source_type>::value) && + !(boost::is_same<source_type, bool>::value) && !(boost::is_same<Target, bool>::value), - lexical_cast_dynamic_num_ignoring_minus, - lexical_cast_dynamic_num_not_ignoring_minus + lexical_cast_dynamic_num_ignoring_minus<Target, source_type>, + lexical_cast_dynamic_num_not_ignoring_minus<Target, source_type> >::type caster_type; return caster_type::try_convert(arg, result); 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 21656e8466..b7ab305773 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 @@ -56,9 +56,6 @@ 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; @@ -254,9 +251,6 @@ 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/try_lexical_convert.hpp b/contrib/restricted/boost/lexical_cast/include/boost/lexical_cast/try_lexical_convert.hpp index 35cc68703e..ffc092643b 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 @@ -23,7 +23,20 @@ # 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> @@ -31,9 +44,33 @@ #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> using is_arithmetic_and_not_xchars = boost::integral_constant< bool, @@ -42,6 +79,70 @@ namespace boost { boost::is_arithmetic<Source>::value && boost::is_arithmetic<Target>::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> + using is_xchar_to_xchar = boost::integral_constant< + bool, + sizeof(Source) == sizeof(Target) && + sizeof(Source) == sizeof(char) && + boost::detail::is_character<Target>::value && + boost::detail::is_character<Source>::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_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 + }; } namespace conversion { namespace detail { @@ -55,14 +156,37 @@ namespace boost { typedef typename boost::detail::array_to_pointer_decay<Source>::type src; + 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 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_with_dynamic_check_t::value, - boost::detail::dynamic_num_converter_impl<Target, src >, - boost::detail::lexical_converter_impl<Target, src > - >::type caster_type; + 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; return caster_type::try_convert(arg, result); } @@ -89,5 +213,11 @@ 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 53582e1aad..4d4ce8f067 100644 --- a/contrib/restricted/boost/lexical_cast/ya.make +++ b/contrib/restricted/boost/lexical_cast/ya.make @@ -6,15 +6,16 @@ LICENSE(BSL-1.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(1.85.0) +VERSION(2024-01-24) -ORIGINAL_SOURCE(https://github.com/boostorg/lexical_cast/archive/boost-1.85.0.tar.gz) +ORIGINAL_SOURCE(https://github.com/boostorg/lexical_cast/archive/f0862bb60ddd56c3e5b4e413605c4e2528540ed6.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 ) |