~ares-developers/ares/gd03

« back to all changes in this revision

Viewing changes to Ext/_Container.hpp

  • Committer: Renegade
  • Date: 2010-05-29 08:12:17 UTC
  • Revision ID: git-v1:0a1bb6321f04d723afe64d1b843dc87b4da783ec
Creating /trunk/src.

git-svn-id: svn://svn.renegadeprojects.com/ares/trunk@622 859b54a9-7a54-0410-aeb3-f8d2f1fa40fd

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifndef CONTAINER_TEMPLATE_MAGIC_H
2
 
#define CONTAINER_TEMPLATE_MAGIC_H
3
 
 
4
 
#ifdef _MSC_VER
5
 
#include <typeinfo>
6
 
#endif
7
 
 
8
 
#ifdef __GNUC__
9
 
#include <ext/hash_fun.h>
10
 
namespace __gnu_cxx {
11
 
        template<>
12
 
        struct hash<void *> {
13
 
                size_t operator()(void* const &v) const {
14
 
                        return reinterpret_cast<std::size_t>(v);
15
 
                }
16
 
        };
17
 
};
18
 
#endif
19
 
 
20
 
#include <xcompile.h>
21
 
#include <CCINIClass.h>
22
 
#include <SwizzleManagerClass.h>
23
 
 
24
 
#include "../Misc/Debug.h"
25
 
 
26
 
enum eInitState {
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
32
 
};
33
 
 
34
 
/*
35
 
 * ==========================
36
 
 *    It's a kind of magic
37
 
 * ==========================
38
 
 
39
 
 * These two templates are the basis of the new class extension standard.
40
 
 
41
 
 * ==========================
42
 
 
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> )
46
 
 
47
 
 * ==========================
48
 
 
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
54
 
 
55
 
      )
56
 
 
57
 
   Requires:
58
 
        typedef TX::TT = T;
59
 
        const DWORD Extension<T>::Canary = (any dword value easily identifiable in a byte stream)
60
 
        class TX::ExtData : public Extension<T> { custom_data; }
61
 
 
62
 
   Complex? Yes. That's partially why you should be happy these are premade for you.
63
 
 *
64
 
 */
65
 
 
66
 
template<typename T>
67
 
class Extension {
68
 
        public:
69
 
                eInitState _Initialized;
70
 
                T* const AttachedToObject;
71
 
        #ifdef DEBUGBUILD
72
 
                DWORD SavedCanary;
73
 
        #endif
74
 
 
75
 
                static const DWORD Canary;
76
 
 
77
 
                Extension(const DWORD Canary, T* const OwnerObject) :
78
 
                _Initialized(is_Blank),
79
 
        #ifdef DEBUGBUILD
80
 
                SavedCanary(Canary),
81
 
        #endif
82
 
                AttachedToObject(OwnerObject)
83
 
                { };
84
 
 
85
 
                virtual ~Extension() { };
86
 
 
87
 
                // use this implementation for all descendants
88
 
                // I mean it
89
 
                // sizeof(facepalm)
90
 
                // virtual size_t Size() const { return sizeof(*this); };
91
 
                virtual size_t Size() const = 0;
92
 
 
93
 
                // major refactoring!
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) {
97
 
                        if(!pINI) {
98
 
                                return;
99
 
                        }
100
 
 
101
 
                        switch(this->_Initialized) {
102
 
                                case is_Blank:
103
 
                                        this->InitializeConstants(pThis);
104
 
                                        this->_Initialized = is_Constanted;
105
 
                                case is_Constanted:
106
 
                                        this->InitializeRuled(pThis);
107
 
                                        this->_Initialized = is_Ruled;
108
 
                                case is_Ruled:
109
 
                                        this->Initialize(pThis);
110
 
                                        this->_Initialized = is_Inited;
111
 
                                case is_Inited:
112
 
                                case is_Completed:
113
 
                                        if(pINI == CCINIClass::INI_Rules) {
114
 
                                                this->LoadFromRulesFile(pThis, pINI);
115
 
                                        }
116
 
                                        this->LoadFromINIFile(pThis, pINI);
117
 
                                        this->_Initialized = is_Completed;
118
 
                        }
119
 
                }
120
 
 
121
 
//      protected:
122
 
                //reimpl in each class separately
123
 
                virtual void LoadFromINIFile(T *pThis, CCINIClass *pINI) {};
124
 
 
125
 
                // for things that only logically work in rules - countries, sides, etc
126
 
                virtual void LoadFromRulesFile(T *pThis, CCINIClass *pINI) {};
127
 
 
128
 
                virtual void InitializeConstants(T *pThis) { };
129
 
 
130
 
                virtual void InitializeRuled(T *pThis) { };
131
 
 
132
 
                virtual void Initialize(T *pThis) { };
133
 
 
134
 
                virtual void InvalidatePointer(void *ptr) = 0;
135
 
 
136
 
        private:
137
 
                void operator = (Extension &RHS) {
138
 
 
139
 
                }
140
 
};
141
 
 
142
 
//template<typename T1, typename T2>
143
 
template<typename T>
144
 
class Container : public hash_map<typename T::TT*, typename T::ExtData* > {
145
 
private:
146
 
        typedef typename T::TT        S_T;
147
 
        typedef typename T::ExtData   E_T;
148
 
        typedef hash_map<S_T*, E_T*>  C_Map;
149
 
 
150
 
