/* ** EPITECH PROJECT, 2021 ** Bomberman ** File description: ** Cache */ #pragma once #include #include #include #include #include #include "Exceptions/RayError.hpp" namespace RAY { //! @brief A templated class used to cache ressources, indexed with a string template class Cache { public: //! @brief Cache(std::function dataLoader, std::function dataUnloader): _dataLoader(dataLoader), _dataUnloader(dataUnloader) {}; //! @brief Default destructor, will destroy ray's data ~Cache() = default; //! @brief default copy constructor Cache(const Cache &) = default; //! @brief a cache is assignable Cache &operator=(const Cache &) = default; //! @param path path of the file //! @return a newly loaded ressource if it hasn't be previously loaded, or one from cache std::shared_ptrfetch(const std::string &path) { if (this->_cache.find(path) == this->_cache.end()) this->_cache.emplace(path, std::shared_ptr( new T(this->_dataLoader(path.c_str())), [this](T *p) { this->_dataUnloader(*p); delete p; })); return _cache[path]; }; private: //! @brief function to call to load data std::function _dataLoader; //! @brief function to call when the ray data will be unloaded std::function _dataUnloader; //! @brief map storing shared ptr of caches std::unordered_map> _cache; }; template<> class Cache<::ModelAnimation> { public: Cache(std::function<::ModelAnimation *(const char *, int *)> dataLoader, std::functiondataUnloader): _dataLoader(std::move(dataLoader)), _dataUnloader(std::move(dataUnloader)) {}; std::shared_ptr<::ModelAnimation> fetch(const std::string &path, int *counter) { if (this->_cache.find(path) != this->_cache.end()) return this->_cache[path]; ::ModelAnimation *animations = this->_dataLoader(path.c_str(), counter); unsigned int animCount = *counter; this->_cache.emplace(path, std::shared_ptr<::ModelAnimation>( animations, [this, animCount](::ModelAnimation *p) { this->_dataUnloader(p, animCount); })); return this->_cache[path]; }; private: //! @brief function to call to load data std::function<::ModelAnimation *(const char *, int *)> _dataLoader; //! @brief function to call when the ray data will be unloaded std::function _dataUnloader; //! @brief map storing shared ptr of caches std::unordered_map> _cache; }; template<> class Cache<::Shader> { public: Cache(std::function<::Shader(const char *, const char *)> dataLoader, std::function dataUnloader) : _dataLoader(std::move(dataLoader)), _dataUnloader(std::move(dataUnloader)) {}; std::shared_ptr<::Shader> fetch(const std::string &vertexFile, const std::string &fragmentFile) { const std::string index = vertexFile + fragmentFile; if (vertexFile.empty() && fragmentFile.empty()) { throw RAY::Exception::WrongInputError(); } if (this->_cache.find(index) != this->_cache.end()) return this->_cache[index]; this->_cache.emplace(index, std::shared_ptr<::Shader>( new ::Shader( this->_dataLoader(vertexFile.empty() ? nullptr : vertexFile.c_str(), fragmentFile.c_str())), [this](::Shader *p) { this->_dataUnloader(*p); })); return this->_cache[index]; }; private: //! @brief function to call to load data std::function<::Shader(const char *, const char *)> _dataLoader; //! @brief function to call when the ray data will be unloaded std::function _dataUnloader; //! @brief map storing shared ptr of caches std::unordered_map> _cache; }; }