5 #include <unordered_map>
7 #include <nlohmann/json.hpp>
8 #include <core/Logger.h>
9 #include <math/Types.h>
10 #include <utility/SharedPointer.h>
11 #include <utility/Types.h>
12 #include "provider/IResourceProvider.h"
16 constexpr std::string_view RESOURCE_ID_SEPARATOR =
"://";
23 explicit Resource(std::string identifier_)
24 : identifier(std::move(identifier_)) {}
28 virtual void compile(
const byte [], std::size_t ) = 0;
30 [[nodiscard]] std::string_view getIdentifier()
const {
31 return this->identifier;
35 std::string identifier;
45 static IResourceProvider* getResourceProviderWithResource(
const std::string& identifier);
47 template<
typename ResourceType,
typename... Params>
50 auto id = Resource::splitResourceIdentifier(identifier);
51 const std::string& provider =
id.first, name =
id.second;
52 if (Resource::resources[provider].count(name) > 0) {
53 return Resource::resources[provider][name].template cast<ResourceType>();
55 return Resource::getUniqueResource<ResourceType>(identifier, std::forward<Params>(params)...);
58 template<
typename ResourceType,
typename... Params>
59 static void precacheResource(
const std::string& identifier, Params... params) {
61 auto id = Resource::splitResourceIdentifier(identifier);
62 const std::string& provider =
id.first, name =
id.second;
63 if (Resource::resources[provider].count(name) > 0) {
67 for (
auto i = Resource::providers[provider].rbegin(); i != Resource::providers[provider].rend(); i++) {
68 if ((*i)->hasResource(name)) {
69 Resource::resources[provider][name] =
SharedPointer<Resource>(
new ResourceType{identifier, std::forward<Params>(params)...});
70 (*i)->compileResource(name, Resource::resources[provider][name].get());
77 template<
typename ResourceType>
80 auto id = Resource::splitResourceIdentifier(identifier);
81 const std::string& provider =
id.first, name =
id.second;
82 if (Resource::resources[provider].count(name) > 0) {
83 return Resource::resources[provider][name].cast<ResourceType>();
86 if (Resource::hasDefaultResource<ResourceType>())
87 return Resource::getDefaultResource<ResourceType>();
91 template<
typename ResourceType,
typename... Params>
93 auto id = Resource::splitResourceIdentifier(identifier);
94 const std::string& provider =
id.first, name =
id.second;
95 for (
auto i = Resource::providers[provider].rbegin(); i != Resource::providers[provider].rend(); i++) {
96 if ((*i)->hasResource(name)) {
97 Resource::resources[provider][name] =
SharedPointer<Resource>(
new ResourceType{identifier, std::forward<Params>(params)...});
98 (*i)->compileResource(name, Resource::resources[provider][name].get());
99 return Resource::resources[provider][name].template cast<ResourceType>();
103 if (Resource::hasDefaultResource<ResourceType>())
104 return Resource::getDefaultResource<ResourceType>();
109 template<
typename ResourceType,
typename... Params>
111 auto id = Resource::splitResourceIdentifier(identifier);
112 const std::string& provider =
id.first, name =
id.second;
113 for (
auto i = Resource::providers[provider].rbegin(); i != Resource::providers[provider].rend(); i++) {
114 if ((*i)->hasResource(name)) {
116 (*i)->compileResource(name, resource.get());
118 resource.setHolderAmountForDelete(0);
128 template<
typename ResourceType,
typename... Params>
130 auto resource = std::make_unique<ResourceType>(identifier, std::forward<Params>(params)...);
131 resource->compile(props);
135 static std::pair<std::string, std::string> splitResourceIdentifier(
const std::string& identifier);
137 static const std::vector<std::unique_ptr<IResourceProvider>>& getResourceProviders(
const std::string& providerName);
139 static bool hasResource(
const std::string& identifier);
150 template<
typename ResourceType>
151 static bool registerDefaultResource(
const std::string& identifier) {
152 Resource::getDefaultResourceConstructors()[typeHash<ResourceType>()] = [identifier] {
153 Resource::defaultResources[typeHash<ResourceType>()] = Resource::getUniqueResource<ResourceType>(identifier).template cast<Resource>();
158 template<
typename ResourceType>
159 static bool hasDefaultResource() {
160 return Resource::defaultResources.contains(typeHash<ResourceType>());
163 template<
typename ResourceType>
164 static SharedPointer<ResourceType> getDefaultResource() {
165 return Resource::defaultResources[typeHash<ResourceType>()].template cast<ResourceType>();
168 static void createDefaultResources() {
169 for (
const auto& [
id, ctor] : Resource::getDefaultResourceConstructors()) {
175 static inline std::unordered_map<std::string, std::vector<std::unique_ptr<IResourceProvider>>> providers;
176 static inline std::unordered_map<std::string, std::unordered_map<std::string, SharedPointer<Resource>>> resources;
177 static inline std::unordered_map<std::type_index, SharedPointer<Resource>> defaultResources;
178 static inline std::vector<std::string> garbageResources;
180 static auto getDefaultResourceConstructors() -> std::unordered_map<std::type_index, std::function<void()>>& {
181 static std::unordered_map<std::type_index, std::function<void()>> defaultResourceConstructors;
182 return defaultResourceConstructors;
186 static void logResourceError(
const std::string& identifier,
const std::string& resourceName);
191 #define CHIRA_REGISTER_DEFAULT_RESOURCE(type, identifier) \
192 static inline const auto type##DefaultResourceRegistryHelper = \
193 chira::Resource::registerDefaultResource<type>(identifier)
A chunk of data, usually a file. Is typically cached and shared.
static void logResourceError(const std::string &identifier, const std::string &resourceName)
We do a few predeclaration workarounds.
static void removeResource(const std::string &identifier)
If resource is present in the cache and has a reference count less than or equal to 2,...
static std::unique_ptr< ResourceType > getUniqueUncachedPropertyResource(const std::string &identifier, const nlohmann::json &props, Params... params)
The only way to make a PropertiesResource without a provider is to make it unique,...
static void cleanup()
Delete all resources marked for removal.
static void discardAll()
Deletes ALL resources and providers. Should only ever be called once, when the program closes.
static SharedPointer< ResourceType > getUniqueUncachedResource(const std::string &identifier, Params... params)
You might want to use this sparingly as it defeats the entire point of a cached, shared resource syst...