Code::Blocks  SVN r11506
SqPlus.cpp
Go to the documentation of this file.
1 #include "sqplus.h"
2 #include <stdio.h>
3 
4 namespace SqPlus {
5 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
SQInteger setInstanceVarFunc(HSQUIRRELVM v)
Definition: SqPlus.cpp:236
SQRESULT sq_get(HSQUIRRELVM v, SQInteger idx)
Definition: sqapi.cpp:840
SQRESULT sq_newclass(HSQUIRRELVM v, SQBool hasbase)
Definition: sqapi.cpp:239
static SQInteger setVar(StackHandler &sa, VarRef *vr, void *data)
Definition: SqPlus.cpp:63
BOOL_T CreateNativeClassInstance(HSQUIRRELVM v, const SQChar *classname, SQUserPointer ud, SQRELEASEHOOK hook)
void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)
Definition: sqapi.cpp:678
SQInteger getVarFunc(HSQUIRRELVM v)
Definition: SqPlus.cpp:223
void sq_pushroottable(HSQUIRRELVM v)
Definition: sqapi.cpp:437
SquirrelObject RegisterClassType(HSQUIRRELVM v, const SQChar *scriptClassName, SQUserPointer classType, SQFUNCTION constructor)
Definition: SqPlus.cpp:286
SQInteger sq_gettop(HSQUIRRELVM v)
Definition: sqapi.cpp:664
static SQInteger getInstanceVarInfo(StackHandler &sa, VarRefPtr &vr, SQUserPointer &data)
Definition: SqPlus.cpp:24
void sq_settop(HSQUIRRELVM v, SQInteger newtop)
Definition: sqapi.cpp:669
void sq_pushstring(HSQUIRRELVM v, const SQChar *s, SQInteger len)
Definition: sqapi.cpp:195
SQInteger setVarFunc(HSQUIRRELVM v)
Definition: SqPlus.cpp:212
BOOL_T CreateClass(HSQUIRRELVM v, SquirrelObject &newClass, SQUserPointer classType, const SQChar *name, const SQChar *baseName)
Definition: SqPlus.cpp:262
char SQChar
SQInteger getInstanceVarFunc(HSQUIRRELVM v)
Definition: SqPlus.cpp:248
SQRESULT sq_settypetag(HSQUIRRELVM v, SQInteger idx, SQUserPointer typetag)
Definition: sqapi.cpp:591
static SQInteger getVar(StackHandler &sa, VarRef *vr, void *data)
Definition: SqPlus.cpp:137
static SQInteger getVarInfo(StackHandler &sa, VarRefPtr &vr)
Definition: SqPlus.cpp:6