xref: /freebsd-src/contrib/llvm-project/libcxx/include/__algorithm/copy.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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