Nebula
Loading...
Searching...
No Matches
attributeregistry.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
9//------------------------------------------------------------------------------
10#include "attribute.h"
11#include "util/stringatom.h"
12
13namespace MemDb
14{
15
17{
18public:
20 template<typename TYPE>
21 static AttributeId Register(Util::StringAtom name, TYPE defaultValue, uint32_t flags = 0);
22
23 template <typename TYPE>
24 static AttributeId Register(Attribute* attribute);
25
27 template <typename TYPE>
28 static bool IsRegistered();
29
31 static AttributeId Register(Util::StringAtom name, SizeT typeSize, void const* defaultValue, uint32_t flags = 0);
32
36 static Attribute* GetAttribute(AttributeId descriptor);
38 static SizeT TypeSize(AttributeId descriptor);
40 static uint32_t Flags(AttributeId descriptor);
42 static void const* const DefaultValue(AttributeId descriptor);
45
46private:
48 static void Destroy();
49
52
54
57};
58
60uint16_t GenerateNewAttributeId();
61
62//------------------------------------------------------------------------------
65template <typename ATTRIBUTE>
68{
69 static_assert(std::is_trivially_destructible<ATTRIBUTE>());
70 static const uint16_t id = MemDb::GenerateNewAttributeId();
71 return AttributeId(id);
72}
73
74//------------------------------------------------------------------------------
77template<typename TYPE>
78inline bool
80{
81 auto* reg = Instance();
83 if (id < reg->componentDescriptions.Size())
84 {
85 return reg->componentDescriptions[id.id] != nullptr;
86 }
87 return false;
88}
89
90//------------------------------------------------------------------------------
97template<typename TYPE>
98inline AttributeId
99AttributeRegistry::Register(Util::StringAtom name, TYPE defaultValue, uint32_t flags)
100{
101 // Special case for string atoms since they actually are trivial to copy and destroy
102 //if constexpr (!std::is_same<TYPE, Util::StringAtom>())
103 //{
104 // static_assert(std::is_trivially_copyable<TYPE>(), "TYPE must be trivially copyable.");
105 // static_assert(std::is_trivially_destructible<TYPE>(), "TYPE must be trivially destructible.");
106 //}
107
108 static_assert(!std::is_polymorphic<TYPE>(), "TYPE must not be polymorpic.");
109 static_assert(!std::is_abstract<TYPE>(), "TYPE must not be abstract.");
110
111 auto* reg = Instance();
112 if (!reg->registry.Contains(name))
113 {
114 // setup a state description with the default values from the type
115 Attribute* desc = new Attribute(name, defaultValue, flags);
116
118 if (descriptor.id >= reg->componentDescriptions.Size())
119 {
120 SizeT prevSize = reg->componentDescriptions.Size();
121 reg->componentDescriptions.Resize(descriptor.id + 1); // fixed increment
122 SizeT num = reg->componentDescriptions.Size() - prevSize;
123 reg->componentDescriptions.Fill(prevSize, num, nullptr); // make sure new entries are null, since we use this to check if attributes are registered or not.
124 }
125
126 reg->componentDescriptions[descriptor.id] = desc;
127 reg->registry.Add(name, descriptor);
128
129 return descriptor;
130 }
131 else
132 {
133 n_error("Tried to register component named %s: Cannot register two components with same name!", name.Value());
134 }
135
136 return AttributeId::Invalid();
137}
138
139
140//------------------------------------------------------------------------------
143template <typename TYPE>
144inline AttributeId
146{
147 static_assert(!std::is_polymorphic<TYPE>(), "TYPE must not be polymorpic.");
148 static_assert(!std::is_abstract<TYPE>(), "TYPE must not be abstract.");
149
150 auto* reg = Instance();
151 if (!reg->registry.Contains(desc->name))
152 {
154 if (attrId.id >= reg->componentDescriptions.Size())
155 {
156 SizeT prevSize = reg->componentDescriptions.Size();
157 reg->componentDescriptions.Resize(attrId.id + 1); // fixed increment
158 SizeT num = reg->componentDescriptions.Size() - prevSize;
159 reg->componentDescriptions.Fill(
160 prevSize, num, nullptr
161 ); // make sure new entries are null, since we use this to check if attributes are registered or not.
162 }
163
164 reg->componentDescriptions[attrId.id] = desc;
165 reg->registry.Add(desc->name, attrId);
166
167 return attrId;
168 }
169 else
170 {
171 n_error("Tried to register component named %s: Cannot register two components with same name!", desc->name.Value());
172 }
173
174 return AttributeId::Invalid();
175}
176
177//------------------------------------------------------------------------------
180inline AttributeId
181AttributeRegistry::Register(Util::StringAtom name, SizeT typeSize, void const* defaultValue, uint32_t flags)
182{
183 auto* reg = Instance();
184 if (!reg->registry.Contains(name))
185 {
186 // setup a state description with the default values from the type
187 Attribute* desc = new Attribute(name, typeSize, defaultValue, flags);
188
190 if (descriptor.id >= reg->componentDescriptions.Size())
191 {
192 reg->componentDescriptions.Resize(descriptor.id + 1);
193
194 }
195
196 reg->componentDescriptions[descriptor.id] = desc;
197 reg->registry.Add(name, descriptor);
198 return descriptor;
199 }
200 else
201 {
202 n_error("Tried to register component named %s: Cannot register two components with same name!", name.Value());
203 }
204
205 return AttributeId::Invalid();
206}
207
208//------------------------------------------------------------------------------
211inline AttributeId
213{
214 auto* reg = Instance();
215 IndexT index = reg->registry.FindIndex(name);
216 if (index != InvalidIndex)
217 {
218 return reg->registry.ValueAtIndex(index);
219 }
220
221 return AttributeId::Invalid();
222}
223
224//------------------------------------------------------------------------------
227inline Attribute*
229{
230 auto* reg = Instance();
231 if (descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size())
232 {
233 n_assert2(
234 reg->componentDescriptions[descriptor.id] != nullptr, "Trying to get description of attribute that is not registered!"
235 );
236 return reg->componentDescriptions[descriptor.id];
237 }
238
239 return nullptr;
240}
241
242//------------------------------------------------------------------------------
245inline SizeT
247{
248 auto* reg = Instance();
249 n_assert(descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size());
250 return reg->componentDescriptions[descriptor.id]->typeSize;
251}
252
253//------------------------------------------------------------------------------
256inline uint32_t
258{
259 auto* reg = Instance();
260 n_assert(descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size());
261 return reg->componentDescriptions[descriptor.id]->externalFlags;
262}
263
264//------------------------------------------------------------------------------
267inline void const* const
269{
270 auto* reg = Instance();
271 n_assert(descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size());
272 return reg->componentDescriptions[descriptor.id]->defVal;
273}
274
275//------------------------------------------------------------------------------
280{
281 auto* reg = Instance();
282 return reg->componentDescriptions;
283}
284
285} // namespace MemDb
Definition attribute.h:29
Util::StringAtom name
name of attribute
Definition attribute.h:49
Definition attributeregistry.h:17
Util::FixedArray< Attribute * > componentDescriptions
Definition attributeregistry.h:55
static AttributeId Register(Util::StringAtom name, TYPE defaultValue, uint32_t flags=0)
register a type (templated)
Definition attributeregistry.h:99
static AttributeRegistry * Instance()
The registry's constructor is called by the Instance() method, and nobody else.
Definition attributeregistry.cc:18
static uint32_t Flags(AttributeId descriptor)
get flags by attribute id
Definition attributeregistry.h:257
~AttributeRegistry()
Definition attributeregistry.cc:55
Util::Dictionary< Util::StringAtom, AttributeId > registry
Definition attributeregistry.h:56
static void const *const DefaultValue(AttributeId descriptor)
get attribute default value pointer
Definition attributeregistry.h:268
AttributeRegistry()
Definition attributeregistry.cc:47
static AttributeId GetAttributeId(Util::StringAtom name)
get attribute id from name
Definition attributeregistry.h:212
static void Destroy()
This static method is used to destroy the registry object and should be called right before the main ...
Definition attributeregistry.cc:35
static SizeT TypeSize(AttributeId descriptor)
get type size by attribute id
Definition attributeregistry.h:246
static Util::FixedArray< Attribute * > const & GetAllAttributes()
get an array of all attributes
Definition attributeregistry.h:279
static Attribute * GetAttribute(AttributeId descriptor)
get attribute description by id
Definition attributeregistry.h:228
static AttributeRegistry * Singleton
Definition attributeregistry.h:53
static bool IsRegistered()
Check if a type is registered.
Definition attributeregistry.h:79
A collection of key/value pairs with quick value retrieval by key at roughly O(log n).
Definition dictionary.h:34
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
A StringAtom.
Definition stringatom.h:22
const char * Value() const
get contained string as char ptr (fast)
Definition stringatom.h:362
void __cdecl n_error(const char *msg,...)
This function is called when a serious situation is encountered which requires abortion of the applic...
Definition debug.cc:138
#define n_assert2(exp, msg)
Definition debug.h:51
#define n_assert(exp)
Definition debug.h:50
Attribute.
Definition attribute.h:26
uint16_t GenerateNewAttributeId()
Do not use.
Definition attributeregistry.cc:65
AttributeId GetAttributeId()
Definition attributeregistry.h:67
Definition attributeid.h:19
static const int InvalidIndex
Definition types.h:54
int SizeT
Definition types.h:49
int IndexT
Definition types.h:48