1 #include "sqplus.h"
2 #include <stdio.h>
3
4 namespace SqPlus {
5
getVarInfo(StackHandler & sa,VarRefPtr & vr)6 static SQInteger getVarInfo(StackHandler & sa,VarRefPtr & vr) {
7 HSQOBJECT htable = sa.GetObjectHandle(1);
8 SquirrelObject table(htable);
9 #ifdef _DEBUG
10 SQObjectType type = (SQObjectType)sa.GetType(2);
11 #endif
12 const SQChar * el = sa.GetString(2);
13 ScriptStringVar256 varNameTag;
14 getVarNameTag(varNameTag,sizeof(varNameTag),el);
15 SQUserPointer data=0;
16 if (!table.RawGetUserData(varNameTag,&data)) {
17 // throw SquirrelError("getVarInfo: Could not retrieve UserData");
18 return sa.ThrowError(sqT("getVarInfo: Could not retrieve UserData")); // Results in variable not being found error.
19 } // if
20 vr = (VarRefPtr)data;
21 return SQ_OK;
22 } // getVarInfo
23
getInstanceVarInfo(StackHandler & sa,VarRefPtr & vr,SQUserPointer & data)24 static SQInteger getInstanceVarInfo(StackHandler & sa,VarRefPtr & vr,SQUserPointer & data) {
25 HSQOBJECT ho = sa.GetObjectHandle(1);
26 SquirrelObject instance(ho);
27 #ifdef _DEBUG
28 SQObjectType type = (SQObjectType)sa.GetType(2);
29 #endif
30 const SQChar * el = sa.GetString(2);
31 ScriptStringVar256 varNameTag;
32 getVarNameTag(varNameTag,sizeof(varNameTag),el);
33 SQUserPointer ivrData=0;
34 if (!instance.RawGetUserData(varNameTag,&ivrData)) {
35 // throw SquirrelError("getInstanceVarInfo: Could not retrieve UserData");
36 return sa.ThrowError(sqT("getInstanceVarInfo: Could not retrieve UserData")); // Results in variable not being found error.
37 } // if
38 vr = (VarRefPtr)ivrData;
39 unsigned char * up;
40 if (!(vr->access & (VAR_ACCESS_STATIC|VAR_ACCESS_CONSTANT))) {
41 #ifdef SQ_USE_CLASS_INHERITANCE
42 SQUserPointer typetag; instance.GetTypeTag(&typetag);
43 if (typetag != vr->instanceType) {
44 SquirrelObject typeTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
45 up = (unsigned char *)typeTable.GetUserPointer(INT_T((size_t)vr->instanceType)); // <TODO> 64-bit compatible version.
46 if (!up) {
47 throw SquirrelError(sqT("Invalid Instance Type"));
48 } // if
49 } else {
50 up = (unsigned char *)instance.GetInstanceUP(0);
51 } // if
52 #else
53 up = (unsigned char *)instance.GetInstanceUP(0);
54 #endif
55 up += (size_t)vr->offsetOrAddrOrConst; // Offset
56 } else {
57 up = (unsigned char *)vr->offsetOrAddrOrConst; // Address
58 } // if
59 data = up;
60 return SQ_OK;
61 } // getInstanceVarInfo
62
setVar(StackHandler & sa,VarRef * vr,void * data)63 static SQInteger setVar(StackHandler & sa,VarRef * vr,void * data) {
64 if (vr->access & (VAR_ACCESS_READ_ONLY|VAR_ACCESS_CONSTANT)) {
65 ScriptStringVar256 msg;
66 const SQChar * el = sa.GetString(2);
67 SCSNPRINTF(msg.s,sizeof(msg.s),sqT("setVar(): Cannot write to constant: %s"),el);
68 throw SquirrelError(msg.s);
69 } // if
70 switch (vr->type) {
71 case TypeInfo<INT_T>::TypeID: {
72 INT_T * val = (INT_T *)data; // Address
73 if (val) {
74 *val = sa.GetInt(3);
75 return sa.Return(*val);
76 } // if
77 break;
78 } // case
79 case TypeInfo<FLOAT_T>::TypeID: {
80 FLOAT_T * val = (FLOAT_T *)data; // Address
81 if (val) {
82 *val = sa.GetFloat(3);
83 return sa.Return(*val);
84 } // if
85 break;
86 } // case
87 case TypeInfo<bool>::TypeID: {
88 bool * val = (bool *)data; // Address
89 if (val) {
90 *val = sa.GetBool(3) ? true : false;
91 return sa.Return(*val);
92 } // if
93 break;
94 } // case
95 case VAR_TYPE_INSTANCE: {
96 // C::B patch: Comment out unused variable
97 //HSQUIRRELVM v = sa.GetVMPtr();
98 // vr->copyFunc is the LHS variable type: the RHS var's type is ClassType<>::type() (both point to ClassType<>::copy()).
99 // src will be null if the LHS and RHS types don't match.
100 SQUserPointer src = sa.GetInstanceUp(3,(SQUserPointer)vr->copyFunc); // Effectively performs: ClassType<>::type() == ClassType<>getCopyFunc().
101 if (!src) throw SquirrelError(sqT("INSTANCE type assignment mismatch"));
102 vr->copyFunc(data,src);
103 #if 0 // Return an instance on the stack (allocates memory)
104 if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address
105 ScriptStringVar256 msg;
106 SCSNPRINTF(msg.s,sizeof(msg),sqT("getVar(): Could not create instance: %s"),vr->typeName);
107 throw SquirrelError(msg.s);
108 } // if
109 return 1;
110 #else // Don't return on stack.
111 return 0;
112 #endif
113 }
114 case TypeInfo<SQUserPointer>::TypeID: {
115 ScriptStringVar256 msg;
116 const SQChar * el = sa.GetString(2);
117 SCSNPRINTF(msg.s,sizeof(msg.s),sqT("setVar(): Cannot write to an SQUserPointer: %s"),el);
118 throw SquirrelError(msg.s);
119 } // case
120 case TypeInfo<ScriptStringVarBase>::TypeID: {
121 ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address
122 if (val) {
123 const SQChar * strVal = sa.GetString(3);
124 if (strVal) {
125 *val = strVal;
126 return sa.Return(val->s);
127 } // if
128 } // if
129 break;
130 } // case
131 // C::B patch: Handle all switch cases
132 default: break;
133 } // switch
134 return SQ_ERROR;
135 } // setVar
136
getVar(StackHandler & sa,VarRef * vr,void * data)137 static SQInteger getVar(StackHandler & sa,VarRef * vr,void * data) {
138 switch (vr->type) {
139 case TypeInfo<INT_T>::TypeID: {
140 if (!(vr->access & VAR_ACCESS_CONSTANT)) {
141 INT_T * val = (INT_T *)data; // Address
142 if (val) {
143 return sa.Return(*val);
144 } // if
145 } else {
146 INT_T * val = (INT_T *)&data; // Constant value
147 return sa.Return(*val);
148 } // if
149 break;
150 } // case
151 case TypeInfo<FLOAT_T>::TypeID: {
152 if (!(vr->access & VAR_ACCESS_CONSTANT)) {
153 FLOAT_T * val = (FLOAT_T *)data; // Address
154 if (val) {
155 return sa.Return(*val);
156 } // if
157 } else {
158 FLOAT_T * val = (FLOAT_T *)&data; // Constant value
159 return sa.Return(*val);
160 } // if
161 break;
162 } // case
163 case TypeInfo<bool>::TypeID: {
164 if (!(vr->access & VAR_ACCESS_CONSTANT)) {
165 bool * val = (bool *)data; // Address
166 if (val) {
167 return sa.Return(*val);
168 } // if
169 } else {
170 bool * val = (bool *)&data; // Constant value
171 return sa.Return(*val);
172 } // if
173 break;
174 } // case
175 case VAR_TYPE_INSTANCE:
176 if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address. Allocates memory.
177 ScriptStringVar256 msg;
178 SCSNPRINTF(msg.s,sizeof(msg.s),sqT("getVar(): Could not create instance: %s"),vr->typeName);
179 throw SquirrelError(msg.s);
180 } // if
181 return 1;
182 case TypeInfo<SQUserPointer>::TypeID: {
183 return sa.Return(data); // The address of member variable, not the variable itself.
184 } // case
185 case TypeInfo<ScriptStringVarBase>::TypeID: {
186 if (!(vr->access & VAR_ACCESS_CONSTANT)) {
187 ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address
188 if (val) {
189 return sa.Return(val->s);
190 } // if
191 } else {
192 throw SquirrelError(sqT("getVar(): Invalid type+access: 'ScriptStringVarBase' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)"));
193 } // if
194 break;
195 } // case
196 case TypeInfo<const SQChar *>::TypeID: {
197 if (!(vr->access & VAR_ACCESS_CONSTANT)) {
198 throw SquirrelError(sqT("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT"));
199 } else {
200 return sa.Return((const SQChar *)data); // Address
201 } // if
202 break;
203 } // case
204 // C::B patch: Handle all switch cases
205 default: break;
206 } // switch
207 return SQ_ERROR;
208 } // getVar
209
210 // === Global Vars ===
211
setVarFunc(HSQUIRRELVM v)212 SQInteger setVarFunc(HSQUIRRELVM v) {
213 StackHandler sa(v);
214 if (sa.GetType(1) == OT_TABLE) {
215 VarRefPtr vr;
216 SQInteger res = getVarInfo(sa,vr);
217 if (res != SQ_OK) return res;
218 return setVar(sa,vr,vr->offsetOrAddrOrConst);
219 } // if
220 return SQ_ERROR;
221 } // setVarFunc
222
getVarFunc(HSQUIRRELVM v)223 SQInteger getVarFunc(HSQUIRRELVM v) {
224 StackHandler sa(v);
225 if (sa.GetType(1) == OT_TABLE) {
226 VarRefPtr vr;
227 SQInteger res = getVarInfo(sa,vr);
228 if (res != SQ_OK) return res;
229 return getVar(sa,vr,vr->offsetOrAddrOrConst);
230 } // if
231 return SQ_ERROR;
232 } // getVarFunc
233
234 // === Instance Vars ===
235
setInstanceVarFunc(HSQUIRRELVM v)236 SQInteger setInstanceVarFunc(HSQUIRRELVM v) {
237 StackHandler sa(v);
238 if (sa.GetType(1) == OT_INSTANCE) {
239 VarRefPtr vr;
240 void * data;
241 SQInteger res = getInstanceVarInfo(sa,vr,data);
242 if (res != SQ_OK) return res;
243 return setVar(sa,vr,data);
244 } // if
245 return SQ_ERROR;
246 } // setInstanceVarFunc
247
getInstanceVarFunc(HSQUIRRELVM v)248 SQInteger getInstanceVarFunc(HSQUIRRELVM v) {
249 StackHandler sa(v);
250 if (sa.GetType(1) == OT_INSTANCE) {
251 VarRefPtr vr;
252 void * data;
253 SQInteger res = getInstanceVarInfo(sa,vr,data);
254 if (res != SQ_OK) return res;
255 return getVar(sa,vr,data);
256 } // if
257 return SQ_ERROR;
258 } // getInstanceVarFunc
259
260 // === Classes ===
261
CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName)262 BOOL_T CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName) {
263 // C::B patch: Comment out unused variable
264 //SQInteger n = 0;
265 SQInteger oldtop = sq_gettop(v);
266 sq_pushroottable(v);
267 sq_pushstring(v,name,-1);
268 if (baseName) {
269 sq_pushstring(v,baseName,-1);
270 if (SQ_FAILED(sq_get(v,-3))) { // Make sure the base exists if specified by baseName.
271 sq_settop(v,oldtop);
272 return FALSE;
273 } // if
274 } // if
275 if (SQ_FAILED(sq_newclass(v,baseName ? 1 : 0))) { // Will inherit from base class on stack from sq_get() above.
276 sq_settop(v,oldtop);
277 return FALSE;
278 } // if
279 newClass.AttachToStackObject(-1);
280 sq_settypetag(v,-1,classType);
281 sq_createslot(v,-3);
282 sq_pop(v,1);
283 return TRUE;
284 } // CreateClass
285
RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,SQUserPointer classType,SQFUNCTION constructor)286 SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,SQUserPointer classType,SQFUNCTION constructor) {
287 SQInteger top = sq_gettop(v);
288 SquirrelObject newClass;
289 if (CreateClass(v,newClass,classType,scriptClassName)) {
290 SquirrelVM::CreateFunction(newClass,constructor,sqT("constructor"));
291 } // if
292 sq_settop(v,top);
293 return newClass;
294 } // RegisterClassType
295
296 }; // namespace SqPlus
297
298 // sqPlus
299