diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-24 15:11:41 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:04:38 +0000 |
commit | fcaf7f8644a9988098ac6be2165bce3ea4786e91 (patch) | |
tree | 08a554363df16b968a623d651c09d82a5a0b1c65 /contrib/llvm-project/libcxx/include | |
parent | 753f127f3ace09432b2baeffd71a308760641a62 (diff) | |
parent | 4b4fe385e49bd883fd183b5f21c1ea486c722e61 (diff) | |
download | src-fcaf7f8644a9988098ac6be2165bce3ea4786e91.tar.gz src-fcaf7f8644a9988098ac6be2165bce3ea4786e91.zip |
Merge llvm-project main llvmorg-15-init-17485-ga3e38b4a206b
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-15-init-17485-ga3e38b4a206b.
PR: 265425
MFC after: 2 weeks
Diffstat (limited to 'contrib/llvm-project/libcxx/include')
71 files changed, 2400 insertions, 1256 deletions
diff --git a/contrib/llvm-project/libcxx/include/__algorithm/equal_range.h b/contrib/llvm-project/libcxx/include/__algorithm/equal_range.h index f30f55be64fc..42d009ebbc0f 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/equal_range.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/equal_range.h @@ -17,9 +17,13 @@ #include <__algorithm/upper_bound.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> #include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -28,59 +32,50 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _ForwardIterator, class _Tp> -_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator> -__equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) -{ - typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; - difference_type __len = _VSTD::distance(__first, __last); - while (__len != 0) - { - difference_type __l2 = _VSTD::__half_positive(__len); - _ForwardIterator __m = __first; - _VSTD::advance(__m, __l2); - if (__comp(*__m, __value)) - { - __first = ++__m; - __len -= __l2 + 1; - } - else if (__comp(__value, *__m)) - { - __last = __m; - __len = __l2; - } - else - { - auto __proj = std::__identity(); - _ForwardIterator __mp1 = __m; - return pair<_ForwardIterator, _ForwardIterator> - ( - _VSTD::__lower_bound_impl<_ClassicAlgPolicy>(__first, __m, __value, __comp, __proj), - _VSTD::__upper_bound<_Compare>(++__mp1, __last, __value, __comp) - ); - } +template <class _AlgPolicy, class _Compare, class _Iter, class _Sent, class _Tp, class _Proj> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_Iter, _Iter> +__equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp, _Proj&& __proj) { + auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); + _Iter __end = _IterOps<_AlgPolicy>::next(__first, __last); + while (__len != 0) { + auto __half_len = std::__half_positive(__len); + _Iter __mid = _IterOps<_AlgPolicy>::next(__first, __half_len); + if (std::__invoke(__comp, std::__invoke(__proj, *__mid), __value)) { + __first = ++__mid; + __len -= __half_len + 1; + } else if (std::__invoke(__comp, __value, std::__invoke(__proj, *__mid))) { + __end = __mid; + __len = __half_len; + } else { + _Iter __mp1 = __mid; + return pair<_Iter, _Iter>( + std::__lower_bound_impl<_AlgPolicy>(__first, __mid, __value, __comp, __proj), + std::__upper_bound<_AlgPolicy>(++__mp1, __end, __value, __comp, __proj)); } - return pair<_ForwardIterator, _ForwardIterator>(__first, __first); + } + return pair<_Iter, _Iter>(__first, __first); } template <class _ForwardIterator, class _Tp, class _Compare> -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -pair<_ForwardIterator, _ForwardIterator> -equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) -{ - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__equal_range<_Comp_ref>(__first, __last, __value, __comp); +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator> +equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { + static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, + "The comparator has to be callable"); + static_assert(is_copy_constructible<_ForwardIterator>::value, + "Iterator has to be copy constructible"); + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return std::__equal_range<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), __value, static_cast<_Comp_ref>(__comp), std::__identity()); } template <class _ForwardIterator, class _Tp> -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -pair<_ForwardIterator, _ForwardIterator> -equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) -{ - return _VSTD::equal_range(__first, __last, __value, - __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator> +equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::equal_range( + std::move(__first), + std::move(__last), + __value, + __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/includes.h b/contrib/llvm-project/libcxx/include/__algorithm/includes.h index 4c87e8d22116..102d3db39a2d 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/includes.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/includes.h @@ -13,6 +13,7 @@ #include <__algorithm/comp_ref_type.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,41 +21,40 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _InputIterator1, class _InputIterator2> -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool -__includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, - _Compare __comp) -{ - for (; __first2 != __last2; ++__first1) - { - if (__first1 == __last1 || __comp(*__first2, *__first1)) - return false; - if (!__comp(*__first1, *__first2)) - ++__first2; - } - return true; +template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Comp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Comp&& __comp) { + for (; __first2 != __last2; ++__first1) { + if (__first1 == __last1 || __comp(*__first2, *__first1)) + return false; + if (!__comp(*__first1, *__first2)) + ++__first2; + } + return true; } template <class _InputIterator1, class _InputIterator2, class _Compare> -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -bool -includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, - _Compare __comp) -{ - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__includes<_Comp_ref>(__first1, __last1, __first2, __last2, __comp); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool includes( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _Compare __comp) { + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return std::__includes( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), static_cast<_Comp_ref>(__comp)); } template <class _InputIterator1, class _InputIterator2> -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -bool -includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) -{ - return _VSTD::includes(__first1, __last1, __first2, __last2, - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { + return std::includes( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + __less<typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/inplace_merge.h b/contrib/llvm-project/libcxx/include/__algorithm/inplace_merge.h index 58919ddbae76..f4364969b8f9 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/inplace_merge.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/inplace_merge.h @@ -11,17 +11,18 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/lower_bound.h> #include <__algorithm/min.h> #include <__algorithm/move.h> #include <__algorithm/rotate.h> #include <__algorithm/upper_bound.h> #include <__config> +#include <__functional/identity.h> #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> -#include <__utility/swap.h> #include <memory> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -53,7 +54,7 @@ public: bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);} }; -template <class _Compare, class _InputIterator1, class _InputIterator2, +template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, @@ -63,25 +64,26 @@ void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, { if (__first2 == __last2) { + // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `move`. _VSTD::move(__first1, __last1, __result); return; } if (__comp(*__first2, *__first1)) { - *__result = _VSTD::move(*__first2); + *__result = _IterOps<_AlgPolicy>::__iter_move(__first2); ++__first2; } else { - *__result = _VSTD::move(*__first1); + *__result = _IterOps<_AlgPolicy>::__iter_move(__first1); ++__first1; } } // __first2 through __last2 are already in the right spot. } -template <class _Compare, class _BidirectionalIterator> +template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> void __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, @@ -95,30 +97,32 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator { value_type* __p = __buff; for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) - ::new ((void*)__p) value_type(_VSTD::move(*__i)); - _VSTD::__half_inplace_merge<_Compare>(__buff, __p, __middle, __last, __first, __comp); + ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); + std::__half_inplace_merge<_AlgPolicy, _Compare>(__buff, __p, __middle, __last, __first, __comp); } else { value_type* __p = __buff; for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) - ::new ((void*)__p) value_type(_VSTD::move(*__i)); + ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); typedef reverse_iterator<_BidirectionalIterator> _RBi; typedef reverse_iterator<value_type*> _Rv; typedef __invert<_Compare> _Inverted; - _VSTD::__half_inplace_merge<_Inverted>(_Rv(__p), _Rv(__buff), + std::__half_inplace_merge<_AlgPolicy, _Inverted>(_Rv(__p), _Rv(__buff), _RBi(__middle), _RBi(__first), _RBi(__last), _Inverted(__comp)); } } -template <class _Compare, class _BidirectionalIterator> +template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> void __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, typename iterator_traits<_BidirectionalIterator>::difference_type __len2, typename iterator_traits<_BidirectionalIterator>::value_type* __buff, ptrdiff_t __buff_size) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; while (true) { @@ -126,7 +130,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, if (__len2 == 0) return; if (__len1 <= __buff_size || __len2 <= __buff_size) - return _VSTD::__buffered_inplace_merge<_Compare> + return std::__buffered_inplace_merge<_AlgPolicy, _Compare> (__first, __middle, __last, __comp, __len1, __len2, __buff); // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 for (; true; ++__first, (void) --__len1) @@ -153,35 +157,38 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, { // __len >= 1, __len2 >= 2 __len21 = __len2 / 2; __m2 = __middle; - _VSTD::advance(__m2, __len21); - __m1 = _VSTD::__upper_bound<_Compare>(__first, __middle, *__m2, __comp); - __len11 = _VSTD::distance(__first, __m1); + _Ops::advance(__m2, __len21); + // TODO: replace _ClassicAlgPolicy and __identity with _AlgPolicy and projection + __m1 = std::__upper_bound<_ClassicAlgPolicy>(__first, __middle, *__m2, __comp, std::__identity()); + __len11 = _Ops::distance(__first, __m1); } else { if (__len1 == 1) { // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1 // It is known *__first > *__middle - swap(*__first, *__middle); + _Ops::iter_swap(__first, __middle); return; } // __len1 >= 2, __len2 >= 1 __len11 = __len1 / 2; __m1 = __first; - _VSTD::advance(__m1, __len11); + _Ops::advance(__m1, __len11); __m2 = std::lower_bound(__middle, __last, *__m1, __comp); - __len21 = _VSTD::distance(__middle, __m2); + __len21 = _Ops::distance(__middle, __m2); } difference_type __len12 = __len1 - __len11; // distance(__m1, __middle) difference_type __len22 = __len2 - __len21; // distance(__m2, __last) // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) // swap middle two partitions + // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `rotate`. __middle = _VSTD::rotate(__m1, __middle, __m2); // __len12 and __len21 now have swapped meanings // merge smaller range with recursive call and larger with tail recursion elimination if (__len11 + __len21 < __len12 + __len22) { - _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); + std::__inplace_merge<_AlgPolicy, _Compare>( + __first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); // _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); __first = __middle; __middle = __m2; @@ -190,7 +197,8 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, } else { - _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); + std::__inplace_merge<_AlgPolicy, _Compare>( + __middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); // _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); __last = __middle; __middle = __m1; @@ -217,7 +225,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH _LIBCPP_SUPPRESS_DEPRECATED_POP unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first); typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__inplace_merge<_Comp_ref>(__first, __middle, __last, __comp, __len1, __len2, + return _VSTD::__inplace_merge<_ClassicAlgPolicy, _Comp_ref>(__first, __middle, __last, __comp, __len1, __len2, __buf.first, __buf.second); } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/iterator_operations.h b/contrib/llvm-project/libcxx/include/__algorithm/iterator_operations.h index eb627e1ace7a..8307d71214e5 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/iterator_operations.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/iterator_operations.h @@ -41,6 +41,7 @@ struct _IterOps<_RangeAlgPolicy> { static constexpr auto next = ranges::next; static constexpr auto __advance_to = ranges::advance; }; + #endif struct _ClassicAlgPolicy {}; @@ -65,11 +66,24 @@ struct _IterOps<_ClassicAlgPolicy> { // iter_move template <class _Iter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 - // Declaring the return type is necessary for the C++03 mode (which doesn't support placeholder return types). - static typename iterator_traits<__uncvref_t<_Iter> >::value_type&& __iter_move(_Iter&& __i) { + // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce. + static __enable_if_t< + is_reference<typename iterator_traits<__uncvref_t<_Iter> >::reference>::value, + typename remove_reference< typename iterator_traits<__uncvref_t<_Iter> >::reference >::type&&> + __iter_move(_Iter&& __i) { return std::move(*std::forward<_Iter>(__i)); } + template <class _Iter> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 + // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce. + static __enable_if_t< + !is_reference<typename iterator_traits<__uncvref_t<_Iter> >::reference>::value, + typename iterator_traits<__uncvref_t<_Iter> >::reference> + __iter_move(_Iter&& __i) { + return *std::forward<_Iter>(__i); + } + // iter_swap template <class _Iter1, class _Iter2> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 @@ -85,7 +99,15 @@ struct _IterOps<_ClassicAlgPolicy> { } template <class _Iter> - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 void __advance_to(_Iter& __first, _Iter __last) { + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 + __uncvref_t<_Iter> next(_Iter&& __it, + typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1){ + return std::next(std::forward<_Iter>(__it), __n); + } + + template <class _Iter> + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 + void __advance_to(_Iter& __first, _Iter __last) { __first = __last; } }; diff --git a/contrib/llvm-project/libcxx/include/__algorithm/make_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/make_heap.h index bc39d82bf916..bf9dd96756af 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/make_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/make_heap.h @@ -11,6 +11,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/sift_down.h> #include <__config> #include <__iterator/iterator_traits.h> @@ -22,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { using _CompRef = typename __comp_ref_type<_Compare>::type; @@ -33,7 +34,7 @@ void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _C if (__n > 1) { // start from the first parent, there is no need to consider children for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) { - std::__sift_down<_CompRef>(__first, __comp_ref, __n, __first + __start); + std::__sift_down<_AlgPolicy, _CompRef>(__first, __comp_ref, __n, __first + __start); } } } @@ -41,7 +42,7 @@ void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _C template <class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - std::__make_heap(std::move(__first), std::move(__last), __comp); + std::__make_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/make_projected.h b/contrib/llvm-project/libcxx/include/__algorithm/make_projected.h index 6d8ebfd3d90e..64fc3dfb6a12 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/make_projected.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/make_projected.h @@ -27,6 +27,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { +template <class _Pred, class _Proj> +_LIBCPP_HIDE_FROM_ABI constexpr static +decltype(auto) __make_projected_pred(_Pred& __pred, _Proj& __proj) { + if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Pred>>) { + // Avoid creating the lambda and just use the pristine predicate -- for certain algorithms, this would enable + // optimizations that rely on the type of the predicate. + return __pred; + + } else { + return [&](auto&& __x) { + return std::invoke(__pred, std::invoke(__proj, std::forward<decltype(__x)>(__x))); + }; + } +} + template <class _Comp, class _Proj> _LIBCPP_HIDE_FROM_ABI constexpr static decltype(auto) __make_projected_comp(_Comp& __comp, _Proj& __proj) { diff --git a/contrib/llvm-project/libcxx/include/__algorithm/min_element.h b/contrib/llvm-project/libcxx/include/__algorithm/min_element.h index 129833d42bda..17b242c341e6 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/min_element.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/min_element.h @@ -12,7 +12,11 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,28 +24,38 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _ForwardIterator> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator -__min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) -{ - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, - "std::min_element requires a ForwardIterator"); - if (__first != __last) - { - _ForwardIterator __i = __first; - while (++__i != __last) - if (__comp(*__i, *__first)) - __first = __i; - } +template <class _Comp, class _Iter, class _Sent, class _Proj> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 +_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) { + if (__first == __last) return __first; + + _Iter __i = __first; + while (++__i != __last) + if (std::__invoke(__comp, std::__invoke(__proj, *__i), std::__invoke(__proj, *__first))) + __first = __i; + + return __first; +} + +template <class _Comp, class _Iter, class _Sent> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 +_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp) { + auto __proj = __identity(); + return std::__min_element<_Comp>(std::move(__first), std::move(__last), __comp, __proj); } template <class _ForwardIterator, class _Compare> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__min_element<_Comp_ref>(__first, __last, __comp); + static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + "std::min_element requires a ForwardIterator"); + static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, + "The comparator has to be callable"); + + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return std::__min_element<_Comp_ref>(std::move(__first), std::move(__last), __comp); } template <class _ForwardIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/nth_element.h b/contrib/llvm-project/libcxx/include/__algorithm/nth_element.h index c7cdef5be817..688398dee814 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/nth_element.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/nth_element.h @@ -11,13 +11,13 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/sort.h> #include <__config> #include <__debug> #include <__debug_utils/randomize_range.h> #include <__iterator/iterator_traits.h> #include <__utility/move.h> -#include <__utility/swap.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -41,10 +41,12 @@ __nth_element_find_guard(_RandomAccessIterator& __i, _RandomAccessIterator& __j, } } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> _LIBCPP_CONSTEXPR_AFTER_CXX11 void __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + // _Compare is known to be a reference type typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; const difference_type __limit = 7; @@ -60,24 +62,24 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando return; case 2: if (__comp(*--__last, *__first)) - swap(*__first, *__last); + _Ops::iter_swap(__first, __last); return; case 3: { _RandomAccessIterator __m = __first; - _VSTD::__sort3<_Compare>(__first, ++__m, --__last, __comp); + std::__sort3<_AlgPolicy, _Compare>(__first, ++__m, --__last, __comp); return; } } if (__len <= __limit) { - _VSTD::__selection_sort<_Compare>(__first, __last, __comp); + std::__selection_sort<_AlgPolicy, _Compare>(__first, __last, __comp); return; } // __len > __limit >= 3 _RandomAccessIterator __m = __first + __len/2; _RandomAccessIterator __lm1 = __last; - unsigned __n_swaps = _VSTD::__sort3<_Compare>(__first, __m, --__lm1, __comp); + unsigned __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, --__lm1, __comp); // *__m is median // partition [__first, __m) < *__m and *__m <= [__m, __last) // (this inhibits tossing elements equivalent to __m around unnecessarily) @@ -90,7 +92,7 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando { // *__first == *__m, *__first doesn't go in first part if (_VSTD::__nth_element_find_guard<_Compare>(__i, __j, __m, __comp)) { - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; } else { // *__first == *__m, *__m <= all other elements @@ -102,7 +104,7 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando if (__i == __j) { return; // [__first, __last) all equivalent elements } else if (__comp(*__first, *__i)) { - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; ++__i; break; @@ -121,7 +123,7 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando ; if (__i >= __j) break; - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; ++__i; } @@ -152,7 +154,7 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando ; if (__i >= __j) break; - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; // It is known that __m != __j // If __m just moved, follow it @@ -164,7 +166,7 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando // [__first, __i) < *__m and *__m <= [__i, __last) if (__i != __m && __comp(*__m, *__i)) { - swap(*__i, *__m); + _Ops::iter_swap(__i, __m); ++__n_swaps; } // [__first, __i) < *__i and *__i <= [__i+1, __last) @@ -220,21 +222,21 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando } } -template <class _RandomAccessIterator, class _Compare> +template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare& __comp) { if (__nth == __last) return; - std::__debug_randomize_range(__first, __last); + std::__debug_randomize_range<_AlgPolicy>(__first, __last); using _Comp_ref = typename __comp_ref_type<_Compare>::type; - std::__nth_element<_Comp_ref>(__first, __nth, __last, __comp); + std::__nth_element<_AlgPolicy, _Comp_ref>(__first, __nth, __last, __comp); - std::__debug_randomize_range(__first, __nth); + std::__debug_randomize_range<_AlgPolicy>(__first, __nth); if (__nth != __last) { - std::__debug_randomize_range(++__nth, __last); + std::__debug_randomize_range<_AlgPolicy>(++__nth, __last); } } @@ -242,7 +244,7 @@ template <class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) { - std::__nth_element_impl(std::move(__first), std::move(__nth), std::move(__last), __comp); + std::__nth_element_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__nth), std::move(__last), __comp); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/partial_sort.h b/contrib/llvm-project/libcxx/include/__algorithm/partial_sort.h index e008c0c99679..24016e5cf5a5 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/partial_sort.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/partial_sort.h @@ -11,6 +11,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_heap.h> #include <__algorithm/sift_down.h> #include <__algorithm/sort_heap.h> @@ -18,7 +19,8 @@ #include <__debug> #include <__debug_utils/randomize_range.h> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,24 +28,47 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _RandomAccessIterator> -_LIBCPP_CONSTEXPR_AFTER_CXX17 void -__partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, - _Compare __comp) -{ - if (__first == __middle) - return; - _VSTD::__make_heap<_Compare>(__first, __middle, __comp); - typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; - for (_RandomAccessIterator __i = __middle; __i != __last; ++__i) - { - if (__comp(*__i, *__first)) - { - swap(*__i, *__first); - _VSTD::__sift_down<_Compare>(__first, __comp, __len, __first); - } - } - _VSTD::__sort_heap<_Compare>(__first, __middle, __comp); +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_AFTER_CXX17 +_RandomAccessIterator __partial_sort_impl( + _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare __comp) { + if (__first == __middle) { + return _IterOps<_AlgPolicy>::next(__middle, __last); + } + + std::__make_heap<_AlgPolicy, _Compare>(__first, __middle, __comp); + + typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; + _RandomAccessIterator __i = __middle; + for (; __i != __last; ++__i) + { + if (__comp(*__i, *__first)) + { + _IterOps<_AlgPolicy>::iter_swap(__i, __first); + std::__sift_down<_AlgPolicy, _Compare>(__first, __comp, __len, __first); + } + + } + std::__sort_heap<_AlgPolicy, _Compare>(std::move(__first), std::move(__middle), __comp); + + return __i; +} + +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_AFTER_CXX17 +_RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, + _Compare& __comp) { + if (__first == __middle) + return _IterOps<_AlgPolicy>::next(__middle, __last); + + std::__debug_randomize_range<_AlgPolicy>(__first, __last); + + using _Comp_ref = typename __comp_ref_type<_Compare>::type; + auto __last_iter = std::__partial_sort_impl<_AlgPolicy, _Comp_ref>(__first, __middle, __last, __comp); + + std::__debug_randomize_range<_AlgPolicy>(__middle, __last); + + return __last_iter; } template <class _RandomAccessIterator, class _Compare> @@ -52,10 +77,10 @@ void partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp) { - std::__debug_randomize_range(__first, __last); - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - _VSTD::__partial_sort<_Comp_ref>(__first, __middle, __last, __comp); - std::__debug_randomize_range(__middle, __last); + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + + (void)std::__partial_sort<_ClassicAlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __comp); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/partial_sort_copy.h b/contrib/llvm-project/libcxx/include/__algorithm/partial_sort_copy.h index 7ed1e538e9b8..3556764e652d 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/partial_sort_copy.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/partial_sort_copy.h @@ -11,6 +11,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_heap.h> #include <__algorithm/sift_down.h> #include <__algorithm/sort_heap.h> @@ -23,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _InputIterator, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _InputIterator, class _RandomAccessIterator> _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator __partial_sort_copy(_InputIterator __first, _InputIterator __last, _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) @@ -33,15 +34,15 @@ __partial_sort_copy(_InputIterator __first, _InputIterator __last, { for (; __first != __last && __r != __result_last; ++__first, (void) ++__r) *__r = *__first; - _VSTD::__make_heap<_Compare>(__result_first, __r, __comp); + std::__make_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp); typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first; for (; __first != __last; ++__first) if (__comp(*__first, *__result_first)) { *__result_first = *__first; - _VSTD::__sift_down<_Compare>(__result_first, __comp, __len, __result_first); + std::__sift_down<_AlgPolicy, _Compare>(__result_first, __comp, __len, __result_first); } - _VSTD::__sort_heap<_Compare>(__result_first, __r, __comp); + std::__sort_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp); } return __r; } @@ -53,7 +54,8 @@ partial_sort_copy(_InputIterator __first, _InputIterator __last, _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) { typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__partial_sort_copy<_Comp_ref>(__first, __last, __result_first, __result_last, __comp); + return std::__partial_sort_copy<_ClassicAlgPolicy, _Comp_ref>( + __first, __last, __result_first, __result_last, __comp); } template <class _InputIterator, class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/partition.h b/contrib/llvm-project/libcxx/include/__algorithm/partition.h index 73d94831ed87..60b4e290ebeb 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/partition.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/partition.h @@ -9,9 +9,12 @@ #ifndef _LIBCPP___ALGORITHM_PARTITION_H #define _LIBCPP___ALGORITHM_PARTITION_H +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,40 +22,45 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Predicate, class _ForwardIterator> -_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -__partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) +template <class _Predicate, class _AlgPolicy, class _ForwardIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator> +__partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred, forward_iterator_tag) { while (true) { if (__first == __last) - return __first; + return std::make_pair(std::move(__first), std::move(__first)); if (!__pred(*__first)) break; ++__first; } - for (_ForwardIterator __p = __first; ++__p != __last;) + + _ForwardIterator __p = __first; + while (++__p != __last) { if (__pred(*__p)) { - swap(*__first, *__p); + _IterOps<_AlgPolicy>::iter_swap(__first, __p); ++__first; } } - return __first; + return std::make_pair(std::move(__first), std::move(__p)); } -template <class _Predicate, class _BidirectionalIterator> -_LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator -__partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, +template <class _Predicate, class _AlgPolicy, class _BidirectionalIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_BidirectionalIterator, _BidirectionalIterator> +__partition_impl(_BidirectionalIterator __first, _Sentinel __sentinel, _Predicate __pred, bidirectional_iterator_tag) { + _BidirectionalIterator __original_last = _IterOps<_AlgPolicy>::next(__first, __sentinel); + _BidirectionalIterator __last = __original_last; + while (true) { while (true) { if (__first == __last) - return __first; + return std::make_pair(std::move(__first), std::move(__original_last)); if (!__pred(*__first)) break; ++__first; @@ -60,20 +68,29 @@ __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Pred do { if (__first == --__last) - return __first; + return std::make_pair(std::move(__first), std::move(__original_last)); } while (!__pred(*__last)); - swap(*__first, *__last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); ++__first; } } +template <class _AlgPolicy, class _ForwardIterator, class _Sentinel, class _Predicate, class _IterCategory> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_ForwardIterator, _ForwardIterator> __partition( + _ForwardIterator __first, _Sentinel __last, _Predicate&& __pred, _IterCategory __iter_category) { + return std::__partition_impl<__uncvref_t<_Predicate>&, _AlgPolicy>( + std::move(__first), std::move(__last), __pred, __iter_category); +} + template <class _ForwardIterator, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - return _VSTD::__partition<_Predicate&>( - __first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); + using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; + auto __result = std::__partition<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred, _IterCategory()); + return __result.first; } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/pop_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/pop_heap.h index cadda81f6c88..870af50c133e 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/pop_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/pop_heap.h @@ -11,12 +11,14 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/push_heap.h> #include <__algorithm/sift_down.h> #include <__assert> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { @@ -35,17 +37,17 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; if (__len > 1) { - value_type __top = std::move(*__first); // create a hole at __first - _RandomAccessIterator __hole = std::__floyd_sift_down<_CompRef>(__first, __comp_ref, __len); + value_type __top = _IterOps<_AlgPolicy>::__iter_move(__first); // create a hole at __first + _RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy, _CompRef>(__first, __comp_ref, __len); --__last; if (__hole == __last) { *__hole = std::move(__top); } else { - *__hole = std::move(*__last); + *__hole = _IterOps<_AlgPolicy>::__iter_move(__last); ++__hole; *__last = std::move(__top); - std::__sift_up<_CompRef>(__first, __hole, __comp_ref, __hole - __first); + std::__sift_up<_AlgPolicy, _CompRef>(__first, __hole, __comp_ref, __hole - __first); } } } @@ -53,8 +55,11 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co template <class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first; - std::__pop_heap(std::move(__first), std::move(__last), __comp, __len); + std::__pop_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp, __len); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/push_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/push_heap.h index 1e3eec373d4f..716670b76788 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/push_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/push_heap.h @@ -11,9 +11,11 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { @@ -32,9 +34,9 @@ void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com _RandomAccessIterator __ptr = __first + __len; if (__comp(*__ptr, *--__last)) { - value_type __t(std::move(*__last)); + value_type __t(_IterOps<_AlgPolicy>::__iter_move(__last)); do { - *__last = std::move(*__ptr); + *__last = _IterOps<_AlgPolicy>::__iter_move(__ptr); __last = __ptr; if (__len == 0) break; @@ -47,18 +49,21 @@ void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com } } -template <class _RandomAccessIterator, class _Compare> +template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { using _CompRef = typename __comp_ref_type<_Compare>::type; typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first; - std::__sift_up<_CompRef>(std::move(__first), std::move(__last), __comp, __len); + std::__sift_up<_AlgPolicy, _CompRef>(std::move(__first), std::move(__last), __comp, __len); } template <class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - std::__push_heap(std::move(__first), std::move(__last), __comp); + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + + std::__push_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_equal_range.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_equal_range.h index 28d721530bda..dd4b377df1a1 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_equal_range.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_equal_range.h @@ -10,7 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_EQUAL_RANGE_H #include <__algorithm/equal_range.h> -#include <__algorithm/make_projected.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -37,27 +37,30 @@ namespace ranges { namespace __equal_range { struct __fn { - - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Tp, class _Proj = identity, - indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, - _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__value; (void)__comp; (void)__proj; - return {}; + template < + forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Tp, + class _Proj = identity, + indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> + _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__equal_range<_RangeAlgPolicy>( + std::move(__first), std::move(__last), __value, __comp, __proj); + return {std::move(__ret.first), std::move(__ret.second)}; } - template <forward_range _Range, class _Tp, class _Proj = identity, - indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, - _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__value; (void)__comp; (void)__proj; - return {}; + template < + forward_range _Range, + class _Tp, + class _Proj = identity, + indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__equal_range<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); + return {std::move(__ret.first), std::move(__ret.second)}; } - }; } // namespace __equal_range diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_fill.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_fill.h index 846e31885141..7ce4a76ba9e9 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_fill.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_fill.h @@ -30,7 +30,7 @@ struct __fn { template <class _Type, output_iterator<const _Type&> _Iter, sentinel_for<_Iter> _Sent> _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const { - if constexpr(random_access_iterator<_Iter>) { + if constexpr(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>) { return ranges::fill_n(__first, __last - __first, __value); } else { for (; __first != __last; ++__first) diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_find_end.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_find_end.h index fec709e79f5a..270b00649848 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_find_end.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_find_end.h @@ -11,6 +11,7 @@ #include <__algorithm/find_end.h> #include <__algorithm/iterator_operations.h> +#include <__algorithm/ranges_iterator_concept.h> #include <__config> #include <__functional/identity.h> #include <__functional/ranges_operations.h> @@ -29,23 +30,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Iter> -consteval auto __get_iterator_concept() { - if constexpr (contiguous_iterator<_Iter>) - return contiguous_iterator_tag(); - else if constexpr (random_access_iterator<_Iter>) - return random_access_iterator_tag(); - else if constexpr (bidirectional_iterator<_Iter>) - return bidirectional_iterator_tag(); - else if constexpr (forward_iterator<_Iter>) - return forward_iterator_tag(); - else if constexpr (input_iterator<_Iter>) - return input_iterator_tag(); -} - -template <class _Iter> -using __iterator_concept = decltype(__get_iterator_concept<_Iter>()); - namespace ranges { namespace __find_end { struct __fn { diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_for_each_n.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_for_each_n.h index ddf8b047cdb2..013afbd19389 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_for_each_n.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_for_each_n.h @@ -18,7 +18,6 @@ #include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/concepts.h> -#include <__ranges/dangling.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_generate_n.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_generate_n.h index bcf50e025ecc..7bde5fb4e579 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_generate_n.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_generate_n.h @@ -23,7 +23,6 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> -#include <__ranges/dangling.h> #include <__utility/forward.h> #include <__utility/move.h> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_includes.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_includes.h index 19c17870ed6f..ba054e6fd89d 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_includes.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_includes.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_INCLUDES_H #define _LIBCPP___ALGORITHM_RANGES_INCLUDES_H -#include <__algorithm/make_projected.h> #include <__algorithm/includes.h> +#include <__algorithm/make_projected.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -20,7 +20,6 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> -#include <__ranges/dangling.h> #include <__utility/forward.h> #include <__utility/move.h> @@ -36,29 +35,46 @@ namespace ranges { namespace __includes { struct __fn { - - template <input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Proj1 = identity, class _Proj2 = identity, - indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - // TODO: implement - (void)__first1; (void)__last1; (void)__first2; (void)__last2; (void)__comp; (void)__proj1; (void)__proj2; - return {}; + template < + input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less> + _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return std::__includes( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); } - template <input_range _Range1, input_range _Range2, class _Proj1 = identity, class _Proj2 = identity, - indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, - projected<iterator_t<_Range2>, _Proj2>> _Comp = ranges::less> - _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - // TODO: implement - (void)__range1; (void)__range2; (void)__comp; (void)__proj1; (void)__proj2; - return {}; + template < + input_range _Range1, + input_range _Range2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> + _Comp = ranges::less> + _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return std::__includes( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); } - }; } // namespace __includes diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_is_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_is_heap.h index 0f10fa4dcec9..00105189fed7 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_is_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_is_heap.h @@ -20,7 +20,6 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> -#include <__ranges/dangling.h> #include <__utility/forward.h> #include <__utility/move.h> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_iterator_concept.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_iterator_concept.h new file mode 100644 index 000000000000..3323119317ae --- /dev/null +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H +#define _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <type_traits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template <class _IterMaybeQualified> +consteval auto __get_iterator_concept() { + using _Iter = __uncvref_t<_IterMaybeQualified>; + + if constexpr (contiguous_iterator<_Iter>) + return contiguous_iterator_tag(); + else if constexpr (random_access_iterator<_Iter>) + return random_access_iterator_tag(); + else if constexpr (bidirectional_iterator<_Iter>) + return bidirectional_iterator_tag(); + else if constexpr (forward_iterator<_Iter>) + return forward_iterator_tag(); + else if constexpr (input_iterator<_Iter>) + return input_iterator_tag(); +} + +template <class _Iter> +using __iterator_concept = decltype(__get_iterator_concept<_Iter>()); + +} // namespace ranges +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_make_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_make_heap.h index fd488dc11a4b..8eabdd12cd2f 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_make_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_make_heap.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H #define _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_heap.h> #include <__algorithm/make_projected.h> #include <__concepts/same_as.h> @@ -45,7 +46,7 @@ struct __fn { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); - std::__make_heap(std::move(__first), __last_iter, __projected_comp); + std::__make_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_min_element.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_min_element.h index ae82dceb9ad8..26f95fe3a6d2 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_min_element.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_min_element.h @@ -30,6 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { +// TODO(ranges): `ranges::min_element` can now simply delegate to `std::__min_element`. template <class _Ip, class _Sp, class _Proj, class _Comp> _LIBCPP_HIDE_FROM_ABI static constexpr _Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_nth_element.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_nth_element.h index 2a929eacb89d..b15eb816b918 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_nth_element.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_nth_element.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H #define _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/nth_element.h> #include <__config> @@ -44,7 +45,7 @@ struct __fn { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); - std::__nth_element_impl(std::move(__first), std::move(__nth), __last_iter, __projected_comp); + std::__nth_element_impl<_RangeAlgPolicy>(std::move(__first), std::move(__nth), __last_iter, __projected_comp); return __last_iter; } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_partial_sort.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partial_sort.h new file mode 100644 index 000000000000..5e82bc6fcc32 --- /dev/null +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partial_sort.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H +#define _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/partial_sort.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __partial_sort { + +struct __fn { + template <class _Iter, class _Sent, class _Comp, class _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + return std::__partial_sort<_RangeAlgPolicy>(std::move(__first), std::move(__middle), __last, __projected_comp); + } + + template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __partial_sort_fn_impl(std::move(__first), std::move(__middle), std::move(__last), __comp, __proj); + } + + template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> + requires sortable<iterator_t<_Range>, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __middle, _Comp __comp = {}, + _Proj __proj = {}) const { + return __partial_sort_fn_impl(ranges::begin(__r), std::move(__middle), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __partial_sort + +inline namespace __cpo { + inline constexpr auto partial_sort = __partial_sort::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition.h index c145e7bdb4a2..60bee699d90e 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition.h @@ -9,8 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_PARTITION_H #define _LIBCPP___ALGORITHM_RANGES_PARTITION_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/partition.h> +#include <__algorithm/ranges_iterator_concept.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -21,10 +23,10 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> -#include <__ranges/dangling.h> #include <__ranges/subrange.h> #include <__utility/forward.h> #include <__utility/move.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -39,13 +41,21 @@ namespace __partition { struct __fn { + template <class _Iter, class _Sent, class _Proj, class _Pred> + _LIBCPP_HIDE_FROM_ABI static constexpr + subrange<__uncvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj); + auto __result = std::__partition<_RangeAlgPolicy>( + std::move(__first), std::move(__last), __projected_pred, __iterator_concept<_Iter>()); + + return {std::move(__result.first), std::move(__result.second)}; + } + template <permutable _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__pred; (void)__proj; - return {}; + return __partition_fn_impl(__first, __last, __pred, __proj); } template <forward_range _Range, class _Proj = identity, @@ -53,9 +63,7 @@ struct __fn { requires permutable<iterator_t<_Range>> _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__pred; (void)__proj; - return {}; + return __partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_copy.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_copy.h index f55089b94ea5..7201a8cbfe45 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_copy.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_copy.h @@ -10,20 +10,17 @@ #define _LIBCPP___ALGORITHM_RANGES_PARTITION_COPY_H #include <__algorithm/in_out_out_result.h> -#include <__algorithm/make_projected.h> -#include <__algorithm/partition_copy.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> -#include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -42,6 +39,27 @@ namespace __partition_copy { struct __fn { + // TODO(ranges): delegate to the classic algorithm. + template <class _InIter, class _Sent, class _OutIter1, class _OutIter2, class _Proj, class _Pred> + _LIBCPP_HIDE_FROM_ABI constexpr + static partition_copy_result< + __uncvref_t<_InIter>, __uncvref_t<_OutIter1>, __uncvref_t<_OutIter2> + > __partition_copy_fn_impl( _InIter&& __first, _Sent&& __last, _OutIter1&& __out_true, _OutIter2&& __out_false, + _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) { + *__out_true = *__first; + ++__out_true; + + } else { + *__out_false = *__first; + ++__out_false; + } + } + + return {std::move(__first), std::move(__out_true), std::move(__out_false)}; + } + template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter1, weakly_incrementable _OutIter2, class _Proj = identity, indirect_unary_predicate<projected<_InIter, _Proj>> _Pred> @@ -50,9 +68,8 @@ struct __fn { partition_copy_result<_InIter, _OutIter1, _OutIter2> operator()(_InIter __first, _Sent __last, _OutIter1 __out_true, _OutIter2 __out_false, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__out_true; (void)__out_false; (void)__pred; (void)__proj; - return {}; + return __partition_copy_fn_impl( + std::move(__first), std::move(__last), std::move(__out_true), std::move(__out_false), __pred, __proj); } template <input_range _Range, weakly_incrementable _OutIter1, weakly_incrementable _OutIter2, @@ -61,9 +78,8 @@ struct __fn { _LIBCPP_HIDE_FROM_ABI constexpr partition_copy_result<borrowed_iterator_t<_Range>, _OutIter1, _OutIter2> operator()(_Range&& __range, _OutIter1 __out_true, _OutIter2 __out_false, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__out_true; (void)__out_false; (void)__pred; (void)__proj; - return {}; + return __partition_copy_fn_impl( + ranges::begin(__range), ranges::end(__range), std::move(__out_true), std::move(__out_false), __pred, __proj); } }; diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_point.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_point.h index 336b29f63284..6614a0bb50fd 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_point.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_partition_point.h @@ -9,19 +9,18 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H #define _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H -#include <__algorithm/make_projected.h> -#include <__algorithm/partition_point.h> +#include <__algorithm/half_positive.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> -#include <__functional/ranges_operations.h> #include <__iterator/concepts.h> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__iterator/next.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -37,22 +36,40 @@ namespace __partition_point { struct __fn { + // TODO(ranges): delegate to the classic algorithm. + template <class _Iter, class _Sent, class _Proj, class _Pred> + _LIBCPP_HIDE_FROM_ABI constexpr + static _Iter __partition_point_fn_impl(_Iter&& __first, _Sent&& __last, _Pred& __pred, _Proj& __proj) { + auto __len = ranges::distance(__first, __last); + + while (__len != 0) { + auto __half_len = std::__half_positive(__len); + auto __mid = ranges::next(__first, __half_len); + + if (std::invoke(__pred, std::invoke(__proj, *__mid))) { + __first = ++__mid; + __len -= __half_len + 1; + + } else { + __len = __half_len; + } + } + + return __first; + } + template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__pred; (void)__proj; - return {}; + return __partition_point_fn_impl(std::move(__first), std::move(__last), __pred, __proj); } template <forward_range _Range, class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__pred; (void)__proj; - return {}; + return __partition_point_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_pop_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_pop_heap.h index d0b8314e5b0a..92df6119d34a 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_pop_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_pop_heap.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H #define _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/pop_heap.h> #include <__concepts/same_as.h> @@ -46,7 +47,7 @@ struct __fn { auto __len = __last_iter - __first; auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); - std::__pop_heap(std::move(__first), __last_iter, __projected_comp, __len); + std::__pop_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp, __len); return __last_iter; } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_push_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_push_heap.h index e46ad19cfed7..4c41b00128de 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_push_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_push_heap.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H #define _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/push_heap.h> #include <__concepts/same_as.h> @@ -45,7 +46,7 @@ struct __fn { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); - std::__push_heap(std::move(__first), __last_iter, __projected_comp); + std::__push_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_set_union.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_set_union.h index 39537503b98f..3826e55688f7 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_set_union.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_set_union.h @@ -42,34 +42,68 @@ using set_union_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; namespace __set_union { struct __fn { - - template <input_iterator _InIter1, sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, class _Comp = ranges::less, - class _Proj1 = identity, class _Proj2 = identity> - requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr - set_union_result<_InIter1, _InIter2, _OutIter> - operator()(_InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - // TODO: implement - (void)__first1; (void)__last1; (void)__first2; (void)__last2; (void)__result; (void)__comp; (void)__proj1; - (void)__proj2; - return {}; + template < + input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_union_result<_InIter1, _InIter2, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_union( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - template <input_range _Range1, input_range _Range2, weakly_incrementable _OutIter, - class _Comp = ranges::less, class _Proj1 = identity, class _Proj2 = identity> - requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr - set_union_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter> - operator()(_Range1&& __range1, _Range2&& __range2, _OutIter __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - // TODO: implement - (void)__range1; (void)__range2; (void)__result; (void)__comp; (void)__proj1; (void)__proj2; - return {}; + template < + input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable< + iterator_t<_Range1>, + iterator_t<_Range2>, + _OutIter, + _Comp, + _Proj1, + _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_union_result<borrowed_iterator_t<_Range1>, + borrowed_iterator_t<_Range2>, + _OutIter> + operator()( + _Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_union( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - }; } // namespace __set_union diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_shuffle.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_shuffle.h index bf9c28b4ce26..b101a8582eac 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_shuffle.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_shuffle.h @@ -9,23 +9,22 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H #define _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H -#include <__algorithm/make_projected.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/shuffle.h> #include <__config> -#include <__functional/identity.h> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__iterator/next.h> #include <__iterator/permutable.h> -#include <__iterator/projected.h> #include <__random/uniform_random_bit_generator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -33,29 +32,57 @@ #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __shuffle { struct __fn { + // `std::shuffle` is more constrained than `std::ranges::shuffle`. `std::ranges::shuffle` only requires the given + // generator to satisfy the `std::uniform_random_bit_generator` concept. `std::shuffle` requires the given + // generator to meet the uniform random bit generator requirements; these requirements include satisfying + // `std::uniform_random_bit_generator` and add a requirement for the generator to provide a nested `result_type` + // typedef (see `[rand.req.urng]`). + // + // To reuse the implementation from `std::shuffle`, make the given generator meet the classic requirements by wrapping + // it into an adaptor type that forwards all of its interface and adds the required typedef. + template <class _Gen> + class _ClassicGenAdaptor { + private: + // The generator is not required to be copyable or movable, so it has to be stored as a reference. + _Gen& __gen; + + public: + using result_type = invoke_result_t<_Gen&>; + + _LIBCPP_HIDE_FROM_ABI + static constexpr auto min() { return __uncvref_t<_Gen>::min(); } + _LIBCPP_HIDE_FROM_ABI + static constexpr auto max() { return __uncvref_t<_Gen>::max(); } + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()() const { return __gen(); } + }; template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Gen> requires permutable<_Iter> && uniform_random_bit_generator<remove_reference_t<_Gen>> _LIBCPP_HIDE_FROM_ABI _Iter operator()(_Iter __first, _Sent __last, _Gen&& __gen) const { - // TODO: implement - (void)__first; (void)__last; (void)__gen; - return {}; + _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); + return std::__shuffle<_RangeAlgPolicy>(std::move(__first), std::move(__last), __adapted_gen); } template<random_access_range _Range, class _Gen> requires permutable<iterator_t<_Range>> && uniform_random_bit_generator<remove_reference_t<_Gen>> _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> operator()(_Range&& __range, _Gen&& __gen) const { - // TODO: implement - (void)__range; (void)__gen; - return {}; + return (*this)(ranges::begin(__range), ranges::end(__range), std::forward<_Gen>(__gen)); } }; @@ -69,6 +96,8 @@ inline namespace __cpo { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) #endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort.h index 8297940df237..ef14db64295d 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_SORT_H #define _LIBCPP___ALGORITHM_RANGES_SORT_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/sort.h> #include <__config> @@ -44,7 +45,7 @@ struct __fn { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); - std::__sort_impl(std::move(__first), __last_iter, __projected_comp); + std::__sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort_heap.h index c753e20c44a6..eb6a30dcd3d0 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_sort_heap.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H #define _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/sort_heap.h> #include <__concepts/same_as.h> @@ -45,7 +46,7 @@ struct __fn { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); - std::__sort_heap(std::move(__first), __last_iter, __projected_comp); + std::__sort_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_partition.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_partition.h index 178c953ebdae..27957db8829f 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_partition.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_partition.h @@ -9,7 +9,9 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H #define _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> +#include <__algorithm/ranges_iterator_concept.h> #include <__algorithm/stable_partition.h> #include <__config> #include <__functional/identity.h> @@ -17,6 +19,7 @@ #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__iterator/next.h> #include <__iterator/permutable.h> #include <__iterator/projected.h> #include <__ranges/access.h> @@ -25,6 +28,7 @@ #include <__ranges/subrange.h> #include <__utility/forward.h> #include <__utility/move.h> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -39,14 +43,25 @@ namespace __stable_partition { struct __fn { + template <class _Iter, class _Sent, class _Proj, class _Pred> + _LIBCPP_HIDE_FROM_ABI static + subrange<__uncvref_t<_Iter>> __stable_partition_fn_impl( + _Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj); + auto __result = std::__stable_partition<_RangeAlgPolicy>( + std::move(__first), __last_iter, __projected_pred, __iterator_concept<_Iter>()); + + return {std::move(__result), std::move(__last_iter)}; + } + template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> requires permutable<_Iter> _LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__pred; (void)__proj; - return {}; + return __stable_partition_fn_impl(__first, __last, __pred, __proj); } template <bidirectional_range _Range, class _Proj = identity, @@ -54,9 +69,7 @@ struct __fn { requires permutable<iterator_t<_Range>> _LIBCPP_HIDE_FROM_ABI borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__pred; (void)__proj; - return {}; + return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; diff --git a/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_sort.h b/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_sort.h index 20e840426434..de48416a41be 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_sort.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/ranges_stable_sort.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H #define _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/stable_sort.h> #include <__config> @@ -44,7 +45,7 @@ struct __fn { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); - std::__stable_sort_impl(std::move(__first), __last_iter, __projected_comp); + std::__stable_sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; } diff --git a/contrib/llvm-project/libcxx/include/__algorithm/rotate.h b/contrib/llvm-project/libcxx/include/__algorithm/rotate.h index c9ea5bad4c5a..fcf8444a65a0 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/rotate.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/rotate.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_ROTATE_H #define _LIBCPP___ALGORITHM_ROTATE_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/move.h> #include <__algorithm/move_backward.h> #include <__algorithm/swap_ranges.h> @@ -26,37 +27,40 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _ForwardIterator> +template <class _AlgPolicy, class _ForwardIterator> _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator __rotate_left(_ForwardIterator __first, _ForwardIterator __last) { typedef typename iterator_traits<_ForwardIterator>::value_type value_type; - value_type __tmp = _VSTD::move(*__first); + value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__first); + // TODO(ranges): pass `_AlgPolicy` to `move`. _ForwardIterator __lm1 = _VSTD::move(_VSTD::next(__first), __last, __first); *__lm1 = _VSTD::move(__tmp); return __lm1; } -template <class _BidirectionalIterator> +template <class _AlgPolicy, class _BidirectionalIterator> _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + // TODO(ranges): pass `_AlgPolicy` to `prev`. _BidirectionalIterator __lm1 = _VSTD::prev(__last); - value_type __tmp = _VSTD::move(*__lm1); + value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__lm1); + // TODO(ranges): pass `_AlgPolicy` to `move_backward`. _BidirectionalIterator __fp1 = _VSTD::move_backward(__first, __lm1, __last); *__first = _VSTD::move(__tmp); return __fp1; } -template <class _ForwardIterator> +template <class _AlgPolicy, class _ForwardIterator> _LIBCPP_CONSTEXPR_AFTER_CXX14 _ForwardIterator __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { _ForwardIterator __i = __middle; while (true) { - swap(*__first, *__i); + _IterOps<_AlgPolicy>::iter_swap(__first, __i); ++__first; if (++__i == __last) break; @@ -69,7 +73,7 @@ __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIt __i = __middle; while (true) { - swap(*__first, *__i); + _IterOps<_AlgPolicy>::iter_swap(__first, __i); ++__first; if (++__i == __last) { @@ -98,7 +102,7 @@ __algo_gcd(_Integral __x, _Integral __y) return __x; } -template<typename _RandomAccessIterator> +template <class _AlgPolicy, typename _RandomAccessIterator> _LIBCPP_CONSTEXPR_AFTER_CXX14 _RandomAccessIterator __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) { @@ -109,18 +113,19 @@ __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ran const difference_type __m2 = __last - __middle; if (__m1 == __m2) { + // TODO(ranges): pass `_AlgPolicy` to `swap_ranges`. _VSTD::swap_ranges(__first, __middle, __middle); return __middle; } const difference_type __g = _VSTD::__algo_gcd(__m1, __m2); for (_RandomAccessIterator __p = __first + __g; __p != __first;) { - value_type __t(_VSTD::move(*--__p)); + value_type __t(_IterOps<_AlgPolicy>::__iter_move(--__p)); _RandomAccessIterator __p1 = __p; _RandomAccessIterator __p2 = __p1 + __m1; do { - *__p1 = _VSTD::move(*__p2); + *__p1 = _IterOps<_AlgPolicy>::__iter_move(__p2); __p1 = __p2; const difference_type __d = __last - __p2; if (__m1 < __d) @@ -133,54 +138,66 @@ __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ran return __first + __m2; } -template <class _ForwardIterator> +template <class _AlgPolicy, class _ForwardIterator> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator -__rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, +__rotate_impl(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, _VSTD::forward_iterator_tag) { typedef typename iterator_traits<_ForwardIterator>::value_type value_type; if (is_trivially_move_assignable<value_type>::value) { - if (_VSTD::next(__first) == __middle) - return _VSTD::__rotate_left(__first, __last); + if (_IterOps<_AlgPolicy>::next(__first) == __middle) + return std::__rotate_left<_AlgPolicy>(__first, __last); } - return _VSTD::__rotate_forward(__first, __middle, __last); + return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); } -template <class _BidirectionalIterator> +template <class _AlgPolicy, class _BidirectionalIterator> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator -__rotate(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, +__rotate_impl(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, bidirectional_iterator_tag) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; if (is_trivially_move_assignable<value_type>::value) { - if (_VSTD::next(__first) == __middle) - return _VSTD::__rotate_left(__first, __last); - if (_VSTD::next(__middle) == __last) - return _VSTD::__rotate_right(__first, __last); + if (_IterOps<_AlgPolicy>::next(__first) == __middle) + return std::__rotate_left<_AlgPolicy>(__first, __last); + if (_IterOps<_AlgPolicy>::next(__middle) == __last) + return std::__rotate_right<_AlgPolicy>(__first, __last); } - return _VSTD::__rotate_forward(__first, __middle, __last); + return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); } -template <class _RandomAccessIterator> +template <class _AlgPolicy, class _RandomAccessIterator> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator -__rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, +__rotate_impl(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, random_access_iterator_tag) { typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; if (is_trivially_move_assignable<value_type>::value) { - if (_VSTD::next(__first) == __middle) - return _VSTD::__rotate_left(__first, __last); - if (_VSTD::next(__middle) == __last) - return _VSTD::__rotate_right(__first, __last); - return _VSTD::__rotate_gcd(__first, __middle, __last); + if (_IterOps<_AlgPolicy>::next(__first) == __middle) + return std::__rotate_left<_AlgPolicy>(__first, __last); + if (_IterOps<_AlgPolicy>::next(__middle) == __last) + return std::__rotate_right<_AlgPolicy>(__first, __last); + return std::__rotate_gcd<_AlgPolicy>(__first, __middle, __last); } - return _VSTD::__rotate_forward(__first, __middle, __last); + return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); +} + +template <class _AlgPolicy, class _RandomAccessIterator, class _IterCategory> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 +_RandomAccessIterator __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, + _RandomAccessIterator __last, _IterCategory __iter_category) { + if (__first == __middle) + return __last; + if (__middle == __last) + return __first; + + return std::__rotate_impl<_AlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __iter_category); } template <class _ForwardIterator> @@ -188,12 +205,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { - if (__first == __middle) - return __last; - if (__middle == __last) - return __first; - return _VSTD::__rotate(__first, __middle, __last, - typename iterator_traits<_ForwardIterator>::iterator_category()); + return std::__rotate<_ClassicAlgPolicy>(__first, __middle, __last, + typename iterator_traits<_ForwardIterator>::iterator_category()); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/search_n.h b/contrib/llvm-project/libcxx/include/__algorithm/search_n.h index 2a0547565ee9..ccb8e845f5b1 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/search_n.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/search_n.h @@ -163,7 +163,7 @@ _ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) { - static_assert(__is_callable<_BinaryPredicate, decltype(*__first), decltype(*__last)>::value, + static_assert(__is_callable<_BinaryPredicate, decltype(*__first), const _Tp&>::value, "BinaryPredicate has to be callable"); auto __proj = __identity(); return std::__search_n_impl(__first, __last, std::__convert_to_integral(__count), __value, __pred, __proj).first; diff --git a/contrib/llvm-project/libcxx/include/__algorithm/set_union.h b/contrib/llvm-project/libcxx/include/__algorithm/set_union.h index 0ec6b09380ed..3bd437980161 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/set_union.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/set_union.h @@ -14,6 +14,7 @@ #include <__algorithm/copy.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,50 +22,77 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> -_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator -__set_union(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) -{ - for (; __first1 != __last1; ++__result) - { - if (__first2 == __last2) - return _VSTD::copy(__first1, __last1, __result); - if (__comp(*__first2, *__first1)) - { - *__result = *__first2; - ++__first2; - } - else - { - if (!__comp(*__first1, *__first2)) - ++__first2; - *__result = *__first1; - ++__first1; - } +template <class _InIter1, class _InIter2, class _OutIter> +struct __set_union_result { + _InIter1 __in1_; + _InIter2 __in2_; + _OutIter __out_; + + // need a constructor as C++03 aggregate init is hard + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 + __set_union_result(_InIter1&& __in_iter1, _InIter2&& __in_iter2, _OutIter&& __out_iter) + : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} +}; + +template <class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 __set_union_result<_InIter1, _InIter2, _OutIter> __set_union( + _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { + for (; __first1 != __last1; ++__result) { + if (__first2 == __last2) { + auto __ret1 = std::__copy_impl(std::move(__first1), std::move(__last1), std::move(__result)); + return __set_union_result<_InIter1, _InIter2, _OutIter>( + std::move(__ret1.first), std::move(__first2), std::move((__ret1.second))); + } + if (__comp(*__first2, *__first1)) { + *__result = *__first2; + ++__first2; + } else { + if (!__comp(*__first1, *__first2)) { + ++__first2; + } + *__result = *__first1; + ++__first1; } - return _VSTD::copy(__first2, __last2, __result); + } + auto __ret2 = std::__copy_impl(std::move(__first2), std::move(__last2), std::move(__result)); + return __set_union_result<_InIter1, _InIter2, _OutIter>( + std::move(__first1), std::move(__ret2.first), std::move((__ret2.second))); } template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_OutputIterator -set_union(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) -{ - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__set_union<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_union( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) { + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return std::__set_union<_Comp_ref>( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __comp) + .__out_; } template <class _InputIterator1, class _InputIterator2, class _OutputIterator> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_OutputIterator -set_union(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) -{ - return _VSTD::set_union(__first1, __last1, __first2, __last2, __result, - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_union( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result) { + return std::set_union( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __less<typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/shuffle.h b/contrib/llvm-project/libcxx/include/__algorithm/shuffle.h index 6c6ff5675dad..e32c6a7608ba 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/shuffle.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/shuffle.h @@ -9,11 +9,13 @@ #ifndef _LIBCPP___ALGORITHM_SHUFFLE_H #define _LIBCPP___ALGORITHM_SHUFFLE_H +#include <__algorithm/iterator_operations.h> #include <__config> #include <__debug> #include <__iterator/iterator_traits.h> #include <__random/uniform_int_distribution.h> -#include <__utility/swap.h> +#include <__utility/forward.h> +#include <__utility/move.h> #include <cstddef> #include <cstdint> @@ -134,13 +136,15 @@ random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, } #endif -template<class _RandomAccessIterator, class _UniformRandomNumberGenerator> - void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, - _UniformRandomNumberGenerator&& __g) -{ +template <class _AlgPolicy, class _RandomAccessIterator, class _Sentinel, class _UniformRandomNumberGenerator> +_RandomAccessIterator __shuffle( + _RandomAccessIterator __first, _Sentinel __last_sentinel, _UniformRandomNumberGenerator&& __g) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef uniform_int_distribution<ptrdiff_t> _Dp; typedef typename _Dp::param_type _Pp; + + auto __original_last = _IterOps<_AlgPolicy>::next(__first, __last_sentinel); + auto __last = __original_last; difference_type __d = __last - __first; if (__d > 1) { @@ -149,9 +153,18 @@ template<class _RandomAccessIterator, class _UniformRandomNumberGenerator> { difference_type __i = __uid(__g, _Pp(0, __d)); if (__i != difference_type(0)) - swap(*__first, *(__first + __i)); + _IterOps<_AlgPolicy>::iter_swap(__first, __first + __i); } } + + return __original_last; +} + +template <class _RandomAccessIterator, class _UniformRandomNumberGenerator> +void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, + _UniformRandomNumberGenerator&& __g) { + (void)std::__shuffle<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::forward<_UniformRandomNumberGenerator>(__g)); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/sift_down.h b/contrib/llvm-project/libcxx/include/__algorithm/sift_down.h index 0351a1c578b0..be2eb29dd53a 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/sift_down.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/sift_down.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_SIFT_DOWN_H #define _LIBCPP___ALGORITHM_SIFT_DOWN_H +#include <__algorithm/iterator_operations.h> #include <__assert> #include <__config> #include <__iterator/iterator_traits.h> @@ -20,12 +21,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> _LIBCPP_CONSTEXPR_AFTER_CXX11 void __sift_down(_RandomAccessIterator __first, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len, _RandomAccessIterator __start) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; // left-child of __start is at 2 * __start + 1 @@ -49,11 +52,11 @@ __sift_down(_RandomAccessIterator __first, _Compare __comp, // we are, __start is larger than its largest child return; - value_type __top(_VSTD::move(*__start)); + value_type __top(_Ops::__iter_move(__start)); do { // we are not in heap-order, swap the parent with its largest child - *__start = _VSTD::move(*__child_i); + *__start = _Ops::__iter_move(__child_i); __start = __child_i; if ((__len - 2) / 2 < __child) @@ -74,7 +77,7 @@ __sift_down(_RandomAccessIterator __first, _Compare __comp, *__start = _VSTD::move(__top); } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator __floyd_sift_down(_RandomAccessIterator __first, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) @@ -97,7 +100,7 @@ __floyd_sift_down(_RandomAccessIterator __first, _Compare __comp, } // swap __hole with its largest child - *__hole = std::move(*__child_i); + *__hole = _IterOps<_AlgPolicy>::__iter_move(__child_i); __hole = __child_i; // if __hole is now a leaf, we're done diff --git a/contrib/llvm-project/libcxx/include/__algorithm/sort.h b/contrib/llvm-project/libcxx/include/__algorithm/sort.h index 76a18215731b..1ca2f1b81712 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/sort.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/sort.h @@ -11,6 +11,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/min_element.h> #include <__algorithm/partial_sort.h> #include <__algorithm/unwrap_iter.h> @@ -21,7 +22,6 @@ #include <__functional/operations.h> #include <__functional/ranges_operations.h> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> #include <climits> #include <memory> @@ -31,37 +31,85 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// Wraps an algorithm policy tag and a comparator in a single struct, used to pass the policy tag around without +// changing the number of template arguments (to keep the ABI stable). This is only used for the "range" policy tag. +// +// To create an object of this type, use `_WrapAlgPolicy<T, C>::type` -- see the specialization below for the rationale. +template <class _PolicyT, class _CompT, class = void> +struct _WrapAlgPolicy { + using type = _WrapAlgPolicy; + + using _AlgPolicy = _PolicyT; + using _Comp = _CompT; + _Comp& __comp; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 + _WrapAlgPolicy(_Comp& __c) : __comp(__c) {} +}; + +// Specialization for the "classic" policy tag that avoids creating a struct and simply defines an alias for the +// comparator. When unwrapping, a pristine comparator is always considered to have the "classic" tag attached. Passing +// the pristine comparator where possible allows using template instantiations from the dylib. +template <class _PolicyT, class _CompT> +struct _WrapAlgPolicy<_PolicyT, _CompT, __enable_if_t<std::is_same<_PolicyT, _ClassicAlgPolicy>::value> > { + using type = _CompT; +}; + +// Unwraps a pristine functor (e.g. `std::less`) as if it were wrapped using `_WrapAlgPolicy`. The policy tag is always +// set to "classic". +template <class _CompT> +struct _UnwrapAlgPolicy { + using _AlgPolicy = _ClassicAlgPolicy; + using _Comp = _CompT; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static + _Comp __get_comp(_Comp __comp) { return __comp; } +}; + +// Unwraps a `_WrapAlgPolicy` struct. +template <class... _Ts> +struct _UnwrapAlgPolicy<_WrapAlgPolicy<_Ts...> > { + using _Wrapped = _WrapAlgPolicy<_Ts...>; + using _AlgPolicy = typename _Wrapped::_AlgPolicy; + using _Comp = typename _Wrapped::_Comp; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static + _Comp __get_comp(_Wrapped& __w) { return __w.__comp; } +}; + // stable, 2-3 compares, 0-2 swaps -template <class _Compare, class _ForwardIterator> +template <class _AlgPolicy, class _Compare, class _ForwardIterator> _LIBCPP_CONSTEXPR_AFTER_CXX11 unsigned __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z, _Compare __c) { + using _Ops = _IterOps<_AlgPolicy>; + unsigned __r = 0; if (!__c(*__y, *__x)) // if x <= y { if (!__c(*__z, *__y)) // if y <= z return __r; // x <= y && y <= z // x <= y && y > z - swap(*__y, *__z); // x <= z && y < z + _Ops::iter_swap(__y, __z); // x <= z && y < z __r = 1; if (__c(*__y, *__x)) // if x > y { - swap(*__x, *__y); // x < y && y <= z + _Ops::iter_swap(__x, __y); // x < y && y <= z __r = 2; } return __r; // x <= y && y < z } if (__c(*__z, *__y)) // x > y, if y > z { - swap(*__x, *__z); // x < y && y < z + _Ops::iter_swap(__x, __z); // x < y && y < z __r = 1; return __r; } - swap(*__x, *__y); // x > y && y <= z + _Ops::iter_swap(__x, __y); // x > y && y <= z __r = 1; // x < y && x <= z if (__c(*__z, *__y)) // if y > z { - swap(*__y, *__z); // x <= y && y < z + _Ops::iter_swap(__y, __z); // x <= y && y < z __r = 2; } return __r; @@ -69,18 +117,20 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 unsigned __sort3(_ForwardIterator __x, _ForwardIte // stable, 3-6 compares, 0-5 swaps -template <class _Compare, class _ForwardIterator> +template <class _AlgPolicy, class _Compare, class _ForwardIterator> unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _Compare __c) { - unsigned __r = _VSTD::__sort3<_Compare>(__x1, __x2, __x3, __c); + using _Ops = _IterOps<_AlgPolicy>; + + unsigned __r = std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); if (__c(*__x4, *__x3)) { - swap(*__x3, *__x4); + _Ops::iter_swap(__x3, __x4); ++__r; if (__c(*__x3, *__x2)) { - swap(*__x2, *__x3); + _Ops::iter_swap(__x2, __x3); ++__r; if (__c(*__x2, *__x1)) { - swap(*__x1, *__x2); + _Ops::iter_swap(__x1, __x2); ++__r; } } @@ -90,21 +140,28 @@ unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator // stable, 4-10 compares, 0-9 swaps -template <class _Compare, class _ForwardIterator> +template <class _WrappedComp, class _ForwardIterator> _LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, - _ForwardIterator __x4, _ForwardIterator __x5, _Compare __c) { - unsigned __r = _VSTD::__sort4<_Compare>(__x1, __x2, __x3, __x4, __c); + _ForwardIterator __x4, _ForwardIterator __x5, _WrappedComp __wrapped_comp) { + using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; + using _AlgPolicy = typename _Unwrap::_AlgPolicy; + using _Ops = _IterOps<_AlgPolicy>; + + using _Compare = typename _Unwrap::_Comp; + _Compare __c = _Unwrap::__get_comp(__wrapped_comp); + + unsigned __r = std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); if (__c(*__x5, *__x4)) { - swap(*__x4, *__x5); + _Ops::iter_swap(__x4, __x5); ++__r; if (__c(*__x4, *__x3)) { - swap(*__x3, *__x4); + _Ops::iter_swap(__x3, __x4); ++__r; if (__c(*__x3, *__x2)) { - swap(*__x2, *__x3); + _Ops::iter_swap(__x2, __x3); ++__r; if (__c(*__x2, *__x1)) { - swap(*__x1, *__x2); + _Ops::iter_swap(__x1, __x2); ++__r; } } @@ -113,6 +170,16 @@ _LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _F return __r; } +template <class _AlgPolicy, class _Compare, class _ForwardIterator> +_LIBCPP_HIDDEN unsigned __sort5_wrap_policy( + _ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _ForwardIterator __x5, + _Compare __c) { + using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; + _WrappedComp __wrapped_comp(__c); + return std::__sort5<_WrappedComp>( + std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __wrapped_comp); +} + // The comparator being simple is a prerequisite for using the branchless optimization. template <class _Tp> struct __is_simple_comparator : false_type {}; @@ -137,6 +204,7 @@ using __use_branchless_sort = // Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary. template <class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) { + // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`). using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; bool __r = __c(*__x, *__y); value_type __tmp = __r ? *__x : *__y; @@ -149,6 +217,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _Random template <class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI void __partially_sorted_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _RandomAccessIterator __z, _Compare __c) { + // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`). using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; bool __r = __c(*__z, *__x); value_type __tmp = __r ? *__z : *__x; @@ -158,7 +227,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __partially_sorted_swap(_RandomAccessIterator *__y = __r ? *__y : __tmp; } -template <class _Compare, class _RandomAccessIterator> +template <class, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> __sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _Compare __c) { @@ -166,14 +235,14 @@ __sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _VSTD::__partially_sorted_swap<_Compare>(__x1, __x2, __x3, __c); } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> __sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _Compare __c) { - _VSTD::__sort3<_Compare>(__x1, __x2, __x3, __c); + std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); } -template <class _Compare, class _RandomAccessIterator> +template <class, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _RandomAccessIterator __x4, _Compare __c) { @@ -184,14 +253,14 @@ __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _VSTD::__cond_swap<_Compare>(__x2, __x3, __c); } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _RandomAccessIterator __x4, _Compare __c) { - _VSTD::__sort4<_Compare>(__x1, __x2, __x3, __x4, __c); + std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); } -template <class _Compare, class _RandomAccessIterator> +template <class, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { @@ -203,53 +272,57 @@ __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _VSTD::__partially_sorted_swap<_Compare>(__x2, __x3, __x4, __c); } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { - _VSTD::__sort5<_Compare>(__x1, __x2, __x3, __x4, __x5, __c); + std::__sort5_wrap_policy<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __x5, __c); } // Assumes size > 0 -template <class _Compare, class _BidirectionalIterator> +template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> _LIBCPP_CONSTEXPR_AFTER_CXX11 void __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { _BidirectionalIterator __lm1 = __last; for (--__lm1; __first != __lm1; ++__first) { - _BidirectionalIterator __i = _VSTD::min_element(__first, __last, __comp); + _BidirectionalIterator __i = std::__min_element<_Compare>(__first, __last, __comp); if (__i != __first) - swap(*__first, *__i); + _IterOps<_AlgPolicy>::iter_swap(__first, __i); } } -template <class _Compare, class _BidirectionalIterator> +template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> void __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; if (__first != __last) { _BidirectionalIterator __i = __first; for (++__i; __i != __last; ++__i) { _BidirectionalIterator __j = __i; - value_type __t(_VSTD::move(*__j)); + value_type __t(_Ops::__iter_move(__j)); for (_BidirectionalIterator __k = __i; __k != __first && __comp(__t, *--__k); --__j) - *__j = _VSTD::move(*__k); + *__j = _Ops::__iter_move(__k); *__j = _VSTD::move(__t); } } } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; _RandomAccessIterator __j = __first + difference_type(2); - _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), __j, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { if (__comp(*__i, *__j)) { - value_type __t(_VSTD::move(*__i)); + value_type __t(_Ops::__iter_move(__i)); _RandomAccessIterator __k = __j; __j = __i; do { - *__j = _VSTD::move(*__k); + *__j = _Ops::__iter_move(__k); __j = __k; } while (__j != __first && __comp(__t, *--__k)); *__j = _VSTD::move(__t); @@ -258,8 +331,16 @@ void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __l } } -template <class _Compare, class _RandomAccessIterator> -bool __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { +template <class _WrappedComp, class _RandomAccessIterator> +bool __insertion_sort_incomplete( + _RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { + using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; + using _AlgPolicy = typename _Unwrap::_AlgPolicy; + using _Ops = _IterOps<_AlgPolicy>; + + using _Compare = typename _Unwrap::_Comp; + _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; switch (__last - __first) { case 0: @@ -267,32 +348,33 @@ bool __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIte return true; case 2: if (__comp(*--__last, *__first)) - swap(*__first, *__last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); return true; case 3: - _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), --__last, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); return true; case 4: - _VSTD::__sort4_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), - --__last, __comp); + std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); return true; case 5: - _VSTD::__sort5_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), - __first + difference_type(3), --__last, __comp); + std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), + --__last, __comp); return true; } typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; _RandomAccessIterator __j = __first + difference_type(2); - _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), __j, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); const unsigned __limit = 8; unsigned __count = 0; for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { if (__comp(*__i, *__j)) { - value_type __t(_VSTD::move(*__i)); + value_type __t(_Ops::__iter_move(__i)); _RandomAccessIterator __k = __j; __j = __i; do { - *__j = _VSTD::move(*__k); + *__j = _Ops::__iter_move(__k); __j = __k; } while (__j != __first && __comp(__t, *--__k)); *__j = _VSTD::move(__t); @@ -304,27 +386,29 @@ bool __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIte return true; } -template <class _Compare, class _BidirectionalIterator> +template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; if (__first1 != __last1) { __destruct_n __d(0); unique_ptr<value_type, __destruct_n&> __h(__first2, __d); value_type* __last2 = __first2; - ::new ((void*)__last2) value_type(_VSTD::move(*__first1)); + ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1)); __d.template __incr<value_type>(); for (++__last2; ++__first1 != __last1; ++__last2) { value_type* __j2 = __last2; value_type* __i2 = __j2; if (__comp(*__first1, *--__i2)) { - ::new ((void*)__j2) value_type(_VSTD::move(*__i2)); + ::new ((void*)__j2) value_type(std::move(*__i2)); __d.template __incr<value_type>(); for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) - *__j2 = _VSTD::move(*__i2); - *__j2 = _VSTD::move(*__first1); + *__j2 = std::move(*__i2); + *__j2 = _Ops::__iter_move(__first1); } else { - ::new ((void*)__j2) value_type(_VSTD::move(*__first1)); + ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1)); __d.template __incr<value_type>(); } } @@ -332,9 +416,11 @@ void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterat } } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __depth) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; const difference_type __limit = @@ -348,28 +434,29 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C return; case 2: if (__comp(*--__last, *__first)) - swap(*__first, *__last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); return; case 3: - _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), --__last, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); return; case 4: - _VSTD::__sort4_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), - --__last, __comp); + std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); return; case 5: - _VSTD::__sort5_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), - __first + difference_type(3), --__last, __comp); + std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), + --__last, __comp); return; } if (__len <= __limit) { - _VSTD::__insertion_sort_3<_Compare>(__first, __last, __comp); + std::__insertion_sort_3<_AlgPolicy, _Compare>(__first, __last, __comp); return; } // __len > 5 if (__depth == 0) { // Fallback to heap sort as Introsort suggests. - _VSTD::__partial_sort<_Compare>(__first, __last, __last, __comp); + std::__partial_sort<_AlgPolicy, _Compare>(__first, __last, __last, __comp); return; } --__depth; @@ -383,11 +470,12 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C __delta = __len / 2; __m += __delta; __delta /= 2; - __n_swaps = _VSTD::__sort5<_Compare>(__first, __first + __delta, __m, __m + __delta, __lm1, __comp); + __n_swaps = std::__sort5_wrap_policy<_AlgPolicy, _Compare>( + __first, __first + __delta, __m, __m + __delta, __lm1, __comp); } else { __delta = __len / 2; __m += __delta; - __n_swaps = _VSTD::__sort3<_Compare>(__first, __m, __lm1, __comp); + __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, __lm1, __comp); } } // *__m is median @@ -414,7 +502,7 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C if (__i == __j) return; // [__first, __last) all equivalent elements if (__comp(*__first, *__i)) { - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; ++__i; break; @@ -432,7 +520,7 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C ; if (__i >= __j) break; - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; ++__i; } @@ -443,7 +531,7 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C goto __restart; } if (__comp(*__j, *__m)) { - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; break; // found guard for downward moving __j, now use unguarded partition } @@ -465,7 +553,7 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C ; if (__i > __j) break; - swap(*__i, *__j); + _Ops::iter_swap(__i, __j); ++__n_swaps; // It is known that __m != __j // If __m just moved, follow it @@ -476,14 +564,16 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C } // [__first, __i) < *__m and *__m <= [__i, __last) if (__i != __m && __comp(*__m, *__i)) { - swap(*__i, *__m); + _Ops::iter_swap(__i, __m); ++__n_swaps; } // [__first, __i) < *__i and *__i <= [__i+1, __last) // If we were given a perfect partition, see if insertion sort is quick... if (__n_swaps == 0) { - bool __fs = _VSTD::__insertion_sort_incomplete<_Compare>(__first, __i, __comp); - if (_VSTD::__insertion_sort_incomplete<_Compare>(__i + difference_type(1), __last, __comp)) { + using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; + _WrappedComp __wrapped_comp(__comp); + bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp); + if (std::__insertion_sort_incomplete<_WrappedComp>(__i + difference_type(1), __last, __wrapped_comp)) { if (__fs) return; __last = __i; @@ -497,10 +587,10 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C } // sort smaller range with recursive call and larger with tail recursion elimination if (__i - __first < __last - __i) { - _VSTD::__introsort<_Compare>(__first, __i, __comp, __depth); + std::__introsort<_AlgPolicy, _Compare>(__first, __i, __comp, __depth); __first = ++__i; } else { - _VSTD::__introsort<_Compare>(__i + difference_type(1), __last, __comp, __depth); + std::__introsort<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp, __depth); __last = __i; } } @@ -525,17 +615,22 @@ inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { return __log2; } -template <class _Compare, class _RandomAccessIterator> -void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { +template <class _WrappedComp, class _RandomAccessIterator> +void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; difference_type __depth_limit = 2 * __log2i(__last - __first); - _VSTD::__introsort<_Compare>(__first, __last, __comp, __depth_limit); + + using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; + using _AlgPolicy = typename _Unwrap::_AlgPolicy; + using _Compare = typename _Unwrap::_Comp; + _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); + std::__introsort<_AlgPolicy, _Compare>(__first, __last, __comp, __depth_limit); } template <class _Compare, class _Tp> inline _LIBCPP_INLINE_VISIBILITY void __sort(_Tp** __first, _Tp** __last, __less<_Tp*>&) { __less<uintptr_t> __comp; - _VSTD::__sort<__less<uintptr_t>&, uintptr_t*>((uintptr_t*)__first, (uintptr_t*)__last, __comp); + std::__sort<__less<uintptr_t>&, uintptr_t*>((uintptr_t*)__first, (uintptr_t*)__last, __comp); } extern template _LIBCPP_FUNC_VIS void __sort<__less<char>&, char*>(char*, char*, __less<char>&); @@ -576,22 +671,27 @@ extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long do extern template _LIBCPP_FUNC_VIS unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); -template <class _RandomAccessIterator, class _Comp> +template <class _AlgPolicy, class _RandomAccessIterator, class _Comp> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { - std::__debug_randomize_range(__first, __last); + std::__debug_randomize_range<_AlgPolicy>(__first, __last); + using _Comp_ref = typename __comp_ref_type<_Comp>::type; if (__libcpp_is_constant_evaluated()) { - std::__partial_sort<_Comp_ref>(__first, __last, __last, _Comp_ref(__comp)); + std::__partial_sort<_AlgPolicy>(__first, __last, __last, __comp); + } else { - std::__sort<_Comp_ref>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), _Comp_ref(__comp)); + using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Comp_ref>::type; + _Comp_ref __comp_ref(__comp); + _WrappedComp __wrapped_comp(__comp_ref); + std::__sort<_WrappedComp>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __wrapped_comp); } } template <class _RandomAccessIterator, class _Comp> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { - std::__sort_impl(std::move(__first), std::move(__last), __comp); + std::__sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/sort_heap.h b/contrib/llvm-project/libcxx/include/__algorithm/sort_heap.h index 261adedd0eaf..b9f0b2c9690d 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/sort_heap.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/sort_heap.h @@ -11,11 +11,12 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/pop_heap.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> -#include <type_traits> // swap +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { using _CompRef = typename __comp_ref_type<_Compare>::type; @@ -31,13 +32,16 @@ void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _C using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n) - std::__pop_heap<_CompRef>(__first, __last, __comp_ref, __n); + std::__pop_heap<_AlgPolicy, _CompRef>(__first, __last, __comp_ref, __n); } template <class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - std::__sort_heap(std::move(__first), std::move(__last), __comp); + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + + std::__sort_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/stable_partition.h b/contrib/llvm-project/libcxx/include/__algorithm/stable_partition.h index 969ac7a6173e..e5ad48b2ed51 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/stable_partition.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/stable_partition.h @@ -9,13 +9,14 @@ #ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H #define _LIBCPP___ALGORITHM_STABLE_PARTITION_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/rotate.h> #include <__config> #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> #include <memory> +#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,11 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Predicate, class _ForwardIterator, class _Distance, class _Pair> +template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair> _ForwardIterator -__stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, +__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, _Distance __len, _Pair __p, forward_iterator_tag __fit) { + using _Ops = _IterOps<_AlgPolicy>; + // *__first is known to be false // __len >= 1 if (__len == 1) @@ -37,7 +40,7 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate _ForwardIterator __m = __first; if (__pred(*++__m)) { - swap(*__first, *__m); + _Ops::iter_swap(__first, __m); return __m; } return __first; @@ -50,7 +53,7 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate // Move the falses into the temporary buffer, and the trues to the front of the line // Update __first to always point to the end of the trues value_type* __t = __p.first; - ::new ((void*)__t) value_type(_VSTD::move(*__first)); + ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); __d.template __incr<value_type>(); ++__t; _ForwardIterator __i = __first; @@ -58,12 +61,12 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate { if (__pred(*__i)) { - *__first = _VSTD::move(*__i); + *__first = _Ops::__iter_move(__i); ++__first; } else { - ::new ((void*)__t) value_type(_VSTD::move(*__i)); + ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); __d.template __incr<value_type>(); ++__t; } @@ -72,7 +75,7 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate // Move falses back into range, but don't mess up __first which points to first false __i = __first; for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) - *__i = _VSTD::move(*__t2); + *__i = _Ops::__iter_move(__t2); // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer return __first; } @@ -80,11 +83,12 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate // __len >= 3 _ForwardIterator __m = __first; _Distance __len2 = __len / 2; // __len2 >= 2 - _VSTD::advance(__m, __len2); + _Ops::advance(__m, __len2); // recurse on [__first, __m), *__first know to be false // F????????????????? // f m l - _ForwardIterator __first_false = _VSTD::__stable_partition<_Predicate&>(__first, __m, __pred, __len2, __p, __fit); + _ForwardIterator __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __first, __m, __pred, __len2, __p, __fit); // TTTFFFFF?????????? // f ff m l // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true @@ -99,18 +103,19 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate } // TTTFFFFFTTTF?????? // f ff m m1 l - __second_false = _VSTD::__stable_partition<_Predicate&>(__m1, __last, __pred, __len_half, __p, __fit); + __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __m1, __last, __pred, __len_half, __p, __fit); __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l - return _VSTD::rotate(__first_false, __m, __second_false); + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __fit); // TTTTTTTTFFFFFFFFFF // | } -template <class _Predicate, class _ForwardIterator> +template <class _AlgPolicy, class _Predicate, class _ForwardIterator> _ForwardIterator -__stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, +__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) { const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment @@ -127,7 +132,7 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate // *__first is known to be false typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; typedef typename iterator_traits<_ForwardIterator>::value_type value_type; - difference_type __len = _VSTD::distance(__first, __last); + difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last); pair<value_type*, ptrdiff_t> __p(0, 0); unique_ptr<value_type, __return_temporary_buffer> __h; if (__len >= __alloc_limit) @@ -138,20 +143,23 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH _LIBCPP_SUPPRESS_DEPRECATED_POP __h.reset(__p.first); } - return _VSTD::__stable_partition<_Predicate&>(__first, __last, __pred, __len, __p, forward_iterator_tag()); + return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag()); } -template <class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair> +template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair> _BidirectionalIterator -__stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, +__stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, _Distance __len, _Pair __p, bidirectional_iterator_tag __bit) { + using _Ops = _IterOps<_AlgPolicy>; + // *__first is known to be false // *__last is known to be true // __len >= 2 if (__len == 2) { - swap(*__first, *__last); + _Ops::iter_swap(__first, __last); return __last; } if (__len == 3) @@ -159,12 +167,12 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last _BidirectionalIterator __m = __first; if (__pred(*++__m)) { - swap(*__first, *__m); - swap(*__m, *__last); + _Ops::iter_swap(__first, __m); + _Ops::iter_swap(__m, __last); return __last; } - swap(*__m, *__last); - swap(*__first, *__m); + _Ops::iter_swap(__m, __last); + _Ops::iter_swap(__first, __m); return __m; } if (__len <= __p.second) @@ -175,7 +183,7 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last // Move the falses into the temporary buffer, and the trues to the front of the line // Update __first to always point to the end of the trues value_type* __t = __p.first; - ::new ((void*)__t) value_type(_VSTD::move(*__first)); + ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); __d.template __incr<value_type>(); ++__t; _BidirectionalIterator __i = __first; @@ -183,23 +191,23 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last { if (__pred(*__i)) { - *__first = _VSTD::move(*__i); + *__first = _Ops::__iter_move(__i); ++__first; } else { - ::new ((void*)__t) value_type(_VSTD::move(*__i)); + ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); __d.template __incr<value_type>(); ++__t; } } // move *__last, known to be true - *__first = _VSTD::move(*__i); + *__first = _Ops::__iter_move(__i); __i = ++__first; // All trues now at start of range, all falses in buffer // Move falses back into range, but don't mess up __first which points to first false for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) - *__i = _VSTD::move(*__t2); + *__i = _Ops::__iter_move(__t2); // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer return __first; } @@ -207,7 +215,7 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last // __len >= 4 _BidirectionalIterator __m = __first; _Distance __len2 = __len / 2; // __len2 >= 2 - _VSTD::advance(__m, __len2); + _Ops::advance(__m, __len2); // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false // F????????????????T // f m l @@ -222,7 +230,8 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last } // F???TFFF?????????T // f m1 m l - __first_false = _VSTD::__stable_partition<_Predicate&>(__first, __m1, __pred, __len_half, __p, __bit); + __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __first, __m1, __pred, __len_half, __p, __bit); __first_half_done: // TTTFFFFF?????????T // f ff m l @@ -239,18 +248,19 @@ __first_half_done: } // TTTFFFFFTTTF?????T // f ff m m1 l - __second_false = _VSTD::__stable_partition<_Predicate&>(__m1, __last, __pred, __len_half, __p, __bit); + __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __m1, __last, __pred, __len_half, __p, __bit); __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l - return _VSTD::rotate(__first_false, __m, __second_false); + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __bit); // TTTTTTTTFFFFFFFFFF // | } -template <class _Predicate, class _BidirectionalIterator> +template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator> _BidirectionalIterator -__stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, +__stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) { typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; @@ -276,7 +286,7 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last // *__first is known to be false // *__last is known to be true // __len >= 2 - difference_type __len = _VSTD::distance(__first, __last) + 1; + difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1; pair<value_type*, ptrdiff_t> __p(0, 0); unique_ptr<value_type, __return_temporary_buffer> __h; if (__len >= __alloc_limit) @@ -287,7 +297,16 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH _LIBCPP_SUPPRESS_DEPRECATED_POP __h.reset(__p.first); } - return _VSTD::__stable_partition<_Predicate&>(__first, __last, __pred, __len, __p, bidirectional_iterator_tag()); + return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag()); +} + +template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory> +_LIBCPP_HIDE_FROM_ABI +_ForwardIterator __stable_partition( + _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) { + return std::__stable_partition_impl<_AlgPolicy, __uncvref_t<_Predicate>&>( + std::move(__first), std::move(__last), __pred, __iter_category); } template <class _ForwardIterator, class _Predicate> @@ -295,7 +314,9 @@ inline _LIBCPP_INLINE_VISIBILITY _ForwardIterator stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - return _VSTD::__stable_partition<_Predicate&>(__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); + using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; + return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>( + std::move(__first), std::move(__last), __pred, _IterCategory()); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/stable_sort.h b/contrib/llvm-project/libcxx/include/__algorithm/stable_sort.h index e3479aad62e6..6122758bdefe 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/stable_sort.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/stable_sort.h @@ -12,11 +12,11 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/inplace_merge.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/sort.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> -#include <__utility/swap.h> #include <memory> #include <type_traits> @@ -26,12 +26,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _InputIterator1, class _InputIterator2> +template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2> void __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, typename iterator_traits<_InputIterator1>::value_type* __result, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_InputIterator1>::value_type value_type; __destruct_n __d(0); unique_ptr<value_type, __destruct_n&> __h(__result, __d); @@ -40,111 +42,115 @@ __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, if (__first1 == __last1) { for (; __first2 != __last2; ++__first2, (void) ++__result, __d.template __incr<value_type>()) - ::new ((void*)__result) value_type(_VSTD::move(*__first2)); + ::new ((void*)__result) value_type(_Ops::__iter_move(__first2)); __h.release(); return; } if (__first2 == __last2) { for (; __first1 != __last1; ++__first1, (void) ++__result, __d.template __incr<value_type>()) - ::new ((void*)__result) value_type(_VSTD::move(*__first1)); + ::new ((void*)__result) value_type(_Ops::__iter_move(__first1)); __h.release(); return; } if (__comp(*__first2, *__first1)) { - ::new ((void*)__result) value_type(_VSTD::move(*__first2)); + ::new ((void*)__result) value_type(_Ops::__iter_move(__first2)); __d.template __incr<value_type>(); ++__first2; } else { - ::new ((void*)__result) value_type(_VSTD::move(*__first1)); + ::new ((void*)__result) value_type(_Ops::__iter_move(__first1)); __d.template __incr<value_type>(); ++__first1; } } } -template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> +template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> void __merge_move_assign(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + for (; __first1 != __last1; ++__result) { if (__first2 == __last2) { for (; __first1 != __last1; ++__first1, (void) ++__result) - *__result = _VSTD::move(*__first1); + *__result = _Ops::__iter_move(__first1); return; } if (__comp(*__first2, *__first1)) { - *__result = _VSTD::move(*__first2); + *__result = _Ops::__iter_move(__first2); ++__first2; } else { - *__result = _VSTD::move(*__first1); + *__result = _Ops::__iter_move(__first1); ++__first1; } } for (; __first2 != __last2; ++__first2, (void) ++__result) - *__result = _VSTD::move(*__first2); + *__result = _Ops::__iter_move(__first2); } -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> void __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len, typename iterator_traits<_RandomAccessIterator>::value_type* __buff, ptrdiff_t __buff_size); -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> void __stable_sort_move(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len, typename iterator_traits<_RandomAccessIterator>::value_type* __first2) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; switch (__len) { case 0: return; case 1: - ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); + ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1)); return; case 2: __destruct_n __d(0); unique_ptr<value_type, __destruct_n&> __h2(__first2, __d); if (__comp(*--__last1, *__first1)) { - ::new ((void*)__first2) value_type(_VSTD::move(*__last1)); + ::new ((void*)__first2) value_type(_Ops::__iter_move(__last1)); __d.template __incr<value_type>(); ++__first2; - ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); + ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1)); } else { - ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); + ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1)); __d.template __incr<value_type>(); ++__first2; - ::new ((void*)__first2) value_type(_VSTD::move(*__last1)); + ::new ((void*)__first2) value_type(_Ops::__iter_move(__last1)); } __h2.release(); return; } if (__len <= 8) { - _VSTD::__insertion_sort_move<_Compare>(__first1, __last1, __first2, __comp); + std::__insertion_sort_move<_AlgPolicy, _Compare>(__first1, __last1, __first2, __comp); return; } typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; _RandomAccessIterator __m = __first1 + __l2; - _VSTD::__stable_sort<_Compare>(__first1, __m, __comp, __l2, __first2, __l2); - _VSTD::__stable_sort<_Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2); - _VSTD::__merge_move_construct<_Compare>(__first1, __m, __m, __last1, __first2, __comp); + std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2); + std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2); + std::__merge_move_construct<_AlgPolicy, _Compare>(__first1, __m, __m, __last1, __first2, __comp); } template <class _Tp> @@ -153,7 +159,7 @@ struct __stable_sort_switch static const unsigned value = 128*is_trivially_copy_assignable<_Tp>::value; }; -template <class _Compare, class _RandomAccessIterator> +template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> void __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len, @@ -168,12 +174,12 @@ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp return; case 2: if (__comp(*--__last, *__first)) - swap(*__first, *__last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); return; } if (__len <= static_cast<difference_type>(__stable_sort_switch<value_type>::value)) { - _VSTD::__insertion_sort<_Compare>(__first, __last, __comp); + std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp); return; } typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; @@ -182,11 +188,12 @@ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp { __destruct_n __d(0); unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); - _VSTD::__stable_sort_move<_Compare>(__first, __m, __comp, __l2, __buff); + std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff); __d.__set(__l2, (value_type*)nullptr); - _VSTD::__stable_sort_move<_Compare>(__m, __last, __comp, __len - __l2, __buff + __l2); + std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2); __d.__set(__len, (value_type*)nullptr); - _VSTD::__merge_move_assign<_Compare>(__buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp); + std::__merge_move_assign<_AlgPolicy, _Compare>( + __buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp); // _VSTD::__merge<_Compare>(move_iterator<value_type*>(__buff), // move_iterator<value_type*>(__buff + __l2), // move_iterator<_RandomAccessIterator>(__buff + __l2), @@ -194,12 +201,12 @@ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp // __first, __comp); return; } - _VSTD::__stable_sort<_Compare>(__first, __m, __comp, __l2, __buff, __buff_size); - _VSTD::__stable_sort<_Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); - _VSTD::__inplace_merge<_Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); + std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size); + std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); + std::__inplace_merge<_AlgPolicy, _Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); } -template <class _RandomAccessIterator, class _Compare> +template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI void __stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; @@ -217,13 +224,13 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP } using _Comp_ref = typename __comp_ref_type<_Compare>::type; - std::__stable_sort<_Comp_ref>(__first, __last, __comp, __len, __buf.first, __buf.second); + std::__stable_sort<_AlgPolicy, _Comp_ref>(__first, __last, __comp, __len, __buf.first, __buf.second); } template <class _RandomAccessIterator, class _Compare> inline _LIBCPP_HIDE_FROM_ABI void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - std::__stable_sort_impl(std::move(__first), std::move(__last), __comp); + std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); } template <class _RandomAccessIterator> diff --git a/contrib/llvm-project/libcxx/include/__algorithm/unwrap_iter.h b/contrib/llvm-project/libcxx/include/__algorithm/unwrap_iter.h index 7d1807b7bbf9..fa9a8fbf2dde 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/unwrap_iter.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/unwrap_iter.h @@ -12,6 +12,7 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> +#include <__utility/move.h> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -20,77 +21,50 @@ _LIBCPP_BEGIN_NAMESPACE_STD -// The job of __unwrap_iter is to lower contiguous iterators (such as -// vector<T>::iterator) into pointers, to reduce the number of template -// instantiations and to enable pointer-based optimizations e.g. in std::copy. -// For iterators that are not contiguous, it must be a no-op. +// TODO: Change the name of __unwrap_iter_impl to something more appropriate +// The job of __unwrap_iter is to remove iterator wrappers (like reverse_iterator or __wrap_iter), +// to reduce the number of template instantiations and to enable pointer-based optimizations e.g. in std::copy. // In debug mode, we don't do this. // -// __unwrap_iter is non-constexpr for user-defined iterators whose -// `to_address` and/or `operator->` is non-constexpr. This is okay; but we -// try to avoid doing __unwrap_iter in constant-evaluated contexts anyway. -// // Some algorithms (e.g. std::copy, but not std::sort) need to convert an -// "unwrapped" result back into a contiguous iterator. Since contiguous iterators -// are random-access, we can do this portably using iterator arithmetic; this -// is the job of __rewrap_iter. +// "unwrapped" result back into the original iterator type. Doing that is the job of __rewrap_iter. +// Default case - we can't unwrap anything template <class _Iter, bool = __is_cpp17_contiguous_iterator<_Iter>::value> struct __unwrap_iter_impl { - static _LIBCPP_CONSTEXPR _Iter - __apply(_Iter __i) _NOEXCEPT { - return __i; - } + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter, _Iter __iter) { return __iter; } + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __unwrap(_Iter __i) _NOEXCEPT { return __i; } }; #ifndef _LIBCPP_ENABLE_DEBUG_MODE +// It's a contiguous iterator, so we can use a raw pointer instead template <class _Iter> struct __unwrap_iter_impl<_Iter, true> { - static _LIBCPP_CONSTEXPR decltype(_VSTD::__to_address(declval<_Iter>())) - __apply(_Iter __i) _NOEXCEPT { - return _VSTD::__to_address(__i); - } -}; + using _ToAddressT = decltype(std::__to_address(std::declval<_Iter>())); -#endif // !_LIBCPP_ENABLE_DEBUG_MODE - -template<class _Iter, class _Impl = __unwrap_iter_impl<_Iter> > -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -decltype(_Impl::__apply(declval<_Iter>())) -__unwrap_iter(_Iter __i) _NOEXCEPT -{ - return _Impl::__apply(__i); -} - -template <class _OrigIter, class _UnwrappedIter> -struct __rewrap_iter_impl { - static _LIBCPP_CONSTEXPR _OrigIter __apply(_OrigIter __first, _UnwrappedIter __result) { - // Precondition: __result is reachable from __first - // Precondition: _OrigIter is a contiguous iterator - return __first + (__result - std::__unwrap_iter(__first)); + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter __orig_iter, _ToAddressT __unwrapped_iter) { + return __orig_iter + (__unwrapped_iter - std::__to_address(__orig_iter)); } -}; -template <class _OrigIter> -struct __rewrap_iter_impl<_OrigIter, _OrigIter> { - static _LIBCPP_CONSTEXPR _OrigIter __apply(_OrigIter, _OrigIter __result) { - return __result; + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToAddressT __unwrap(_Iter __i) _NOEXCEPT { + return std::__to_address(__i); } }; -template<class _OrigIter> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR -_OrigIter __rewrap_iter(_OrigIter, _OrigIter __result) -{ - return __result; +#endif // !_LIBCPP_ENABLE_DEBUG_MODE + +template<class _Iter, + class _Impl = __unwrap_iter_impl<_Iter>, + __enable_if_t<is_copy_constructible<_Iter>::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 +decltype(_Impl::__unwrap(std::declval<_Iter>())) __unwrap_iter(_Iter __i) _NOEXCEPT { + return _Impl::__unwrap(__i); } -template<class _OrigIter, class _UnwrappedIter, class _Impl = __rewrap_iter_impl<_OrigIter, _UnwrappedIter> > -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR -_OrigIter __rewrap_iter(_OrigIter __first, _UnwrappedIter __result) -{ - return _Impl::__apply(__first, __result); +template <class _OrigIter, class _Iter, class _Impl = __unwrap_iter_impl<_OrigIter> > +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _OrigIter __rewrap_iter(_OrigIter __orig_iter, _Iter __iter) _NOEXCEPT { + return _Impl::__rewrap(std::move(__orig_iter), std::move(__iter)); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__algorithm/upper_bound.h b/contrib/llvm-project/libcxx/include/__algorithm/upper_bound.h index 3fc254873532..1045380bc84e 100644 --- a/contrib/llvm-project/libcxx/include/__algorithm/upper_bound.h +++ b/contrib/llvm-project/libcxx/include/__algorithm/upper_bound.h @@ -11,10 +11,15 @@ #include <__algorithm/comp.h> #include <__algorithm/half_positive.h> +#include <__algorithm/iterator_operations.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,45 +27,40 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Compare, class _ForwardIterator, class _Tp> -_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -__upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) -{ - typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; - difference_type __len = _VSTD::distance(__first, __last); - while (__len != 0) - { - difference_type __l2 = _VSTD::__half_positive(__len); - _ForwardIterator __m = __first; - _VSTD::advance(__m, __l2); - if (__comp(__value, *__m)) - __len = __l2; - else - { - __first = ++__m; - __len -= __l2 + 1; - } +template <class _AlgPolicy, class _Compare, class _Iter, class _Sent, class _Tp, class _Proj> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter +__upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp, _Proj&& __proj) { + auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); + while (__len != 0) { + auto __half_len = std::__half_positive(__len); + auto __mid = _IterOps<_AlgPolicy>::next(__first, __half_len); + if (std::__invoke(__comp, __value, std::__invoke(__proj, *__mid))) + __len = __half_len; + else { + __first = ++__mid; + __len -= __half_len + 1; } - return __first; + } + return __first; } template <class _ForwardIterator, class _Tp, class _Compare> -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_ForwardIterator -upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) -{ - return _VSTD::__upper_bound<_Compare&>(__first, __last, __value, __comp); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { + static_assert(is_copy_constructible<_ForwardIterator>::value, + "Iterator has to be copy constructible"); + return std::__upper_bound<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), __value, std::move(__comp), std::__identity()); } template <class _ForwardIterator, class _Tp> -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_ForwardIterator -upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) -{ - return _VSTD::upper_bound(__first, __last, __value, - __less<_Tp, typename iterator_traits<_ForwardIterator>::value_type>()); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::upper_bound( + std::move(__first), + std::move(__last), + __value, + __less<_Tp, typename iterator_traits<_ForwardIterator>::value_type>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/llvm-project/libcxx/include/__config b/contrib/llvm-project/libcxx/include/__config index 22c2ed7fd87b..8c2f7614af53 100644 --- a/contrib/llvm-project/libcxx/include/__config +++ b/contrib/llvm-project/libcxx/include/__config @@ -214,6 +214,12 @@ # error "libc++ only supports C++03 with Clang-based compilers. Please enable C++11" # endif +# ifdef _LIBCPP_COMPILER_MSVC +# error If you successfully use libc++ with MSVC please tell the libc++ developers and consider upstreaming your \ +changes. We are not aware of anybody using this configuration and know that at least some code is currently broken. \ +If there are users of this configuration we are happy to provide support. +# endif + // FIXME: ABI detection should be done via compiler builtin macros. This // is just a placeholder until Clang implements such macros. For now assume // that Windows compilers pretending to be MSVC++ target the Microsoft ABI, @@ -237,6 +243,19 @@ # define _LIBCPP_ABI_VCRUNTIME # endif +# if __has_feature(experimental_library) +# ifndef _LIBCPP_ENABLE_EXPERIMENTAL +# define _LIBCPP_ENABLE_EXPERIMENTAL +# endif +# endif + +// Incomplete features get their own specific disabling flags. This makes it +// easier to grep for target specific flags once the feature is complete. +# if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_HAS_NO_INCOMPLETE_FORMAT +# define _LIBCPP_HAS_NO_INCOMPLETE_RANGES +# endif + // Need to detect which libc we're using if we're on Linux. # if defined(__linux__) # include <features.h> @@ -545,11 +564,15 @@ typedef __char32_t char32_t; # define _LIBCPP_TYPE_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_TEMPLATE_DATA_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_VISIBILITY("default") -# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_EXCEPTION_ABI _LIBCPP_VISIBILITY("default") # define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS +// TODO: Make this a proper customization point or remove the option to override it. +# ifndef _LIBCPP_OVERRIDABLE_FUNC_VIS +# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default") +# endif + # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) // The inline should be removed once PR32114 is resolved # define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS inline _LIBCPP_HIDDEN diff --git a/contrib/llvm-project/libcxx/include/__debug_utils/randomize_range.h b/contrib/llvm-project/libcxx/include/__debug_utils/randomize_range.h index fd5b9e588493..9843709019d4 100644 --- a/contrib/llvm-project/libcxx/include/__debug_utils/randomize_range.h +++ b/contrib/llvm-project/libcxx/include/__debug_utils/randomize_range.h @@ -22,15 +22,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Iterator> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __debug_randomize_range(_Iterator __first, _Iterator __last) { +template <class _AlgPolicy, class _Iterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 +void __debug_randomize_range(_Iterator __first, _Sentinel __last) { #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY # ifdef _LIBCPP_CXX03_LANG # error Support for unspecified stability is only for C++11 and higher # endif if (!__libcpp_is_constant_evaluated()) - std::shuffle(__first, __last, __libcpp_debug_randomizer()); + std::__shuffle<_AlgPolicy>(__first, __last, __libcpp_debug_randomizer()); #else (void)__first; (void)__last; diff --git a/contrib/llvm-project/libcxx/include/__format/extended_grapheme_cluster_table.h b/contrib/llvm-project/libcxx/include/__format/extended_grapheme_cluster_table.h new file mode 100644 index 000000000000..00cd0e91cd15 --- /dev/null +++ b/contrib/llvm-project/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -0,0 +1,332 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utiles/generate_extended_grapheme_cluster_table.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use <https://www.unicode.org/copyright.html> +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H +#define _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H + +#include <__algorithm/upper_bound.h> +#include <__config> +#include <__iterator/access.h> +#include <cstddef> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __extended_grapheme_custer_property_boundary { + +enum class __property : uint8_t { + // Values generated from the data files. + __CR, + __Control, + __Extend, + __Extended_Pictographic, + __L, + __LF, + __LV, + __LVT, + __Prepend, + __Regional_Indicator, + __SpacingMark, + __T, + __V, + __ZWJ, + + // The properies below aren't stored in the "database". + + // Text position properties. + __sot, + __eot, + + // The code unit has none of above properties. + __none +}; + +/// The entries of the extended grapheme cluster bondary property table. +/// +/// The data is generated from +/// - https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt +/// - https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt +/// +/// The data has 3 values +/// - bits [0, 3] The property. One of the values generated form the datafiles +/// of \ref __property +/// - bits [4, 10] The size of the range. +/// - bits [11, 31] The lower bound code point of the range. The upper bound of +/// the range is lower bound + size. +/// +/// The 7 bits for the size allow a maximum range of 128 elements. Some ranges +/// in the Unicode tables are larger. They are stored in multiple consecutive +/// ranges in the data table. An alternative would be to store the sizes in a +/// separate 16-bit value. The original MSVC STL code had such an approach, but +/// this approach uses less space for the data and is about 4% faster in the +/// following benchmark. +/// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp +inline constexpr uint32_t __entries[1480] = { + 0x00000091, 0x00005005, 0x00005811, 0x00006800, 0x00007111, 0x0003fa01, 0x00054803, 0x00056801, 0x00057003, + 0x001806f2, 0x00241862, 0x002c8ac2, 0x002df802, 0x002e0812, 0x002e2012, 0x002e3802, 0x00300058, 0x003080a2, + 0x0030e001, 0x00325942, 0x00338002, 0x0036b062, 0x0036e808, 0x0036f852, 0x00373812, 0x00375032, 0x00387808, + 0x00388802, 0x003981a2, 0x003d30a2, 0x003f5882, 0x003fe802, 0x0040b032, 0x0040d882, 0x00412822, 0x00414842, + 0x0042c822, 0x00448018, 0x0044c072, 0x00465172, 0x00471008, 0x004719f2, 0x0048180a, 0x0049d002, 0x0049d80a, + 0x0049e002, 0x0049f02a, 0x004a0872, 0x004a483a, 0x004a6802, 0x004a701a, 0x004a8862, 0x004b1012, 0x004c0802, + 0x004c101a, 0x004de002, 0x004df002, 0x004df81a, 0x004e0832, 0x004e381a, 0x004e581a, 0x004e6802, 0x004eb802, + 0x004f1012, 0x004ff002, 0x00500812, 0x0050180a, 0x0051e002, 0x0051f02a, 0x00520812, 0x00523812, 0x00525822, + 0x00528802, 0x00538012, 0x0053a802, 0x00540812, 0x0054180a, 0x0055e002, 0x0055f02a, 0x00560842, 0x00563812, + 0x0056480a, 0x0056581a, 0x00566802, 0x00571012, 0x0057d052, 0x00580802, 0x0058101a, 0x0059e002, 0x0059f012, + 0x005a000a, 0x005a0832, 0x005a381a, 0x005a581a, 0x005a6802, 0x005aa822, 0x005b1012, 0x005c1002, 0x005df002, + 0x005df80a, 0x005e0002, 0x005e081a, 0x005e302a, 0x005e502a, 0x005e6802, 0x005eb802, 0x00600002, 0x0060082a, + 0x00602002, 0x0061e002, 0x0061f022, 0x0062083a, 0x00623022, 0x00625032, 0x0062a812, 0x00631012, 0x00640802, + 0x0064101a, 0x0065e002, 0x0065f00a, 0x0065f802, 0x0066001a, 0x00661002, 0x0066181a, 0x00663002, 0x0066381a, + 0x0066501a, 0x00666012, 0x0066a812, 0x00671012, 0x00680012, 0x0068101a, 0x0069d812, 0x0069f002, 0x0069f81a, + 0x006a0832, 0x006a302a, 0x006a502a, 0x006a6802, 0x006a7008, 0x006ab802, 0x006b1012, 0x006c0802, 0x006c101a, + 0x006e5002, 0x006e7802, 0x006e801a, 0x006e9022, 0x006eb002, 0x006ec06a, 0x006ef802, 0x006f901a, 0x00718802, + 0x0071980a, 0x0071a062, 0x00723872, 0x00758802, 0x0075980a, 0x0075a082, 0x00764052, 0x0078c012, 0x0079a802, + 0x0079b802, 0x0079c802, 0x0079f01a, 0x007b88d2, 0x007bf80a, 0x007c0042, 0x007c3012, 0x007c68a2, 0x007cca32, + 0x007e3002, 0x00816832, 0x0081880a, 0x00819052, 0x0081c812, 0x0081d81a, 0x0081e812, 0x0082b01a, 0x0082c012, + 0x0082f022, 0x00838832, 0x00841002, 0x0084200a, 0x00842812, 0x00846802, 0x0084e802, 0x008805f4, 0x008b047c, + 0x008d457b, 0x009ae822, 0x00b89022, 0x00b8a80a, 0x00b99012, 0x00b9a00a, 0x00ba9012, 0x00bb9012, 0x00bda012, + 0x00bdb00a, 0x00bdb862, 0x00bdf07a, 0x00be3002, 0x00be381a, 0x00be48a2, 0x00bee802, 0x00c05822, 0x00c07001, + 0x00c07802, 0x00c42812, 0x00c54802, 0x00c90022, 0x00c9183a, 0x00c93812, 0x00c9482a, 0x00c9801a, 0x00c99002, + 0x00c9985a, 0x00c9c822, 0x00d0b812, 0x00d0c81a, 0x00d0d802, 0x00d2a80a, 0x00d2b002, 0x00d2b80a, 0x00d2c062, + 0x00d30002, 0x00d31002, 0x00d32872, 0x00d3685a, 0x00d39892, 0x00d3f802, 0x00d581e2, 0x00d80032, 0x00d8200a, + 0x00d9a062, 0x00d9d80a, 0x00d9e002, 0x00d9e84a, 0x00da1002, 0x00da181a, 0x00db5882, 0x00dc0012, 0x00dc100a, + 0x00dd080a, 0x00dd1032, 0x00dd301a, 0x00dd4012, 0x00dd500a, 0x00dd5822, 0x00df3002, 0x00df380a, 0x00df4012, + 0x00df502a, 0x00df6802, 0x00df700a, 0x00df7822, 0x00df901a, 0x00e1207a, 0x00e16072, 0x00e1a01a, 0x00e1b012, + 0x00e68022, 0x00e6a0c2, 0x00e7080a, 0x00e71062, 0x00e76802, 0x00e7a002, 0x00e7b80a, 0x00e7c012, 0x00ee03f2, + 0x01005801, 0x01006002, 0x0100680d, 0x01007011, 0x01014061, 0x0101e003, 0x01024803, 0x010300f1, 0x01068202, + 0x01091003, 0x0109c803, 0x010ca053, 0x010d4813, 0x0118d013, 0x01194003, 0x011c4003, 0x011e7803, 0x011f48a3, + 0x011fc023, 0x01261003, 0x012d5013, 0x012db003, 0x012e0003, 0x012fd833, 0x01300053, 0x013038b3, 0x0130a713, + 0x01348753, 0x013840a3, 0x0138a003, 0x0138b003, 0x0138e803, 0x01390803, 0x01394003, 0x01399813, 0x013a2003, + 0x013a3803, 0x013a6003, 0x013a7003, 0x013a9823, 0x013ab803, 0x013b1843, 0x013ca823, 0x013d0803, 0x013d8003, + 0x013df803, 0x0149a013, 0x01582823, 0x0158d813, 0x015a8003, 0x015aa803, 0x01677822, 0x016bf802, 0x016f01f2, + 0x01815052, 0x01818003, 0x0181e803, 0x0184c812, 0x0194b803, 0x0194c803, 0x05337832, 0x0533a092, 0x0534f012, + 0x05378012, 0x05401002, 0x05403002, 0x05405802, 0x0541181a, 0x05412812, 0x0541380a, 0x05416002, 0x0544001a, + 0x0545a0fa, 0x05462012, 0x05470112, 0x0547f802, 0x05493072, 0x054a38a2, 0x054a901a, 0x054b01c4, 0x054c0022, + 0x054c180a, 0x054d9802, 0x054da01a, 0x054db032, 0x054dd01a, 0x054de012, 0x054df02a, 0x054f2802, 0x05514852, + 0x0551781a, 0x05518812, 0x0551981a, 0x0551a812, 0x05521802, 0x05526002, 0x0552680a, 0x0553e002, 0x05558002, + 0x05559022, 0x0555b812, 0x0555f012, 0x05560802, 0x0557580a, 0x05576012, 0x0557701a, 0x0557a80a, 0x0557b002, + 0x055f181a, 0x055f2802, 0x055f301a, 0x055f4002, 0x055f481a, 0x055f600a, 0x055f6802, 0x05600006, 0x056009a7, + 0x0560e006, 0x0560e9a7, 0x0561c006, 0x0561c9a7, 0x0562a006, 0x0562a9a7, 0x05638006, 0x056389a7, 0x05646006, + 0x056469a7, 0x05654006, 0x056549a7, 0x05662006, 0x056629a7, 0x05670006, 0x056709a7, 0x0567e006, 0x0567e9a7, + 0x0568c006, 0x0568c9a7, 0x0569a006, 0x0569a9a7, 0x056a8006, 0x056a89a7, 0x056b6006, 0x056b69a7, 0x056c4006, + 0x056c49a7, 0x056d2006, 0x056d29a7, 0x056e0006, 0x056e09a7, 0x056ee006, 0x056ee9a7, 0x056fc006, 0x056fc9a7, + 0x0570a006, 0x0570a9a7, 0x05718006, 0x057189a7, 0x05726006, 0x057269a7, 0x05734006, 0x057349a7, 0x05742006, + 0x057429a7, 0x05750006, 0x057509a7, 0x0575e006, 0x0575e9a7, 0x0576c006, 0x0576c9a7, 0x0577a006, 0x0577a9a7, + 0x05788006, 0x057889a7, 0x05796006, 0x057969a7, 0x057a4006, 0x057a49a7, 0x057b2006, 0x057b29a7, 0x057c0006, + 0x057c09a7, 0x057ce006, 0x057ce9a7, 0x057dc006, 0x057dc9a7, 0x057ea006, 0x057ea9a7, 0x057f8006, 0x057f89a7, + 0x05806006, 0x058069a7, 0x05814006, 0x058149a7, 0x05822006, 0x058229a7, 0x05830006, 0x058309a7, 0x0583e006, + 0x0583e9a7, 0x0584c006, 0x0584c9a7, 0x0585a006, 0x0585a9a7, 0x05868006, 0x058689a7, 0x05876006, 0x058769a7, + 0x05884006, 0x058849a7, 0x05892006, 0x058929a7, 0x058a0006, 0x058a09a7, 0x058ae006, 0x058ae9a7, 0x058bc006, + 0x058bc9a7, 0x058ca006, 0x058ca9a7, 0x058d8006, 0x058d89a7, 0x058e6006, 0x058e69a7, 0x058f4006, 0x058f49a7, + 0x05902006, 0x059029a7, 0x05910006, 0x059109a7, 0x0591e006, 0x0591e9a7, 0x0592c006, 0x0592c9a7, 0x0593a006, + 0x0593a9a7, 0x05948006, 0x059489a7, 0x05956006, 0x059569a7, 0x05964006, 0x059649a7, 0x05972006, 0x059729a7, + 0x05980006, 0x059809a7, 0x0598e006, 0x0598e9a7, 0x0599c006, 0x0599c9a7, 0x059aa006, 0x059aa9a7, 0x059b8006, + 0x059b89a7, 0x059c6006, 0x059c69a7, 0x059d4006, 0x059d49a7, 0x059e2006, 0x059e29a7, 0x059f0006, 0x059f09a7, + 0x059fe006, 0x059fe9a7, 0x05a0c006, 0x05a0c9a7, 0x05a1a006, 0x05a1a9a7, 0x05a28006, 0x05a289a7, 0x05a36006, + 0x05a369a7, 0x05a44006, 0x05a449a7, 0x05a52006, 0x05a529a7, 0x05a60006, 0x05a609a7, 0x05a6e006, 0x05a6e9a7, + 0x05a7c006, 0x05a7c9a7, 0x05a8a006, 0x05a8a9a7, 0x05a98006, 0x05a989a7, 0x05aa6006, 0x05aa69a7, 0x05ab4006, + 0x05ab49a7, 0x05ac2006, 0x05ac29a7, 0x05ad0006, 0x05ad09a7, 0x05ade006, 0x05ade9a7, 0x05aec006, 0x05aec9a7, + 0x05afa006, 0x05afa9a7, 0x05b08006, 0x05b089a7, 0x05b16006, 0x05b169a7, 0x05b24006, 0x05b249a7, 0x05b32006, + 0x05b329a7, 0x05b40006, 0x05b409a7, 0x05b4e006, 0x05b4e9a7, 0x05b5c006, 0x05b5c9a7, 0x05b6a006, 0x05b6a9a7, + 0x05b78006, 0x05b789a7, 0x05b86006, 0x05b869a7, 0x05b94006, 0x05b949a7, 0x05ba2006, 0x05ba29a7, 0x05bb0006, + 0x05bb09a7, 0x05bbe006, 0x05bbe9a7, 0x05bcc006, 0x05bcc9a7, 0x05bda006, 0x05bda9a7, 0x05be8006, 0x05be89a7, + 0x05bf6006, 0x05bf69a7, 0x05c04006, 0x05c049a7, 0x05c12006, 0x05c129a7, 0x05c20006, 0x05c209a7, 0x05c2e006, + 0x05c2e9a7, 0x05c3c006, 0x05c3c9a7, 0x05c4a006, 0x05c4a9a7, 0x05c58006, 0x05c589a7, 0x05c66006, 0x05c669a7, + 0x05c74006, 0x05c749a7, 0x05c82006, 0x05c829a7, 0x05c90006, 0x05c909a7, 0x05c9e006, 0x05c9e9a7, 0x05cac006, + 0x05cac9a7, 0x05cba006, 0x05cba9a7, 0x05cc8006, 0x05cc89a7, 0x05cd6006, 0x05cd69a7, 0x05ce4006, 0x05ce49a7, + 0x05cf2006, 0x05cf29a7, 0x05d00006, 0x05d009a7, 0x05d0e006, 0x05d0e9a7, 0x05d1c006, 0x05d1c9a7, 0x05d2a006, + 0x05d2a9a7, 0x05d38006, 0x05d389a7, 0x05d46006, 0x05d469a7, 0x05d54006, 0x05d549a7, 0x05d62006, 0x05d629a7, + 0x05d70006, 0x05d709a7, 0x05d7e006, 0x05d7e9a7, 0x05d8c006, 0x05d8c9a7, 0x05d9a006, 0x05d9a9a7, 0x05da8006, + 0x05da89a7, 0x05db6006, 0x05db69a7, 0x05dc4006, 0x05dc49a7, 0x05dd2006, 0x05dd29a7, 0x05de0006, 0x05de09a7, + 0x05dee006, 0x05dee9a7, 0x05dfc006, 0x05dfc9a7, 0x05e0a006, 0x05e0a9a7, 0x05e18006, 0x05e189a7, 0x05e26006, + 0x05e269a7, 0x05e34006, 0x05e349a7, 0x05e42006, 0x05e429a7, 0x05e50006, 0x05e509a7, 0x05e5e006, 0x05e5e9a7, + 0x05e6c006, 0x05e6c9a7, 0x05e7a006, 0x05e7a9a7, 0x05e88006, 0x05e889a7, 0x05e96006, 0x05e969a7, 0x05ea4006, + 0x05ea49a7, 0x05eb2006, 0x05eb29a7, 0x05ec0006, 0x05ec09a7, 0x05ece006, 0x05ece9a7, 0x05edc006, 0x05edc9a7, + 0x05eea006, 0x05eea9a7, 0x05ef8006, 0x05ef89a7, 0x05f06006, 0x05f069a7, 0x05f14006, 0x05f149a7, 0x05f22006, + 0x05f229a7, 0x05f30006, 0x05f309a7, 0x05f3e006, 0x05f3e9a7, 0x05f4c006, 0x05f4c9a7, 0x05f5a006, 0x05f5a9a7, + 0x05f68006, 0x05f689a7, 0x05f76006, 0x05f769a7, 0x05f84006, 0x05f849a7, 0x05f92006, 0x05f929a7, 0x05fa0006, + 0x05fa09a7, 0x05fae006, 0x05fae9a7, 0x05fbc006, 0x05fbc9a7, 0x05fca006, 0x05fca9a7, 0x05fd8006, 0x05fd89a7, + 0x05fe6006, 0x05fe69a7, 0x05ff4006, 0x05ff49a7, 0x06002006, 0x060029a7, 0x06010006, 0x060109a7, 0x0601e006, + 0x0601e9a7, 0x0602c006, 0x0602c9a7, 0x0603a006, 0x0603a9a7, 0x06048006, 0x060489a7, 0x06056006, 0x060569a7, + 0x06064006, 0x060649a7, 0x06072006, 0x060729a7, 0x06080006, 0x060809a7, 0x0608e006, 0x0608e9a7, 0x0609c006, + 0x0609c9a7, 0x060aa006, 0x060aa9a7, 0x060b8006, 0x060b89a7, 0x060c6006, 0x060c69a7, 0x060d4006, 0x060d49a7, + 0x060e2006, 0x060e29a7, 0x060f0006, 0x060f09a7, 0x060fe006, 0x060fe9a7, 0x0610c006, 0x0610c9a7, 0x0611a006, + 0x0611a9a7, 0x06128006, 0x061289a7, 0x06136006, 0x061369a7, 0x06144006, 0x061449a7, 0x06152006, 0x061529a7, + 0x06160006, 0x061609a7, 0x0616e006, 0x0616e9a7, 0x0617c006, 0x0617c9a7, 0x0618a006, 0x0618a9a7, 0x06198006, + 0x061989a7, 0x061a6006, 0x061a69a7, 0x061b4006, 0x061b49a7, 0x061c2006, 0x061c29a7, 0x061d0006, 0x061d09a7, + 0x061de006, 0x061de9a7, 0x061ec006, 0x061ec9a7, 0x061fa006, 0x061fa9a7, 0x06208006, 0x062089a7, 0x06216006, + 0x062169a7, 0x06224006, 0x062249a7, 0x06232006, 0x062329a7, 0x06240006, 0x062409a7, 0x0624e006, 0x0624e9a7, + 0x0625c006, 0x0625c9a7, 0x0626a006, 0x0626a9a7, 0x06278006, 0x062789a7, 0x06286006, 0x062869a7, 0x06294006, + 0x062949a7, 0x062a2006, 0x062a29a7, 0x062b0006, 0x062b09a7, 0x062be006, 0x062be9a7, 0x062cc006, 0x062cc9a7, + 0x062da006, 0x062da9a7, 0x062e8006, 0x062e89a7, 0x062f6006, 0x062f69a7, 0x06304006, 0x063049a7, 0x06312006, + 0x063129a7, 0x06320006, 0x063209a7, 0x0632e006, 0x0632e9a7, 0x0633c006, 0x0633c9a7, 0x0634a006, 0x0634a9a7, + 0x06358006, 0x063589a7, 0x06366006, 0x063669a7, 0x06374006, 0x063749a7, 0x06382006, 0x063829a7, 0x06390006, + 0x063909a7, 0x0639e006, 0x0639e9a7, 0x063ac006, 0x063ac9a7, 0x063ba006, 0x063ba9a7, 0x063c8006, 0x063c89a7, + 0x063d6006, 0x063d69a7, 0x063e4006, 0x063e49a7, 0x063f2006, 0x063f29a7, 0x06400006, 0x064009a7, 0x0640e006, + 0x0640e9a7, 0x0641c006, 0x0641c9a7, 0x0642a006, 0x0642a9a7, 0x06438006, 0x064389a7, 0x06446006, 0x064469a7, + 0x06454006, 0x064549a7, 0x06462006, 0x064629a7, 0x06470006, 0x064709a7, 0x0647e006, 0x0647e9a7, 0x0648c006, + 0x0648c9a7, 0x0649a006, 0x0649a9a7, 0x064a8006, 0x064a89a7, 0x064b6006, 0x064b69a7, 0x064c4006, 0x064c49a7, + 0x064d2006, 0x064d29a7, 0x064e0006, 0x064e09a7, 0x064ee006, 0x064ee9a7, 0x064fc006, 0x064fc9a7, 0x0650a006, + 0x0650a9a7, 0x06518006, 0x065189a7, 0x06526006, 0x065269a7, 0x06534006, 0x065349a7, 0x06542006, 0x065429a7, + 0x06550006, 0x065509a7, 0x0655e006, 0x0655e9a7, 0x0656c006, 0x0656c9a7, 0x0657a006, 0x0657a9a7, 0x06588006, + 0x065889a7, 0x06596006, 0x065969a7, 0x065a4006, 0x065a49a7, 0x065b2006, 0x065b29a7, 0x065c0006, 0x065c09a7, + 0x065ce006, 0x065ce9a7, 0x065dc006, 0x065dc9a7, 0x065ea006, 0x065ea9a7, 0x065f8006, 0x065f89a7, 0x06606006, + 0x066069a7, 0x06614006, 0x066149a7, 0x06622006, 0x066229a7, 0x06630006, 0x066309a7, 0x0663e006, 0x0663e9a7, + 0x0664c006, 0x0664c9a7, 0x0665a006, 0x0665a9a7, 0x06668006, 0x066689a7, 0x06676006, 0x066769a7, 0x06684006, + 0x066849a7, 0x06692006, 0x066929a7, 0x066a0006, 0x066a09a7, 0x066ae006, 0x066ae9a7, 0x066bc006, 0x066bc9a7, + 0x066ca006, 0x066ca9a7, 0x066d8006, 0x066d89a7, 0x066e6006, 0x066e69a7, 0x066f4006, 0x066f49a7, 0x06702006, + 0x067029a7, 0x06710006, 0x067109a7, 0x0671e006, 0x0671e9a7, 0x0672c006, 0x0672c9a7, 0x0673a006, 0x0673a9a7, + 0x06748006, 0x067489a7, 0x06756006, 0x067569a7, 0x06764006, 0x067649a7, 0x06772006, 0x067729a7, 0x06780006, + 0x067809a7, 0x0678e006, 0x0678e9a7, 0x0679c006, 0x0679c9a7, 0x067aa006, 0x067aa9a7, 0x067b8006, 0x067b89a7, + 0x067c6006, 0x067c69a7, 0x067d4006, 0x067d49a7, 0x067e2006, 0x067e29a7, 0x067f0006, 0x067f09a7, 0x067fe006, + 0x067fe9a7, 0x0680c006, 0x0680c9a7, 0x0681a006, 0x0681a9a7, 0x06828006, 0x068289a7, 0x06836006, 0x068369a7, + 0x06844006, 0x068449a7, 0x06852006, 0x068529a7, 0x06860006, 0x068609a7, 0x0686e006, 0x0686e9a7, 0x0687c006, + 0x0687c9a7, 0x0688a006, 0x0688a9a7, 0x06898006, 0x068989a7, 0x068a6006, 0x068a69a7, 0x068b4006, 0x068b49a7, + 0x068c2006, 0x068c29a7, 0x068d0006, 0x068d09a7, 0x068de006, 0x068de9a7, 0x068ec006, 0x068ec9a7, 0x068fa006, + 0x068fa9a7, 0x06908006, 0x069089a7, 0x06916006, 0x069169a7, 0x06924006, 0x069249a7, 0x06932006, 0x069329a7, + 0x06940006, 0x069409a7, 0x0694e006, 0x0694e9a7, 0x0695c006, 0x0695c9a7, 0x0696a006, 0x0696a9a7, 0x06978006, + 0x069789a7, 0x06986006, 0x069869a7, 0x06994006, 0x069949a7, 0x069a2006, 0x069a29a7, 0x069b0006, 0x069b09a7, + 0x069be006, 0x069be9a7, 0x069cc006, 0x069cc9a7, 0x069da006, 0x069da9a7, 0x069e8006, 0x069e89a7, 0x069f6006, + 0x069f69a7, 0x06a04006, 0x06a049a7, 0x06a12006, 0x06a129a7, 0x06a20006, 0x06a209a7, 0x06a2e006, 0x06a2e9a7, + 0x06a3c006, 0x06a3c9a7, 0x06a4a006, 0x06a4a9a7, 0x06a58006, 0x06a589a7, 0x06a66006, 0x06a669a7, 0x06a74006, + 0x06a749a7, 0x06a82006, 0x06a829a7, 0x06a90006, 0x06a909a7, 0x06a9e006, 0x06a9e9a7, 0x06aac006, 0x06aac9a7, + 0x06aba006, 0x06aba9a7, 0x06ac8006, 0x06ac89a7, 0x06ad6006, 0x06ad69a7, 0x06ae4006, 0x06ae49a7, 0x06af2006, + 0x06af29a7, 0x06b00006, 0x06b009a7, 0x06b0e006, 0x06b0e9a7, 0x06b1c006, 0x06b1c9a7, 0x06b2a006, 0x06b2a9a7, + 0x06b38006, 0x06b389a7, 0x06b46006, 0x06b469a7, 0x06b54006, 0x06b549a7, 0x06b62006, 0x06b629a7, 0x06b70006, + 0x06b709a7, 0x06b7e006, 0x06b7e9a7, 0x06b8c006, 0x06b8c9a7, 0x06b9a006, 0x06b9a9a7, 0x06ba8006, 0x06ba89a7, + 0x06bb6006, 0x06bb69a7, 0x06bc4006, 0x06bc49a7, 0x06bd816c, 0x06be5b0b, 0x07d8f002, 0x07f000f2, 0x07f100f2, + 0x07f7f801, 0x07fcf012, 0x07ff80b1, 0x080fe802, 0x08170002, 0x081bb042, 0x08500822, 0x08502812, 0x08506032, + 0x0851c022, 0x0851f802, 0x08572812, 0x08692032, 0x08755812, 0x087a30a2, 0x087c1032, 0x0880000a, 0x08800802, + 0x0880100a, 0x0881c0e2, 0x08838002, 0x08839812, 0x0883f822, 0x0884100a, 0x0885802a, 0x08859832, 0x0885b81a, + 0x0885c812, 0x0885e808, 0x08861002, 0x08866808, 0x08880022, 0x08893842, 0x0889600a, 0x08896872, 0x088a281a, + 0x088b9802, 0x088c0012, 0x088c100a, 0x088d982a, 0x088db082, 0x088df81a, 0x088e1018, 0x088e4832, 0x088e700a, + 0x088e7802, 0x0891602a, 0x08917822, 0x0891901a, 0x0891a002, 0x0891a80a, 0x0891b012, 0x0891f002, 0x0896f802, + 0x0897002a, 0x08971872, 0x08980012, 0x0898101a, 0x0899d812, 0x0899f002, 0x0899f80a, 0x089a0002, 0x089a083a, + 0x089a381a, 0x089a582a, 0x089ab802, 0x089b101a, 0x089b3062, 0x089b8042, 0x08a1a82a, 0x08a1c072, 0x08a2001a, + 0x08a21022, 0x08a2280a, 0x08a23002, 0x08a2f002, 0x08a58002, 0x08a5881a, 0x08a59852, 0x08a5c80a, 0x08a5d002, + 0x08a5d81a, 0x08a5e802, 0x08a5f00a, 0x08a5f812, 0x08a6080a, 0x08a61012, 0x08ad7802, 0x08ad801a, 0x08ad9032, + 0x08adc03a, 0x08ade012, 0x08adf00a, 0x08adf812, 0x08aee012, 0x08b1802a, 0x08b19872, 0x08b1d81a, 0x08b1e802, + 0x08b1f00a, 0x08b1f812, 0x08b55802, 0x08b5600a, 0x08b56802, 0x08b5701a, 0x08b58052, 0x08b5b00a, 0x08b5b802, + 0x08b8e822, 0x08b91032, 0x08b9300a, 0x08b93842, 0x08c1602a, 0x08c17882, 0x08c1c00a, 0x08c1c812, 0x08c98002, + 0x08c9884a, 0x08c9b81a, 0x08c9d812, 0x08c9e80a, 0x08c9f002, 0x08c9f808, 0x08ca000a, 0x08ca0808, 0x08ca100a, + 0x08ca1802, 0x08ce882a, 0x08cea032, 0x08ced012, 0x08cee03a, 0x08cf0002, 0x08cf200a, 0x08d00892, 0x08d19852, + 0x08d1c80a, 0x08d1d008, 0x08d1d832, 0x08d23802, 0x08d28852, 0x08d2b81a, 0x08d2c822, 0x08d42058, 0x08d450c2, + 0x08d4b80a, 0x08d4c012, 0x08e1780a, 0x08e18062, 0x08e1c052, 0x08e1f00a, 0x08e1f802, 0x08e49152, 0x08e5480a, + 0x08e55062, 0x08e5880a, 0x08e59012, 0x08e5a00a, 0x08e5a812, 0x08e98852, 0x08e9d002, 0x08e9e012, 0x08e9f862, + 0x08ea3008, 0x08ea3802, 0x08ec504a, 0x08ec8012, 0x08ec981a, 0x08eca802, 0x08ecb00a, 0x08ecb802, 0x08f79812, + 0x08f7a81a, 0x09a18081, 0x0b578042, 0x0b598062, 0x0b7a7802, 0x0b7a8b6a, 0x0b7c7832, 0x0b7f2002, 0x0b7f801a, + 0x0de4e812, 0x0de50031, 0x0e7802d2, 0x0e798162, 0x0e8b2802, 0x0e8b300a, 0x0e8b3822, 0x0e8b680a, 0x0e8b7042, + 0x0e8b9871, 0x0e8bd872, 0x0e8c2862, 0x0e8d5032, 0x0e921022, 0x0ed00362, 0x0ed1db12, 0x0ed3a802, 0x0ed42002, + 0x0ed4d842, 0x0ed508e2, 0x0f000062, 0x0f004102, 0x0f00d862, 0x0f011812, 0x0f013042, 0x0f098062, 0x0f157002, + 0x0f176032, 0x0f468062, 0x0f4a2062, 0x0f8007f3, 0x0f8407f3, 0x0f886823, 0x0f897803, 0x0f8b6053, 0x0f8bf013, + 0x0f8c7003, 0x0f8c8893, 0x0f8d6b83, 0x0f8f3199, 0x0f9008e3, 0x0f90d003, 0x0f917803, 0x0f919083, 0x0f91e033, + 0x0f924ff3, 0x0f964ff3, 0x0f9a4ff3, 0x0f9e4b13, 0x0f9fd842, 0x0fa007f3, 0x0fa407f3, 0x0fa803d3, 0x0faa37f3, + 0x0fae37f3, 0x0fb23093, 0x0fb407f3, 0x0fbba0b3, 0x0fbeaaa3, 0x0fc06033, 0x0fc24073, 0x0fc2d053, 0x0fc44073, + 0x0fc57513, 0x0fc862e3, 0x0fc9e093, 0x0fca3ff3, 0x0fce3ff3, 0x0fd23ff3, 0x0fd63b83, 0x0fe007f3, 0x0fe407f3, + 0x0fe807f3, 0x0fec07f3, 0x0ff007f3, 0x0ff407f3, 0x0ff807f3, 0x0ffc07d3, 0x700001f1, 0x700105f2, 0x700407f1, + 0x700807f2, 0x700c06f2, 0x700f87f1, 0x701387f1, 0x701787f1, 0x701b87f1, 0x701f87f1, 0x702387f1, 0x702787f1, + 0x702b87f1, 0x702f87f1, 0x703387f1, 0x703787f1, 0x703b87f1, 0x703f87f1, 0x704387f1, 0x704787f1, 0x704b87f1, + 0x704f87f1, 0x705387f1, 0x705787f1, 0x705b87f1, 0x705f87f1, 0x706387f1, 0x706787f1, 0x706b87f1, 0x706f87f1, + 0x707387f1, 0x707787f1, 0x707b87f1, 0x707f80f1}; + +/// Returns the extended grapheme cluster bondary property of a code point. +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __property __get_property(const char32_t __code_point) noexcept { + // TODO FMT use std::ranges::upper_bound. + + // The algorithm searches for the upper bound of the range and, when found, + // steps back one entry. This algorithm is used since the code point can be + // anywhere in the range. After a lower bound is found the next step is to + // compare whether the code unit is indeed in the range. + // + // Since the entry contains a code unit, size, and property the code point + // being sought needs to be adjusted. Just shifting the code point to the + // proper position doesn't work; suppose an entry has property 0, size 1, + // and lower bound 3. This results in the entry 0x1810. + // When searching for code point 3 it will search for 0x1800, find 0x1810 + // and moves to the previous entry. Thus the lower bound value will never + // be found. + // The simple solution is to set the bits belonging to the property and + // size. Then the upper bound for code point 3 will return the entry after + // 0x1810. After moving to the previous entry the algorithm arrives at the + // correct entry. + ptrdiff_t __i = std::upper_bound(__entries, std::end(__entries), (__code_point << 11) | 0x7ffu) - __entries; + if (__i == 0) + return __property::__none; + + --__i; + uint32_t __upper_bound = (__entries[__i] >> 11) + ((__entries[__i] >> 4) & 0x7f); + if (__code_point <= __upper_bound) + return static_cast<__property>(__entries[__i] & 0xf); + + return __property::__none; +} + +} // namespace __extended_grapheme_custer_property_boundary + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H diff --git a/contrib/llvm-project/libcxx/include/__format/formatter_integral.h b/contrib/llvm-project/libcxx/include/__format/formatter_integral.h index d6fa5ec18eb8..b9ed5fe80f7f 100644 --- a/contrib/llvm-project/libcxx/include/__format/formatter_integral.h +++ b/contrib/llvm-project/libcxx/include/__format/formatter_integral.h @@ -343,7 +343,7 @@ __format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications< if (__specs.__std_.__locale_specific_form_) { const auto& __np = use_facet<numpunct<_CharT>>(__ctx.locale()); basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename(); - return __formatter::__write_unicode_no_precision(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); + return __formatter::__write_string_no_precision(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); } # endif basic_string_view<_CharT> __str = diff --git a/contrib/llvm-project/libcxx/include/__format/formatter_output.h b/contrib/llvm-project/libcxx/include/__format/formatter_output.h index c59cbbeeb5dd..e09534c41dff 100644 --- a/contrib/llvm-project/libcxx/include/__format/formatter_output.h +++ b/contrib/llvm-project/libcxx/include/__format/formatter_output.h @@ -17,6 +17,7 @@ #include <__config> #include <__format/formatter.h> #include <__format/parser_std_format_spec.h> +#include <__format/unicode.h> #include <__utility/move.h> #include <__utility/unreachable.h> #include <cstddef> @@ -59,8 +60,8 @@ struct _LIBCPP_TYPE_VIS __padding_size_result { _LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result __padding_size(size_t __size, size_t __width, __format_spec::__alignment __align) { _LIBCPP_ASSERT(__width > __size, "don't call this function when no padding is required"); - _LIBCPP_ASSERT(__align != __format_spec::__alignment::__zero_padding, - "the caller should have handled the zero-padding"); + _LIBCPP_ASSERT( + __align != __format_spec::__alignment::__zero_padding, "the caller should have handled the zero-padding"); size_t __fill = __width - __size; switch (__align) { @@ -75,7 +76,7 @@ __padding_size(size_t __size, size_t __width, __format_spec::__alignment __align // __before = floor(__fill, 2); // __after = ceil(__fill, 2); size_t __before = __fill / 2; - size_t __after = __fill - __before; + size_t __after = __fill - __before; return {__before, __after}; } case __format_spec::__alignment::__default: @@ -173,10 +174,12 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, c /// conversion, which means the [\a __first, \a __last) always contains elements /// of the type \c char. template <class _CharT, class _ParserCharT> -_LIBCPP_HIDE_FROM_ABI auto __write(const _CharT* __first, const _CharT* __last, - output_iterator<const _CharT&> auto __out_it, - __format_spec::__parsed_specifications<_ParserCharT> __specs, ptrdiff_t __size) - -> decltype(__out_it) { +_LIBCPP_HIDE_FROM_ABI auto __write( + const _CharT* __first, + const _CharT* __last, + output_iterator<const _CharT&> auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs, + ptrdiff_t __size) -> decltype(__out_it) { _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); if (__size >= __specs.__width_) @@ -189,6 +192,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write(const _CharT* __first, const _CharT* __last, } /// \overload +/// /// Calls the function above where \a __size = \a __last - \a __first. template <class _CharT, class _ParserCharT> _LIBCPP_HIDE_FROM_ABI auto __write(const _CharT* __first, const _CharT* __last, @@ -243,77 +247,56 @@ _LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros( return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); } -# ifndef _LIBCPP_HAS_NO_UNICODE +/// Writes a string using format's width estimation algorithm. +/// +/// \pre !__specs.__has_precision() +/// +/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the +/// input is ASCII. template <class _CharT> -_LIBCPP_HIDE_FROM_ABI auto __write_unicode_no_precision(basic_string_view<_CharT> __str, - output_iterator<const _CharT&> auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__out_it) { +_LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision( + basic_string_view<_CharT> __str, + output_iterator<const _CharT&> auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + _LIBCPP_ASSERT(!__specs.__has_precision(), "use __write_string"); - _LIBCPP_ASSERT(!__specs.__has_precision(), "use __write_unicode"); // No padding -> copy the string if (!__specs.__has_width()) return _VSTD::copy(__str.begin(), __str.end(), _VSTD::move(__out_it)); - // Non Unicode part larger than width -> copy the string - auto __last = __format_spec::__detail::__estimate_column_width_fast(__str.begin(), __str.end()); - ptrdiff_t __size = __last - __str.begin(); - if (__size >= __specs.__width_) - return _VSTD::copy(__str.begin(), __str.end(), _VSTD::move(__out_it)); - - // Is there a non Unicode part? - if (__last != __str.end()) { - // Non Unicode and Unicode part larger than width -> copy the string - __format_spec::__detail::__column_width_result __column_width = - __format_spec::__detail::__estimate_column_width(__last, __str.end(), __specs.__width_); - __size += __column_width.__width; // Note this new size is used when __size < __specs.__width_ - if (__size >= __specs.__width_) - return _VSTD::copy(__str.begin(), __str.end(), _VSTD::move(__out_it)); - } + // Note when the estimated width is larger than size there's no padding. So + // there's no reason to get the real size when the estimate is larger than or + // equal to the minimum field width. + size_t __size = + __format_spec::__estimate_column_width(__str, __specs.__width_, __format_spec::__column_width_rounding::__up) + .__width_; return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); } -# endif template <class _CharT> -_LIBCPP_HIDE_FROM_ABI auto __write_unicode(basic_string_view<_CharT> __str, - output_iterator<const _CharT&> auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__out_it) { -# ifndef _LIBCPP_HAS_NO_UNICODE - if (!__specs.__has_precision()) - return __formatter::__write_unicode_no_precision(__str, _VSTD::move(__out_it), __specs); - - // Non unicode part larger than precision -> truncate the output and use the normal write operation. - auto __last = __format_spec::__detail::__estimate_column_width_fast(__str.begin(), __str.end()); - ptrdiff_t __size = __last - __str.begin(); - if (__size >= __specs.__precision_) - return __formatter::__write(__str.begin(), __str.begin() + __specs.__precision_, _VSTD::move(__out_it), __specs, - __specs.__precision_); - - // No non Unicode part, implies __size < __specs.__precision_ -> use normal write operation - if (__last == __str.end()) - return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __str.size()); - - __format_spec::__detail::__column_width_result __column_width = - __format_spec::__detail::__estimate_column_width(__last, __str.end(), __specs.__precision_ - __size); - __size += __column_width.__width; - // Truncate the output - if (__column_width.__ptr != __str.end()) - __str.remove_suffix(__str.end() - __column_width.__ptr); +_LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __precision) { + __format_spec::__column_width_result<_CharT> __result = + __format_spec::__estimate_column_width(__str, __precision, __format_spec::__column_width_rounding::__down); + __str = basic_string_view<_CharT>{__str.begin(), __result.__last_}; + return __result.__width_; +} - return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); +/// Writes a string using format's width estimation algorithm. +/// +/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the +/// input is ASCII. +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI auto __write_string( + basic_string_view<_CharT> __str, + output_iterator<const _CharT&> auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + if (!__specs.__has_precision()) + return __formatter::__write_string_no_precision(__str, _VSTD::move(__out_it), __specs); -# else - if (__specs.__has_precision()) { - ptrdiff_t __size = __str.size(); - if (__size > __specs.__precision_) - return __formatter::__write(__str.begin(), __str.begin() + __specs.__precision_, _VSTD::move(__out_it), __specs, - __specs.__precision_); - } - return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __str.size()); + int __size = __formatter::__truncate(__str, __specs.__precision_); -# endif + return __write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); } } // namespace __formatter diff --git a/contrib/llvm-project/libcxx/include/__format/formatter_string.h b/contrib/llvm-project/libcxx/include/__format/formatter_string.h index 139c05e58c28..71bda4fcded1 100644 --- a/contrib/llvm-project/libcxx/include/__format/formatter_string.h +++ b/contrib/llvm-project/libcxx/include/__format/formatter_string.h @@ -40,7 +40,7 @@ public: } _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT> __str, auto& __ctx) const -> decltype(__ctx.out()) { - return __formatter::__write_unicode(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); + return __formatter::__write_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); } __format_spec::__parser<_CharT> __parser_; @@ -69,7 +69,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const _CharT*, // TODO FMT Implement these improvements. __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); if (__specs.__has_width() || __specs.__has_precision()) - return __formatter::__write_unicode(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); + return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); // No formatting required, copy the string to the output. auto __out_it = __ctx.out(); diff --git a/contrib/llvm-project/libcxx/include/__format/parser_std_format_spec.h b/contrib/llvm-project/libcxx/include/__format/parser_std_format_spec.h index 034fc55a44dc..1425a953ebaa 100644 --- a/contrib/llvm-project/libcxx/include/__format/parser_std_format_spec.h +++ b/contrib/llvm-project/libcxx/include/__format/parser_std_format_spec.h @@ -25,10 +25,12 @@ #include <__format/format_error.h> #include <__format/format_parse_context.h> #include <__format/format_string.h> +#include <__format/unicode.h> #include <__variant/monostate.h> #include <bit> #include <concepts> #include <cstdint> +#include <string_view> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -91,462 +93,6 @@ __substitute_arg_id(basic_format_arg<_Context> __format_arg) { __format_arg); } -/** Helper struct returned from @ref __get_string_alignment. */ -template <class _CharT> -struct _LIBCPP_TEMPLATE_VIS __string_alignment { - /** Points beyond the last character to write to the output. */ - const _CharT* __last; - /** - * The estimated number of columns in the output or 0. - * - * Only when the output needs to be aligned it's required to know the exact - * number of columns in the output. So if the formatted output has only a - * minimum width the exact size isn't important. It's only important to know - * the minimum has been reached. The minimum width is the width specified in - * the format-spec. - * - * For example in this code @code std::format("{:10}", MyString); @endcode - * the width estimation can stop once the algorithm has determined the output - * width is 10 columns. - * - * So if: - * * @ref __align == @c true the @ref __size is the estimated number of - * columns required. - * * @ref __align == @c false the @ref __size is the estimated number of - * columns required or 0 when the estimation algorithm stopped prematurely. - */ - ptrdiff_t __size; - /** - * Does the output need to be aligned. - * - * When alignment is needed the output algorithm needs to add the proper - * padding. Else the output algorithm just needs to copy the input up to - * @ref __last. - */ - bool __align; -}; - -#ifndef _LIBCPP_HAS_NO_UNICODE -namespace __detail { - -/** - * Unicode column width estimates. - * - * Unicode can be stored in several formats: UTF-8, UTF-16, and UTF-32. - * Depending on format the relation between the number of code units stored and - * the number of output columns differs. The first relation is the number of - * code units forming a code point. (The text assumes the code units are - * unsigned.) - * - UTF-8 The number of code units is between one and four. The first 127 - * Unicode code points match the ASCII character set. When the highest bit is - * set it means the code point has more than one code unit. - * - UTF-16: The number of code units is between 1 and 2. When the first - * code unit is in the range [0xd800,0xdfff) it means the code point uses two - * code units. - * - UTF-32: The number of code units is always one. - * - * The code point to the number of columns isn't well defined. The code uses the - * estimations defined in [format.string.std]/11. This list might change in the - * future. - * - * The algorithm of @ref __get_string_alignment uses two different scanners: - * - The simple scanner @ref __estimate_column_width_fast. This scanner assumes - * 1 code unit is 1 column. This scanner stops when it can't be sure the - * assumption is valid: - * - UTF-8 when the code point is encoded in more than 1 code unit. - * - UTF-16 and UTF-32 when the first multi-column code point is encountered. - * (The code unit's value is lower than 0xd800 so the 2 code unit encoding - * is irrelevant for this scanner.) - * Due to these assumptions the scanner is faster than the full scanner. It - * can process all text only containing ASCII. For UTF-16/32 it can process - * most (all?) European languages. (Note the set it can process might be - * reduced in the future, due to updates in the scanning rules.) - * - The full scanner @ref __estimate_column_width. This scanner, if needed, - * converts multiple code units into one code point then converts the code - * point to a column width. - * - * See also: - * - [format.string.general]/11 - * - https://en.wikipedia.org/wiki/UTF-8#Encoding - * - https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - */ - -/** - * The first 2 column code point. - * - * This is the point where the fast UTF-16/32 scanner needs to stop processing. - */ -inline constexpr uint32_t __two_column_code_point = 0x1100; - -/** Helper concept for an UTF-8 character type. */ -template <class _CharT> -concept __utf8_character = same_as<_CharT, char> || same_as<_CharT, char8_t>; - -/** Helper concept for an UTF-16 character type. */ -template <class _CharT> -concept __utf16_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) || same_as<_CharT, char16_t>; - -/** Helper concept for an UTF-32 character type. */ -template <class _CharT> -concept __utf32_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) || same_as<_CharT, char32_t>; - -/** Helper concept for an UTF-16 or UTF-32 character type. */ -template <class _CharT> -concept __utf16_or_32_character = __utf16_character<_CharT> || __utf32_character<_CharT>; - -/** - * Converts a code point to the column width. - * - * The estimations are conforming to [format.string.general]/11 - * - * This version expects a value less than 0x1'0000, which is a 3-byte UTF-8 - * character. - */ -_LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width_3(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c < 0x10000, - "Use __column_width_4 or __column_width for larger values"); - - // clang-format off - return 1 + (__c >= 0x1100 && (__c <= 0x115f || - (__c >= 0x2329 && (__c <= 0x232a || - (__c >= 0x2e80 && (__c <= 0x303e || - (__c >= 0x3040 && (__c <= 0xa4cf || - (__c >= 0xac00 && (__c <= 0xd7a3 || - (__c >= 0xf900 && (__c <= 0xfaff || - (__c >= 0xfe10 && (__c <= 0xfe19 || - (__c >= 0xfe30 && (__c <= 0xfe6f || - (__c >= 0xff00 && (__c <= 0xff60 || - (__c >= 0xffe0 && (__c <= 0xffe6 - )))))))))))))))))))); - // clang-format on -} - -/** - * @overload - * - * This version expects a value greater than or equal to 0x1'0000, which is a - * 4-byte UTF-8 character. - */ -_LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width_4(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c >= 0x10000, - "Use __column_width_3 or __column_width for smaller values"); - - // clang-format off - return 1 + (__c >= 0x1'f300 && (__c <= 0x1'f64f || - (__c >= 0x1'f900 && (__c <= 0x1'f9ff || - (__c >= 0x2'0000 && (__c <= 0x2'fffd || - (__c >= 0x3'0000 && (__c <= 0x3'fffd - )))))))); - // clang-format on -} - -/** - * @overload - * - * The general case, accepting all values. - */ -_LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width(uint32_t __c) noexcept { - if (__c < 0x10000) - return __column_width_3(__c); - - return __column_width_4(__c); -} - -/** - * Estimate the column width for the UTF-8 sequence using the fast algorithm. - */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__estimate_column_width_fast(const _CharT* __first, - const _CharT* __last) noexcept { - return _VSTD::find_if(__first, __last, - [](unsigned char __c) { return __c & 0x80; }); -} - -/** - * @overload - * - * The implementation for UTF-16/32. - */ -template <__utf16_or_32_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__estimate_column_width_fast(const _CharT* __first, - const _CharT* __last) noexcept { - return _VSTD::find_if(__first, __last, - [](uint32_t __c) { return __c >= 0x1100; }); -} - -template <class _CharT> -struct _LIBCPP_TEMPLATE_VIS __column_width_result { - /** The number of output columns. */ - size_t __width; - /** - * The last parsed element. - * - * This limits the original output to fit in the wanted number of columns. - */ - const _CharT* __ptr; -}; - -/** - * Small helper to determine the width of malformed Unicode. - * - * @note This function's only needed for UTF-8. During scanning UTF-8 there - * are multiple place where it can be detected that the Unicode is malformed. - * UTF-16 only requires 1 test and UTF-32 requires no testing. - */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width_malformed(const _CharT* __first, const _CharT* __last, - size_t __maximum, size_t __result) noexcept { - size_t __size = __last - __first; - size_t __n = _VSTD::min(__size, __maximum); - return {__result + __n, __first + __n}; -} - -/** - * Determines the number of output columns needed to render the input. - * - * @note When the scanner encounters malformed Unicode it acts as-if every code - * unit at the end of the input is one output column. It's expected the output - * terminal will replace these malformed code units with a one column - * replacement characters. - * - * @param __first Points to the first element of the input range. - * @param __last Points beyond the last element of the input range. - * @param __maximum The maximum number of output columns. The returned number - * of estimated output columns will not exceed this value. - */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - // Based on the number of leading 1 bits the number of code units in the - // code point can be determined. See - // https://en.wikipedia.org/wiki/UTF-8#Encoding - switch (_VSTD::countl_one(static_cast<unsigned char>(*__first))) { - case 0: // 1-code unit encoding: all 1 column - ++__result; - ++__first; - break; - - case 2: // 2-code unit encoding: all 1 column - // Malformed Unicode. - if (__last - __first < 2) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - __first += 2; - ++__result; - break; - - case 3: // 3-code unit encoding: either 1 or 2 columns - // Malformed Unicode. - if (__last - __first < 3) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - { - uint32_t __c = static_cast<unsigned char>(*__first++) & 0x0f; - __c <<= 6; - __c |= static_cast<unsigned char>(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast<unsigned char>(*__first++) & 0x3f; - __result += __column_width_3(__c); - if (__result > __maximum) - return {__result - 2, __first - 3}; - } - break; - case 4: // 4-code unit encoding: either 1 or 2 columns - // Malformed Unicode. - if (__last - __first < 4) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - { - uint32_t __c = static_cast<unsigned char>(*__first++) & 0x07; - __c <<= 6; - __c |= static_cast<unsigned char>(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast<unsigned char>(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast<unsigned char>(*__first++) & 0x3f; - __result += __column_width_4(__c); - if (__result > __maximum) - return {__result - 2, __first - 4}; - } - break; - default: - // Malformed Unicode. - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - } - - if (__result >= __maximum) - return {__result, __first}; - } - return {__result, __first}; -} - -template <__utf16_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - uint32_t __c = *__first; - // Is the code unit part of a surrogate pair? See - // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - if (__c >= 0xd800 && __c <= 0xDfff) { - // Malformed Unicode. - if (__last - __first < 2) [[unlikely]] - return {__result + 1, __first + 1}; - - __c -= 0xd800; - __c <<= 10; - __c += (*(__first + 1) - 0xdc00); - __c += 0x10000; - - __result += __column_width_4(__c); - if (__result > __maximum) - return {__result - 2, __first}; - __first += 2; - } else { - __result += __column_width_3(__c); - if (__result > __maximum) - return {__result - 2, __first}; - ++__first; - } - - if (__result >= __maximum) - return {__result, __first}; - } - - return {__result, __first}; -} - -template <__utf32_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - uint32_t __c = *__first; - __result += __column_width(__c); - - if (__result > __maximum) - return {__result - 2, __first}; - - ++__first; - if (__result >= __maximum) - return {__result, __first}; - } - - return {__result, __first}; -} - -} // namespace __detail - -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> -__get_string_alignment(const _CharT* __first, const _CharT* __last, - ptrdiff_t __width, ptrdiff_t __precision) noexcept { - _LIBCPP_ASSERT(__width != 0 || __precision != -1, - "The function has no effect and shouldn't be used"); - - // TODO FMT There might be more optimizations possible: - // If __precision == __format::__number_max and the encoding is: - // * UTF-8 : 4 * (__last - __first) >= __width - // * UTF-16 : 2 * (__last - __first) >= __width - // * UTF-32 : (__last - __first) >= __width - // In these cases it's certain the output is at least the requested width. - // It's unknown how often this happens in practice. For now the improvement - // isn't implemented. - - /* - * First assume there are no special Unicode code units in the input. - * - Apply the precision (this may reduce the size of the input). When - * __precison == -1 this step is omitted. - * - Scan for special code units in the input. - * If our assumption was correct the __pos will be at the end of the input. - */ - const ptrdiff_t __length = __last - __first; - const _CharT* __limit = - __first + - (__precision == -1 ? __length : _VSTD::min(__length, __precision)); - ptrdiff_t __size = __limit - __first; - const _CharT* __pos = - __detail::__estimate_column_width_fast(__first, __limit); - - if (__pos == __limit) - return {__limit, __size, __size < __width}; - - /* - * Our assumption was wrong, there are special Unicode code units. - * The range [__first, __pos) contains a set of code units with the - * following property: - * Every _CharT in the range will be rendered in 1 column. - * - * If there's no maximum width and the parsed size already exceeds the - * minimum required width. The real size isn't important. So bail out. - */ - if (__precision == -1 && (__pos - __first) >= __width) - return {__last, 0, false}; - - /* If there's a __precision, truncate the output to that width. */ - ptrdiff_t __prefix = __pos - __first; - if (__precision != -1) { - _LIBCPP_ASSERT(__precision > __prefix, "Logic error."); - auto __lengh_info = __detail::__estimate_column_width( - __pos, __last, __precision - __prefix); - __size = __lengh_info.__width + __prefix; - return {__lengh_info.__ptr, __size, __size < __width}; - } - - /* Else use __width to determine the number of required padding characters. */ - _LIBCPP_ASSERT(__width > __prefix, "Logic error."); - /* - * The column width is always one or two columns. For the precision the wanted - * column width is the maximum, for the width it's the minimum. Using the - * width estimation with its truncating behavior will result in the wrong - * result in the following case: - * - The last code unit processed requires two columns and exceeds the - * maximum column width. - * By increasing the __maximum by one avoids this issue. (It means it may - * pass one code point more than required to determine the proper result; - * that however isn't a problem for the algorithm.) - */ - size_t __maximum = 1 + __width - __prefix; - auto __lengh_info = - __detail::__estimate_column_width(__pos, __last, __maximum); - if (__lengh_info.__ptr != __last) { - // Consumed the width number of code units. The exact size of the string - // is unknown. We only know we don't need to align the output. - _LIBCPP_ASSERT(static_cast<ptrdiff_t>(__lengh_info.__width + __prefix) >= - __width, - "Logic error"); - return {__last, 0, false}; - } - - __size = __lengh_info.__width + __prefix; - return {__last, __size, __size < __width}; -} -#else // _LIBCPP_HAS_NO_UNICODE -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> -__get_string_alignment(const _CharT* __first, const _CharT* __last, - ptrdiff_t __width, ptrdiff_t __precision) noexcept { - const ptrdiff_t __length = __last - __first; - const _CharT* __limit = - __first + - (__precision == -1 ? __length : _VSTD::min(__length, __precision)); - ptrdiff_t __size = __limit - __first; - return {__limit, __size, __size < __width}; -} -#endif // _LIBCPP_HAS_NO_UNICODE - /// These fields are a filter for which elements to parse. /// /// They default to false so when a new field is added it needs to be opted in @@ -1143,6 +689,212 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_pointer(__format_spe } } +template <class _CharT> +struct __column_width_result { + /// The number of output columns. + size_t __width_; + /// One beyond the last code unit used in the estimation. + /// + /// This limits the original output to fit in the wanted number of columns. + const _CharT* __last_; +}; + +/// Since a column width can be two it's possible that the requested column +/// width can't be achieved. Depending on the intended usage the policy can be +/// selected. +/// - When used as precision the maximum width may not be exceeded and the +/// result should be "rounded down" to the previous boundary. +/// - When used as a width we're done once the minimum is reached, but +/// exceeding is not an issue. Rounding down is an issue since that will +/// result in writing fill characters. Therefore the result needs to be +/// "rounded up". +enum class __column_width_rounding { __down, __up }; + +# ifndef _LIBCPP_HAS_NO_UNICODE + +namespace __detail { + +/// Converts a code point to the column width. +/// +/// The estimations are conforming to [format.string.general]/11 +/// +/// This version expects a value less than 0x1'0000, which is a 3-byte UTF-8 +/// character. +_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_3(uint32_t __c) noexcept { + _LIBCPP_ASSERT(__c < 0x10000, "Use __column_width_4 or __column_width for larger values"); + + // clang-format off + return 1 + (__c >= 0x1100 && (__c <= 0x115f || + (__c >= 0x2329 && (__c <= 0x232a || + (__c >= 0x2e80 && (__c <= 0x303e || + (__c >= 0x3040 && (__c <= 0xa4cf || + (__c >= 0xac00 && (__c <= 0xd7a3 || + (__c >= 0xf900 && (__c <= 0xfaff || + (__c >= 0xfe10 && (__c <= 0xfe19 || + (__c >= 0xfe30 && (__c <= 0xfe6f || + (__c >= 0xff00 && (__c <= 0xff60 || + (__c >= 0xffe0 && (__c <= 0xffe6 + )))))))))))))))))))); + // clang-format on +} + +/// @overload +/// +/// This version expects a value greater than or equal to 0x1'0000, which is a +/// 4-byte UTF-8 character. +_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_4(uint32_t __c) noexcept { + _LIBCPP_ASSERT(__c >= 0x10000, "Use __column_width_3 or __column_width for smaller values"); + + // clang-format off + return 1 + (__c >= 0x1'f300 && (__c <= 0x1'f64f || + (__c >= 0x1'f900 && (__c <= 0x1'f9ff || + (__c >= 0x2'0000 && (__c <= 0x2'fffd || + (__c >= 0x3'0000 && (__c <= 0x3'fffd + )))))))); + // clang-format on +} + +/// @overload +/// +/// The general case, accepting all values. +_LIBCPP_HIDE_FROM_ABI constexpr int __column_width(uint32_t __c) noexcept { + if (__c < 0x10000) + return __detail::__column_width_3(__c); + + return __detail::__column_width_4(__c); +} + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width_grapheme_clustering( + const _CharT* __first, const _CharT* __last, size_t __maximum, __column_width_rounding __rounding) noexcept { + __unicode::__extended_grapheme_cluster_view<_CharT> __view{__first, __last}; + + __column_width_result<_CharT> __result{0, __first}; + while (__result.__last_ != __last && __result.__width_ <= __maximum) { + typename __unicode::__extended_grapheme_cluster_view<_CharT>::__cluster __cluster = __view.__consume(); + int __width = __detail::__column_width(__cluster.__code_point_); + + // When the next entry would exceed the maximum width the previous width + // might be returned. For example when a width of 100 is requested the + // returned width might be 99, since the next code point has an estimated + // column width of 2. This depends on the rounding flag. + // When the maximum is exceeded the loop will abort the next iteration. + if (__rounding == __column_width_rounding::__down && __result.__width_ + __width > __maximum) + return __result; + + __result.__width_ += __width; + __result.__last_ = __cluster.__last_; + } + + return __result; +} + +} // namespace __detail + +// Unicode can be stored in several formats: UTF-8, UTF-16, and UTF-32. +// Depending on format the relation between the number of code units stored and +// the number of output columns differs. The first relation is the number of +// code units forming a code point. (The text assumes the code units are +// unsigned.) +// - UTF-8 The number of code units is between one and four. The first 127 +// Unicode code points match the ASCII character set. When the highest bit is +// set it means the code point has more than one code unit. +// - UTF-16: The number of code units is between 1 and 2. When the first +// code unit is in the range [0xd800,0xdfff) it means the code point uses two +// code units. +// - UTF-32: The number of code units is always one. +// +// The code point to the number of columns is specified in +// [format.string.std]/11. This list might change in the future. +// +// Another thing to be taken into account is Grapheme clustering. This means +// that in some cases multiple code points are combined one element in the +// output. For example: +// - an ASCII character with a combined diacritical mark +// - an emoji with a skin tone modifier +// - a group of combined people emoji to create a family +// - a combination of flag emoji +// +// See also: +// - [format.string.general]/11 +// - https://en.wikipedia.org/wiki/UTF-8#Encoding +// - https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_ascii(char32_t __c) { return __c < 0x80; } + +/// Determines the number of output columns needed to render the input. +/// +/// \note When the scanner encounters malformed Unicode it acts as-if every +/// code unit is a one column code point. Typically a terminal uses the same +/// strategy and replaces every malformed code unit with a one column +/// replacement character. +/// +/// \param __first Points to the first element of the input range. +/// \param __last Points beyond the last element of the input range. +/// \param __maximum The maximum number of output columns. The returned number +/// of estimated output columns will not exceed this value. +/// \param __rounding Selects the rounding method. +/// \c __down result.__width_ <= __maximum +/// \c __up result.__width_ <= __maximum + 1 +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width( + basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding __rounding) noexcept { + // The width estimation is done in two steps: + // - Quickly process for the ASCII part. ASCII has the following properties + // - One code unit is one code point + // - Every code point has an estimated width of one + // - When needed it will a Unicode Grapheme clustering algorithm to find + // the proper place for truncation. + + if (__str.empty() || __maximum == 0) + return {0, __str.begin()}; + + // ASCII has one caveat; when an ASCII character is followed by a non-ASCII + // character they might be part of an extended grapheme cluster. For example: + // an ASCII letter and a COMBINING ACUTE ACCENT + // The truncate should happen after the COMBINING ACUTE ACCENT. Therefore we + // need to scan one code unit beyond the requested precision. When this code + // unit is non-ASCII we omit the current code unit and let the Grapheme + // clustering algorithm do its work. + const _CharT* __it = __str.begin(); + if (__is_ascii(*__it)) { + do { + --__maximum; + ++__it; + if (__it == __str.end()) + return {__str.size(), __str.end()}; + + if (__maximum == 0) { + if (__is_ascii(*__it)) + return {static_cast<size_t>(__it - __str.begin()), __it}; + + break; + } + } while (__is_ascii(*__it)); + --__it; + ++__maximum; + } + + ptrdiff_t __ascii_size = __it - __str.begin(); + __column_width_result __result = + __detail::__estimate_column_width_grapheme_clustering(__it, __str.end(), __maximum, __rounding); + + __result.__width_ += __ascii_size; + return __result; +} +# else // !defined(_LIBCPP_HAS_NO_UNICODE) +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +__estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding) noexcept { + // When Unicode isn't supported assume ASCII and every code unit is one code + // point. In ASCII the estimated column width is always one. Thus there's no + // need for rounding. + size_t __width_ = _VSTD::min(__str.size(), __maximum); + return {__width_, __str.begin() + __width_}; +} + +# endif // !defined(_LIBCPP_HAS_NO_UNICODE) + } // namespace __format_spec #endif //_LIBCPP_STD_VER > 17 diff --git a/contrib/llvm-project/libcxx/include/__format/unicode.h b/contrib/llvm-project/libcxx/include/__format/unicode.h new file mode 100644 index 000000000000..3316217f4a1e --- /dev/null +++ b/contrib/llvm-project/libcxx/include/__format/unicode.h @@ -0,0 +1,339 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_UNICODE_H +#define _LIBCPP___FORMAT_UNICODE_H + +#include <__assert> +#include <__config> +#include <__format/extended_grapheme_cluster_table.h> +#include <__utility/unreachable.h> +#include <bit> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +# ifndef _LIBCPP_HAS_NO_UNICODE + +/// Implements the grapheme cluster boundary rules +/// +/// These rules are used to implement format's width estimation as stated in +/// [format.string.std]/11 +/// +/// The Standard refers to UAX \#29 for Unicode 12.0.0 +/// https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules +/// +/// The data tables used are +/// https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt +/// https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt +/// https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt (for testing only) + +namespace __unicode { + +inline constexpr char32_t __replacement_character = U'\ufffd'; + +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(const char* __char, int __count) { + do { + if ((*__char & 0b1000'0000) != 0b1000'0000) + return false; + --__count; + ++__char; + } while (__count); + return true; +} + +/// Helper class to extract a code unit from a Unicode character range. +/// +/// The stored range is a view. There are multiple specialization for different +/// character types. +template <class _CharT> +class __code_point_view; + +/// UTF-8 specialization. +template <> +class __code_point_view<char> { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const char* __first, const char* __last) + : __first_(__first), __last_(__last) {} + + _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } + _LIBCPP_HIDE_FROM_ABI constexpr const char* __position() const noexcept { return __first_; } + + _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + // Based on the number of leading 1 bits the number of code units in the + // code point can be determined. See + // https://en.wikipedia.org/wiki/UTF-8#Encoding + switch (_VSTD::countl_one(static_cast<unsigned char>(*__first_))) { + case 0: + return *__first_++; + + case 2: + if (__last_ - __first_ < 2 || !__unicode::__is_continuation(__first_ + 1, 1)) [[unlikely]] + break; + else { + char32_t __value = static_cast<unsigned char>(*__first_++) & 0x1f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + return __value; + } + + case 3: + if (__last_ - __first_ < 3 || !__unicode::__is_continuation(__first_ + 1, 2)) [[unlikely]] + break; + else { + char32_t __value = static_cast<unsigned char>(*__first_++) & 0x0f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + return __value; + } + + case 4: + if (__last_ - __first_ < 4 || !__unicode::__is_continuation(__first_ + 1, 3)) [[unlikely]] + break; + else { + char32_t __value = static_cast<unsigned char>(*__first_++) & 0x07; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + return __value; + } + } + // An invalid number of leading ones can be garbage or a code unit in the + // middle of a code point. By consuming one code unit the parser may get + // "in sync" after a few code units. + ++__first_; + return __replacement_character; + } + +private: + const char* __first_; + const char* __last_; +}; + +# ifndef TEST_HAS_NO_WIDE_CHARACTERS +/// This specialization depends on the size of wchar_t +/// - 2 UTF-16 (for example Windows and AIX) +/// - 4 UTF-32 (for example Linux) +template <> +class __code_point_view<wchar_t> { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const wchar_t* __first, const wchar_t* __last) + : __first_(__first), __last_(__last) {} + + _LIBCPP_HIDE_FROM_ABI constexpr const wchar_t* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } + + _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + if constexpr (sizeof(wchar_t) == 2) { + char32_t __result = *__first_++; + // Is the code unit part of a surrogate pair? See + // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + if (__result >= 0xd800 && __result <= 0xDfff) { + // Malformed Unicode. + if (__first_ == __last_) [[unlikely]] + return __replacement_character; + + __result -= 0xd800; + __result <<= 10; + __result += *__first_++ - 0xdc00; + __result += 0x10000; + } + return __result; + + } else if constexpr (sizeof(wchar_t) == 4) { + char32_t __result = *__first_++; + if (__result > 0x10FFFF) [[unlikely]] + return __replacement_character; + return __result; + } else { + // TODO FMT P2593R0 Use static_assert(false, "sizeof(wchar_t) has a not implemented value"); + _LIBCPP_ASSERT(sizeof(wchar_t) == 0, "sizeof(wchar_t) has a not implemented value"); + __libcpp_unreachable(); + } + } + +private: + const wchar_t* __first_; + const wchar_t* __last_; +}; +# endif + +_LIBCPP_HIDE_FROM_ABI constexpr bool __at_extended_grapheme_cluster_break( + bool& __ri_break_allowed, + bool __has_extened_pictographic, + __extended_grapheme_custer_property_boundary::__property __prev, + __extended_grapheme_custer_property_boundary::__property __next) { + using __extended_grapheme_custer_property_boundary::__property; + + __has_extened_pictographic |= __prev == __property::__Extended_Pictographic; + + // https://www.unicode.org/reports/tr29/tr29-39.html#Grapheme_Cluster_Boundary_Rules + + // *** Break at the start and end of text, unless the text is empty. *** + + _LIBCPP_ASSERT(__prev != __property::__sot, "should be handled in the constructor"); // GB1 + _LIBCPP_ASSERT(__prev != __property::__eot, "should be handled by our caller"); // GB2 + + // *** Do not break between a CR and LF. Otherwise, break before and after controls. *** + if (__prev == __property::__CR && __next == __property::__LF) // GB3 + return false; + + if (__prev == __property::__Control || __prev == __property::__CR || __prev == __property::__LF) // GB4 + return true; + + if (__next == __property::__Control || __next == __property::__CR || __next == __property::__LF) // GB5 + return true; + + // *** Do not break Hangul syllable sequences. *** + if (__prev == __property::__L && + (__next == __property::__L || __next == __property::__V || __next == __property::__LV || + __next == __property::__LVT)) // GB6 + return false; + + if ((__prev == __property::__LV || __prev == __property::__V) && + (__next == __property::__V || __next == __property::__T)) // GB7 + return false; + + if ((__prev == __property::__LVT || __prev == __property::__T) && __next == __property::__T) // GB8 + return false; + + // *** Do not break before extending characters or ZWJ. *** + if (__next == __property::__Extend || __next == __property::__ZWJ) + return false; // GB9 + + // *** Do not break before SpacingMarks, or after Prepend characters. *** + if (__next == __property::__SpacingMark) // GB9a + return false; + + if (__prev == __property::__Prepend) // GB9b + return false; + + // *** Do not break within emoji modifier sequences or emoji zwj sequences. *** + + // GB11 \p{Extended_Pictographic} Extend* ZWJ x \p{Extended_Pictographic} + // + // Note that several parts of this rule are matched by GB9: Any x (Extend | ZWJ) + // - \p{Extended_Pictographic} x Extend + // - Extend x Extend + // - \p{Extended_Pictographic} x ZWJ + // - Extend x ZWJ + // + // So the only case left to test is + // - \p{Extended_Pictographic}' x ZWJ x \p{Extended_Pictographic} + // where \p{Extended_Pictographic}' is stored in __has_extened_pictographic + if (__has_extened_pictographic && __prev == __property::__ZWJ && __next == __property::__Extended_Pictographic) + return false; + + // *** Do not break within emoji flag sequences *** + + // That is, do not break between regional indicator (RI) symbols if there + // is an odd number of RI characters before the break point. + + if (__prev == __property::__Regional_Indicator && __next == __property::__Regional_Indicator) { // GB12 + GB13 + __ri_break_allowed = !__ri_break_allowed; + if (__ri_break_allowed) + return true; + + return false; + } + + // *** Otherwise, break everywhere. *** + return true; // GB999 +} + +/// Helper class to extract an extended grapheme cluster from a Unicode character range. +/// +/// This function is used to determine the column width of an extended grapheme +/// cluster. In order to do that only the first code point is evaluated. +/// Therefore only this code point is extracted. +template <class _CharT> +class __extended_grapheme_cluster_view { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(const _CharT* __first, const _CharT* __last) + : __code_point_view_(__first, __last), + __next_code_point_(__code_point_view_.__consume()), + __next_prop_(__extended_grapheme_custer_property_boundary::__get_property(__next_code_point_)) {} + + struct __cluster { + /// The first code point of the extended grapheme cluster. + /// + /// The first code point is used to estimate the width of the extended + /// grapheme cluster. + char32_t __code_point_; + + /// Points one beyond the last code unit in the extended grapheme cluster. + /// + /// It's expected the caller has the start position and thus can determine + /// the code unit range of the extended grapheme cluster. + const _CharT* __last_; + }; + + _LIBCPP_HIDE_FROM_ABI constexpr __cluster __consume() { + _LIBCPP_ASSERT( + __next_prop_ != __extended_grapheme_custer_property_boundary::__property::__eot, + "can't move beyond the end of input"); + char32_t __code_point = __next_code_point_; + if (!__code_point_view_.__at_end()) + return {__code_point, __get_break()}; + + __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; + return {__code_point, __code_point_view_.__position()}; + } + +private: + __code_point_view<_CharT> __code_point_view_; + + char32_t __next_code_point_; + __extended_grapheme_custer_property_boundary::__property __next_prop_; + + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __get_break() { + bool __ri_break_allowed = true; + bool __has_extened_pictographic = false; + while (true) { + const _CharT* __result = __code_point_view_.__position(); + __extended_grapheme_custer_property_boundary::__property __prev = __next_prop_; + if (__code_point_view_.__at_end()) { + __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; + return __result; + } + __next_code_point_ = __code_point_view_.__consume(); + __next_prop_ = __extended_grapheme_custer_property_boundary::__get_property(__next_code_point_); + + __has_extened_pictographic |= + __prev == __extended_grapheme_custer_property_boundary::__property::__Extended_Pictographic; + + if (__at_extended_grapheme_cluster_break(__ri_break_allowed, __has_extened_pictographic, __prev, __next_prop_)) + return __result; + } + } +}; + +} // namespace __unicode + +# endif // _LIBCPP_HAS_NO_UNICODE + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_UNICODE_H diff --git a/contrib/llvm-project/libcxx/include/__iterator/reverse_iterator.h b/contrib/llvm-project/libcxx/include/__iterator/reverse_iterator.h index a915609dbe33..7f4ef3c3d503 100644 --- a/contrib/llvm-project/libcxx/include/__iterator/reverse_iterator.h +++ b/contrib/llvm-project/libcxx/include/__iterator/reverse_iterator.h @@ -332,41 +332,16 @@ using _ReverseWrapper = reverse_iterator<reverse_iterator<_Iter> >; template <class _Iter, bool __b> struct __unwrap_iter_impl<_ReverseWrapper<_Iter>, __b> { - static _LIBCPP_CONSTEXPR decltype(std::__unwrap_iter(std::declval<_Iter>())) - __apply(_ReverseWrapper<_Iter> __i) _NOEXCEPT { - return std::__unwrap_iter(__i.base().base()); - } -}; - -template <class _OrigIter, class _UnwrappedIter> -struct __rewrap_iter_impl<_ReverseWrapper<_OrigIter>, _UnwrappedIter> { - template <class _Iter> - struct _ReverseWrapperCount { - static _LIBCPP_CONSTEXPR const size_t value = 1; - }; - - template <class _Iter> - struct _ReverseWrapperCount<_ReverseWrapper<_Iter> > { - static _LIBCPP_CONSTEXPR const size_t value = 1 + _ReverseWrapperCount<_Iter>::value; - }; - - template <size_t _RewrapCount, class _OIter, class _UIter, __enable_if_t<_RewrapCount != 0, int> = 0> - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _ReverseWrapper<_OIter> __rewrap(_ReverseWrapper<_OIter> __iter1, - _UIter __iter2) { - return _ReverseWrapper<_OIter>( - reverse_iterator<_OIter>(__rewrap<_RewrapCount - 1>(__iter1.base().base(), __iter2))); - } + using _UnwrappedIter = decltype(__unwrap_iter_impl<_Iter>::__unwrap(std::declval<_Iter>())); - template <size_t _RewrapCount, class _OIter, class _UIter, __enable_if_t<_RewrapCount == 0, int> = 0> - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR decltype(std::__rewrap_iter(std::declval<_OIter>(), - std::declval<_UIter>())) - __rewrap(_OIter __iter1, _UIter __iter2) { - return std::__rewrap_iter(__iter1, __iter2); + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ReverseWrapper<_Iter> + __rewrap(_ReverseWrapper<_Iter> __orig_iter, _UnwrappedIter __unwrapped_iter) { + return _ReverseWrapper<_Iter>( + reverse_iterator<_Iter>(__unwrap_iter_impl<_Iter>::__rewrap(__orig_iter.base().base(), __unwrapped_iter))); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _ReverseWrapper<_OrigIter> __apply(_ReverseWrapper<_OrigIter> __iter1, - _UnwrappedIter __iter2) { - return __rewrap<_ReverseWrapperCount<_OrigIter>::value>(__iter1, __iter2); + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _UnwrappedIter __unwrap(_ReverseWrapper<_Iter> __i) _NOEXCEPT { + return __unwrap_iter_impl<_Iter>::__unwrap(__i.base().base()); } }; diff --git a/contrib/llvm-project/libcxx/include/__locale b/contrib/llvm-project/libcxx/include/__locale index 4450123db194..40f9a3ff57c2 100644 --- a/contrib/llvm-project/libcxx/include/__locale +++ b/contrib/llvm-project/libcxx/include/__locale @@ -33,7 +33,7 @@ # include <__support/newlib/xlocale.h> #elif defined(__OpenBSD__) # include <__support/openbsd/xlocale.h> -#elif (defined(__APPLE__) || defined(__FreeBSD__) || defined(__IBMCPP__)) +#elif (defined(__APPLE__) || defined(__FreeBSD__)) # include <xlocale.h> #elif defined(__Fuchsia__) # include <__support/fuchsia/xlocale.h> @@ -492,7 +492,11 @@ public: static const mask punct = _ISPUNCT; static const mask xdigit = _ISXDIGIT; static const mask blank = _ISBLANK; +# if defined(_AIX) + static const mask __regex_word = 0x8000; +# else static const mask __regex_word = 0x80; +# endif #elif defined(_NEWLIB_VERSION) // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h. typedef char mask; @@ -545,11 +549,8 @@ public: _LIBCPP_INLINE_VISIBILITY ctype_base() {} -// TODO: Remove the ifndef when the assert no longer fails on AIX. -#ifndef _AIX static_assert((__regex_word & ~(space | print | cntrl | upper | lower | alpha | digit | punct | xdigit | blank)) == __regex_word, "__regex_word can't overlap other bits"); -#endif }; template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype; diff --git a/contrib/llvm-project/libcxx/include/__random/binomial_distribution.h b/contrib/llvm-project/libcxx/include/__random/binomial_distribution.h index d0e8f3034939..af60fa2a38e0 100644 --- a/contrib/llvm-project/libcxx/include/__random/binomial_distribution.h +++ b/contrib/llvm-project/libcxx/include/__random/binomial_distribution.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template<class _IntType = int> class _LIBCPP_TEMPLATE_VIS binomial_distribution { - static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type"); public: // types typedef _IntType result_type; diff --git a/contrib/llvm-project/libcxx/include/__random/discrete_distribution.h b/contrib/llvm-project/libcxx/include/__random/discrete_distribution.h index d899e72d87f9..8dc63c0e98b4 100644 --- a/contrib/llvm-project/libcxx/include/__random/discrete_distribution.h +++ b/contrib/llvm-project/libcxx/include/__random/discrete_distribution.h @@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template<class _IntType = int> class _LIBCPP_TEMPLATE_VIS discrete_distribution { - static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type"); public: // types typedef _IntType result_type; diff --git a/contrib/llvm-project/libcxx/include/__random/geometric_distribution.h b/contrib/llvm-project/libcxx/include/__random/geometric_distribution.h index 8e1be522e0e3..751cf7860e66 100644 --- a/contrib/llvm-project/libcxx/include/__random/geometric_distribution.h +++ b/contrib/llvm-project/libcxx/include/__random/geometric_distribution.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template<class _IntType = int> class _LIBCPP_TEMPLATE_VIS geometric_distribution { - static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type"); public: // types typedef _IntType result_type; diff --git a/contrib/llvm-project/libcxx/include/__random/is_valid.h b/contrib/llvm-project/libcxx/include/__random/is_valid.h index d41bfa45ea70..be3b61b8dc01 100644 --- a/contrib/llvm-project/libcxx/include/__random/is_valid.h +++ b/contrib/llvm-project/libcxx/include/__random/is_valid.h @@ -10,6 +10,7 @@ #define _LIBCPP___RANDOM_IS_VALID_H #include <__config> +#include <cstdint> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -25,18 +26,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD // unsigned int, unsigned long, or unsigned long long. template<class> struct __libcpp_random_is_valid_inttype : false_type {}; +template<> struct __libcpp_random_is_valid_inttype<int8_t> : true_type {}; // extension template<> struct __libcpp_random_is_valid_inttype<short> : true_type {}; template<> struct __libcpp_random_is_valid_inttype<int> : true_type {}; template<> struct __libcpp_random_is_valid_inttype<long> : true_type {}; template<> struct __libcpp_random_is_valid_inttype<long long> : true_type {}; +template<> struct __libcpp_random_is_valid_inttype<uint8_t> : true_type {}; // extension template<> struct __libcpp_random_is_valid_inttype<unsigned short> : true_type {}; template<> struct __libcpp_random_is_valid_inttype<unsigned int> : true_type {}; template<> struct __libcpp_random_is_valid_inttype<unsigned long> : true_type {}; template<> struct __libcpp_random_is_valid_inttype<unsigned long long> : true_type {}; #ifndef _LIBCPP_HAS_NO_INT128 -template<> struct __libcpp_random_is_valid_inttype<__int128_t> : true_type {}; -template<> struct __libcpp_random_is_valid_inttype<__uint128_t> : true_type {}; +template<> struct __libcpp_random_is_valid_inttype<__int128_t> : true_type {}; // extension +template<> struct __libcpp_random_is_valid_inttype<__uint128_t> : true_type {}; // extension #endif // _LIBCPP_HAS_NO_INT128 // [rand.req.urng]/3: diff --git a/contrib/llvm-project/libcxx/include/__random/negative_binomial_distribution.h b/contrib/llvm-project/libcxx/include/__random/negative_binomial_distribution.h index 72ce88ea74ba..90d3f0178914 100644 --- a/contrib/llvm-project/libcxx/include/__random/negative_binomial_distribution.h +++ b/contrib/llvm-project/libcxx/include/__random/negative_binomial_distribution.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template<class _IntType = int> class _LIBCPP_TEMPLATE_VIS negative_binomial_distribution { - static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type"); public: // types typedef _IntType result_type; @@ -121,7 +121,9 @@ negative_binomial_distribution<_IntType>::operator()(_URNG& __urng, const param_ static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); result_type __k = __pr.k(); double __p = __pr.p(); - if (__k <= 21 * __p) + // When the number of bits in _IntType is small, we are too likely to + // overflow __f below to use this technique. + if (__k <= 21 * __p && sizeof(_IntType) > 1) { bernoulli_distribution __gen(__p); result_type __f = 0; @@ -133,6 +135,8 @@ negative_binomial_distribution<_IntType>::operator()(_URNG& __urng, const param_ else ++__f; } + _LIBCPP_ASSERT(__f >= 0, "std::negative_binomial_distribution should never produce negative values. " + "This is almost certainly a signed integer overflow issue on __f."); return __f; } return poisson_distribution<result_type>(gamma_distribution<double> diff --git a/contrib/llvm-project/libcxx/include/__random/poisson_distribution.h b/contrib/llvm-project/libcxx/include/__random/poisson_distribution.h index 7730923ad6ca..ef55b1be4844 100644 --- a/contrib/llvm-project/libcxx/include/__random/poisson_distribution.h +++ b/contrib/llvm-project/libcxx/include/__random/poisson_distribution.h @@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template<class _IntType = int> class _LIBCPP_TEMPLATE_VIS poisson_distribution { - static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type"); public: // types typedef _IntType result_type; diff --git a/contrib/llvm-project/libcxx/include/__random/uniform_int_distribution.h b/contrib/llvm-project/libcxx/include/__random/uniform_int_distribution.h index dd0a7e4e4982..46b627f45da9 100644 --- a/contrib/llvm-project/libcxx/include/__random/uniform_int_distribution.h +++ b/contrib/llvm-project/libcxx/include/__random/uniform_int_distribution.h @@ -159,7 +159,7 @@ __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) template<class _IntType = int> class uniform_int_distribution { - static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type"); public: // types typedef _IntType result_type; diff --git a/contrib/llvm-project/libcxx/include/algorithm b/contrib/llvm-project/libcxx/include/algorithm index f616a031960e..5958ad1a95af 100644 --- a/contrib/llvm-project/libcxx/include/algorithm +++ b/contrib/llvm-project/libcxx/include/algorithm @@ -360,6 +360,17 @@ namespace ranges { borrowed_iterator_t<R> ranges::stable_sort(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 + template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, + class Proj = identity> + requires sortable<I, Comp, Proj> + constexpr I + ranges::partial_sort(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // since C++20 + + template<random_access_range R, class Comp = ranges::less, class Proj = identity> + requires sortable<iterator_t<R>, Comp, Proj> + constexpr borrowed_iterator_t<R> + ranges::partial_sort(R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {}); // since C++20 + template<class T, output_iterator<const T&> O, sentinel_for<O> S> constexpr O ranges::fill(O first, S last, const T& value); // since C++20 @@ -464,6 +475,28 @@ namespace ranges { ranges::less> constexpr bool binary_search(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 + + template<permutable I, sentinel_for<I> S, class Proj = identity, + indirect_unary_predicate<projected<I, Proj>> Pred> + constexpr subrange<I> + partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20 + + template<forward_range R, class Proj = identity, + indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> + requires permutable<iterator_t<R>> + constexpr borrowed_subrange_t<R> + partition(R&& r, Pred pred, Proj proj = {}); // Since C++20 + + template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity, + indirect_unary_predicate<projected<I, Proj>> Pred> + requires permutable<I> + subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20 + + template<bidirectional_range R, class Proj = identity, + indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> + requires permutable<iterator_t<R>> + borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20 + template<input_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> @@ -548,6 +581,34 @@ namespace ranges { constexpr ranges::move_result<borrowed_iterator_t<R>, O> ranges::move(R&& r, O result); // since C++20 + template<class I, class O1, class O2> + using partition_copy_result = in_out_out_result<I, O1, O2>; // since C++20 + + template<input_iterator I, sentinel_for<I> S, + weakly_incrementable O1, weakly_incrementable O2, + class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> + requires indirectly_copyable<I, O1> && indirectly_copyable<I, O2> + constexpr partition_copy_result<I, O1, O2> + partition_copy(I first, S last, O1 out_true, O2 out_false, Pred pred, + Proj proj = {}); // Since C++20 + + template<input_range R, weakly_incrementable O1, weakly_incrementable O2, + class Proj = identity, + indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> + requires indirectly_copyable<iterator_t<R>, O1> && + indirectly_copyable<iterator_t<R>, O2> + constexpr partition_copy_result<borrowed_iterator_t<R>, O1, O2> + partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); // Since C++20 + + template<forward_iterator I, sentinel_for<I> S, class Proj = identity, + indirect_unary_predicate<projected<I, Proj>> Pred> + constexpr I partition_point(I first, S last, Pred pred, Proj proj = {}); // Since C++20 + + template<forward_range R, class Proj = identity, + indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> + constexpr borrowed_iterator_t<R> + partition_point(R&& r, Pred pred, Proj proj = {}); // Since C++20 + template<class I1, class I2, class O> using merge_result = in_in_out_result<I1, I2, O>; // since C++20 @@ -649,6 +710,16 @@ namespace ranges { constexpr ranges::rotate_copy_result<borrowed_iterator_t<R>, O> ranges::rotate_copy(R&& r, iterator_t<R> middle, O result); // since C++20 + template<random_access_iterator I, sentinel_for<I> S, class Gen> + requires permutable<I> && + uniform_random_bit_generator<remove_reference_t<Gen>> + I shuffle(I first, S last, Gen&& g); // Since C++20 + + template<random_access_range R, class Gen> + requires permutable<iterator_t<R>> && + uniform_random_bit_generator<remove_reference_t<Gen>> + borrowed_iterator_t<R> shuffle(R&& r, Gen&& g); // Since C++20 + template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -711,7 +782,49 @@ namespace ranges { borrowed_iterator_t<R2>, O> set_symmetric_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 + + template<forward_iterator I, sentinel_for<I> S, class T, class Proj = identity, + indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> + constexpr subrange<I> + equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 + + template<forward_range R, class T, class Proj = identity, + indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = + ranges::less> + constexpr borrowed_subrange_t<R> + equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 + + template<class I1, class I2, class O> + using set_union_result = in_in_out_result<I1, I2, O>; // since C++20 + + template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, + weakly_incrementable O, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires mergeable<I1, I2, O, Comp, Proj1, Proj2> + constexpr set_union_result<I1, I2, O> + set_union(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 + + template<input_range R1, input_range R2, weakly_incrementable O, + class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> + requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> + constexpr set_union_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> + set_union(R1&& r1, R2&& r2, O result, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 + + template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, + class Proj1 = identity, class Proj2 = identity, + indirect_strict_weak_order<projected<I1, Proj1>, projected<I2, Proj2>> Comp = + ranges::less> + constexpr bool includes(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + template<input_range R1, input_range R2, class Proj1 = identity, + class Proj2 = identity, + indirect_strict_weak_order<projected<iterator_t<R1>, Proj1>, + projected<iterator_t<R2>, Proj2>> Comp = ranges::less> + constexpr bool includes(R1&& r1, R2&& r2, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 } constexpr bool // constexpr in C++20 @@ -1452,6 +1565,7 @@ template <class BidirectionalIterator, class Compare> #include <__algorithm/ranges_count.h> #include <__algorithm/ranges_count_if.h> #include <__algorithm/ranges_equal.h> +#include <__algorithm/ranges_equal_range.h> #include <__algorithm/ranges_fill.h> #include <__algorithm/ranges_fill_n.h> #include <__algorithm/ranges_find.h> @@ -1461,6 +1575,7 @@ template <class BidirectionalIterator, class Compare> #include <__algorithm/ranges_find_if_not.h> #include <__algorithm/ranges_for_each.h> #include <__algorithm/ranges_for_each_n.h> +#include <__algorithm/ranges_includes.h> #include <__algorithm/ranges_is_partitioned.h> #include <__algorithm/ranges_is_sorted.h> #include <__algorithm/ranges_is_sorted_until.h> @@ -1479,6 +1594,10 @@ template <class BidirectionalIterator, class Compare> #include <__algorithm/ranges_move_backward.h> #include <__algorithm/ranges_none_of.h> #include <__algorithm/ranges_nth_element.h> +#include <__algorithm/ranges_partial_sort.h> +#include <__algorithm/ranges_partition.h> +#include <__algorithm/ranges_partition_copy.h> +#include <__algorithm/ranges_partition_point.h> #include <__algorithm/ranges_pop_heap.h> #include <__algorithm/ranges_push_heap.h> #include <__algorithm/ranges_remove.h> @@ -1493,8 +1612,11 @@ template <class BidirectionalIterator, class Compare> #include <__algorithm/ranges_set_difference.h> #include <__algorithm/ranges_set_intersection.h> #include <__algorithm/ranges_set_symmetric_difference.h> +#include <__algorithm/ranges_set_union.h> +#include <__algorithm/ranges_shuffle.h> #include <__algorithm/ranges_sort.h> #include <__algorithm/ranges_sort_heap.h> +#include <__algorithm/ranges_stable_partition.h> #include <__algorithm/ranges_stable_sort.h> #include <__algorithm/ranges_swap_ranges.h> #include <__algorithm/ranges_transform.h> diff --git a/contrib/llvm-project/libcxx/include/bit b/contrib/llvm-project/libcxx/include/bit index fe1bcadc818a..15bc13a504b1 100644 --- a/contrib/llvm-project/libcxx/include/bit +++ b/contrib/llvm-project/libcxx/include/bit @@ -75,9 +75,6 @@ namespace std { # include <iosfwd> #endif -#if defined(__IBMCPP__) -# include "__support/ibm/support.h" -#endif #if defined(_LIBCPP_COMPILER_MSVC) # include <intrin.h> #endif diff --git a/contrib/llvm-project/libcxx/include/format b/contrib/llvm-project/libcxx/include/format index 60197d24523f..d2ec8fc23363 100644 --- a/contrib/llvm-project/libcxx/include/format +++ b/contrib/llvm-project/libcxx/include/format @@ -131,7 +131,7 @@ namespace std { #include <__assert> // all public C++ headers provide the assertion handler // Make sure all feature-test macros are available. #include <version> -// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES. +// Enable the contents of the header only when libc++ was built with experimental features enabled. #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) #include <__algorithm/clamp.h> @@ -157,6 +157,7 @@ namespace std { #include <__format/formatter_pointer.h> #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> +#include <__format/unicode.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/incrementable_traits.h> #include <__variant/monostate.h> diff --git a/contrib/llvm-project/libcxx/include/limits b/contrib/llvm-project/libcxx/include/limits index 35e4d85734de..1fa3a8228fd8 100644 --- a/contrib/llvm-project/libcxx/include/limits +++ b/contrib/llvm-project/libcxx/include/limits @@ -110,10 +110,6 @@ template<> class numeric_limits<cv long double>; #include "__support/win32/limits_msvc_win32.h" #endif // _LIBCPP_MSVCRT -#if defined(__IBMCPP__) -#include "__support/ibm/limits.h" -#endif // __IBMCPP__ - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/contrib/llvm-project/libcxx/include/module.modulemap.in b/contrib/llvm-project/libcxx/include/module.modulemap.in index 25e1c6e6d0e2..cbf0b4f7f16d 100644 --- a/contrib/llvm-project/libcxx/include/module.modulemap.in +++ b/contrib/llvm-project/libcxx/include/module.modulemap.in @@ -337,6 +337,7 @@ module std [system] { module ranges_is_partitioned { private header "__algorithm/ranges_is_partitioned.h" } module ranges_is_sorted { private header "__algorithm/ranges_is_sorted.h" } module ranges_is_sorted_until { private header "__algorithm/ranges_is_sorted_until.h" } + module ranges_iterator_concept { private header "__algorithm/ranges_iterator_concept.h" } module ranges_lexicographical_compare { private header "__algorithm/ranges_lexicographical_compare.h" } module ranges_lower_bound { private header "__algorithm/ranges_lower_bound.h" } module ranges_make_heap { private header "__algorithm/ranges_make_heap.h" } @@ -352,6 +353,7 @@ module std [system] { module ranges_move_backward { private header "__algorithm/ranges_move_backward.h" } module ranges_none_of { private header "__algorithm/ranges_none_of.h" } module ranges_nth_element { private header "__algorithm/ranges_nth_element.h" } + module ranges_partial_sort { private header "__algorithm/ranges_partial_sort.h" } module ranges_partial_sort_copy { private header "__algorithm/ranges_partial_sort_copy.h" } module ranges_partition { private header "__algorithm/ranges_partition.h" } module ranges_partition_copy { private header "__algorithm/ranges_partition_copy.h" } @@ -614,32 +616,34 @@ module std [system] { export * module __format { - module buffer { private header "__format/buffer.h" } - module concepts { private header "__format/concepts.h" } - module enable_insertable { private header "__format/enable_insertable.h" } - module format_arg { private header "__format/format_arg.h" } - module format_arg_store { private header "__format/format_arg_store.h" } - module format_args { private header "__format/format_args.h" } + module buffer { private header "__format/buffer.h" } + module concepts { private header "__format/concepts.h" } + module enable_insertable { private header "__format/enable_insertable.h" } + module extended_grapheme_cluster_table { private header "__format/extended_grapheme_cluster_table.h" } + module format_arg { private header "__format/format_arg.h" } + module format_arg_store { private header "__format/format_arg_store.h" } + module format_args { private header "__format/format_args.h" } module format_context { private header "__format/format_context.h" export optional export locale } - module format_error { private header "__format/format_error.h" } - module format_fwd { private header "__format/format_fwd.h" } - module format_parse_context { private header "__format/format_parse_context.h" } - module format_string { private header "__format/format_string.h" } - module format_to_n_result { private header "__format/format_to_n_result.h" } - module formatter { private header "__format/formatter.h" } - module formatter_bool { private header "__format/formatter_bool.h" } - module formatter_char { private header "__format/formatter_char.h" } - module formatter_floating_point { private header "__format/formatter_floating_point.h" } - module formatter_integer { private header "__format/formatter_integer.h" } - module formatter_integral { private header "__format/formatter_integral.h" } - module formatter_output { private header "__format/formatter_output.h" } - module formatter_pointer { private header "__format/formatter_pointer.h" } - module formatter_string { private header "__format/formatter_string.h" } - module parser_std_format_spec { private header "__format/parser_std_format_spec.h" } + module format_error { private header "__format/format_error.h" } + module format_fwd { private header "__format/format_fwd.h" } + module format_parse_context { private header "__format/format_parse_context.h" } + module format_string { private header "__format/format_string.h" } + module format_to_n_result { private header "__format/format_to_n_result.h" } + module formatter { private header "__format/formatter.h" } + module formatter_bool { private header "__format/formatter_bool.h" } + module formatter_char { private header "__format/formatter_char.h" } + module formatter_floating_point { private header "__format/formatter_floating_point.h" } + module formatter_integer { private header "__format/formatter_integer.h" } + module formatter_integral { private header "__format/formatter_integral.h" } + module formatter_output { private header "__format/formatter_output.h" } + module formatter_pointer { private header "__format/formatter_pointer.h" } + module formatter_string { private header "__format/formatter_string.h" } + module parser_std_format_spec { private header "__format/parser_std_format_spec.h" } + module unicode { private header "__format/unicode.h" } } } module forward_list { diff --git a/contrib/llvm-project/libcxx/include/ostream b/contrib/llvm-project/libcxx/include/ostream index 283774585b92..14b49d78cb03 100644 --- a/contrib/llvm-project/libcxx/include/ostream +++ b/contrib/llvm-project/libcxx/include/ostream @@ -130,6 +130,35 @@ template <class charT, class traits> template <class Stream, class T> Stream&& operator<<(Stream&& os, const T& x); +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, wchar_t) = delete; // since C++20 +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, char8_t) = delete; // since C++20 +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, char16_t) = delete; // since C++20 +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, char32_t) = delete; // since C++20 +template<class traits> +basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, char8_t) = delete; // since C++20 +template<class traits> +basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, char16_t) = delete; // since C++20 +template<class traits> +basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, char32_t) = delete; // since C++20 +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const wchar_t*) = delete; // since C++20 +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char8_t*) = delete; // since C++20 +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char16_t*) = delete; // since C++20 +template<class traits> +basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char32_t*) = delete; // since C++20 +template<class traits> +basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, const char8_t*) = delete; // since C++20 +template<class traits> +basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, const char16_t*) = delete; // since C++20 +template<class traits> +basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, const char32_t*) = delete; // since C++20 + } // std */ @@ -225,9 +254,13 @@ public: basic_ostream& operator<<(basic_streambuf<char_type, traits_type>* __sb); +#if _LIBCPP_STD_VER > 14 +// LWG 2221 - nullptr. This is not backported to older standards modes. +// See https://reviews.llvm.org/D127033 for more info on the rationale. _LIBCPP_INLINE_VISIBILITY basic_ostream& operator<<(nullptr_t) { return *this << "nullptr"; } +#endif // 27.7.2.7 Unformatted output: basic_ostream& put(char_type __c); @@ -1098,6 +1131,57 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x) use_facet<ctype<_CharT> >(__os.getloc()).widen('1')); } +#if _LIBCPP_STD_VER > 17 + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, wchar_t) = delete; + +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, const wchar_t*) = delete; + +template <class _Traits> +basic_ostream<wchar_t, _Traits>& operator<<(basic_ostream<wchar_t, _Traits>&, char16_t) = delete; + +template <class _Traits> +basic_ostream<wchar_t, _Traits>& operator<<(basic_ostream<wchar_t, _Traits>&, char32_t) = delete; + +template <class _Traits> +basic_ostream<wchar_t, _Traits>& operator<<(basic_ostream<wchar_t, _Traits>&, const char16_t*) = delete; + +template <class _Traits> +basic_ostream<wchar_t, _Traits>& operator<<(basic_ostream<wchar_t, _Traits>&, const char32_t*) = delete; + +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, char8_t) = delete; + +template <class _Traits> +basic_ostream<wchar_t, _Traits>& operator<<(basic_ostream<wchar_t, _Traits>&, char8_t) = delete; + +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, const char8_t*) = delete; + +template <class _Traits> +basic_ostream<wchar_t, _Traits>& operator<<(basic_ostream<wchar_t, _Traits>&, const char8_t*) = delete; +#endif + +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, char16_t) = delete; + +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, char32_t) = delete; + +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, const char16_t*) = delete; + +template <class _Traits> +basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, const char32_t*) = delete; + +#endif // _LIBCPP_STD_VER > 17 + extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<char>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<wchar_t>; diff --git a/contrib/llvm-project/libcxx/include/version b/contrib/llvm-project/libcxx/include/version index 2034e4b1f3d9..1df51fa1cb86 100644 --- a/contrib/llvm-project/libcxx/include/version +++ b/contrib/llvm-project/libcxx/include/version @@ -47,7 +47,7 @@ __cpp_lib_bounded_array_traits 201902L <type_traits> __cpp_lib_boyer_moore_searcher 201603L <functional> __cpp_lib_byte 201603L <cstddef> __cpp_lib_byteswap 202110L <bit> -__cpp_lib_char8_t 201811L <atomic> <filesystem> <istream> +__cpp_lib_char8_t 201907L <atomic> <filesystem> <istream> <limits> <locale> <ostream> <string> <string_view> __cpp_lib_chrono 201611L <chrono> @@ -308,7 +308,7 @@ __cpp_lib_void_t 201411L <type_traits> // # define __cpp_lib_bitops 201907L # define __cpp_lib_bounded_array_traits 201902L # if !defined(_LIBCPP_HAS_NO_CHAR8_T) -# define __cpp_lib_char8_t 201811L +# define __cpp_lib_char8_t 201907L # endif # define __cpp_lib_concepts 202002L # define __cpp_lib_constexpr_algorithms 201806L |