VoxelEngine
 
Loading...
Searching...
No Matches
Registry.h
1#pragma once
2
3#include <glm/glm.hpp>
4
5#include <concepts>
6#include <memory>
7#include <stdexcept>
8#include <string>
9#include <unordered_map>
10
11
12namespace engine {
13
14 namespace RegistryStoragePolicy {
15 struct ByValue {};
16 struct ByPointer {};
17
18 struct UserProvidedID {};
19 struct AutoGeneratedID {};
20 }; // namespace RegistryStoragePolicy
21
22 template <typename T>
23 concept HasID = requires(T t) {
24 { t.getID() } -> std::convertible_to<unsigned int>;
25 };
26
27 template <
28 typename T,
29 typename StoragePolicy = RegistryStoragePolicy::ByValue,
30 typename IDPolicy = RegistryStoragePolicy::UserProvidedID>
31 requires(std::same_as<IDPolicy, RegistryStoragePolicy::AutoGeneratedID> || HasID<T>)
32 class Registry;
33
34 template <typename T, typename IDPolicy>
35 requires(std::same_as<IDPolicy, RegistryStoragePolicy::AutoGeneratedID> || HasID<T>)
37 public:
38 void add(const T& data, const std::string& name) {
39 unsigned int id = getID(data);
40 if (m_data.find(id) != m_data.end()) {
41 throw std::runtime_error("Data with this ID already exists");
42 }
43 if (m_nameToID.find(name) != m_nameToID.end()) {
44 throw std::runtime_error("Data with this name already exists");
45 }
46 m_data.emplace(id, data);
47 m_nameToID.emplace(name, id);
48 }
49
50 void add(T&& data, const std::string& name) {
51 unsigned int id = getID(data);
52 if (m_data.find(id) != m_data.end()) {
53 throw std::runtime_error("Data with this ID already exists");
54 }
55 if (m_nameToID.find(name) != m_nameToID.end()) {
56 throw std::runtime_error("Data with this name already exists");
57 }
58 m_data.emplace(id, std::move(data));
59 m_nameToID.emplace(name, id);
60 }
61
62 const T& get(unsigned int id) const { return m_data.at(id); }
63
64 const T& get(const char* name) const { return m_data.at(m_nameToID.at(name)); }
65
66 unsigned int idOf(const char* name) const { return m_nameToID.at(name); }
67
68 bool has(unsigned int id) const { return m_data.find(id) != m_data.end(); }
69 bool has(const char* name) const { return m_nameToID.find(name) != m_nameToID.end(); }
70
71 const std::vector<std::reference_wrapper<const T>> all() const {
72 std::vector<std::reference_wrapper<const T>> out;
73 out.reserve(m_data.size());
74 for (const auto& [id, data] : m_data) {
75 out.push_back(std::ref(data));
76 }
77 return out;
78 }
79
80 Registry() = default;
81
82 protected:
83 std::unordered_map<unsigned int, T> m_data;
84 std::unordered_map<std::string, unsigned int> m_nameToID;
85 unsigned int m_idCounter = 0;
86
87
88 private:
89 unsigned int getID(const T& data) {
90 if constexpr (std::same_as<IDPolicy, RegistryStoragePolicy::UserProvidedID>) {
91 return data.getID();
92 } else {
93 return m_idCounter++;
94 }
95 }
96 };
97
98
99 template <typename T, typename IDPolicy>
100 requires(std::same_as<IDPolicy, RegistryStoragePolicy::AutoGeneratedID> || HasID<T>)
102 friend class RegistryManager;
103
104 public:
105 template <typename Derived>
106 requires std::derived_from<std::decay_t<Derived>, T>
107 void add(Derived&& data, const std::string& name) {
108 unsigned int id = getID(&data);
109 if (m_data.find(id) != m_data.end()) {
110 throw std::runtime_error("Data with this ID already exists");
111 }
112 if (m_nameToID.find(name) != m_nameToID.end()) {
113 throw std::runtime_error("Data with this name already exists");
114 }
115 m_data.emplace(
116 id, std::make_unique<std::decay_t<Derived>>(std::forward<Derived>(data))
117 );
118 m_nameToID.emplace(name, id);
119 }
120
121 const T* get(unsigned int id) const {
122 auto it = m_data.find(id);
123 return it != m_data.end() ? it->second.get() : nullptr;
124 }
125
126 const T* get(const char* name) const {
127 auto it = m_nameToID.find(name);
128 return it != m_nameToID.end() ? get(it->second) : nullptr;
129 }
130
131 unsigned int idOf(const char* name) const { return m_nameToID.at(name); }
132
133 bool has(unsigned int id) const { return m_data.find(id) != m_data.end(); }
134 bool has(const char* name) const { return m_nameToID.find(name) != m_nameToID.end(); }
135
136 const std::vector<const T*> all() const {
137 std::vector<const T*> out;
138 out.reserve(m_data.size());
139 for (const auto& [id, data] : m_data) {
140 out.push_back(data.get());
141 }
142 return out;
143 }
144
145 Registry() = default;
146
147 protected:
148 std::unordered_map<unsigned int, std::unique_ptr<T>> m_data;
149 std::unordered_map<std::string, unsigned int> m_nameToID;
150 unsigned int m_idCounter = 0;
151
152 private:
153 unsigned int getID(T* data) {
154 if constexpr (std::same_as<IDPolicy, RegistryStoragePolicy::UserProvidedID>) {
155 return data->getID();
156 } else {
157 return m_idCounter++;
158 }
159 }
160 };
161} // namespace engine
Definition RegistryManager.h:9
Definition Registry.h:32
Definition Registry.h:23