1
#ifndef CONTAINER_TEMPLATE_MAGIC_H
2
#define CONTAINER_TEMPLATE_MAGIC_H
9
#include <ext/hash_fun.h>
13
size_t operator()(void* const &v) const {
14
return reinterpret_cast<std::size_t>(v);
21
#include <CCINIClass.h>
22
#include <SwizzleManagerClass.h>
24
#include "../Misc/Debug.h"
27
is_Blank = 0x0, // CTOR'd
28
is_Constanted = 0x1, // values that can be set without looking at Rules (i.e. country default loadscreen)
29
is_Ruled = 0x2, // Rules has been loaded and props set (i.e. country powerplants taken from [General])
30
is_Inited = 0x3, // values that need the object's state (i.e. is object a secretlab? -> load default boons)
31
is_Completed = 0x4 // INI has been read and values set
35
* ==========================
36
* It's a kind of magic
37
* ==========================
39
* These two templates are the basis of the new class extension standard.
41
* ==========================
43
* Extension<T> is the parent class for the data you want to link with this instance of T
44
( for example, [Warhead]MindControl.Permanent= should be stored in WarheadClassExt::ExtData
45
which itself should be a derivate of Extension<WarheadTypeClass> )
47
* ==========================
49
Container<TX> is the storage for all the Extension<T> which share the same T,
50
where TX is the containing class of the relevant derivate of Extension<T>. // complex, huh?
51
( for example, there is Container<WarheadTypeExt>
52
which contains all the custom data for all WarheadTypeClass instances,
53
and WarheadTypeExt itself contains just statics like the Container itself
59
const DWORD Extension<T>::Canary = (any dword value easily identifiable in a byte stream)
60
class TX::ExtData : public Extension<T> { custom_data; }
62
Complex? Yes. That's partially why you should be happy these are premade for you.
69
eInitState _Initialized;
70
T* const AttachedToObject;
75
static const DWORD Canary;
77
Extension(const DWORD Canary, T* const OwnerObject) :
78
_Initialized(is_Blank),
82
AttachedToObject(OwnerObject)
85
virtual ~Extension() { };
87
// use this implementation for all descendants
90
// virtual size_t Size() const { return sizeof(*this); };
91
virtual size_t Size() const = 0;
94
// LoadFromINI is now a non-virtual public function that orchestrates the initialization/loading of extension data
95
// all its slaves are now protected functions
96
void LoadFromINI(T *pThis, CCINIClass *pINI) {
101
switch(this->_Initialized) {
103
this->InitializeConstants(pThis);
104
this->_Initialized = is_Constanted;
106
this->InitializeRuled(pThis);
107
this->_Initialized = is_Ruled;
109
this->Initialize(pThis);
110
this->_Initialized = is_Inited;
113
if(pINI == CCINIClass::INI_Rules) {
114
this->LoadFromRulesFile(pThis, pINI);
116
this->LoadFromINIFile(pThis, pINI);
117
this->_Initialized = is_Completed;
122
//reimpl in each class separately
123
virtual void LoadFromINIFile(T *pThis, CCINIClass *pINI) {};
125
// for things that only logically work in rules - countries, sides, etc
126
virtual void LoadFromRulesFile(T *pThis, CCINIClass *pINI) {};
128
virtual void InitializeConstants(T *pThis) { };
130
virtual void InitializeRuled(T *pThis) { };
132
virtual void Initialize(T *pThis) { };
134
virtual void InvalidatePointer(void *ptr) = 0;
137
void operator = (Extension &RHS) {
142
//template<typename T1, typename T2>
144
class Container : public hash_map<typename T::TT*, typename T::ExtData* > {
146
typedef typename T::TT S_T;
147
typedef typename T::ExtData E_T;
148
typedef hash_map<S_T*, E_T*> C_Map;
150
unsigned int CTOR_Count;
151
unsigned int DTOR_Count;
152
unsigned int Lookup_Failure_Count;
153
unsigned int Lookup_Success_Count;
156
static S_T * SavingObject;
157
static IStream * SavingStream;
159
void PointerGotInvalid(void *ptr) {
160
this->InvalidatePointer(ptr);
161
this->InvalidateExtDataPointer(ptr);
164
#define INVALID_CTR(type, p) \
165
type::ExtMap.PointerGotInvalid(p);
168
// invalidate pointers to container's static gunk here (use full qualified names)
169
virtual void InvalidatePointer(void *ptr) {
172
void InvalidateExtDataPointer(void *ptr) {
173
for(typename C_Map::iterator i = this->begin(); i != this->end(); ++i) {
174
i->second->InvalidatePointer(ptr);
182
Lookup_Failure_Count(0),
183
Lookup_Success_Count(0)
187
virtual ~Container() {
191
E_T *FindOrAllocate(S_T* key) {
193
const std::type_info &info = typeid(*this);
194
Debug::Log("CTOR of %s attempted for a NULL pointer! WTF!\n", info.name());
197
typename C_Map::iterator i = this->find(key);
198
if(i == this->end()) {
200
E_T * val = new E_T(/*typename*/ E_T::Canary, key);
201
val->InitializeConstants(key);
202
i = this->insert(typename C_Map::value_type(key, val)).first;
207
E_T *Find(S_T* key) {
208
typename C_Map::iterator i = this->find(key);
209
if(i == this->end()) {
210
++Lookup_Failure_Count;
213
++Lookup_Success_Count;
217
void Remove(S_T* key) {
218
typename C_Map::iterator i = this->find(key);
219
if(i != this->end()) {
226
void Remove(typename C_Map::iterator i) {
227
if(i != this->end()) {
235
for(typename C_Map::iterator i = this->begin(); i != this->end(); ) {
242
void LoadAllFromINI(CCINIClass *pINI) {
243
for(typename C_Map::iterator i = this->begin(); i != this->end(); i++) {
244
i->second->LoadFromINI(i->first, pINI);
248
void LoadFromINI(S_T*key, CCINIClass *pINI) {
249
typename C_Map::iterator i = this->find(key);
250
if(i != this->end()) {
251
i->second->LoadFromINI(key, pINI);
255
void LoadAllFromRules(CCINIClass *pINI) {
256
for(typename C_Map::iterator i = this->begin(); i != this->end(); i++) {
257
i->second->LoadFromRulesFile(i->first, pINI);
262
if(Container<T>::SavingObject && Container<T>::SavingStream) {
263
this->Save(Container<T>::SavingObject, Container<T>::SavingStream);
264
Container<T>::SavingObject = NULL;
265
Container<T>::SavingStream = NULL;
269
void Save(S_T *key, IStream *pStm) {
270
this->SaveKey(key, pStm);
273
E_T* SaveKey(S_T *key, IStream *pStm) {
276
const std::type_info &info = typeid(key);
277
Debug::Log("Saving Key [%s] (%X)\n", info.name(), key);
282
E_T* buffer = this->Find(key);
283
Debug::Log("\tKey maps to %X\n", buffer);
285
pStm->Write(&buffer, 4, &out);
286
pStm->Write(buffer, buffer->Size(), &out);
287
// Debug::Log("Save used up 0x%X bytes (HRESULT 0x%X)\n", out, res);
295
if(Container<T>::SavingObject && Container<T>::SavingStream) {
296
this->Load(Container<T>::SavingObject, Container<T>::SavingStream);
297
Container<T>::SavingObject = NULL;
298
Container<T>::SavingStream = NULL;
302
void Load(S_T *key, IStream *pStm) {
303
this->LoadKey(key, pStm);
306
E_T* LoadKey(S_T *key, IStream *pStm) {
309
const std::type_info &info = typeid(key);
310
Debug::Log("Loading Key [%s] (%X)\n", info.name(), key);
313
Debug::Log("Load attempted for a NULL pointer! WTF!\n");
316
E_T* buffer = this->FindOrAllocate(key);
318
pStm->Read(&origPtr, 4, &out);
319
pStm->Read(buffer, buffer->Size(), &out);
320
Debug::Log("LoadKey Swizzle: %X => %X\n", origPtr, buffer);
321
SwizzleManagerClass::Instance.Here_I_Am(origPtr, (void *)buffer);
322
SWIZZLE(buffer->AttachedToObject);
324
assert(buffer->SavedCanary == typename E_T::Canary);
330
const std::type_info &info = typeid(*this);
331
Debug::Log("Stats for container %s:\n", info.name());
333
Debug::Log("|%08d|%08d|%08d/%08d|%08d|%08d|\n",
334
CTOR_Count, DTOR_Count, Lookup_Success_Count, Lookup_Failure_Count, this->size(), S_T::Array->Count);