sqrat  0.9
sqrat
 All Classes Functions Variables Enumerations Enumerator Pages
sqratObject.h
1 //
2 // SqratObject: Referenced Squirrel Object Wrapper
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_OBJECT_H_)
29 #define _SCRAT_OBJECT_H_
30 
31 #include <squirrel.h>
32 #include <string.h>
33 
34 #include "sqratAllocator.h"
35 #include "sqratTypes.h"
36 #include "sqratOverloadMethods.h"
37 #include "sqratUtil.h"
38 
39 namespace Sqrat {
40 
48 class Object {
49 protected:
51  HSQUIRRELVM vm;
52  HSQOBJECT obj;
53  bool release;
54 
55  Object(HSQUIRRELVM v, bool releaseOnDestroy = true) : vm(v), release(releaseOnDestroy) {
56  sq_resetobject(&obj);
57  }
59 
60 public:
65  Object() : vm(0), release(true) {
66  sq_resetobject(&obj);
67  }
68 
75  Object(const Object& so) : vm(so.vm), obj(so.obj), release(so.release) {
76  sq_addref(vm, &obj);
77  }
78 
86  Object(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : vm(v), obj(o), release(true) {
87  sq_addref(vm, &obj);
88  }
89 
99  template<class T>
100  Object(T* instance, HSQUIRRELVM v = DefaultVM::Get()) : vm(v), release(true) {
101  ClassType<T>::PushInstance(vm, instance);
102  sq_getstackobj(vm, -1, &obj);
103  sq_addref(vm, &obj);
104  }
105 
110  virtual ~Object() {
111  if(release) {
112  Release();
113  release = false;
114  }
115  }
116 
125  Object& operator=(const Object& so) {
126  if(release) {
127  Release();
128  }
129  vm = so.vm;
130  obj = so.obj;
131  release = so.release;
132  sq_addref(vm, &GetObject());
133  return *this;
134  }
135 
142  HSQUIRRELVM& GetVM() {
143  return vm;
144  }
145 
152  HSQUIRRELVM GetVM() const {
153  return vm;
154  }
155 
162  SQObjectType GetType() const {
163  return GetObject()._type;
164  }
165 
172  bool IsNull() const {
173  return sq_isnull(GetObject());
174  }
175 
182  virtual HSQOBJECT GetObject() const {
183  return obj;
184  }
185 
192  virtual HSQOBJECT& GetObject() {
193  return obj;
194  }
195 
200  operator HSQOBJECT&() {
201  return GetObject();
202  }
203 
208  void Release() {
209  sq_release(vm, &obj);
210  sq_resetobject(&obj);
211  }
212 
221  Object GetSlot(const SQChar* slot) const {
222  HSQOBJECT slotObj;
223  sq_pushobject(vm, GetObject());
224  sq_pushstring(vm, slot, -1);
225 
226 #if !defined (SCRAT_NO_ERROR_CHECKING)
227  if(SQ_FAILED(sq_get(vm, -2))) {
228  sq_pop(vm, 1);
229  return Object(vm); // Return a NULL object
230  } else {
231  sq_getstackobj(vm, -1, &slotObj);
232  Object ret(slotObj, vm); // must addref before the pop!
233  sq_pop(vm, 2);
234  return ret;
235  }
236 #else
237  sq_get(vm, -2);
238  sq_getstackobj(vm, -1, &slotObj);
239  Object ret(slotObj, vm); // must addref before the pop!
240  sq_pop(vm, 2);
241  return ret;
242 #endif
243  }
244 
253  Object GetSlot(SQInteger index) const {
254  HSQOBJECT slotObj;
255  sq_pushobject(vm, GetObject());
256  sq_pushinteger(vm, index);
257 
258 #if !defined (SCRAT_NO_ERROR_CHECKING)
259  if(SQ_FAILED(sq_get(vm, -2))) {
260  sq_pop(vm, 1);
261  return Object(vm); // Return a NULL object
262  } else {
263  sq_getstackobj(vm, -1, &slotObj);
264  Object ret(slotObj, vm); // must addref before the pop!
265  sq_pop(vm, 2);
266  return ret;
267  }
268 #else
269  sq_get(vm, -2);
270  sq_getstackobj(vm, -1, &slotObj);
271  Object ret(slotObj, vm); // must addref before the pop!
272  sq_pop(vm, 2);
273  return ret;
274 #endif
275  }
276 
288  template <class T>
289  T Cast() const {
290  sq_pushobject(vm, GetObject());
291  T ret = Var<T>(vm, -1).value;
292  sq_pop(vm, 1);
293  return ret;
294  }
295 
306  template <class T>
307  inline Object operator[](T slot)
308  {
309  return GetSlot(slot);
310  }
311 
318  SQInteger GetSize() const {
319  sq_pushobject(vm, GetObject());
320  SQInteger ret = sq_getsize(vm, -1);
321  sq_pop(vm, 1);
322  return ret;
323  }
324 
328  struct iterator
329  {
331  friend class Object;
333 
339  {
340  Index = 0;
341  sq_resetobject(&Key);
342  sq_resetobject(&Value);
343  Key._type = OT_NULL;
344  Value._type = OT_NULL;
345  }
346 
353  HSQOBJECT getKey() { return Key; }
354 
361  HSQOBJECT getValue() { return Value; }
362  private:
363 
364  HSQOBJECT Key;
365  HSQOBJECT Value;
366  SQInteger Index;
367  };
368 
377  bool Next(iterator& iter) const
378  {
379  sq_pushobject(vm,obj);
380  sq_pushinteger(vm,iter.Index);
381  if(SQ_SUCCEEDED(sq_next(vm,-2)))
382  {
383  sq_getstackobj(vm,-1,&iter.Value);
384  sq_getstackobj(vm,-2,&iter.Key);
385  sq_getinteger(vm,-3,&iter.Index);
386  sq_pop(vm,4);
387  return true;
388  }
389  else
390  {
391  sq_pop(vm,2);
392  return false;
393  }
394  }
395 
396 protected:
398 
399  // Bind a function and it's associated Squirrel closure to the object
400  inline void BindFunc(const SQChar* name, void* method, size_t methodSize, SQFUNCTION func, bool staticVar = false) {
401  sq_pushobject(vm, GetObject());
402  sq_pushstring(vm, name, -1);
403 
404  SQUserPointer methodPtr = sq_newuserdata(vm, static_cast<SQUnsignedInteger>(methodSize));
405  memcpy(methodPtr, method, methodSize);
406 
407  sq_newclosure(vm, func, 1);
408  sq_newslot(vm, -3, staticVar);
409  sq_pop(vm,1); // pop table
410  }
411 
412  inline void BindFunc(const SQInteger index, void* method, size_t methodSize, SQFUNCTION func, bool staticVar = false) {
413  sq_pushobject(vm, GetObject());
414  sq_pushinteger(vm, index);
415 
416  SQUserPointer methodPtr = sq_newuserdata(vm, static_cast<SQUnsignedInteger>(methodSize));
417  memcpy(methodPtr, method, methodSize);
418 
419  sq_newclosure(vm, func, 1);
420  sq_newslot(vm, -3, staticVar);
421  sq_pop(vm,1); // pop table
422  }
423 
424 
425  // Bind a function and it's associated Squirrel closure to the object
426  inline void BindOverload(const SQChar* name, void* method, size_t methodSize, SQFUNCTION func, SQFUNCTION overload, int argCount, bool staticVar = false) {
427  string overloadName = SqOverloadName::Get(name, argCount);
428 
429  sq_pushobject(vm, GetObject());
430 
431  // Bind overload handler
432  sq_pushstring(vm, name, -1);
433  sq_pushstring(vm, name, -1); // function name is passed as a free variable
434  sq_newclosure(vm, overload, 1);
435  sq_newslot(vm, -3, staticVar);
436 
437  // Bind overloaded function
438  sq_pushstring(vm, overloadName.c_str(), -1);
439  SQUserPointer methodPtr = sq_newuserdata(vm, static_cast<SQUnsignedInteger>(methodSize));
440  memcpy(methodPtr, method, methodSize);
441  sq_newclosure(vm, func, 1);
442  sq_newslot(vm, -3, staticVar);
443 
444  sq_pop(vm,1); // pop table
445  }
446 
447  // Set the value of a variable on the object. Changes to values set this way are not reciprocated
448  template<class V>
449  inline void BindValue(const SQChar* name, const V& val, bool staticVar = false) {
450  sq_pushobject(vm, GetObject());
451  sq_pushstring(vm, name, -1);
452  PushVar(vm, val);
453  sq_newslot(vm, -3, staticVar);
454  sq_pop(vm,1); // pop table
455  }
456  template<class V>
457  inline void BindValue(const SQInteger index, const V& val, bool staticVar = false) {
458  sq_pushobject(vm, GetObject());
459  sq_pushinteger(vm, index);
460  PushVar(vm, val);
461  sq_newslot(vm, -3, staticVar);
462  sq_pop(vm,1); // pop table
463  }
464 
465  // Set the value of an instance on the object. Changes to values set this way are reciprocated back to the source instance
466  template<class V>
467  inline void BindInstance(const SQChar* name, V* val, bool staticVar = false) {
468  sq_pushobject(vm, GetObject());
469  sq_pushstring(vm, name, -1);
470  PushVar(vm, val);
471  sq_newslot(vm, -3, staticVar);
472  sq_pop(vm,1); // pop table
473  }
474  template<class V>
475  inline void BindInstance(const SQInteger index, V* val, bool staticVar = false) {
476  sq_pushobject(vm, GetObject());
477  sq_pushinteger(vm, index);
478  PushVar(vm, val);
479  sq_newslot(vm, -3, staticVar);
480  sq_pop(vm,1); // pop table
481  }
482 
484 };
485 
487 template<>
488 inline void Object::BindValue<int>(const SQChar* name, const int & val, bool staticVar /* = false */) {
489  sq_pushobject(vm, GetObject());
490  sq_pushstring(vm, name, -1);
491  PushVar<int>(vm, val);
492  sq_newslot(vm, -3, staticVar);
493  sq_pop(vm,1); // pop table
494 }
496 
500 template<>
501 struct Var<Object> {
502 
504 
515  Var(HSQUIRRELVM vm, SQInteger idx) {
516  HSQOBJECT sqValue;
517  sq_getstackobj(vm, idx, &sqValue);
518  value = Object(sqValue, vm);
519  }
520 
528  static void push(HSQUIRRELVM vm, Object& value) {
529  sq_pushobject(vm, value.GetObject());
530  }
531 };
532 
536 template<>
537 struct Var<Object&> {
539 
550  Var(HSQUIRRELVM vm, SQInteger idx) {
551  HSQOBJECT sqValue;
552  sq_getstackobj(vm, idx, &sqValue);
553  value = Object(sqValue, vm);
554  }
555 
563  static void push(HSQUIRRELVM vm, Object& value) {
564  sq_pushobject(vm, value.GetObject());
565  }
566 };
567 
568 }
569 
570 #endif
static void push(HSQUIRRELVM vm, Object &value)
Definition: sqratObject.h:563
static HSQUIRRELVM Get()
Definition: sqratUtil.h:92
Object GetSlot(SQInteger index) const
Definition: sqratObject.h:253
void Release()
Definition: sqratObject.h:208
Object value
The actual value of get operations.
Definition: sqratObject.h:538
HSQOBJECT getKey()
Definition: sqratObject.h:353
SQObjectType GetType() const
Definition: sqratObject.h:162
T value
The actual value of get operations.
Definition: sqratTypes.h:152
HSQOBJECT getValue()
Definition: sqratObject.h:361
Object value
The actual value of get operations.
Definition: sqratObject.h:503
Definition: sqratTypes.h:150
T Cast() const
Definition: sqratObject.h:289
Object(HSQOBJECT o, HSQUIRRELVM v=DefaultVM::Get())
Definition: sqratObject.h:86
bool IsNull() const
Definition: sqratObject.h:172
SQInteger GetSize() const
Definition: sqratObject.h:318
iterator()
Definition: sqratObject.h:338
Object(const Object &so)
Definition: sqratObject.h:75
HSQUIRRELVM GetVM() const
Definition: sqratObject.h:152
Object GetSlot(const SQChar *slot) const
Definition: sqratObject.h:221
Object & operator=(const Object &so)
Definition: sqratObject.h:125
virtual HSQOBJECT GetObject() const
Definition: sqratObject.h:182
Object()
Definition: sqratObject.h:65
static void push(HSQUIRRELVM vm, Object &value)
Definition: sqratObject.h:528
Object(T *instance, HSQUIRRELVM v=DefaultVM::Get())
Definition: sqratObject.h:100
bool Next(iterator &iter) const
Definition: sqratObject.h:377
virtual HSQOBJECT & GetObject()
Definition: sqratObject.h:192
Definition: sqratObject.h:48
virtual ~Object()
Definition: sqratObject.h:110
Var(HSQUIRRELVM vm, SQInteger idx)
Definition: sqratObject.h:515
Var(HSQUIRRELVM vm, SQInteger idx)
Definition: sqratObject.h:550
Iterator for going over the slots in the object using Object::Next.
Definition: sqratObject.h:328
HSQUIRRELVM & GetVM()
Definition: sqratObject.h:142
Object operator[](T slot)
Definition: sqratObject.h:307