geode/loader/include/Geode/utils/ranges.hpp

202 lines
6.2 KiB
C++
Raw Normal View History

#pragma once
#include <Geode/DefaultInclude.hpp>
#include <string>
#include <algorithm>
namespace geode::utils::ranges {
template<class C>
concept ValidConstContainer = requires(C const& c) {
c.begin();
c.end();
{ c.size() } -> std::convertible_to<size_t>;
typename C::value_type;
typename C::iterator;
typename C::const_iterator;
};
template<class C>
concept ValidMutContainer = requires(C& c) {
c.begin();
c.end();
{ c.size() } -> std::convertible_to<size_t>;
typename C::value_type;
typename C::iterator;
typename C::const_iterator;
};
template<class C>
concept ValidContainer = ValidConstContainer<C> && ValidMutContainer<C>;
template<class P, class C>
concept ValidCUnaryPredicate = requires(P p, typename C::value_type const& t) {
{ p(t) } -> std::convertible_to<bool>;
};
template<class P, class From, class Into>
concept ValidIntoConverter = requires(P p, From const& t) {
{ p(t) } -> std::convertible_to<Into>;
};
template<ValidConstContainer C>
bool contains(C const& cont, typename C::value_type const& elem) {
return std::find(cont.begin(), cont.end(), elem) != cont.end();
}
template<ValidConstContainer C, ValidCUnaryPredicate<C> Predicate>
bool contains(C const& cont, Predicate fun) {
return std::find_if(cont.begin(), cont.end(), fun) != cont.end();
}
template<ValidConstContainer C, ValidCUnaryPredicate<C> Predicate>
std::optional<typename C::value_type> find(C const& cont, Predicate fun) {
auto it = std::find_if(cont.begin(), cont.end(), fun);
if (it != cont.end()) {
return std::optional(*it);
}
return std::nullopt;
}
template<ValidConstContainer C>
std::optional<size_t> indexOf(C const& cont, typename C::value_type const& elem) {
auto it = std::find(cont.begin(), cont.end(), elem);
if (it != cont.end()) {
return std::optional(std::distance(cont.begin(), it));
}
return std::nullopt;
}
template<ValidConstContainer C, ValidCUnaryPredicate<C> Predicate>
std::optional<size_t> indexOf(C const& cont, Predicate fun) {
auto it = std::find_if(cont.begin(), cont.end(), fun);
if (it != cont.end()) {
return std::optional(std::distance(cont.begin(), it));
}
return std::nullopt;
}
template<ValidMutContainer C>
bool move(C& cont, typename C::value_type const& elem, size_t where) {
if (where > cont.size() - 1) {
return false;
}
auto ix = indexOf(cont, elem);
if (ix) {
if (ix.value() > where) {
std::rotate(
cont.rend() - ix.value() - 1,
cont.rend() - ix.value(),
cont.rend() - where
);
} else {
std::rotate(
cont.begin() + ix.value(),
cont.begin() + ix.value() + 1,
cont.begin() + where + 1
);
}
return true;
}
return false;
}
template<ValidConstContainer C, class Output>
requires
std::is_default_constructible_v<Output> &&
std::is_convertible_v<Output, typename C::value_type>
Output join(C const& cont, Output const& separator) {
auto res = Output();
bool first = true;
for (auto& p : cont) {
if (!first) {
res += separator;
} else {
first = false;
}
res += p;
}
return res;
}
template<ValidConstContainer C>
std::string join(C const& cont, std::string const& separator) {
auto res = std::string();
bool first = true;
for (auto& p : cont) {
if (!first) {
res += separator;
} else {
first = false;
}
res += p;
}
return res;
}
template<
ValidConstContainer C,
class Output,
ValidIntoConverter<typename C::value_type, Output> Conv
>
requires
std::is_default_constructible_v<Output>
Output join(C const& cont, Output const& separator, Conv converter) {
auto res = Output();
bool first = true;
for (auto& p : cont) {
if (!first) {
res += separator;
} else {
first = false;
}
2022-10-24 15:46:39 -04:00
res += converter(p);
}
return res;
}
template<ValidContainer C>
C& push(C& container, C const& toAdd) {
container.insert(container.end(), toAdd.begin(), toAdd.end());
return container;
}
template<ValidMutContainer C>
C& remove(C& container, typename C::value_type const& value) {
container.erase(
std::remove(container.begin(), container.end(), value),
container.end()
);
return container;
}
template<ValidContainer C, ValidCUnaryPredicate<C> Predicate>
C filter(C const& container, Predicate filterFun) {
auto res = C();
std::copy_if(container.begin(), container.end(), res.end(), filterFun);
return res;
}
template<class R, ValidConstContainer C, class Reducer>
requires requires(Reducer r, R& acc, typename C::value_type t) {
r(acc, t);
}
R reduce(C const& container, Reducer reducer) {
auto res = R();
for (auto& item : container) {
reducer(res, item);
}
return res;
}
template<
ValidConstContainer From,
ValidContainer Into,
ValidIntoConverter<typename From::value_type, typename Into::value_type> Mapper
>
Into map(From const& from, Mapper mapper) {
auto res = Into();
std::transform(from.begin(), from.end(), res.end(), mapper);
return res;
}
}