mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-25 15:12:29 +02:00 
			
		
		
		
	refactor(bar): prefer standard unique_ptr
This commit is contained in:
		| @@ -1,823 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <functional> | ||||
| #include <initializer_list> | ||||
| #include <numeric> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
|  | ||||
| namespace waybar::util { | ||||
|  | ||||
|   /// Joins a sequence of strings, separating them using `js` | ||||
|   template<class StrIterator> // Models InputIterator<std::string> | ||||
|   std::string join_strings(StrIterator b, StrIterator e, std::string_view js = ", ") | ||||
|   { | ||||
|     std::string result; | ||||
|     std::for_each(b, e, [&](auto&& s) { | ||||
|       if (!result.empty()) { | ||||
|         result.append(js); | ||||
|       } | ||||
|       result.append(s); | ||||
|     }); | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   inline const char* nonull(const char* str) { | ||||
|     if (str == nullptr) return ""; | ||||
|     return str; | ||||
|   }; | ||||
|  | ||||
|   inline bool iequals(std::string_view a, std::string_view b) | ||||
|   { | ||||
|     return std::equal(a.begin(), a.end(), b.begin(), b.end(), | ||||
|                       [](char a, char b) { return tolower(a) == tolower(b); }); | ||||
|   } | ||||
|  | ||||
|   inline bool starts_with(std::string_view prefix, std::string_view a) | ||||
|   { | ||||
|     return a.compare(0, prefix.size(), prefix) == 0; | ||||
|   } | ||||
|  | ||||
|   inline bool ends_with(std::string_view prefix, std::string_view a) | ||||
|   { | ||||
|     return a.compare(a.size() - prefix.size(), prefix.size(), prefix) == 0; | ||||
|   } | ||||
|  | ||||
|   /// Return a closure which compares the adress any reference to T to the address of t | ||||
|   template<typename T> | ||||
|   constexpr auto addr_eq(T&& t) { | ||||
|     return [&t] (auto&& t2) { | ||||
|       return &t == &t2; | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   template<typename T> | ||||
|   bool erase_this(std::vector<T>& cont, T* el) | ||||
|   { | ||||
|     if (el < cont.data() && el >= cont.data() + cont.size()) return false; | ||||
|     cont.erase(cont.begin() + (el - cont.data())); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   template<typename T> | ||||
|   bool erase_this(std::vector<T>& cont, T& el) | ||||
|   { | ||||
|     return erase_this(cont, &el); | ||||
|   } | ||||
|  | ||||
|   namespace detail { | ||||
|     template<class Func, int... ns> | ||||
|     constexpr auto generate_array_impl(std::integer_sequence<int, ns...>&&, Func&& gen) | ||||
|     { | ||||
|       return std::array<std::decay_t<decltype(std::invoke(gen, std::declval<int>()))>, | ||||
|                         sizeof...(ns)>{{std::invoke(gen, ns)...}}; | ||||
|     } | ||||
|   } // namespace detail | ||||
|  | ||||
|   template<int n, class Func> | ||||
|   constexpr auto generate_array(Func&& gen) | ||||
|   { | ||||
|     auto intseq = std::make_integer_sequence<int, n>(); | ||||
|     return detail::generate_array_impl(std::move(intseq), std::forward<Func>(gen)); | ||||
|   } | ||||
|  | ||||
|   namespace view { | ||||
|  | ||||
|     namespace detail { | ||||
|       template<typename T> | ||||
|       using store_or_ref_t = std::conditional_t<std::is_rvalue_reference_v<T>, std::decay_t<T>, T&>; | ||||
|     } | ||||
|  | ||||
|     template<typename Cont> | ||||
|     struct reverse { | ||||
|  | ||||
|       reverse(Cont&& cont) noexcept : _container(std::forward<Cont>(cont)) {} | ||||
|  | ||||
|       auto begin() | ||||
|       { | ||||
|         return std::rbegin(_container); | ||||
|       } | ||||
|  | ||||
|       auto end() | ||||
|       { | ||||
|         return std::rend(_container); | ||||
|       } | ||||
|  | ||||
|       auto begin() const | ||||
|       { | ||||
|         return std::rbegin(_container); | ||||
|       } | ||||
|  | ||||
|       auto end() const | ||||
|       { | ||||
|         return std::rend(_container); | ||||
|       } | ||||
|  | ||||
|       auto cbegin() const | ||||
|       { | ||||
|         return std::crbegin(_container); | ||||
|       } | ||||
|  | ||||
|       auto cend() const | ||||
|       { | ||||
|         return std::crend(_container); | ||||
|       } | ||||
|  | ||||
|       detail::store_or_ref_t<Cont&&> _container; | ||||
|     }; | ||||
|  | ||||
|     template<typename ContRef> | ||||
|     reverse(ContRef&& cont) -> reverse<ContRef&&>; | ||||
|  | ||||
|     template<typename Cont> | ||||
|     struct constant { | ||||
|       constant(Cont&& cont) noexcept : _container(std::forward<Cont>(cont)){}; | ||||
|  | ||||
|       auto begin() const | ||||
|       { | ||||
|         return std::cbegin(_container); | ||||
|       } | ||||
|  | ||||
|       auto end() const | ||||
|       { | ||||
|         return std::cend(_container); | ||||
|       } | ||||
|  | ||||
|       auto cbegin() const | ||||
|       { | ||||
|         return std::cbegin(_container); | ||||
|       } | ||||
|  | ||||
|       auto cend() const | ||||
|       { | ||||
|         return std::cend(_container); | ||||
|       } | ||||
|  | ||||
|       detail::store_or_ref_t<Cont&&> _container; | ||||
|     }; | ||||
|  | ||||
|     template<typename ContRef> | ||||
|     constant(ContRef&& cont) -> constant<ContRef&&>; | ||||
|  | ||||
|   } // namespace view | ||||
|  | ||||
|  | ||||
|   /* | ||||
|    * Range algorithms | ||||
|    */ | ||||
|  | ||||
|   template<typename InputIt, typename Size, typename F> | ||||
|   constexpr InputIt for_each_n(InputIt&& first, Size n, F&& f) | ||||
|   { | ||||
|     for (Size i = 0; i < n; ++first, ++i) { | ||||
|       std::invoke(f, *first); | ||||
|     } | ||||
|     return first; | ||||
|   } | ||||
|  | ||||
|   /// `for_each` with access to an index value. Function called as `f(*it, i)` | ||||
|   /// | ||||
|   /// For each item in range `[first, last)`, invoke `f` with args | ||||
|   /// `*iter, i` where `iter` is the current iterator, and `i` is | ||||
|   /// an incrementing value, starting at zero. Use this instead of | ||||
|   /// raw indexed loops wherever possible. | ||||
|   /// | ||||
|   /// \param first Input iterator to the begining of the range | ||||
|   /// \param last Input iterator to the end of the range | ||||
|   /// \param f Must be invocable with arguments `value_type`, `std::size_t` | ||||
|   /// \returns The number of iterations performed | ||||
|   template<typename InputIt, typename F> | ||||
|   constexpr std::size_t indexed_for(InputIt&& first, InputIt&& last, F&& f) | ||||
|   { | ||||
|     std::size_t i = 0; | ||||
|     std::for_each(std::forward<InputIt>(first), std::forward<InputIt>(last), [&](auto&& a) { | ||||
|       std::invoke(f, a, i); | ||||
|       i++; | ||||
|     }); | ||||
|     return i; | ||||
|   } | ||||
|  | ||||
|   template<typename Rng, typename F> | ||||
|   constexpr std::size_t indexed_for(Rng&& rng, F&& f) | ||||
|   { | ||||
|     return indexed_for(std::begin(rng), std::end(rng), std::forward<F>(f)); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /// `for_each_n` with access to an index value. Function called as `f(*it, i)` | ||||
|   /// | ||||
|   /// for `n` iterations, invoke `f` with args `*iter, i` | ||||
|   /// where `iter` is the current iterator starting with `first`, | ||||
|   /// and `i` is an incrementing value, starting at zero. | ||||
|   /// Use this instead of raw indexed loops wherever possible. | ||||
|   /// | ||||
|   /// \param first Input iterator to the begining of the range | ||||
|   /// \param n Number of iterations to go through | ||||
|   /// \param f Must be invocable with arguments `value_type`, `std::size_t` | ||||
|   /// \returns An iterator one past the last one visited | ||||
|   template<class InputIt, class Size, class F> | ||||
|   constexpr InputIt indexed_for_n(InputIt first, Size n, F&& f) | ||||
|   { | ||||
|     for (Size i = 0; i < n; ++first, ++i) { | ||||
|       std::invoke(f, *first, i); | ||||
|     } | ||||
|     return first; | ||||
|   } | ||||
|  | ||||
|   template<class Rng, class Size, class F> | ||||
|   constexpr std::size_t indexed_for_n(Rng&& rng, Size n, F&& f) | ||||
|   { | ||||
|     return indexed_for_n(std::begin(rng), std::end(rng), n, std::forward<F>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Iter1, typename Iter2, typename F> | ||||
|   constexpr void for_both(Iter1&& f1, Iter1&& l1, Iter2&& f2, Iter2&& l2, F&& f) | ||||
|   { | ||||
|     Iter1 i1 = std::forward<Iter1>(f1); | ||||
|     Iter2 i2 = std::forward<Iter2>(f2); | ||||
|     for (; i1 != l1 && i2 != l2; i1++, i2++) { | ||||
|       std::invoke(f, *i1, *i2); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<typename Rng1, typename Rng2, typename F> | ||||
|   constexpr void for_both(Rng1&& r1, Rng2&& r2, F&& f) | ||||
|   { | ||||
|     for_both(std::begin(r1), std::end(r1), std::begin(r2), std::end(r2), std::forward<F>(f)); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Range based standard algorithms | ||||
|    * | ||||
|    * Thanks, chris from SO! | ||||
|    */ | ||||
|  | ||||
|   template<typename Cont, typename T> | ||||
|   constexpr auto accumulate(Cont&& cont, T&& init) | ||||
|   { | ||||
|     // TODO C++20: std::accumulate is constexpr | ||||
|     using std::begin, std::end; | ||||
|     auto first = begin(cont); | ||||
|     auto last = end(cont); | ||||
|     for (; first != last; ++first) init = init + *first; | ||||
|     return init; | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T, typename BinaryOperation> | ||||
|   constexpr auto accumulate(Cont&& cont, T&& init, BinaryOperation&& op) | ||||
|   { | ||||
|     // TODO C++20: std::accumulate is constexpr | ||||
|     using std::begin, std::end; | ||||
|     auto first = begin(cont); | ||||
|     auto last = end(cont); | ||||
|     for (; first != last; ++first) init = op(init, *first); | ||||
|     return init; | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator> | ||||
|   decltype(auto) adjacent_difference(Cont&& cont, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::adjacent_difference(begin(cont), end(cont), std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) prev_permutation(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::prev_permutation(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Compare> | ||||
|   decltype(auto) prev_permutation(Cont&& cont, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::prev_permutation(begin(cont), end(cont), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) push_heap(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::push_heap(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Compare> | ||||
|   decltype(auto) push_heap(Cont&& cont, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::push_heap(begin(cont), end(cont), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T> | ||||
|   decltype(auto) remove(Cont&& cont, T&& value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::remove(begin(cont), end(cont), std::forward<T>(value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator, typename T> | ||||
|   decltype(auto) remove_copy(Cont&& cont, OutputIterator&& first, T&& value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::remove_copy(begin(cont), end(cont), std::forward<OutputIterator>(first), | ||||
|                             std::forward<T>(value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator, typename UnaryPredicate> | ||||
|   decltype(auto) remove_copy_if(Cont&& cont, OutputIterator&& first, UnaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::remove_copy_if(begin(cont), end(cont), std::forward<OutputIterator>(first), | ||||
|                                std::forward<UnaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UnaryPredicate> | ||||
|   decltype(auto) remove_if(Cont&& cont, UnaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::remove_if(begin(cont), end(cont), std::forward<UnaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T, typename T2> | ||||
|   decltype(auto) replace(Cont&& cont, T&& old_value, T2&& new_value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::replace(begin(cont), end(cont), std::forward<T>(old_value), | ||||
|                         std::forward<T2>(new_value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator, typename T, typename T2> | ||||
|   decltype(auto) replace_copy(Cont&& cont, OutputIterator&& first, T&& old_value, T2&& new_value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::replace_copy(begin(cont), end(cont), std::forward<OutputIterator>(first), | ||||
|                              std::forward<T>(old_value), std::forward<T2>(old_value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator, typename UnaryPredicate, typename T> | ||||
|   decltype(auto) replace_copy_if(Cont&& cont, | ||||
|                                  OutputIterator&& first, | ||||
|                                  UnaryPredicate&& p, | ||||
|                                  T&& new_value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::replace_copy(begin(cont), end(cont), std::forward<OutputIterator>(first), | ||||
|                              std::forward<UnaryPredicate>(p), std::forward<T>(new_value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UnaryPredicate, typename T> | ||||
|   decltype(auto) replace_if(Cont&& cont, UnaryPredicate&& p, T&& new_value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::replace_if(begin(cont), end(cont), std::forward<UnaryPredicate>(p), | ||||
|                            std::forward<T>(new_value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) reverse(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::reverse(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator> | ||||
|   decltype(auto) reverse_copy(Cont&& cont, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::reverse_copy(begin(cont), end(cont), std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename ForwardIterator> | ||||
|   decltype(auto) rotate(Cont&& cont, ForwardIterator&& new_first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::rotate(begin(cont), std::forward<ForwardIterator>(new_first), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename ForwardIterator, typename OutputIterator> | ||||
|   decltype(auto) rotate_copy(Cont&& cont, ForwardIterator&& new_first, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::rotate_copy(begin(cont), std::forward<ForwardIterator>(new_first), end(cont), | ||||
|                             std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2> | ||||
|   decltype(auto) search(Cont&& cont, Cont2&& cont2) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::search(begin(cont), end(cont), begin(cont2), end(cont2)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename BinaryPredicate> | ||||
|   decltype(auto) search(Cont&& cont, Cont2&& cont2, BinaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::search(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                        std::forward<BinaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Size, typename T> | ||||
|   decltype(auto) search_n(Cont&& cont, Size count, T&& value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::search_n(begin(cont), end(cont), count, std::forward<T>(value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Size, typename T, typename BinaryPredicate> | ||||
|   decltype(auto) search_n(Cont&& cont, Size count, T&& value, BinaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::search_n(begin(cont), end(cont), count, std::forward<T>(value), | ||||
|                          std::forward<BinaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator> | ||||
|   decltype(auto) set_difference(Cont&& cont, Cont2&& cont2, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_difference(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                                std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator, typename Compare> | ||||
|   decltype(auto) set_difference(Cont&& cont, Cont2&& cont2, OutputIterator&& first, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_difference(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                                std::forward<OutputIterator>(first), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator> | ||||
|   decltype(auto) set_intersection(Cont&& cont, Cont2&& cont2, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_intersection(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                                  std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator, typename Compare> | ||||
|   decltype(auto) set_intersection(Cont&& cont, | ||||
|                                   Cont2&& cont2, | ||||
|                                   OutputIterator&& first, | ||||
|                                   Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_intersection(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                                  std::forward<OutputIterator>(first), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator> | ||||
|   decltype(auto) set_symmetric_difference(Cont&& cont, Cont2&& cont2, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_symmetric_difference(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                                          std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator, typename Compare> | ||||
|   decltype(auto) set_symmetric_difference(Cont&& cont, | ||||
|                                           Cont2&& cont2, | ||||
|                                           OutputIterator&& first, | ||||
|                                           Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_symmetric_difference(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                                          std::forward<OutputIterator>(first), | ||||
|                                          std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator> | ||||
|   decltype(auto) set_union(Cont&& cont, Cont2&& cont2, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_union(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                           std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename OutputIterator, typename Compare> | ||||
|   decltype(auto) set_union(Cont&& cont, Cont2&& cont2, OutputIterator&& first, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::set_union(begin(cont), end(cont), begin(cont2), end(cont2), | ||||
|                           std::forward<OutputIterator>(first), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UniformRandomNumberGenerator> | ||||
|   decltype(auto) shuffle(Cont&& cont, UniformRandomNumberGenerator&& g) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::shuffle(begin(cont), end(cont), std::forward<UniformRandomNumberGenerator>(g)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) sort(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::sort(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Compare> | ||||
|   decltype(auto) sort(Cont&& cont, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::sort(begin(cont), end(cont), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) sort_heap(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::sort_heap(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Compare> | ||||
|   decltype(auto) sort_heap(Cont&& cont, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::sort_heap(begin(cont), end(cont), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UnaryPredicate> | ||||
|   decltype(auto) stable_partition(Cont&& cont, UnaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::stable_partition(begin(cont), end(cont), std::forward<UnaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) stable_sort(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::stable_sort(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Compare> | ||||
|   decltype(auto) stable_sort(Cont&& cont, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::stable_sort(begin(cont), end(cont), std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename ForwardIterator> | ||||
|   decltype(auto) swap_ranges(Cont&& cont, ForwardIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::swap_ranges(begin(cont), end(cont), std::forward<ForwardIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename F> | ||||
|   auto transform(Cont&& cont, Cont2&& cont2, F&& f) -> decltype(begin(cont2)) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::transform(begin(cont), end(cont), begin(cont2), std::forward<F>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Iter, typename F> | ||||
|   decltype(auto) transform(Cont&& cont, Iter&& iter, F&& f) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::transform(begin(cont), end(cont), std::forward<Iter>(iter), std::forward<F>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename Cont3, typename BinaryPredicate> | ||||
|   auto transform(Cont&& cont, Cont2&& cont2, Cont3&& cont3, BinaryPredicate&& f) | ||||
|     -> decltype(begin(cont2), begin(cont3)) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::transform(begin(cont), end(cont), begin(cont2), begin(cont3), | ||||
|                           std::forward<BinaryPredicate>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename InputIterator, typename Cont3, typename BinaryPredicate> | ||||
|   auto transform(Cont&& cont, InputIterator&& iter, Cont3&& cont3, BinaryPredicate&& f) | ||||
|     -> decltype(begin(cont), begin(cont3)) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::transform(begin(cont), end(cont), std::forward<InputIterator>(iter), begin(cont3), | ||||
|                           std::forward<BinaryPredicate>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Cont2, typename InputIterator, typename BinaryPredicate> | ||||
|   auto transform(Cont&& cont, Cont2&& cont2, InputIterator&& iter, BinaryPredicate&& f) | ||||
|     -> decltype(begin(cont), begin(cont2), iter) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::transform(begin(cont), end(cont), begin(cont2), std::forward<InputIterator>(iter), | ||||
|                           std::forward<BinaryPredicate>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename InputIterator, typename OutputIterator, typename BinaryOperation> | ||||
|   decltype(auto) transform(Cont&& cont, | ||||
|                            InputIterator&& firstIn, | ||||
|                            OutputIterator&& firstOut, | ||||
|                            BinaryOperation&& op) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::transform(begin(cont), end(cont), std::forward<InputIterator>(firstIn), | ||||
|                           std::forward<OutputIterator>(firstOut), | ||||
|                           std::forward<BinaryOperation>(op)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) unique(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::unique(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename BinaryPredicate> | ||||
|   decltype(auto) unique(Cont&& cont, BinaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::unique(begin(cont), end(cont), std::forward<BinaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator> | ||||
|   decltype(auto) unique_copy(Cont&& cont, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::unique_copy(begin(cont), end(cont), std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator, typename BinaryPredicate> | ||||
|   decltype(auto) unique_copy(Cont&& cont, OutputIterator&& first, BinaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::unique_copy(begin(cont), end(cont), std::forward<OutputIterator>(first), | ||||
|                             std::forward<BinaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T> | ||||
|   decltype(auto) upper_bound(Cont&& cont, T&& value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::upper_bound(begin(cont), end(cont), std::forward<T>(value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T, typename Compare> | ||||
|   decltype(auto) upper_bound(Cont&& cont, T&& value, Compare&& comp) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::upper_bound(begin(cont), end(cont), std::forward<T>(value), | ||||
|                             std::forward<Compare>(comp)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator> | ||||
|   decltype(auto) copy(Cont&& cont, OutputIterator&& first) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::copy(begin(cont), end(cont), std::forward<OutputIterator>(first)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename OutputIterator, typename UnaryPredicate> | ||||
|   decltype(auto) copy_if(Cont&& cont, OutputIterator&& first, UnaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::copy_if(begin(cont), end(cont), std::forward<OutputIterator>(first), | ||||
|                         std::forward<UnaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T> | ||||
|   decltype(auto) fill(Cont&& cont, T&& value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::fill(begin(cont), end(cont), std::forward<T>(value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T> | ||||
|   decltype(auto) fill_n(Cont&& cont, std::size_t n, T&& value) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::fill_n(begin(cont), n, std::forward<T>(value)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UnaryPredicate> | ||||
|   decltype(auto) any_of(Cont&& cont, UnaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::any_of(begin(cont), end(cont), std::forward<UnaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UnaryPredicate> | ||||
|   decltype(auto) all_of(Cont&& cont, UnaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::all_of(begin(cont), end(cont), std::forward<UnaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UnaryPredicate> | ||||
|   decltype(auto) none_of(Cont&& cont, UnaryPredicate&& p) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::none_of(begin(cont), end(cont), std::forward<UnaryPredicate>(p)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) max_element(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::max_element(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont> | ||||
|   decltype(auto) min_element(Cont&& cont) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::min_element(begin(cont), end(cont)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Compare> | ||||
|   decltype(auto) min_element(Cont&& cont, Compare&& f) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::min_element(begin(cont), end(cont), std::forward<Compare>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename Compare> | ||||
|   decltype(auto) max_element(Cont&& cont, Compare&& f) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::max_element(begin(cont), end(cont), std::forward<Compare>(f)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename T> | ||||
|   decltype(auto) find(Cont&& cont, T&& t) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::find(begin(cont), end(cont), std::forward<T>(t)); | ||||
|   } | ||||
|  | ||||
|   template<typename Cont, typename UnaryPredicate> | ||||
|   decltype(auto) find_if(Cont&& cont, UnaryPredicate&& f) | ||||
|   { | ||||
|     using std::begin; | ||||
|     using std::end; | ||||
|     return std::find_if(begin(cont), end(cont), std::forward<UnaryPredicate>(f)); | ||||
|   } | ||||
|  | ||||
| } // namespace waybar::util | ||||
| @@ -1,581 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <cassert> | ||||
| #include <memory> | ||||
| #include <type_traits> | ||||
| #include <vector> | ||||
| #include "algorithm.hpp" | ||||
|  | ||||
| namespace waybar::util { | ||||
|  | ||||
|   /// An iterator wrapper that dereferences twice. | ||||
|   template<typename Iter> | ||||
|   struct double_iterator { | ||||
|     using wrapped = Iter; | ||||
|  | ||||
|     using value_type = std::decay_t<decltype(*std::declval<typename wrapped::value_type>())>; | ||||
|     using difference_type = typename wrapped::difference_type; | ||||
|     using reference = value_type&; | ||||
|     using pointer = value_type*; | ||||
|     using iterator_category = std::random_access_iterator_tag; | ||||
|  | ||||
|     using self_t = double_iterator<Iter>; | ||||
|  | ||||
|     double_iterator(wrapped w) : _iter(std::move(w)) {} | ||||
|     double_iterator() : _iter() {} | ||||
|  | ||||
|     reference operator*() const | ||||
|     { | ||||
|       return (**_iter); | ||||
|     } | ||||
|     pointer operator->() const | ||||
|     { | ||||
|       return &(**_iter); | ||||
|     } | ||||
|  | ||||
|     self_t& operator++() | ||||
|     { | ||||
|       _iter.operator++(); | ||||
|       return *this; | ||||
|     } | ||||
|     self_t operator++(int i) | ||||
|     { | ||||
|       return _iter.operator++(i); | ||||
|     } | ||||
|     self_t& operator--() | ||||
|     { | ||||
|       _iter.operator--(); | ||||
|       return *this; | ||||
|     } | ||||
|     self_t operator--(int i) | ||||
|     { | ||||
|       return _iter.operator--(i); | ||||
|     } | ||||
|  | ||||
|     auto operator==(const self_t& rhs) const noexcept | ||||
|     { | ||||
|       return _iter == rhs._iter; | ||||
|     } | ||||
|     auto operator!=(const self_t& rhs) const noexcept | ||||
|     { | ||||
|       return _iter != rhs._iter; | ||||
|     } | ||||
|     auto operator<(const self_t& rhs) const noexcept | ||||
|     { | ||||
|       return _iter < rhs._iter; | ||||
|     } | ||||
|     auto operator>(const self_t& rhs) const noexcept | ||||
|     { | ||||
|       return _iter > rhs._iter; | ||||
|     } | ||||
|     auto operator<=(const self_t& rhs) const noexcept | ||||
|     { | ||||
|       return _iter <= rhs._iter; | ||||
|     } | ||||
|     auto operator>=(const self_t& rhs) const noexcept | ||||
|     { | ||||
|       return _iter >= rhs._iter; | ||||
|     } | ||||
|  | ||||
|     self_t operator+(difference_type d) const noexcept | ||||
|     { | ||||
|       return _iter + d; | ||||
|     } | ||||
|     self_t operator-(difference_type d) const noexcept | ||||
|     { | ||||
|       return _iter - d; | ||||
|     } | ||||
|     auto operator-(const self_t& rhs) const noexcept | ||||
|     { | ||||
|       return _iter - rhs._iter; | ||||
|     } | ||||
|  | ||||
|     self_t& operator+=(difference_type d) | ||||
|     { | ||||
|       _iter += d; | ||||
|       return *this; | ||||
|     } | ||||
|     self_t& operator-=(difference_type d) | ||||
|     { | ||||
|       _iter -= d; | ||||
|       return *this; | ||||
|     } | ||||
|  | ||||
|     operator wrapped&() | ||||
|     { | ||||
|       return _iter; | ||||
|     } | ||||
|     operator const wrapped&() const | ||||
|     { | ||||
|       return _iter; | ||||
|     } | ||||
|  | ||||
|     wrapped& data() | ||||
|     { | ||||
|       return _iter; | ||||
|     } | ||||
|     const wrapped& data() const | ||||
|     { | ||||
|       return _iter; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     wrapped _iter; | ||||
|   }; | ||||
|  | ||||
|   template<typename Iter> | ||||
|   auto operator+(typename double_iterator<Iter>::difference_type diff, double_iterator<Iter> iter) | ||||
|   { | ||||
|     return iter + diff; | ||||
|   } | ||||
|  | ||||
|   /// To avoid clients being moved, they are stored in unique_ptrs, which are | ||||
|   /// moved around in a vector. This class is purely for convenience, to still | ||||
|   /// have iterator semantics, and a few other utility functions | ||||
|   template<typename T> | ||||
|   struct ptr_vec { | ||||
|     using value_type = T; | ||||
|  | ||||
|     std::vector<std::unique_ptr<value_type>> _order; | ||||
|  | ||||
|     using iterator = double_iterator<typename decltype(_order)::iterator>; | ||||
|     using const_iterator = double_iterator<typename decltype(_order)::const_iterator>; | ||||
|  | ||||
|     using reverse_iterator = double_iterator<typename decltype(_order)::reverse_iterator>; | ||||
|     using const_reverse_iterator = | ||||
|       double_iterator<typename decltype(_order)::const_reverse_iterator>; | ||||
|  | ||||
|     value_type& push_back(const value_type& v) | ||||
|     { | ||||
|       auto ptr = std::make_unique<value_type>(v); | ||||
|       auto res = ptr.get(); | ||||
|       _order.push_back(std::move(ptr)); | ||||
|       return *res; | ||||
|     } | ||||
|  | ||||
|     value_type& push_back(value_type&& v) | ||||
|     { | ||||
|       auto ptr = std::make_unique<value_type>(std::move(v)); | ||||
|       auto res = ptr.get(); | ||||
|       _order.push_back(std::move(ptr)); | ||||
|       return *res; | ||||
|     } | ||||
|  | ||||
|     value_type& push_back(std::unique_ptr<value_type> ptr) | ||||
|     { | ||||
|       auto res = ptr.get(); | ||||
|       _order.push_back(std::move(ptr)); | ||||
|       return *res; | ||||
|     } | ||||
|  | ||||
|     template<typename... Args> | ||||
|     value_type& emplace_back(Args&&... args) | ||||
|     { | ||||
|       return push_back(std::make_unique<value_type>(std::forward<Args>(args)...)); | ||||
|     } | ||||
|  | ||||
|     std::unique_ptr<value_type> erase(const value_type& v) | ||||
|     { | ||||
|       auto iter = | ||||
|         std::find_if(_order.begin(), _order.end(), [&v](auto&& uptr) { return uptr.get() == &v; }); | ||||
|       if (iter != _order.end()) { | ||||
|         auto uptr = std::move(*iter); | ||||
|         _order.erase(iter); | ||||
|         return uptr; | ||||
|       } | ||||
|       return nullptr; | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_back(const value_type& v) | ||||
|     { | ||||
|       auto iter = | ||||
|         std::find_if(_order.begin(), _order.end(), [&v](auto&& uptr) { return uptr.get() == &v; }); | ||||
|       return rotate_to_back(iter); | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_back(iterator iter) | ||||
|     { | ||||
|       if (iter != _order.end()) { | ||||
|         { | ||||
|           return std::rotate(iter.data(), iter.data() + 1, _order.end()); | ||||
|         } | ||||
|       } | ||||
|       return end(); | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_front(const value_type& v) | ||||
|     { | ||||
|       auto iter = | ||||
|         std::find_if(_order.begin(), _order.end(), [&v](auto&& uptr) { return uptr.get() == &v; }); | ||||
|       return rotate_to_front(iter); | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_front(iterator iter) | ||||
|     { | ||||
|       if (iter != _order.end()) { | ||||
|         { | ||||
|           return std::rotate(_order.begin(), iter.data(), iter.data() + 1); | ||||
|         } | ||||
|       } | ||||
|       return end(); | ||||
|     } | ||||
|  | ||||
|     std::size_t size() const noexcept | ||||
|     { | ||||
|       return _order.size(); | ||||
|     } | ||||
|  | ||||
|     bool empty() const noexcept | ||||
|     { | ||||
|       return _order.empty(); | ||||
|     } | ||||
|  | ||||
|     std::size_t capacity() const noexcept | ||||
|     { | ||||
|       return _order.capacity(); | ||||
|     } | ||||
|  | ||||
|     std::size_t max_size() const noexcept | ||||
|     { | ||||
|       return _order.max_size(); | ||||
|     } | ||||
|  | ||||
|     void reserve(std::size_t new_cap)  | ||||
|     { | ||||
|       _order.reserve(new_cap); | ||||
|     } | ||||
|  | ||||
|     void shrink_to_fit() | ||||
|     { | ||||
|       _order.shrink_to_fit(); | ||||
|     } | ||||
|  | ||||
|     value_type& operator[](std::size_t n) | ||||
|     { | ||||
|       return *_order[n]; | ||||
|     } | ||||
|  | ||||
|     const value_type& operator[](std::size_t n) const | ||||
|     { | ||||
|       return *_order[n]; | ||||
|     } | ||||
|  | ||||
|     value_type& at(std::size_t n) | ||||
|     { | ||||
|       return *_order.at(n); | ||||
|     } | ||||
|  | ||||
|     const value_type& at(std::size_t n) const | ||||
|     { | ||||
|       return *_order.at(n); | ||||
|     } | ||||
|  | ||||
|     iterator begin() | ||||
|     { | ||||
|       return _order.begin(); | ||||
|     } | ||||
|     iterator end() | ||||
|     { | ||||
|       return _order.end(); | ||||
|     } | ||||
|     const_iterator begin() const | ||||
|     { | ||||
|       return _order.begin(); | ||||
|     } | ||||
|     const_iterator end() const | ||||
|     { | ||||
|       return _order.end(); | ||||
|     } | ||||
|  | ||||
|     reverse_iterator rbegin() | ||||
|     { | ||||
|       return _order.rbegin(); | ||||
|     } | ||||
|     reverse_iterator rend() | ||||
|     { | ||||
|       return _order.rend(); | ||||
|     } | ||||
|     const_reverse_iterator rbegin() const | ||||
|     { | ||||
|       return _order.rbegin(); | ||||
|     } | ||||
|     const_reverse_iterator rend() const | ||||
|     { | ||||
|       return _order.rend(); | ||||
|     } | ||||
|  | ||||
|     value_type& front() | ||||
|     { | ||||
|       return *_order.front(); | ||||
|     } | ||||
|  | ||||
|     value_type& back() | ||||
|     { | ||||
|       return *_order.back(); | ||||
|     } | ||||
|  | ||||
|     const value_type& front() const | ||||
|     { | ||||
|       return *_order.front(); | ||||
|     } | ||||
|  | ||||
|     const value_type& back() const | ||||
|     { | ||||
|       return *_order.back(); | ||||
|     } | ||||
|  | ||||
|     std::vector<std::unique_ptr<value_type>>& underlying() { | ||||
|       return _order; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<typename T, typename T2> | ||||
|   std::unique_ptr<T> erase_this(ptr_vec<T>& vec, T2* el) | ||||
|   { | ||||
|     return vec.erase(*el); | ||||
|   } | ||||
|  | ||||
|   template<typename T, typename T2> | ||||
|   std::unique_ptr<T> erase_this(ptr_vec<T>& vec, T2& el) | ||||
|   { | ||||
|     return vec.erase(el); | ||||
|   } | ||||
|  | ||||
|   template<typename T> | ||||
|   struct non_null_ptr { | ||||
|     non_null_ptr() = delete; | ||||
|     constexpr non_null_ptr(T* ptr) : _ptr(ptr) | ||||
|     { | ||||
|       assert(ptr != nullptr); | ||||
|     } | ||||
|     non_null_ptr(std::nullptr_t) = delete; | ||||
|  | ||||
|     constexpr non_null_ptr(const non_null_ptr&) = default; | ||||
|     constexpr non_null_ptr(non_null_ptr&&) = default; | ||||
|     constexpr non_null_ptr& operator=(const non_null_ptr&) = default; | ||||
|     constexpr non_null_ptr& operator=(non_null_ptr&&) = default; | ||||
|  | ||||
|     constexpr T& operator*() const noexcept | ||||
|     { | ||||
|       return *_ptr; | ||||
|     } | ||||
|  | ||||
|     constexpr T* operator->() const noexcept | ||||
|     { | ||||
|       return _ptr; | ||||
|     } | ||||
|  | ||||
|     constexpr operator T*() noexcept | ||||
|     { | ||||
|       return _ptr; | ||||
|     } | ||||
|  | ||||
|     constexpr operator T* const() const noexcept | ||||
|     { | ||||
|       return _ptr; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     T* _ptr; | ||||
|   }; | ||||
|  | ||||
|   template<typename T> | ||||
|   struct ref_vec { | ||||
|     using value_type = T; | ||||
|  | ||||
|     std::vector<value_type*> _order; | ||||
|  | ||||
|     using iterator = double_iterator<typename decltype(_order)::iterator>; | ||||
|     using const_iterator = double_iterator<typename decltype(_order)::const_iterator>; | ||||
|  | ||||
|     using reverse_iterator = double_iterator<typename decltype(_order)::reverse_iterator>; | ||||
|     using const_reverse_iterator = | ||||
|       double_iterator<typename decltype(_order)::const_reverse_iterator>; | ||||
|  | ||||
|     ref_vec() = default; | ||||
|  | ||||
|     ref_vec(std::initializer_list<value_type*> lst) : _order {lst} { }; | ||||
|  | ||||
|     template<typename InputIter, typename = std::enable_if_t<std::is_same_v<decltype(*std::declval<InputIter>()), value_type&>>> | ||||
|     ref_vec(InputIter iter1, InputIter iter2) { | ||||
|       _order.reserve(std::distance(iter1, iter2)); | ||||
|       std::transform(iter1, iter2, std::back_inserter(_order), [] (auto& v) {return &v; });       | ||||
|     } | ||||
|  | ||||
|     template<typename Range, typename  = std::enable_if_t<std::is_same_v<decltype(*std::declval<Range>().begin()), value_type&>>> | ||||
|     ref_vec(Range&& rng) : ref_vec (std::begin(rng), std::end(rng)) { } | ||||
|  | ||||
|     value_type& push_back(value_type& v) | ||||
|     { | ||||
|       _order.push_back(&v); | ||||
|       return v; | ||||
|     } | ||||
|  | ||||
|     value_type& push_back(non_null_ptr<value_type> ptr) | ||||
|     { | ||||
|       _order.push_back(ptr); | ||||
|       return *ptr; | ||||
|     } | ||||
|  | ||||
|     value_type& emplace_back(value_type& v) | ||||
|     { | ||||
|       return push_back(v); | ||||
|     } | ||||
|  | ||||
|     std::unique_ptr<value_type> erase(const value_type& v) | ||||
|     { | ||||
|       auto iter = | ||||
|         std::find_if(_order.begin(), _order.end(), [&v](auto&& ptr) { return ptr == &v; }); | ||||
|       if (iter != _order.end()) { | ||||
|         auto uptr = std::move(*iter); | ||||
|         _order.erase(iter); | ||||
|         return uptr; | ||||
|       } | ||||
|       return nullptr; | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_back(const value_type& v) | ||||
|     { | ||||
|       auto iter = | ||||
|         std::find_if(_order.begin(), _order.end(), [&v](auto&& ptr) { return ptr == &v; }); | ||||
|       return rotate_to_back(iter); | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_back(iterator iter) | ||||
|     { | ||||
|       if (iter != _order.end()) { | ||||
|         { | ||||
|           return std::rotate(iter.data(), iter.data() + 1, _order.end()); | ||||
|         } | ||||
|       } | ||||
|       return end(); | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_front(const value_type& v) | ||||
|     { | ||||
|       auto iter = | ||||
|         std::find_if(_order.begin(), _order.end(), [&v](auto&& ptr) { return ptr == &v; }); | ||||
|       return rotate_to_front(iter); | ||||
|     } | ||||
|  | ||||
|     iterator rotate_to_front(iterator iter) | ||||
|     { | ||||
|       if (iter != _order.end()) { | ||||
|         { | ||||
|           return std::rotate(_order.begin(), iter.data(), iter.data() + 1); | ||||
|         } | ||||
|       } | ||||
|       return end(); | ||||
|     } | ||||
|  | ||||
|     std::size_t size() const noexcept | ||||
|     { | ||||
|       return _order.size(); | ||||
|     } | ||||
|  | ||||
|     bool empty() const noexcept | ||||
|     { | ||||
|       return _order.empty(); | ||||
|     } | ||||
|  | ||||
|     std::size_t capacity() const noexcept | ||||
|     { | ||||
|       return _order.capacity(); | ||||
|     } | ||||
|  | ||||
|     std::size_t max_size() const noexcept | ||||
|     { | ||||
|       return _order.max_size(); | ||||
|     } | ||||
|  | ||||
|     void reserve(std::size_t new_cap)  | ||||
|     { | ||||
|       _order.reserve(new_cap); | ||||
|     } | ||||
|  | ||||
|     void shrink_to_fit() | ||||
|     { | ||||
|       _order.shrink_to_fit(); | ||||
|     } | ||||
|  | ||||
|     value_type& operator[](std::size_t n) | ||||
|     { | ||||
|       return *_order[n]; | ||||
|     } | ||||
|  | ||||
|     const value_type& operator[](std::size_t n) const | ||||
|     { | ||||
|       return *_order[n]; | ||||
|     } | ||||
|  | ||||
|     value_type& at(std::size_t n) | ||||
|     { | ||||
|       return *_order.at(n); | ||||
|     } | ||||
|  | ||||
|     const value_type& at(std::size_t n) const | ||||
|     { | ||||
|       return *_order.at(n); | ||||
|     } | ||||
|  | ||||
|     iterator begin() | ||||
|     { | ||||
|       return _order.begin(); | ||||
|     } | ||||
|     iterator end() | ||||
|     { | ||||
|       return _order.end(); | ||||
|     } | ||||
|     const_iterator begin() const | ||||
|     { | ||||
|       return _order.begin(); | ||||
|     } | ||||
|     const_iterator end() const | ||||
|     { | ||||
|       return _order.end(); | ||||
|     } | ||||
|  | ||||
|     reverse_iterator rbegin() | ||||
|     { | ||||
|       return _order.rbegin(); | ||||
|     } | ||||
|     reverse_iterator rend() | ||||
|     { | ||||
|       return _order.rend(); | ||||
|     } | ||||
|     const_reverse_iterator rbegin() const | ||||
|     { | ||||
|       return _order.rbegin(); | ||||
|     } | ||||
|     const_reverse_iterator rend() const | ||||
|     { | ||||
|       return _order.rend(); | ||||
|     } | ||||
|  | ||||
|     value_type& front() | ||||
|     { | ||||
|       return *_order.front(); | ||||
|     } | ||||
|  | ||||
|     value_type& back() | ||||
|     { | ||||
|       return *_order.back(); | ||||
|     } | ||||
|  | ||||
|     const value_type& front() const | ||||
|     { | ||||
|       return *_order.front(); | ||||
|     } | ||||
|  | ||||
|     const value_type& back() const | ||||
|     { | ||||
|       return *_order.back(); | ||||
|     } | ||||
|  | ||||
|     std::vector<value_type*>& underlying() { | ||||
|       return _order; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|  | ||||
| } // namespace waybar::util | ||||
		Reference in New Issue
	
	Block a user
	 Alexis
					Alexis