sqrat  0.9
sqrat
 All Classes Functions Variables Enumerations Enumerator Pages
sqratClassType.h
1 //
2 // SqratClassType: Type Translators
3 //
4 
5 //
6 // Copyright (c) 2009 Brandon Jones
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 //
21 // 2. Altered source versions must be plainly marked as such, and must not be
22 // misrepresented as being the original software.
23 //
24 // 3. This notice may not be removed or altered from any source
25 // distribution.
26 //
27 
28 #if !defined(_SCRAT_CLASSTYPE_H_)
29 #define _SCRAT_CLASSTYPE_H_
30 
31 #include <squirrel.h>
32 #include <map>
33 
34 #include "sqratUtil.h"
35 
36 namespace Sqrat
37 {
38 
40 
41 // The copy function for a class
42 typedef SQInteger (*COPYFUNC)(HSQUIRRELVM, SQInteger, const void*);
43 
44 // Every Squirrel class object made by Sqrat has its type tag set to a unique ClassTypeDataBase object
45 struct ClassTypeDataBase {
46  HSQOBJECT classObj;
47  HSQOBJECT getTable;
48  HSQOBJECT setTable;
49  COPYFUNC copyFunc;
50  string className;
51  ClassTypeDataBase* baseClass;
52  bool ctorCalled;
53  virtual ~ClassTypeDataBase() {}
54  virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) = 0;
55  ClassTypeDataBase() : ctorCalled(false){}
56 };
57 
58 // Keeps track of the nearest base class and the class associated with a ClassTypeDataBase in order to cast pointers to the right base class
59 template<class C, class B>
60 struct ClassTypeData : public ClassTypeDataBase {
61  virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) {
62  if (classType != this) {
63  ptr = baseClass->Cast(static_cast<B*>(static_cast<C*>(ptr)), classType);
64  }
65  return ptr;
66  }
67 };
68 
69 // Internal helper class for managing classes
70 template<class C>
71 struct ClassType {
72 
73  static std::map< HSQUIRRELVM, ClassTypeDataBase* > s_classTypeDataMap;
74 
75  static inline ClassTypeDataBase*& getClassTypeData(HSQUIRRELVM vm) {
76  //TODO: use mutex to lock s_classTypeDataMap in multithreaded environment
77  return s_classTypeDataMap[vm];
78  }
79 
80  static inline bool hasClassTypeData(HSQUIRRELVM vm) {
81  //TODO: use mutex to lock s_classTypeDataMap in multithreaded environment
82  return (s_classTypeDataMap.find(vm) != s_classTypeDataMap.end());
83  }
84 
85  static inline void deleteClassTypeData(HSQUIRRELVM vm) {
86  //TODO: use mutex to lock s_classTypeDataMap in multithreaded environment
87  std::map< HSQUIRRELVM, ClassTypeDataBase* >::iterator it = s_classTypeDataMap.find(vm);
88  if(it != s_classTypeDataMap.end()) {
89  s_classTypeDataMap.erase(it);
90  }
91  }
92 
93  // Get the Squirrel Object for this Class
94  static inline HSQOBJECT& ClassObject(HSQUIRRELVM vm) {
95  return getClassTypeData(vm)->classObj;
96  }
97 
98  // Get the Get Table for this Class
99  static inline HSQOBJECT& GetTable(HSQUIRRELVM vm) {
100  return getClassTypeData(vm)->getTable;
101  }
102 
103  // Get the Set Table for this Class
104  static inline HSQOBJECT& SetTable(HSQUIRRELVM vm) {
105  return getClassTypeData(vm)->setTable;
106  }
107 
108  static inline COPYFUNC& CopyFunc(HSQUIRRELVM vm) {
109  return getClassTypeData(vm)->copyFunc;
110  }
111 
112  static inline string& ClassName(HSQUIRRELVM vm) {
113  return getClassTypeData(vm)->className;
114  }
115 
116  static inline ClassTypeDataBase*& BaseClass(HSQUIRRELVM vm) {
117  return getClassTypeData(vm)->baseClass;
118  }
119 
120  static void PushInstance(HSQUIRRELVM vm, C* ptr) {
121 #if !defined (SCRAT_NO_ERROR_CHECKING)
122  if (ptr != NULL) {
123  sq_pushobject(vm, ClassObject(vm));
124  sq_createinstance(vm, -1);
125  sq_remove(vm, -2);
126  sq_setinstanceup(vm, -1, ptr);
127  }
128  else
129  sq_pushnull(vm);
130 #else
131  sq_pushobject(vm, ClassObject(vm));
132  sq_createinstance(vm, -1);
133  sq_remove(vm, -2);
134  sq_setinstanceup(vm, -1, ptr);
135 #endif
136  }
137 
138  static void PushInstanceCopy(HSQUIRRELVM vm, const C& value) {
139  sq_pushobject(vm, ClassObject(vm));
140  sq_createinstance(vm, -1);
141  sq_remove(vm, -2);
142  CopyFunc(vm)(vm, -1, &value);
143  }
144 
145  static C* GetInstance(HSQUIRRELVM vm, SQInteger idx) {
146  SQUserPointer ptr = NULL;
147  ClassTypeDataBase* classType = getClassTypeData(vm);
148  if (classType != 0) /* type checking only done if the value has type data else it may be enum */
149  {
150 #if !defined (SCRAT_NO_ERROR_CHECKING)
151  if (SQ_FAILED(sq_getinstanceup(vm, idx, &ptr, classType))) {
152  Error::Instance().Throw(vm, Sqrat::Error::FormatTypeError(vm, idx, ClassName(vm)));
153  return NULL;
154  }
155 #else
156  sq_getinstanceup(vm, idx, &ptr, 0);
157 #endif
158  }
159  else /* value is likely of integral type like enums, cannot return a pointer */
160  {
161 #if !defined (SCRAT_NO_ERROR_CHECKING)
162  Error::Instance().Throw(vm, Sqrat::Error::FormatTypeError(vm, idx, _SC("unknown")));
163 #endif
164  return NULL;
165  }
166  ClassTypeDataBase* actualType;
167  sq_gettypetag(vm, idx, (SQUserPointer*)&actualType);
168  if (actualType == NULL) {
169  SQInteger top = sq_gettop(vm);
170  sq_getclass(vm, idx);
171  while (actualType == NULL) {
172  sq_getbase(vm, -1);
173  sq_gettypetag(vm, -1, (SQUserPointer*)&actualType);
174  }
175  sq_settop(vm, top);
176  }
177  if (classType != actualType) {
178  return static_cast<C*>(actualType->Cast(ptr, classType));
179  }
180  return static_cast<C*>(ptr);
181  }
182 };
183 
184 template<class C>
185 std::map< HSQUIRRELVM, ClassTypeDataBase* > ClassType<C>::s_classTypeDataMap;
186 
188 
189 }
190 
191 #endif
static string FormatTypeError(HSQUIRRELVM vm, SQInteger idx, const string &expectedType)
Definition: sqratUtil.h:149
static Error & Instance()
Definition: sqratUtil.h:134
void Throw(HSQUIRRELVM vm, const string &err)
Definition: sqratUtil.h:210