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_PSTL_REPLACE_H
10#define _LIBCPP___ALGORITHM_PSTL_REPLACE_H
11
12#include <__algorithm/pstl_backend.h>
13#include <__algorithm/pstl_for_each.h>
14#include <__algorithm/pstl_frontend_dispatch.h>
15#include <__algorithm/pstl_transform.h>
16#include <__config>
17#include <__iterator/iterator_traits.h>
18#include <__type_traits/enable_if.h>
19#include <__type_traits/remove_cvref.h>
20#include <__utility/move.h>
21#include <optional>
22
23#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24#  pragma GCC system_header
25#endif
26
27_LIBCPP_PUSH_MACROS
28#include <__undef_macros>
29
30#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
31
32_LIBCPP_BEGIN_NAMESPACE_STD
33
34template <class>
35void __pstl_replace_if();
36
37template <class _ExecutionPolicy,
38          class _ForwardIterator,
39          class _Pred,
40          class _Tp,
41          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
42          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
43[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
44__replace_if(_ExecutionPolicy&& __policy,
45             _ForwardIterator&& __first,
46             _ForwardIterator&& __last,
47             _Pred&& __pred,
48             const _Tp& __new_value) noexcept {
49  return std::__pstl_frontend_dispatch(
50      _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_if, _RawPolicy),
51      [&__policy](
52          _ForwardIterator&& __g_first, _ForwardIterator&& __g_last, _Pred&& __g_pred, const _Tp& __g_new_value) {
53        std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) {
54          if (__g_pred(__element))
55            __element = __g_new_value;
56        });
57        return optional<__empty>{__empty{}};
58      },
59      std::move(__first),
60      std::move(__last),
61      std::move(__pred),
62      __new_value);
63}
64
65template <class _ExecutionPolicy,
66          class _ForwardIterator,
67          class _Pred,
68          class _Tp,
69          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
70          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
71_LIBCPP_HIDE_FROM_ABI void
72replace_if(_ExecutionPolicy&& __policy,
73           _ForwardIterator __first,
74           _ForwardIterator __last,
75           _Pred __pred,
76           const _Tp& __new_value) {
77  auto __res = std::__replace_if(__policy, std::move(__first), std::move(__last), std::move(__pred), __new_value);
78  if (!__res)
79    std::__throw_bad_alloc();
80}
81
82template <class>
83void __pstl_replace();
84
85template <class _ExecutionPolicy,
86          class _ForwardIterator,
87          class _Tp,
88          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
89          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
90[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
91__replace(_ExecutionPolicy&& __policy,
92          _ForwardIterator __first,
93          _ForwardIterator __last,
94          const _Tp& __old_value,
95          const _Tp& __new_value) noexcept {
96  return std::__pstl_frontend_dispatch(
97      _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace, _RawPolicy),
98      [&__policy](
99          _ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_old_value, const _Tp& __g_new_value) {
100        return std::__replace_if(
101            __policy,
102            std::move(__g_first),
103            std::move(__g_last),
104            [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; },
105            __g_new_value);
106      },
107      std::move(__first),
108      std::move(__last),
109      __old_value,
110      __new_value);
111}
112
113template <class _ExecutionPolicy,
114          class _ForwardIterator,
115          class _Tp,
116          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
117          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
118_LIBCPP_HIDE_FROM_ABI void
119replace(_ExecutionPolicy&& __policy,
120        _ForwardIterator __first,
121        _ForwardIterator __last,
122        const _Tp& __old_value,
123        const _Tp& __new_value) {
124  if (!std::__replace(__policy, std::move(__first), std::move(__last), __old_value, __new_value))
125    std::__throw_bad_alloc();
126}
127
128template <class>
129void __pstl_replace_copy_if();
130
131template <class _ExecutionPolicy,
132          class _ForwardIterator,
133          class _ForwardOutIterator,
134          class _Pred,
135          class _Tp,
136          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
137          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
138[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy_if(
139    _ExecutionPolicy&& __policy,
140    _ForwardIterator&& __first,
141    _ForwardIterator&& __last,
142    _ForwardOutIterator&& __result,
143    _Pred&& __pred,
144    const _Tp& __new_value) {
145  return std::__pstl_frontend_dispatch(
146      _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy_if, _RawPolicy),
147      [&__policy](_ForwardIterator __g_first,
148                  _ForwardIterator __g_last,
149                  _ForwardOutIterator __g_result,
150                  _Pred __g_pred,
151                  const _Tp& __g_new_value) -> optional<__empty> {
152        if (!std::__transform(
153                __policy, __g_first, __g_last, __g_result, [&](__iter_reference<_ForwardIterator> __element) {
154                  return __g_pred(__element) ? __g_new_value : __element;
155                }))
156          return nullopt;
157        return __empty{};
158      },
159      std::move(__first),
160      std::move(__last),
161      std::move(__result),
162      std::move(__pred),
163      __new_value);
164}
165
166template <class _ExecutionPolicy,
167          class _ForwardIterator,
168          class _ForwardOutIterator,
169          class _Pred,
170          class _Tp,
171          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
172          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
173_LIBCPP_HIDE_FROM_ABI void replace_copy_if(
174    _ExecutionPolicy&& __policy,
175    _ForwardIterator __first,
176    _ForwardIterator __last,
177    _ForwardOutIterator __result,
178    _Pred __pred,
179    const _Tp& __new_value) {
180  if (!std::__replace_copy_if(
181          __policy, std::move(__first), std::move(__last), std::move(__result), std::move(__pred), __new_value))
182    std::__throw_bad_alloc();
183}
184
185template <class>
186void __pstl_replace_copy();
187
188template <class _ExecutionPolicy,
189          class _ForwardIterator,
190          class _ForwardOutIterator,
191          class _Tp,
192          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
193          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
194[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy(
195    _ExecutionPolicy&& __policy,
196    _ForwardIterator&& __first,
197    _ForwardIterator&& __last,
198    _ForwardOutIterator&& __result,
199    const _Tp& __old_value,
200    const _Tp& __new_value) noexcept {
201  return std::__pstl_frontend_dispatch(
202      _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy, _RawPolicy),
203      [&__policy](_ForwardIterator __g_first,
204                  _ForwardIterator __g_last,
205                  _ForwardOutIterator __g_result,
206                  const _Tp& __g_old_value,
207                  const _Tp& __g_new_value) {
208        return std::__replace_copy_if(
209            __policy,
210            std::move(__g_first),
211            std::move(__g_last),
212            std::move(__g_result),
213            [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; },
214            __g_new_value);
215      },
216      std::move(__first),
217      std::move(__last),
218      std::move(__result),
219      __old_value,
220      __new_value);
221}
222
223template <class _ExecutionPolicy,
224          class _ForwardIterator,
225          class _ForwardOutIterator,
226          class _Tp,
227          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
228          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
229_LIBCPP_HIDE_FROM_ABI void replace_copy(
230    _ExecutionPolicy&& __policy,
231    _ForwardIterator __first,
232    _ForwardIterator __last,
233    _ForwardOutIterator __result,
234    const _Tp& __old_value,
235    const _Tp& __new_value) {
236  if (!std::__replace_copy(
237          __policy, std::move(__first), std::move(__last), std::move(__result), __old_value, __new_value))
238    std::__throw_bad_alloc();
239}
240
241_LIBCPP_END_NAMESPACE_STD
242
243#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
244
245_LIBCPP_POP_MACROS
246
247#endif // _LIBCPP___ALGORITHM_PSTL_REPLACE_H
248