OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
algorithms.hpp
Go to the documentation of this file.
1#pragma once
2#include <ossia/detail/config.hpp>
3
4#include <ossia/detail/string_view.hpp>
5
6#include <algorithm>
7#include <array>
8#include <iterator>
9#include <ranges>
10#include <type_traits>
11#include <utility>
12
21namespace ossia
22{
23template <typename Vector>
24using iterator_t = typename std::remove_reference<Vector>::type::iterator;
25
26template <typename Vector, typename Value>
27auto find(Vector&& v, const Value& val) noexcept
28{
29 auto end = std::end(v);
30 for(auto it = std::begin(v); it != end; ++it)
31 if(*it == val)
32 return it;
33 return end;
34}
35
36template <typename Vector, typename Fun>
37auto find_if(Vector&& v, Fun&& fun)
38{
39 auto end = std::end(v);
40 for(auto it = std::begin(v); it != end; ++it)
41 if(fun(*it))
42 return it;
43 return end;
44}
45
46template <typename Vector, typename Value>
47auto* ptr_find(Vector&& v, const Value& val) noexcept
48{
49 if constexpr(requires { v.find(val) != v.end(); })
50 {
51 auto it = v.find(val);
52 return it != v.end() ? &it->second : nullptr;
53 }
54 else
55 {
56 auto it = ossia::find(v, val);
57 return it != std::end(v) ? &*it : nullptr;
58 }
59}
60
61template <typename Vector, typename Fun>
62auto* ptr_find_if(Vector&& v, Fun&& fun)
63{
64 auto it = ossia::find_if(v, fun);
65 return it != std::end(v) ? &*it : nullptr;
66}
67
68template <typename Vector, typename Value>
69bool contains(Vector&& v, const Value& val) noexcept
70{
71 return ossia::find(v, val) != std::end(v);
72}
73
74template <typename Vector, typename Value>
75void remove_one(Vector&& v, const Value& val)
76{
77 auto it = ossia::find(v, val);
78 if(it != v.end())
79 {
80 v.erase(it);
81 }
82}
83
84template <typename Vector, typename Function>
85void remove_one_if(Vector& v, const Function& val)
86{
87 auto it = ossia::find_if(v, val);
88 if(it != v.end())
89 {
90 v.erase(it);
91 }
92}
93
94template <typename Vector, typename Value>
95void remove_erase(Vector& v, const Value& val)
96{
97 v.erase(std::remove(v.begin(), v.end(), val), v.end());
98}
99
100template <typename Vector, typename Function>
101void remove_erase_if(Vector& v, const Function& val)
102{
103 v.erase(std::remove_if(v.begin(), v.end(), val), v.end());
104}
105
106template <typename Vector, typename Fun>
107void erase_if(Vector& r, Fun f)
108{
109 for(auto it = std::begin(r); it != std::end(r);)
110 {
111 it = f(*it) ? r.erase(it) : ++it;
112 }
113}
114
115template <typename Vector, typename Fun>
116bool any_of(Vector&& v, Fun&& fun) noexcept
117{
118 for(auto it = std::begin(v); it != std::end(v); ++it)
119 if(fun(*it))
120 return true;
121 return false;
122}
123
124template <typename Vector, typename Fun>
125auto all_of(Vector&& v, Fun&& fun) noexcept
126{
127 for(auto it = std::begin(v); it != std::end(v); ++it)
128 if(!fun(*it))
129 return false;
130 return true;
131}
132
133template <typename Vector, typename Fun>
134bool none_of(Vector&& v, Fun&& fun) noexcept
135{
136 for(auto it = std::begin(v); it != std::end(v); ++it)
137 if(fun(*it))
138 return false;
139 return true;
140}
141
142template <typename Vector, typename Fun>
143auto remove_if(Vector&& v, Fun&& fun)
144{
145 return std::remove_if(std::begin(v), std::end(v), std::forward<Fun>(fun));
146}
147
148template <typename Vector, typename Fun>
149auto count_if(Vector&& v, Fun&& fun)
150{
151 std::size_t count = 0;
152
153 for(auto it = std::begin(v); it != std::end(v); ++it)
154 if(fun(*it))
155 ++count;
156
157 return count;
158}
159
160template <typename Vector, typename Fun>
161auto max_element(Vector&& v, Fun&& fun)
162{
163 return std::max_element(std::begin(v), std::end(v), std::forward<Fun>(fun));
164}
165
166template <typename Vector>
167auto sort(Vector&& v)
168{
169 using value_type = typename std::remove_cvref_t<Vector>::value_type;
170 return std::ranges::sort(v, std::less<value_type>{});
171}
172
173template <typename Vector, typename T>
174auto fill(Vector&& v, const T& val)
175{
176 return std::fill(std::begin(v), std::end(v), val);
177}
178
179template <typename Vector>
180auto unique(Vector&& v)
181{
182 return std::unique(std::begin(v), std::end(v));
183}
184
185template <typename Vector, typename Fun>
186auto sort(Vector&& v, Fun&& fun)
187{
188 return std::ranges::sort(v, std::forward<Fun>(fun));
189}
190
191template <typename Vector, typename OutputIterator, typename Fun>
192auto transform(Vector&& v, OutputIterator it, Fun f)
193{
194 return std::transform(v.begin(), v.end(), it, f);
195}
196
197template <typename Array1, typename Array2>
198auto equal(const Array1& v, const Array2& v2) noexcept
199{
200 return std::equal(std::begin(v), std::end(v), std::begin(v2));
201}
202
203template <typename Vector1, typename Vector2>
204void copy(const Vector1& source, Vector2& destination)
205{
206 destination.reserve(destination.size() + source.size());
207 std::copy(source.begin(), source.end(), std::back_inserter(destination));
208}
209
210template <typename Vector1, typename Vector2, typename Pred>
211void copy_if(const Vector1& source, Vector2& destination, Pred predicate)
212{
213 std::copy_if(source.begin(), source.end(), std::back_inserter(destination), predicate);
214}
215
216template <typename T, typename K>
217auto last_before(T&& container, const K& k)
218{
219 auto it = container.upper_bound(k);
220 if(it != container.begin())
221 {
222 std::advance(it, -1);
223 }
224 return it;
225}
226
227template <typename T, typename K>
228auto find_key(T&& vec, const K& key) noexcept
229{
230 return std::find_if(
231 vec.begin(), vec.end(), [&](const auto& elt) { return elt.first == key; });
232}
233
234template <typename T, typename K0, typename K1>
235auto find_key(T&& vec, const K0& k0, const K1& k1) noexcept
236{
237 return std::find_if(vec.begin(), vec.end(), [&](const auto& elt) {
238 using namespace std;
239 return get<0>(elt) == k0 && get<1>(elt) == k1;
240 });
241}
242
243template <std::size_t N>
244struct num
245{
246 static const constexpr auto value = N;
247};
248
249template <class F, std::size_t... Is>
250void for_each_in_range(F&& func, std::index_sequence<Is...>)
251{
252 (std::forward<F>(func)(num<Is>{}), ...);
253}
254
255template <std::size_t N, typename F>
256void for_each_in_range(F&& func)
257{
258 for_each_in_range(std::forward<F>(func), std::make_index_sequence<N>());
259}
260
261namespace detail
262{
263template <class T, std::size_t N, std::size_t... I>
264constexpr std::array<std::remove_cv_t<T>, N>
265to_array_impl(T (&a)[N], std::index_sequence<I...>) noexcept
266{
267 return {{a[I]...}};
268}
269}
270
271template <class T, std::size_t N>
272constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N]) noexcept
273{
274 return detail::to_array_impl(a, std::make_index_sequence<N>{});
275}
276
277template <typename... Args>
278constexpr std::array<const char*, sizeof...(Args)> make_array(Args&&... args) noexcept
279{
280 return {args...};
281}
282
283template <typename T>
284void remove_duplicates(T& vec)
285{
286 if(vec.size() <= 1)
287 return;
288
289 std::sort(vec.begin(), vec.end());
290 vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
291}
292
293template <typename T, typename Comp>
294void remove_duplicates(T& vec, Comp comparator)
295{
296 if(vec.size() <= 1)
297 return;
298
299 std::sort(vec.begin(), vec.end(), comparator);
300 vec.erase(std::unique(vec.begin(), vec.end(), comparator), vec.end());
301}
302
303template <typename Container, typename K, typename Comp, typename... Args>
304auto emplace_sorted(Container& vec, const K& k, Comp&& comp, Args&&... args)
305 -> decltype(auto)
306{
307 auto it = std::lower_bound(vec.begin(), vec.end(), k, std::forward<Comp>(comp));
308 return vec.emplace(it, std::forward<Args>(args)...);
309}
310
311template <
312 typename D, template <typename, typename> typename S, typename T, typename Alloc>
313auto insert_at_end(D& dest, S<T, Alloc>&& src)
314{
315 dest.insert(
316 dest.end(), std::make_move_iterator(src.begin()),
317 std::make_move_iterator(src.end()));
318}
319
320// https://stackoverflow.com/questions/45447361/how-to-move-certain-elements-of-stdvector-to-a-new-index-within-the-vector
321template <typename T>
322void change_item_position(T& v, size_t oldIndex, size_t newIndex)
323{
324 if(oldIndex > newIndex)
325 std::rotate(v.rend() - oldIndex - 1, v.rend() - oldIndex, v.rend() - newIndex);
326 else
327 std::rotate(
328 v.begin() + oldIndex, v.begin() + oldIndex + 1, v.begin() + newIndex + 1);
329}
330
331template <typename Container, typename Item>
332int index_in_container(Container& vec, Item i) noexcept
333{
334 auto it = std::find(vec.begin(), vec.end(), i);
335 if(it != vec.end())
336 return std::distance(vec.begin(), it);
337 else
338 return -1;
339}
340}
Definition git_info.h:7