        unsigned int CTOR_Count;
151
 
        unsigned int DTOR_Count;
152
 
        unsigned int Lookup_Failure_Count;
153
 
        unsigned int Lookup_Success_Count;
154
 
 
155
 
public:
156
 
        static S_T * SavingObject;
157
 
        static IStream * SavingStream;
158
 
 
159
 
        void PointerGotInvalid(void *ptr) {
160
 
                this->InvalidatePointer(ptr);
161
 
                this->InvalidateExtDataPointer(ptr);
162
 
        }
163
 
 
164
 
#define INVALID_CTR(type, p) \
165
 
        type::ExtMap.PointerGotInvalid(p);
166
 
 
167
 
protected:
168
 
        // invalidate pointers to container's static gunk here (use full qualified names)
169
 
        virtual void InvalidatePointer(void *ptr) {
170
 
        };
171
 
 
172
 
        void InvalidateExtDataPointer(void *ptr) {
173
 
                for(typename C_Map::iterator i = this->begin(); i != this->end(); ++i) {
174
 
                        i->second->InvalidatePointer(ptr);
175
 
                }
176
 
        }
177
 
 
178
 
public:
179
 
        Container() :
180
 
                CTOR_Count(0),
181
 
                DTOR_Count(0),
182
 
                Lookup_Failure_Count(0),
183
 
                Lookup_Success_Count(0)
184
 
        {
185
 
        }
186
 
 
187
 
        virtual ~Container() {
188
 
                Empty();
189
 
        }
190
 
 
191
 
        E_T *FindOrAllocate(S_T* key) {
192
 
                if(key == NULL) {
193
 
                        const std::type_info &info = typeid(*this);
194
 
                        Debug::Log("CTOR of %s attempted for a NULL pointer! WTF!\n", info.name());
195
 
                        return NULL;
196
 
                }
197
 
                typename C_Map::iterator i = this->find(key);
198
 
                if(i == this->end()) {
199
 
                        ++CTOR_Count;
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;
203
 
                }
204
 
                return i->second;
205
 
        }
206
 
 
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;
211
 
                        return NULL;
212
 
                }
213
 
                ++Lookup_Success_Count;
214
 
                return i->second;
215
 
        }
216
 
 
217
 
        void Remove(S_T* key) {
218
 
                typename C_Map::iterator i = this->find(key);
219
 
                if(i != this->end()) {
220
 
                        delete i->second;
221
 
                        erase(i);
222
 
                        ++DTOR_Count;
223
 
                }
224
 
        }
225
 
 
226
 
        void Remove(typename C_Map::iterator i) {
227
 
                if(i != this->end()) {
228
 
                        delete i->second;
229
 
                        erase(i);
230
 
                        ++DTOR_Count;
231
 
                }
232
 
        }
233
 
 
234
 
        void Empty() {
235
 
                for(typename C_Map::iterator i = this->begin(); i != this->end(); ) {
236
 
                        delete i->second;
237
 
                        erase(i++);
238
 
        //              ++i;
239
 
                }
240
 
        }
241
 
 
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);
245
 
                }
246
 
        }
247
 
 
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);
252
 
                }
253
 
        }
254
 
 
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);
258
 
                }
259
 
        }
260
 
 
261
 
        void SaveStatic() {
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;
266
 
                }
267
 
        }
268
 
 
269
 
        void Save(S_T *key, IStream *pStm) {
270
 
                this->SaveKey(key, pStm);
271
 
        }
272
 
 
273
 
        E_T* SaveKey(S_T *key, IStream *pStm) {
274
 
                ULONG out;
275
 
 
276
 
                const std::type_info &info = typeid(key);
277
 
                Debug::Log("Saving Key [%s] (%X)\n", info.name(), key);
278
 
 
279
 
                if(key == NULL) {
280
 
                        return NULL;
281
 
                }
282
 
                E_T* buffer = this->Find(key);
283
 
                Debug::Log("\tKey maps to %X\n", buffer);
284
 
                if(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);
288
 
                }
289
 
 
290
 
                Debug::Log("\n\n");
291
 
                return buffer;
292
 
        };
293
 
 
294
 
        void LoadStatic() {
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;
299
 
                }
300
 
        }
301
 
 
302
 
        void Load(S_T *key, IStream *pStm) {
303
 
                this->LoadKey(key, pStm);
304
 
        }
305
 
 
306
 
        E_T* LoadKey(S_T *key, IStream *pStm) {
307
 
                ULONG out;
308
 
 
309
 
                const std::type_info &info = typeid(key);
310
 
                Debug::Log("Loading Key [%s] (%X)\n", info.name(), key);
311
 
 
312
 
                if(key == NULL) {
313
 
                        Debug::Log("Load attempted for a NULL pointer! WTF!\n");
314
 
                        return NULL;
315
 
                }
316
 
                E_T* buffer = this->FindOrAllocate(key);
317
 
                long origPtr;
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);
323
 
#ifdef DEBUGBUILD
324
 
                        assert(buffer->SavedCanary == typename E_T::Canary);
325
 
#endif
326
 
                return buffer;
327
 
        };
328
 
 
329
 
        void Stat() {
330
 
                const std::type_info &info = typeid(*this);
331
 
                Debug::Log("Stats for container %s:\n", info.name());
332
 
 
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);
335
 
        }
336
 
 
337
 
};
338
 
 
339
 
#endif