1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 /*
4  * creg - Code compoment registration system
5  * Classes for serialization of registrated class instances
6  */
7 
8 #include <map>
9 #include <vector>
10 #include <string>
11 #include <string.h>
12 
13 
14 // creg has to be made aware of mmgr explicitly
15 #define	operator_new		::operator new
16 #define	operator_delete		::operator delete
17 
18 #include "System/Util.h"
19 
20 #include "creg_cond.h"
21 
22 using namespace creg;
23 using std::map;
24 using std::vector;
25 using std::string;
26 
27 static map<string, Class*> mapNameToClass;
28 static int currentMemberFlags = 0; // used when registering class members
29 
30 // -------------------------------------------------------------------
31 // Class Binder
32 // -------------------------------------------------------------------
33 
34 ClassBinder* System::binderList = 0;
35 vector<Class*> System::classes;
36 
ClassBinder(const char * className,unsigned int cf,ClassBinder * baseClsBinder,IMemberRegistrator ** mreg,int instanceSize,int instanceAlignment,bool hasVTable,void (* constructorProc)(void * inst),void (* destructorProc)(void * inst))37 ClassBinder::ClassBinder(const char* className, unsigned int cf,
38 		ClassBinder* baseClsBinder, IMemberRegistrator** mreg, int instanceSize, int instanceAlignment, bool hasVTable,
39 		void (*constructorProc)(void* inst), void (*destructorProc)(void* inst))
40 	: class_(NULL)
41 	, base(baseClsBinder)
42 	, flags((ClassFlags)cf)
43 	, memberRegistrator(mreg)
44 	, name(className)
45 	, size(instanceSize)
46 	, alignment(instanceAlignment)
47 	, hasVTable(hasVTable)
48 	, constructor(constructorProc)
49 	, destructor(destructorProc)
50 	, nextBinder(NULL)
51 {
52 
53 	// link to the list of class binders
54 	System::AddClassBinder(this);
55 }
56 
InitializeClasses()57 void System::InitializeClasses()
58 {
59 	if (!classes.empty())
60 		return;
61 
62 	// Create Class instances
63 	for (ClassBinder* c = binderList; c; c = c->nextBinder) {
64 		c->class_ = new Class;
65 	}
66 
67 	// Initialize class instances
68 	for (ClassBinder* c = binderList; c; c = c->nextBinder) {
69 		Class* cls = c->class_;
70 
71 		cls->binder = c;
72 		cls->name = c->name;
73 		cls->size = c->size;
74 		cls->alignment = c->alignment;
75 		cls->base = c->base ? c->base->class_ : NULL;
76 		mapNameToClass [cls->name] = cls;
77 
78 		if (cls->base) {
79 			cls->base->derivedClasses.push_back(cls);
80 		}
81 
82 		currentMemberFlags = 0;
83 		// Register members
84 		if (*c->memberRegistrator) {
85 			(*c->memberRegistrator)->RegisterMembers(cls);
86 		}
87 
88 		classes.push_back(cls);
89 	}
90 }
91 
FreeClasses()92 void System::FreeClasses()
93 {
94 	for (uint a = 0; a < classes.size(); a++) {
95 		delete classes[a];
96 	}
97 	classes.clear();
98 }
99 
GetClass(const string & name)100 Class* System::GetClass(const string& name)
101 {
102 	map<string, Class*>::const_iterator c = mapNameToClass.find(name);
103 	if (c == mapNameToClass.end()) {
104 		return NULL;
105 	}
106 	return c->second;
107 }
108 
AddClassBinder(ClassBinder * cb)109 void System::AddClassBinder(ClassBinder* cb)
110 {
111 	cb->nextBinder = binderList;
112 	binderList = cb;
113 }
114 
115 // ------------------------------------------------------------------
116 // creg::Class: Class description
117 // ------------------------------------------------------------------
118 
Class()119 Class::Class() :
120 	binder(NULL),
121 	size(0),
122 	alignment(0),
123 	base(NULL),
124 	serializeProc(NULL),
125 	postLoadProc(NULL)
126 {}
127 
~Class()128 Class::~Class()
129 {
130 	for (unsigned int a = 0; a < members.size(); a++) {
131 		delete members[a];
132 	}
133 	members.clear();
134 }
135 
IsSubclassOf(Class * other) const136 bool Class::IsSubclassOf(Class* other) const
137 {
138 	for (const Class* c = this; c; c = c->base) {
139 		if (c == other) {
140 			return true;
141 		}
142 	}
143 
144 	return false;
145 }
146 
GetImplementations()147 std::vector<Class*> Class::GetImplementations()
148 {
149 	std::vector<Class*> classes;
150 
151 	for (unsigned int a = 0; a < derivedClasses.size(); a++) {
152 		Class* dc = derivedClasses[a];
153 		if (!dc->IsAbstract()) {
154 			classes.push_back(dc);
155 		}
156 
157 		const std::vector<Class*>& impl = dc->GetImplementations();
158 		classes.insert(classes.end(), impl.begin(), impl.end());
159 	}
160 
161 	return classes;
162 }
163 
BeginFlag(ClassMemberFlag flag)164 void Class::BeginFlag(ClassMemberFlag flag)
165 {
166 	currentMemberFlags |= (int)flag;
167 }
168 
EndFlag(ClassMemberFlag flag)169 void Class::EndFlag(ClassMemberFlag flag)
170 {
171 	currentMemberFlags &= ~(int)flag;
172 }
173 
SetFlag(ClassFlags flag)174 void Class::SetFlag(ClassFlags flag)
175 {
176 	binder->flags = (ClassFlags) (binder->flags | flag);
177 }
178 
AddMember(const char * name,IType * type,unsigned int offset,int alignment)179 bool Class::AddMember(const char* name, IType* type, unsigned int offset, int alignment)
180 {
181 	if (FindMember(name))
182 		return false;
183 
184 	Member* member = new Member;
185 
186 	member->name = name;
187 	member->offset = offset;
188 	member->type = boost::shared_ptr<IType>(type);
189 	member->alignment = alignment;
190 	member->flags = currentMemberFlags;
191 
192 	members.push_back(member);
193 	return true;
194 }
195 
AddMember(const char * name,boost::shared_ptr<IType> type,unsigned int offset,int alignment)196 bool Class::AddMember(const char* name, boost::shared_ptr<IType> type, unsigned int offset, int alignment)
197 {
198 	if (FindMember(name))
199 		return false;
200 
201 	Member* member = new Member;
202 
203 	member->name = name;
204 	member->offset = offset;
205 	member->type = type;
206 	member->alignment = alignment;
207 	member->flags = currentMemberFlags;
208 
209 	members.push_back(member);
210 	return true;
211 }
212 
FindMember(const char * name)213 Class::Member* Class::FindMember(const char* name)
214 {
215 	for (Class* c = this; c; c = c->base) {
216 		for (uint a = 0; a < c->members.size(); a++) {
217 			Member* member = c->members[a];
218 			if (!STRCASECMP(member->name, name))
219 				return member;
220 		}
221 	}
222 	return NULL;
223 }
224 
SetMemberFlag(const char * name,ClassMemberFlag f)225 void Class::SetMemberFlag(const char* name, ClassMemberFlag f)
226 {
227 	for (uint a = 0; a < members.size(); a++) {
228 		if (!strcmp(members[a]->name, name)) {
229 			members[a]->flags |= (int)f;
230 			break;
231 		}
232 	}
233 }
234 
CreateInstance()235 void* Class::CreateInstance()
236 {
237 	void* inst = operator_new(binder->size);
238 
239 	if (binder->constructor) {
240 		binder->constructor(inst);
241 	}
242 	return inst;
243 }
244 
DeleteInstance(void * inst)245 void Class::DeleteInstance(void* inst)
246 {
247 	if (binder->destructor) {
248 		binder->destructor(inst);
249 	}
250 
251 	operator_delete(inst);
252 }
253 
StringHash(const std::string & str,unsigned int & hash)254 static void StringHash(const std::string& str, unsigned int& hash)
255 {
256 	// FIXME use HsiehHash.h?
257 	unsigned int a = 63689;
258 	for (std::string::const_iterator si = str.begin(); si != str.end(); ++si) {
259 		hash = hash * a + (*si);
260 		a *= 378551;
261 	}
262 }
263 
CalculateChecksum(unsigned int & checksum)264 void Class::CalculateChecksum(unsigned int& checksum)
265 {
266 	for (size_t a = 0; a < members.size(); a++) {
267 		Member* m = members[a];
268 		checksum += m->flags;
269 		StringHash(m->name, checksum);
270 		StringHash(m->type->GetName(), checksum);
271 		checksum += m->type->GetSize();
272 	}
273 	if (base) {
274 		base->CalculateChecksum(checksum);
275 	}
276 }
277 
278 
~IType()279 IType::~IType() {
280 }
281 
~IMemberRegistrator()282 IMemberRegistrator::~IMemberRegistrator() {
283 }
284 
285 
286