xref: /llvm-project/libcxx/include/__algorithm/copy.h (revision 7ed7d4ccb8991e2b5b95334b508f8cec2faee737)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___ALGORITHM_COPY_H
10 #define _LIBCPP___ALGORITHM_COPY_H
11 
12 #include <__config>
13 #include <__algorithm/unwrap_iter.h>
14 #include <__iterator/iterator_traits.h>
15 #include <cstring>
16 #include <type_traits>
17 
18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19 #pragma GCC system_header
20 #endif
21 
22 _LIBCPP_PUSH_MACROS
23 #include <__undef_macros>
24 
25 _LIBCPP_BEGIN_NAMESPACE_STD
26 
27 // copy
28 
29 template <class _InputIterator, class _OutputIterator>
30 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
31 _OutputIterator
32 __copy_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
33 {
34     for (; __first != __last; ++__first, (void) ++__result)
35         *__result = *__first;
36     return __result;
37 }
38 
39 template <class _InputIterator, class _OutputIterator>
40 inline _LIBCPP_INLINE_VISIBILITY
41 _OutputIterator
42 __copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
43 {
44     return _VSTD::__copy_constexpr(__first, __last, __result);
45 }
46 
47 template <class _Tp, class _Up>
48 inline _LIBCPP_INLINE_VISIBILITY
49 typename enable_if
50 <
51     is_same<typename remove_const<_Tp>::type, _Up>::value &&
52     is_trivially_copy_assignable<_Up>::value,
53     _Up*
54 >::type
55 __copy(_Tp* __first, _Tp* __last, _Up* __result)
56 {
57     const size_t __n = static_cast<size_t>(__last - __first);
58     if (__n > 0)
59         _VSTD::memmove(__result, __first, __n * sizeof(_Up));
60     return __result + __n;
61 }
62 
63 template <class _InputIterator, class _OutputIterator>
64 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
65 _OutputIterator
66 copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
67 {
68     if (__libcpp_is_constant_evaluated()) {
69         return _VSTD::__copy_constexpr(__first, __last, __result);
70     } else {
71         return _VSTD::__rewrap_iter(__result,
72             _VSTD::__copy(_VSTD::__unwrap_iter(__first),
73                           _VSTD::__unwrap_iter(__last),
74                           _VSTD::__unwrap_iter(__result)));
75     }
76 }
77 
78 // copy_backward
79 
80 template <class _BidirectionalIterator, class _OutputIterator>
81 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
82 _OutputIterator
83 __copy_backward_constexpr(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result)
84 {
85     while (__first != __last)
86         *--__result = *--__last;
87     return __result;
88 }
89 
90 template <class _BidirectionalIterator, class _OutputIterator>
91 inline _LIBCPP_INLINE_VISIBILITY
92 _OutputIterator
93 __copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result)
94 {
95     return _VSTD::__copy_backward_constexpr(__first, __last, __result);
96 }
97 
98 template <class _Tp, class _Up>
99 inline _LIBCPP_INLINE_VISIBILITY
100 typename enable_if
101 <
102     is_same<typename remove_const<_Tp>::type, _Up>::value &&
103     is_trivially_copy_assignable<_Up>::value,
104     _Up*
105 >::type
106 __copy_backward(_Tp* __first, _Tp* __last, _Up* __result)
107 {
108     const size_t __n = static_cast<size_t>(__last - __first);
109     if (__n > 0)
110     {
111         __result -= __n;
112         _VSTD::memmove(__result, __first, __n * sizeof(_Up));
113     }
114     return __result;
115 }
116 
117 template <class _BidirectionalIterator1, class _BidirectionalIterator2>
118 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
119 _BidirectionalIterator2
120 copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
121               _BidirectionalIterator2 __result)
122 {
123     if (__libcpp_is_constant_evaluated()) {
124         return _VSTD::__copy_backward_constexpr(__first, __last, __result);
125     } else {
126         return _VSTD::__rewrap_iter(__result,
127             _VSTD::__copy_backward(_VSTD::__unwrap_iter(__first),
128                                    _VSTD::__unwrap_iter(__last),
129                                    _VSTD::__unwrap_iter(__result)));
130     }
131 }
132 
133 // copy_if
134 
135 template<class _InputIterator, class _OutputIterator, class _Predicate>
136 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
137 _OutputIterator
138 copy_if(_InputIterator __first, _InputIterator __last,
139         _OutputIterator __result, _Predicate __pred)
140 {
141     for (; __first != __last; ++__first)
142     {
143         if (__pred(*__first))
144         {
145             *__result = *__first;
146             ++__result;
147         }
148     }
149     return __result;
150 }
151 
152 // copy_n
153 
154 template<class _InputIterator, class _Size, class _OutputIterator>
155 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
156 typename enable_if
157 <
158     __is_cpp17_input_iterator<_InputIterator>::value &&
159    !__is_cpp17_random_access_iterator<_InputIterator>::value,
160     _OutputIterator
161 >::type
162 copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result)
163 {
164     typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize;
165     _IntegralSize __n = __orig_n;
166     if (__n > 0)
167     {
168         *__result = *__first;
169         ++__result;
170         for (--__n; __n > 0; --__n)
171         {
172             ++__first;
173             *__result = *__first;
174             ++__result;
175         }
176     }
177     return __result;
178 }
179 
180 template<class _InputIterator, class _Size, class _OutputIterator>
181 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
182 typename enable_if
183 <
184     __is_cpp17_random_access_iterator<_InputIterator>::value,
185     _OutputIterator
186 >::type
187 copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result)
188 {
189     typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize;
190     _IntegralSize __n = __orig_n;
191     return _VSTD::copy(__first, __first + __n, __result);
192 }
193 
194 _LIBCPP_END_NAMESPACE_STD
195 
196 _LIBCPP_POP_MACROS
197 
198 #endif // _LIBCPP___ALGORITHM_COPY_H
199