1fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #ifndef _LIBCPP___ALGORITHM_COPY_H 10fe6060f1SDimitry Andric #define _LIBCPP___ALGORITHM_COPY_H 11fe6060f1SDimitry Andric 12bdd1243dSDimitry Andric #include <__algorithm/copy_move_common.h> 1306c3fb27SDimitry Andric #include <__algorithm/for_each_segment.h> 14bdd1243dSDimitry Andric #include <__algorithm/iterator_operations.h> 15bdd1243dSDimitry Andric #include <__algorithm/min.h> 1604eeddc0SDimitry Andric #include <__config> 17bdd1243dSDimitry Andric #include <__iterator/segmented_iterator.h> 18bdd1243dSDimitry Andric #include <__type_traits/common_type.h> 1981ad6265SDimitry Andric #include <__utility/move.h> 2081ad6265SDimitry Andric #include <__utility/pair.h> 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23fe6060f1SDimitry Andric # pragma GCC system_header 24fe6060f1SDimitry Andric #endif 25fe6060f1SDimitry Andric 26bdd1243dSDimitry Andric _LIBCPP_PUSH_MACROS 27bdd1243dSDimitry Andric #include <__undef_macros> 28bdd1243dSDimitry Andric 29fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 30fe6060f1SDimitry Andric 31bdd1243dSDimitry Andric template <class, class _InIter, class _Sent, class _OutIter> 32bdd1243dSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); 33fe6060f1SDimitry Andric 34bdd1243dSDimitry Andric template <class _AlgPolicy> 35*0fca6ea1SDimitry Andric struct __copy_impl { 3681ad6265SDimitry Andric template <class _InIter, class _Sent, class _OutIter> 37bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> 38bdd1243dSDimitry Andric operator()(_InIter __first, _Sent __last, _OutIter __result) const { 3981ad6265SDimitry Andric while (__first != __last) { 40fe6060f1SDimitry Andric *__result = *__first; 4181ad6265SDimitry Andric ++__first; 4281ad6265SDimitry Andric ++__result; 4381ad6265SDimitry Andric } 44bdd1243dSDimitry Andric 45bdd1243dSDimitry Andric return std::make_pair(std::move(__first), std::move(__result)); 46fe6060f1SDimitry Andric } 47fe6060f1SDimitry Andric 4806c3fb27SDimitry Andric template <class _InIter, class _OutIter> 4906c3fb27SDimitry Andric struct _CopySegment { 5006c3fb27SDimitry Andric using _Traits = __segmented_iterator_traits<_InIter>; 5106c3fb27SDimitry Andric 5206c3fb27SDimitry Andric _OutIter& __result_; 5306c3fb27SDimitry Andric 545f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit _CopySegment(_OutIter& __result) 555f757f3fSDimitry Andric : __result_(__result) {} 5606c3fb27SDimitry Andric 575f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void 5806c3fb27SDimitry Andric operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { 5906c3fb27SDimitry Andric __result_ = std::__copy<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; 6006c3fb27SDimitry Andric } 6106c3fb27SDimitry Andric }; 6206c3fb27SDimitry Andric 63bdd1243dSDimitry Andric template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> 64bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> 65bdd1243dSDimitry Andric operator()(_InIter __first, _InIter __last, _OutIter __result) const { 6606c3fb27SDimitry Andric std::__for_each_segment(__first, __last, _CopySegment<_InIter, _OutIter>(__result)); 67bdd1243dSDimitry Andric return std::make_pair(__last, std::move(__result)); 6881ad6265SDimitry Andric } 6981ad6265SDimitry Andric 70bdd1243dSDimitry Andric template <class _InIter, 71bdd1243dSDimitry Andric class _OutIter, 7206c3fb27SDimitry Andric __enable_if_t<__has_random_access_iterator_category<_InIter>::value && 73bdd1243dSDimitry Andric !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, 74bdd1243dSDimitry Andric int> = 0> 75bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> 7606c3fb27SDimitry Andric operator()(_InIter __first, _InIter __last, _OutIter __result) const { 77bdd1243dSDimitry Andric using _Traits = __segmented_iterator_traits<_OutIter>; 78bdd1243dSDimitry Andric using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; 7981ad6265SDimitry Andric 80bdd1243dSDimitry Andric if (__first == __last) 81bdd1243dSDimitry Andric return std::make_pair(std::move(__first), std::move(__result)); 82bdd1243dSDimitry Andric 83bdd1243dSDimitry Andric auto __local_first = _Traits::__local(__result); 84bdd1243dSDimitry Andric auto __segment_iterator = _Traits::__segment(__result); 85bdd1243dSDimitry Andric while (true) { 86bdd1243dSDimitry Andric auto __local_last = _Traits::__end(__segment_iterator); 87bdd1243dSDimitry Andric auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); 88bdd1243dSDimitry Andric auto __iters = std::__copy<_AlgPolicy>(__first, __first + __size, __local_first); 89bdd1243dSDimitry Andric __first = std::move(__iters.first); 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric if (__first == __last) 92bdd1243dSDimitry Andric return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second))); 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric __local_first = _Traits::__begin(++__segment_iterator); 95bdd1243dSDimitry Andric } 96bdd1243dSDimitry Andric } 97bdd1243dSDimitry Andric 98bdd1243dSDimitry Andric // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. 9906c3fb27SDimitry Andric template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> 100bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> 101bdd1243dSDimitry Andric operator()(_In* __first, _In* __last, _Out* __result) const { 102bdd1243dSDimitry Andric return std::__copy_trivial_impl(__first, __last, __result); 103bdd1243dSDimitry Andric } 104bdd1243dSDimitry Andric }; 105bdd1243dSDimitry Andric 106bdd1243dSDimitry Andric template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> 107bdd1243dSDimitry Andric pair<_InIter, _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 108bdd1243dSDimitry Andric __copy(_InIter __first, _Sent __last, _OutIter __result) { 109*0fca6ea1SDimitry Andric return std::__copy_move_unwrap_iters<__copy_impl<_AlgPolicy> >( 110bdd1243dSDimitry Andric std::move(__first), std::move(__last), std::move(__result)); 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric 113fe6060f1SDimitry Andric template <class _InputIterator, class _OutputIterator> 1145f757f3fSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator 11581ad6265SDimitry Andric copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { 116bdd1243dSDimitry Andric return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second; 117fe6060f1SDimitry Andric } 118fe6060f1SDimitry Andric 119fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 120fe6060f1SDimitry Andric 121bdd1243dSDimitry Andric _LIBCPP_POP_MACROS 122bdd1243dSDimitry Andric 123fe6060f1SDimitry Andric #endif // _LIBCPP___ALGORITHM_COPY_H 124