6#ifndef MIMICPP_UTILITIES_ALGORITHM_HPP
7#define MIMICPP_UTILITIES_ALGORITHM_HPP
14#ifndef MIMICPP_DETAIL_IS_MODULE
21 #include <string_view>
23 #include <type_traits>
52 std::ranges::random_access_range Target,
53 std::ranges::random_access_range Control,
54 typename Projection = std::identity,
55 std::indirect_unary_predicate<
56 std::projected<std::ranges::iterator_t<Control>, Projection>> Predicate>
57 requires std::ranges::sized_range<Target>
58 && std::ranges::sized_range<Control>
63 Target && targetRange,
64 Control && controlRange,
66 Projection projection = {})
68 MIMICPP_ASSERT(std::ranges::size(targetRange) == std::ranges::size(controlRange),
"Size mismatch.");
70 auto const targetBegin = std::ranges::begin(targetRange);
71 auto const controlBegin = std::ranges::begin(controlRange);
72 auto midpoint = std::ranges::end(targetRange);
73 auto end = std::ranges::end(controlRange);
74 for (
auto iter = std::ranges::find_if_not(controlRange, std::ref(predicate), std::ref(projection));
76 iter = std::ranges::find_if_not(iter, end, std::ref(predicate), std::ref(projection)))
78 auto const index = std::ranges::distance(controlBegin, iter);
79 std::ranges::iter_swap(iter, --end);
80 std::ranges::iter_swap(std::ranges::next(targetBegin, index), --midpoint);
83 return {std::move(midpoint), std::ranges::end(targetRange)};
98 template <std::ranges::borrowed_range Range>
102 std::ranges::range_value_t<Range>
const& openingToken,
103 std::ranges::range_value_t<Range>
const& closingToken)
105 auto const begin = std::ranges::begin(str);
106 auto const end = std::ranges::end(str);
107 auto closingIter = std::ranges::find(str, closingToken);
108 if (closingIter == end)
113 for (
auto openingIter = std::ranges::find(begin, closingIter, openingToken);
114 openingIter != closingIter
115 && closingIter != end;
116 openingIter = std::ranges::find(openingIter + 1, closingIter, openingToken))
118 closingIter = std::ranges::find(closingIter + 1, end, closingToken);
138 template <std::ranges::borrowed_range Range>
142 std::string_view
const token,
143 std::ranges::forward_range
auto&& opening,
144 std::ranges::forward_range
auto&& closing)
146 using count_t = std::ranges::range_difference_t<Range>;
147 constexpr auto countAllOf = [](
auto const& source,
auto const& collection) {
149 for (
auto const c : collection)
151 count += std::ranges::count(source, c);
157 count_t openScopes{};
158 std::ranges::borrowed_subrange_t<Range> pending{str};
159 while (
auto const match = std::ranges::search(pending, token))
163 openScopes += countAllOf(std::ranges::subrange{pending.begin(), match.begin()}, opening);
164 openScopes -= countAllOf(std::ranges::subrange{pending.begin(), match.end()}, closing);
165 MIMICPP_ASSERT(0 <= openScopes,
"More scopes closed than opened.");
171 openScopes += countAllOf(match, opening);
173 pending = {match.end(), pending.end()};
176 return {std::ranges::end(str), std::ranges::end(str)};
189 template <std::ranges::forward_range Range, std::ranges::forward_range Prefix>
190 requires std::totally_ordered_with<std::ranges::range_value_t<Range>, Prefix>
192 constexpr std::ranges::borrowed_subrange_t<Range>
prefix_range(Range && range, Prefix && prefix)
194 auto const lower = std::ranges::lower_bound(range, prefix);
195 auto const end = std::ranges::lower_bound(
197 std::ranges::end(range),
199 [](
auto const& element,
auto const& p) {
200 auto const iter = std::ranges::mismatch(element, p).in2;
201 return iter == std::ranges::end(p);
216 template <std::copyable T, std::
size_t firstN, std::
size_t secondN>
218 constexpr std::array<T, firstN + secondN>
concat_arrays(std::array<T, firstN>
const& first, std::array<T, secondN>
const& second)
221 [&]<std::size_t... firstIs, std::size_t... secondIs>(
222 [[maybe_unused]] std::index_sequence<firstIs...>
const,
223 [[maybe_unused]] std::index_sequence<secondIs...>
const) {
224 return std::array<T, firstN + secondN>{
225 std::get<firstIs>(first)...,
226 std::get<secondIs>(second)...};
228 std::make_index_sequence<firstN>{},
229 std::make_index_sequence<secondN>{});
241 template <std::copyable T, std::size_t firstN,
typename... Others>
242 requires(... && std::same_as<T, std::ranges::range_value_t<Others>>)
244 && (... && (0u <= std::tuple_size_v<Others>))
246 constexpr auto concat_arrays(std::array<T, firstN>
const& first, Others
const&... others)
248 if constexpr (0u ==
sizeof...(Others))
261namespace mimicpp::util::detail
263 struct binary_find_fn
266 std::forward_iterator Iterator,
267 std::sentinel_for<Iterator> Sentinel,
268 typename Projection = std::identity,
270 std::indirect_strict_weak_order<
272 std::projected<Iterator, Projection>> Comparator = std::ranges::less>
274 constexpr Iterator operator()(
275 Iterator
const first,
278 Comparator compare = {},
279 Projection projection = {})
const
281 if (
auto const iter = std::ranges::lower_bound(first, last, value, compare, projection);
283 && !std::invoke(compare, value, std::invoke(projection, *iter)))
292 std::ranges::forward_range Range,
293 typename Projection = std::identity,
295 std::indirect_strict_weak_order<
297 std::projected<std::ranges::iterator_t<Range>, Projection>> Comparator = std::ranges::less>
299 constexpr std::ranges::borrowed_iterator_t<Range> operator()(
302 Comparator compare = {},
303 Projection projection = {})
const
307 std::ranges::begin(range),
308 std::ranges::end(range),
311 std::move(projection));
318 std::input_iterator Iterator,
319 std::sentinel_for<Iterator> Sentinel,
320 typename Projection = std::identity,
322 requires std::indirect_binary_predicate<
323 std::ranges::equal_to,
324 std::projected<Iterator, Projection>,
327 constexpr bool operator()(Iterator first, Sentinel last, T
const& value, Projection projection = {})
const
329 auto const iter = std::ranges::find(std::move(first), last, value, std::move(projection));
334 std::ranges::input_range Range,
335 typename Projection = std::identity,
337 requires std::indirect_binary_predicate<
338 std::ranges::equal_to,
339 std::projected<std::ranges::iterator_t<Range>, Projection>,
342 constexpr bool operator()(Range&& r, T
const& value, Projection projection = {})
const
346 std::ranges::begin(r),
349 std::move(projection));
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:51
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
std::remove_cvref_t< std::invoke_result_t< Projection &, std::iter_value_t< I > & > > projected_value_t
The alias template projected_value_t obtains the value type by stripping any reference and its topmos...
Definition C++26Backports.hpp:31
constexpr std::ranges::borrowed_subrange_t< Target > partition_by(Target &&targetRange, Control &&controlRange, Predicate predicate, Projection projection={})
Partitions the target range by the predicate results on the control range.
Definition Algorithm.hpp:62
constexpr std::ranges::borrowed_subrange_t< Range > prefix_range(Range &&range, Prefix &&prefix)
Returns a view containing all elements, which start with the given prefix.
Definition Algorithm.hpp:192
constexpr std::array< T, firstN+secondN > concat_arrays(std::array< T, firstN > const &first, std::array< T, secondN > const &second)
Concatenates the given arrays by copying all elements into a new array.
Definition Algorithm.hpp:218
constexpr detail::contains_fn contains
Determines, whether the specified value is contained in the given range.
Definition Algorithm.hpp:370
constexpr std::ranges::borrowed_iterator_t< Range > find_closing_token(Range &&str, std::ranges::range_value_t< Range > const &openingToken, std::ranges::range_value_t< Range > const &closingToken)
Finds the next closing token in the given string.
Definition Algorithm.hpp:100
constexpr std::ranges::borrowed_subrange_t< Range > find_next_unwrapped_token(Range &&str, std::string_view const token, std::ranges::forward_range auto &&opening, std::ranges::forward_range auto &&closing)
Finds the next unwrapped token in the given string.
Definition Algorithm.hpp:140
constexpr detail::binary_find_fn binary_find
Finds the specified value within the container and returns an iterator pointing to it....
Definition Algorithm.hpp:361