diff --git a/loader/include/Geode/loader/Setting.hpp b/loader/include/Geode/loader/Setting.hpp index 0d203e03..30efd6e6 100644 --- a/loader/include/Geode/loader/Setting.hpp +++ b/loader/include/Geode/loader/Setting.hpp @@ -9,6 +9,7 @@ #include <Geode/utils/JsonValidation.hpp> #include <Geode/utils/convert.hpp> #include <Geode/utils/platform.hpp> +#include <Geode/utils/ranges.hpp> #include <regex> #pragma warning(push) @@ -266,7 +267,7 @@ namespace geode { value = static_cast<Class*>(this)->getDefault(); return Err( "Value must be one of " + - utils::container::join(m_oneOf.value(), ", ") + utils::ranges::join(m_oneOf.value(), ", ") ); } return Ok(); diff --git a/loader/include/Geode/utils/container.hpp b/loader/include/Geode/utils/container.hpp index 411feff6..d2faf9ae 100644 --- a/loader/include/Geode/utils/container.hpp +++ b/loader/include/Geode/utils/container.hpp @@ -12,6 +12,7 @@ namespace geode::utils::container { * @returns True if element is in `vec`, false if not. */ template<class C, class T> + [[deprecated("Use geode::utils::ranges::contains instead")]] bool contains(C const& cont, T const& elem) { return std::find(cont.begin(), cont.end(), elem) != cont.end(); } @@ -25,6 +26,7 @@ namespace geode::utils::container { * in `vec`, false if not. */ template<class C, class T> + [[deprecated("Use geode::utils::ranges::contains instead")]] bool contains(C const& cont, std::function<bool(T)> containFunc) { for (auto const& item : cont) { if (containFunc(item)) @@ -41,6 +43,7 @@ namespace geode::utils::container { * @returns Joined string. */ template<class C> + [[deprecated("Use geode::utils::ranges::join instead")]] std::string join(C const& cont, std::string const& sep) { std::string res = ""; bool first = true; @@ -67,6 +70,7 @@ namespace geode::utils::container { * @returns Mapped container. */ template<class C, class C2, class T, class T2> + [[deprecated("Use geode::utils::ranges::map instead")]] C2 map(C const& cont, std::function<T2(T)> mapFunc) { C2 res; std::transform(cont.begin(), cont.end(), res.end(), mapFunc); diff --git a/loader/include/Geode/utils/ranges.hpp b/loader/include/Geode/utils/ranges.hpp new file mode 100644 index 00000000..ed7e0471 --- /dev/null +++ b/loader/include/Geode/utils/ranges.hpp @@ -0,0 +1,143 @@ +#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(); + typename C::value_type; + }; + + template<class C> + concept ValidMutContainer = requires(C& c) { + c.begin(); + c.end(); + typename C::value_type; + }; + + 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, 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; + } + res += Conv(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) } -> std::same_as<void>; + } + 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; + } +} diff --git a/loader/include/Geode/utils/vector.hpp b/loader/include/Geode/utils/vector.hpp index 003b5144..f9919fbf 100644 --- a/loader/include/Geode/utils/vector.hpp +++ b/loader/include/Geode/utils/vector.hpp @@ -14,7 +14,8 @@ namespace geode::utils::vector { * @returns True if element is in `vec`, false if not. */ template<class T> - bool contains(gd::vector<T> const& vec, T const& elem) { + [[deprecated("Use geode::utils::ranges::contains instead")]] + bool contains(std::vector<T> const& vec, T const& elem) { return std::find(vec.begin(), vec.end(), elem) != vec.end(); } @@ -23,10 +24,11 @@ namespace geode::utils::vector { * @param vec The vector to check. * @param elem The element to get the index of. * @returns Iterator to the index of element, or - * gd::vector::end if the item is not in the vector. + * std::vector::end if the item is not in the vector. */ template<class T> - typename gd::vector<T>::const_iterator indexOf(gd::vector<T> const& vec, T const& elem) { + [[deprecated("Useless utility, if you want it added to geode::utils::ranges open an Issue on GitHub")]] + typename std::vector<T>::const_iterator indexOf(std::vector<T> const& vec, T const& elem) { return std::find(vec.begin(), vec.end(), elem); } @@ -39,7 +41,8 @@ namespace geode::utils::vector { * in `vec`, false if not. */ template<class T> - bool contains(gd::vector<T> const& vec, std::function<bool(T)> containFunc) { + [[deprecated("Use geode::utils::ranges::contains instead")]] + bool contains(std::vector<T> const& vec, std::function<bool(T)> containFunc) { for (auto const& item : vec) { if (containFunc(item)) return true; @@ -53,7 +56,8 @@ namespace geode::utils::vector { * @param subVec The vector to add. */ template<class T> - void push(gd::vector<T> & vec, gd::vector<T> const& subVec) { + [[deprecated("Use geode::utils::ranges::push instead")]] + void push(std::vector<T> & vec, std::vector<T> const& subVec) { vec.insert(vec.begin(), subVec.begin(), subVec.end()); } @@ -65,7 +69,8 @@ namespace geode::utils::vector { * @returns Joined string. */ template<class T> - std::string join(gd::vector<T> const& vec, std::string const& sep) { + [[deprecated("Use geode::utils::ranges::join instead")]] + std::string join(std::vector<T> const& vec, std::string const& sep) { std::string res = ""; for (auto p : vec) { @@ -89,8 +94,9 @@ namespace geode::utils::vector { * @returns Mapped vector. */ template<class T, class T2> - gd::vector<T2> map(gd::vector<T> const& vec, std::function<T2(T)> mapFunc) { - gd::vector<T2> res; + [[deprecated("Use geode::utils::ranges::map instead")]] + std::vector<T2> map(std::vector<T> const& vec, std::function<T2(T)> mapFunc) { + std::vector<T2> res; std::transform(vec.begin(), vec.end(), res.end(), mapFunc); return res; } @@ -104,8 +110,9 @@ namespace geode::utils::vector { * @returns Filtered vector. */ template<class T> - gd::vector<T>& filterIP(gd::vector<T> & vec, std::function<bool(T)> filterFunc) { - gd::vector<T> res; + [[deprecated("Useless utility, if you want it added to geode::utils::ranges open an Issue on GitHub")]] + std::vector<T>& filterIP(std::vector<T> & vec, std::function<bool(T)> filterFunc) { + std::vector<T> res; for (auto m : vec) { if (filterFunc(m)) { res.push_back(m); @@ -124,8 +131,9 @@ namespace geode::utils::vector { * @returns Filtered vector. */ template<class T> - gd::vector<T> filter(gd::vector<T> const& vec, std::function<bool(T)> filterFunc) { - gd::vector<T> res; + [[deprecated("Use geode::utils::ranges::filter instead")]] + std::vector<T> filter(std::vector<T> const& vec, std::function<bool(T)> filterFunc) { + std::vector<T> res; for (auto m : vec) { if (filterFunc(m)) { res.push_back(m); @@ -145,7 +153,8 @@ namespace geode::utils::vector { * found, the return type is nullptr. */ template<class T> - T select(gd::vector<T> const& vec, std::function<bool(T)> selectFunc) { + [[deprecated("Useless utility, if you want it added to geode::utils::ranges open an Issue on GitHub")]] + T select(std::vector<T> const& vec, std::function<bool(T)> selectFunc) { for (auto const& v : vec) { if (selectFunc(v)) { return v; @@ -165,7 +174,8 @@ namespace geode::utils::vector { * @returns Filtered vector. */ template<class T> - gd::vector<T> selectAll(gd::vector<T> const& vec, std::function<bool(T)> selectFunc) { + [[deprecated("Useless utility, if you want it added to geode::utils::ranges open an Issue on GitHub")]] + std::vector<T> selectAll(std::vector<T> const& vec, std::function<bool(T)> selectFunc) { return filter<T>(vec, selectFunc); } @@ -176,7 +186,8 @@ namespace geode::utils::vector { * @returns Reference to vector. */ template<class T> - gd::vector<T>& erase(gd::vector<T>& vec, T const& element) { + [[deprecated("Use geode::utils::ranges::remove instead")]] + std::vector<T>& erase(std::vector<T>& vec, T const& element) { vec.erase(std::remove(vec.begin(), vec.end(), element), vec.end()); return vec; } @@ -189,7 +200,8 @@ namespace geode::utils::vector { * @returns Reference to vector. */ template<class T> - gd::vector<T>& erase(gd::vector<T>& vec, std::function<bool(T)> eraseFunc) { + [[deprecated("Use geode::utils::ranges::remove instead")]] + std::vector<T>& erase(std::vector<T>& vec, std::function<bool(T)> eraseFunc) { vec.erase(std::remove_if(vec.begin(), vec.end(), eraseFunc), vec.end()); return vec; } @@ -204,7 +216,7 @@ namespace geode::utils::vector { * accumulator, for example with R += T, to * compute the reduced value. * @example ```cpp - * gd::vector<int> numbers = { 1, 3, 7, 8, }; + * std::vector<int> numbers = { 1, 3, 7, 8, }; * int total = reduce<int, int>(numbers, [](int& acc, int val) -> void { * acc += val; * }); // 19 @@ -212,7 +224,8 @@ namespace geode::utils::vector { * @returns Reduced value. */ template<class R, class T> - R reduce(gd::vector<T> const& vec, std::function<void(R&, T)> reduceFunc) { + [[deprecated("Use geode::utils::ranges::reduce instead")]] + R reduce(std::vector<T> const& vec, std::function<void(R&, T)> reduceFunc) { R res = R(); for (auto const& item : vec) { reduceFunc(res, item); @@ -228,7 +241,8 @@ namespace geode::utils::vector { * @param after Element to insert before. */ template<class T> - void insertBefore(gd::vector<T> & vec, T const& item, T const& before) { + [[deprecated("Useless utility, if you want it added to geode::utils::ranges open an Issue on GitHub")]] + void insertBefore(std::vector<T> & vec, T const& item, T const& before) { vec.insert(utils::vector::indexOf(vec, before), item); } @@ -240,7 +254,8 @@ namespace geode::utils::vector { * @param after Element to insert after. */ template<class T> - void insertAfter(gd::vector<T> & vec, T const& item, T const& after) { + [[deprecated("Useless utility, if you want it added to geode::utils::ranges open an Issue on GitHub")]] + void insertAfter(std::vector<T> & vec, T const& item, T const& after) { vec.insert(utils::vector::indexOf(vec, after) + 1, item); } } diff --git a/loader/src/index/Index.cpp b/loader/src/index/Index.cpp index a2b0a018..5b0037b4 100644 --- a/loader/src/index/Index.cpp +++ b/loader/src/index/Index.cpp @@ -9,6 +9,7 @@ #include <Geode/utils/vector.hpp> #include <Geode/utils/map.hpp> #include <Geode/utils/general.hpp> +#include <Geode/utils/ranges.hpp> #include <Geode/loader/Loader.hpp> #include <Geode/loader/Mod.hpp> #include <Geode/binding/FLAlertLayer.hpp> @@ -447,7 +448,7 @@ Result<InstallHandle> Index::installItems( if (!list) { return Err(list.error()); } - utils::vector::push(ids, list.value()); + ranges::push(ids, list.value()); } auto ret = std::make_shared<InstallItems>( std::unordered_set(ids.begin(), ids.end()) @@ -617,7 +618,7 @@ void InstallItems::finish(bool replaceFiles) { FLAlertLayer::create( "Mods installed", "The following <cy>mods</c> have been installed: " + - container::join(m_toInstall, ",") + "\n" + ranges::join(m_toInstall, std::string(",")) + "\n" "Please <cr>restart the game</c> to apply", "OK" )->show(); diff --git a/loader/src/load/Hook.cpp b/loader/src/load/Hook.cpp index 70b9c248..135bd330 100644 --- a/loader/src/load/Hook.cpp +++ b/loader/src/load/Hook.cpp @@ -4,6 +4,7 @@ #include <Geode/loader/Loader.hpp> #include <Geode/utils/casts.hpp> #include <Geode/utils/vector.hpp> +#include <Geode/utils/ranges.hpp> // #include <hook/hook.hpp> #include <Geode/hook-core/Hook.hpp> #include "InternalLoader.hpp" @@ -60,7 +61,7 @@ Result<> Mod::disableHook(Hook* hook) { Result<> Mod::removeHook(Hook* hook) { auto res = this->disableHook(hook); if (res) { - utils::vector::erase<Hook*>(this->m_hooks, hook); + ranges::remove(m_hooks, hook); delete hook; } return res; diff --git a/loader/src/load/Loader.cpp b/loader/src/load/Loader.cpp index 48d26034..39a13a41 100644 --- a/loader/src/load/Loader.cpp +++ b/loader/src/load/Loader.cpp @@ -6,7 +6,7 @@ #include <InternalMod.hpp> #include <Geode/utils/file.hpp> #include <Geode/utils/conststring.hpp> -#include <Geode/utils/vector.hpp> +#include <Geode/utils/ranges.hpp> #include <Geode/utils/map.hpp> #include <Geode/utils/types.hpp> #include <mutex> @@ -41,7 +41,7 @@ void Loader::createDirectories() { ghc::filesystem::create_directory(logDir); ghc::filesystem::create_directory(tempDir); - if (!utils::vector::contains(m_modDirectories, modDir)) { + if (!ranges::contains(m_modDirectories, modDir)) { m_modDirectories.push_back(modDir); } @@ -388,12 +388,7 @@ void Loader::pushLog(log::Log&& log) { } void Loader::popLog(log::Log* log) { - /*for (auto i = m_logs.begin(); i < m_logs.end(); ++i) { - if (i == log) { - m_logs.erase(i); - } - }*/ - utils::vector::erase(m_logs, *log); + ranges::remove(m_logs, *log); } std::vector<log::Log*> Loader::getLogs( @@ -402,9 +397,7 @@ std::vector<log::Log*> Loader::getLogs( std::vector<log::Log*> logs; for (auto& log : m_logs) { - if (utils::vector::contains<Severity>( - severityFilter, log.getSeverity() - ) || !severityFilter.size()) { + if (ranges::contains(severityFilter, log.getSeverity()) || !severityFilter.size()) { logs.push_back(&log); } } diff --git a/loader/src/load/Mod.cpp b/loader/src/load/Mod.cpp index 0d2504c0..e973d005 100644 --- a/loader/src/load/Mod.cpp +++ b/loader/src/load/Mod.cpp @@ -10,6 +10,7 @@ #include <Geode/utils/map.hpp> #include <Geode/utils/string.hpp> #include <Geode/utils/vector.hpp> +#include <Geode/utils/ranges.hpp> #include <InternalMod.hpp> #include <ZipUtils.h> @@ -519,9 +520,9 @@ std::vector<Hook*> Mod::getHooks() const { } bool Mod::depends(std::string const& id) const { - return utils::vector::contains<Dependency>( + return utils::ranges::contains( m_info.m_dependencies, - [id](Dependency t) -> bool { return t.m_id == id; } + [id](Dependency const& t) { return t.m_id == id; } ); } diff --git a/loader/src/load/Patch.cpp b/loader/src/load/Patch.cpp index 30b652af..10dabf33 100644 --- a/loader/src/load/Patch.cpp +++ b/loader/src/load/Patch.cpp @@ -4,6 +4,7 @@ #include <Geode/loader/Loader.hpp> #include <Geode/utils/casts.hpp> #include <Geode/utils/vector.hpp> +#include <Geode/utils/ranges.hpp> #include <InternalLoader.hpp> #include <lilac/include/geode/core/hook/hook.hpp> @@ -34,7 +35,7 @@ Result<Patch*> Mod::patch(void* address, byte_array data) { Result<> Mod::unpatch(Patch* patch) { if (patch->restore()) { - utils::vector::erase<Patch*>(m_patches, patch); + ranges::remove(m_patches, patch); delete patch; return Ok<>(); } diff --git a/loader/src/ui/internal/info/ModInfoLayer.cpp b/loader/src/ui/internal/info/ModInfoLayer.cpp index 525207bb..2af43fa1 100644 --- a/loader/src/ui/internal/info/ModInfoLayer.cpp +++ b/loader/src/ui/internal/info/ModInfoLayer.cpp @@ -4,6 +4,7 @@ #include "../list/ModListView.hpp" #include <Geode/utils/casts.hpp> #include <Geode/utils/vector.hpp> +#include <Geode/utils/ranges.hpp> #include <Geode/ui/IconButtonSprite.hpp> #include <Geode/ui/MDPopup.hpp> #include "../settings/ModSettingsPopup.hpp" @@ -520,7 +521,7 @@ void ModInfoLayer::onInstallMod(CCObject*) { createQuickPopup( "Install", "The following <cb>mods</c> will be installed: " + - utils::container::join(m_installation->toInstall(), ",") + ".", + ranges::join(m_installation->toInstall(), ",") + ".", "Cancel", "OK", [this](FLAlertLayer*, bool btn2) { if (btn2) { diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 28c99d7b..809178c9 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -2,9 +2,13 @@ #include <md4c.h> #include <Geode/binding/ProfilePage.hpp> #include <Geode/utils/cocos.hpp> +#include <Geode/utils/convert.hpp> #include <Geode/utils/string.hpp> #include <Geode/utils/casts.hpp> -#include <Geode/utils/vector.hpp> +#include <Geode/utils/ranges.hpp> +#include <Geode/utils/fetch.hpp> +#include <Geode/utils/platform.hpp> +#include <Geode/loader/Mod.hpp> USE_GEODE_NAMESPACE(); @@ -227,7 +231,7 @@ struct MDParser { // rendering is done since the position of the // rendered labels may change after alignments // are adjusted - utils::vector::push(s_codeSpans, rendered); + ranges::push(s_codeSpans, rendered); } } break; diff --git a/loader/src/ui/nodes/Notification.cpp b/loader/src/ui/nodes/Notification.cpp index a14a75b2..db84fd1b 100644 --- a/loader/src/ui/nodes/Notification.cpp +++ b/loader/src/ui/nodes/Notification.cpp @@ -2,7 +2,10 @@ #include <Geode/ui/TextRenderer.hpp> #include <Geode/binding/GameSoundManager.hpp> #include <Geode/utils/cocos.hpp> -#include <Geode/utils/vector.hpp> +#include <Geode/utils/ranges.hpp> +#include <Geode/utils/container.hpp> +#include <Geode/utils/ranges.hpp> +#include <Geode/loader/Mod.hpp> USE_GEODE_NAMESPACE(); @@ -439,7 +442,7 @@ Notification* NotificationBuilder::show() { bool NotificationManager::isInQueue(Notification* notification) { auto location = notification->m_location; if (m_notifications.count(location)) { - return utils::vector::contains( + return utils::ranges::contains( m_notifications.at(location), Ref(notification) ); } @@ -460,9 +463,7 @@ void NotificationManager::pop(Notification* notification) { auto location = notification->m_location; if (m_notifications.count(location)) { auto ref = Ref(notification); - utils::vector::erase( - m_notifications.at(location), ref - ); + ranges::remove(m_notifications.at(location), ref); if (!m_notifications.at(location).size()) { m_notifications.erase(location); } else {