/** * @file Foundation.hpp * @author LiteLDev (https://github.com/LiteLDev) * @brief Foundation data classes for PermissionAPI * * @copyright Copyright (c) 2021-present LiteLoaderBDS developers and all contributors * */ #pragma once #include "llapi/Global.h" namespace PERM { /** * @brief Vector for Members. * * @tparam T Type of the elements in the vector. */ template class PermVector : public std::vector { using Base = std::vector; public: PermVector() : Base() { } PermVector(const Base& base) : Base(base) { } PermVector(Base&& base) : Base(base) { } PermVector(const PermVector& other) = default; PermVector(PermVector&& other) = default; bool contains(const T& xuid) const { for (auto& member : *this) { if (member == xuid) { return true; } } return false; } size_t count(const T& xuid) const { size_t result = 0; for (auto& member : *this) { if (member == xuid) { result++; } } return result; } T& push_back(const T& xuid) { if (contains(xuid)) { throw std::out_of_range("Failed to add the element: the element already exists"); } Base::push_back(xuid); return this->back(); } template T& emplace_back(Args&&... args) { return this->push_back(T(std::forward(args)...)); } PermVector& operator=(const Base& other) { return (PermVector&)(((Base&)*this) = other); } PermVector& operator=(const PermVector& other) = default; PermVector& operator=(PermVector&& other) = default; }; /** * @brief Vector for PermInfoList. * * @tparam T Type of the elements in the vector(object with field `name`). */ template class PermContainer : public std::vector { using Base = std::vector; public: PermContainer() : Base() { } PermContainer(const Base& base) : Base(base) { } PermContainer(Base&& base) : Base(base) { } PermContainer(const PermContainer& other) = default; PermContainer(PermContainer&& other) = default; bool contains(const std::string& name) const { for (auto& el : *this) { if (el.name == name) { return true; } } return false; } typename Base::iterator find(const std::string& name) { for (auto it = this->begin(); it != this->end(); it++) { if (it->name == name) { return it; } } return this->end(); } typename Base::const_iterator find(const std::string& name) const { for (auto it = this->begin(); it != this->end(); it++) { if (it->name == name) { return it; } } return this->end(); } size_t count(const std::string& name) const { size_t result = 0; for (auto& el : *this) { if (el.name == name) { result++; } } return result; } template T& getOrCreate(const std::string& name, Args&&... args) { for (auto& el : *this) { if (el.name == name) { return el; } } auto& el = this->emplace_back(args...); return el; } T& at(const std::string& name) { for (auto& el : *this) { if (el.name == name) { return el; } } throw std::out_of_range("Failed to get the element: the element does not exist"); } const T& at(const std::string& name) const { for (auto& el : *this) { if (el.name == name) { return el; } } throw std::out_of_range("Failed to get the element: the element does not exist"); } T& push_back(const T& el) { if (contains(el.name)) { throw std::out_of_range("Failed to add the element: the element with the same name already exists"); } Base::push_back(el); return this->back(); } template T& emplace_back(Args&&... args) { Base::emplace_back(std::forward(args)...); if (count(this->back().name) > 1) { this->pop_back(); throw std::out_of_range("Failed to add the element: the element with the same name already exists"); } return this->back(); } void remove(const std::string& name) { for (auto it = this->begin(); it != this->end(); it++) { if (it->name == name) { this->erase(it); return; } } throw std::out_of_range("Failed to remove the element: the target element does not exist"); } T& operator[](const std::string& name) { T def{}; def.name = name; return this->getOrCreate(name, def); } PermContainer& operator=(const PermContainer& other) = default; PermContainer& operator=(PermContainer&& other) = default; PermContainer& operator=(const Base& other) { return (PermContainer&)(((Base&)*this) = other); } }; /** * @brief Vector for Roles. * * @tparam T Type of the elements in the vector(object with field `name`). */ template class PermPtrContainer : public std::vector> { using Base = std::vector>; public: PermPtrContainer() : Base() { } PermPtrContainer(const Base& base) : Base(base) { } PermPtrContainer(Base&& base) : Base(base) { } PermPtrContainer(const PermPtrContainer& other) = default; PermPtrContainer(PermPtrContainer&& other) = default; bool contains(const std::string& name) const { for (auto& el : *this) { if (el->name == name) { return true; } } return false; } typename Base::iterator find(const std::string& name) { for (auto it = this->begin(); it != this->end(); it++) { if (it->name == name) { return it; } } return this->end(); } typename Base::const_iterator find(const std::string& name) const { for (auto it = this->begin(); it != this->end(); it++) { if (it->name == name) { return it; } } return this->end(); } size_t count(const std::string& name) const { size_t result = 0; for (auto& el : *this) { if (el->name == name) { result++; } } return result; } template std::shared_ptr& getOrCreate(const std::string& name, Args&&... args) { for (auto& el : *this) { if (el->name == name) { return el; } } auto& el = this->emplace_back(args...); return el; } std::shared_ptr& at(const std::string& name) { for (auto& el : *this) { if (el->name == name) { return el; } } throw std::out_of_range("Failed to get the element: the element does not exist"); } const std::shared_ptr& at(const std::string& name) const { for (auto& el : *this) { if (el->name == name) { return el; } } throw std::out_of_range("Failed to get the element: the element does not exist"); } T& push_back(const T& el) { if (contains(el->name)) { throw std::out_of_range("Failed to add the element: the element with the same name already exists"); } Base::push_back(std::make_shared(el)); return *this->back(); } std::shared_ptr& push_back(const std::shared_ptr& el) { if (contains(el->name)) { throw std::out_of_range("Failed to add the element: the element with the same name already exists"); } Base::push_back(el); return this->back(); } template std::shared_ptr& emplace_back(Args&&... args) { Base::emplace_back(std::forward(args)...); if (count(this->back()->name) > 1) { this->pop_back(); throw std::out_of_range("Failed to add the element: the element with the same name already exists"); } return this->back(); } void remove(const std::string& name) { for (auto it = this->begin(); it != this->end(); it++) { if ((*it)->name == name) { this->erase(it); return; } } throw std::out_of_range("Failed to remove the element: the target element does not exist"); } std::shared_ptr& operator[](const std::string& name) { auto def = std::make_shared(new T); def->name = name; return this->getOrCreate(name, def); } PermPtrContainer& operator=(const PermPtrContainer& other) = default; PermPtrContainer& operator=(PermPtrContainer&& other) = default; PermPtrContainer& operator=(const Base& other) { return (PermPtrContainer&)(((Base&)*this) = other); } }; } // namespace PERM