~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/include/scripting/sqplus/sqplus.h

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// SqPlus.h
 
2
// Created by John Schultz 9/05/05, major update 10/05/05.
 
3
// Template function call design from LuaPlusCD by Joshua C. Jensen,
 
4
// inspired by luabind which was inspired by boost::python.
 
5
// Const argument, const member functions, and Mac OS-X changes by Simon Michelmore.
 
6
// DECLARE_INSTANCE_TYPE_NAME changes by Ben (Project5) from http://www.squirrel-lang.org/forums/.
 
7
// Added Kamaitati's changes 5/28/06.
 
8
// Free for any use.
 
9
 
 
10
#ifndef _SQ_PLUS_H_
 
11
#define _SQ_PLUS_H_
 
12
 
 
13
#include <stdlib.h>
 
14
 
 
15
#ifdef __APPLE__
 
16
  #include <malloc/malloc.h>
 
17
#else
 
18
  // C::B patch: support for FreeBSD
 
19
  #ifdef __FreeBSD__
 
20
    #include <stdlib.h>
 
21
  #else
 
22
    #include <malloc.h>
 
23
  #endif
 
24
#endif
 
25
#include <memory.h>
 
26
#if defined(_MSC_VER) || defined(__BORLANDC__)
 
27
  #include <tchar.h>
 
28
  #ifndef UNICODE
 
29
    #define SCSNPRINTF _snprintf
 
30
    #define SCPUTS puts
 
31
  #else
 
32
    #define SCSNPRINTF _snwprintf
 
33
    #define SCPUTS _putws
 
34
  #endif
 
35
#else
 
36
  // C::B patch: Convert conflicting _T() to sqT() --> applies to nearly *all* files!
 
37
//  #define _T(n) n
 
38
  #define sqT(n) n
 
39
  #define SCSNPRINTF snprintf
 
40
  #include <stdio.h> // for snprintf
 
41
  #define SCPUTS puts
 
42
#endif
 
43
 
 
44
#if 1
 
45
#define SQ_CALL_RAISE_ERROR SQTrue
 
46
#else
 
47
#define SQ_CALL_RAISE_ERROR SQFalse
 
48
#endif
 
49
 
 
50
#include "squirrel.h"
 
51
 
 
52
// C::B patch: so it builds on 64bit, ecapsulate bool/int/float using Squirrel types (this patch applies everywhere, where threse types are used)
 
53
typedef SQInteger BOOL_T;
 
54
typedef SQInteger INT_T;
 
55
typedef SQFloat   FLOAT_T;
 
56
#define TRUE 1
 
57
#define FALSE 0
 
58
 
 
59
#include "SquirrelObject.h"
 
60
#include "SquirrelVM.h"
 
61
#include "SquirrelBindingsUtils.h"
 
62
 
 
63
namespace SqPlus {
 
64
 
 
65
// === Class Inheritance Support ===
 
66
// Inheritance in Squirrel allows one class to inherit a base class's functions and variables.
 
67
// Variables are merged: if Derived has a var name 'val' and Base has a var of the same name,
 
68
// the resulting var 'val' will take Derived's initialization value.
 
69
// Functions are not merged, and can be called via Squirrel scoping rules.
 
70
 
 
71
// Define SQ_USE_CLASS_INHERITANCE to enable class inheritance support
 
72
// (requires slightly more memory and adds some CPU overhead).
 
73
// Can also be useful for debugging, as class type information is checked before
 
74
// dispatching instance function calls and before accessing instance member variables.
 
75
#define SQ_USE_CLASS_INHERITANCE
 
76
 
 
77
// Comment out to turn off instance type info support (to save a small amount of memory).
 
78
#define SQ_SUPPORT_INSTANCE_TYPE_INFO
 
79
 
 
80
// === Constant argument and constant member function support ===
 
81
// Define SQPLUS_CONST_OPT before including SqPlus.h for constant argument + constant member function support.
 
82
// C::B patch: Enable this option
 
83
#define SQPLUS_CONST_OPT
 
84
 
 
85
// === Uncomment to support std::string ===
 
86
//#define SQPLUS_SUPPORT_STD_STRING
 
87
 
 
88
// === Uncomment to support typedef std::basic_string<SQChar> sq_std_string ===
 
89
//#define SQPLUS_SUPPORT_SQ_STD_STRING
 
90
 
 
91
// === Uncomment to support NULL INSTANCE arguments ===
 
92
//#define SQPLUS_SUPPORT_NULL_INSTANCES
 
93
 
 
94
// === Uncomment to support C++ style inheritance
 
95
#define CPP_STYLE_INHERITANCE
 
96
 
 
97
// === Uncomment to skip sq_argassert() ===
 
98
//#define SQ_SKIP_ARG_ASSERT
 
99
 
 
100
template<class T> struct TypeWrapper {};
 
101
struct SquirrelNull {};
 
102
struct SQAnything { void * anything; }; // Needed for binding pointers to variables (cannot dereference void *).
 
103
typedef SQAnything * SQAnythingPtr;
 
104
typedef SQChar * SQCharPtr;
 
105
 
 
106
// === Do not use directly: use one of the predefined sizes below ===
 
107
 
 
108
struct ScriptStringVarBase {
 
109
  //const unsigned char MaxLength; // Real length is MaxLength+1.
 
110
  const SQInteger MaxLength; // C::B patch- to eliminate compiler warning
 
111
  SQChar s[1];
 
112
  ScriptStringVarBase(SQInteger _MaxLength) : MaxLength(_MaxLength) {}
 
113
  operator SQChar * () { return &s[0]; }
 
114
  operator void * () { return (void *)&s[0]; }
 
115
  const SQChar * operator = (const SQChar * _s) {
 
116
    return safeStringCopy(s,_s,MaxLength);
 
117
  }
 
118
  // Special safe string copy where MaxLength is 1 less than true buffer length.
 
119
  // strncpy() pads out nulls for the full length of the buffer specified by MaxLength.
 
120
  static inline SQChar * safeStringCopy(SQChar * d,const SQChar * s,SQInteger MaxLength) {
 
121
    SQInteger i=0;
 
122
    while (s[i]) {
 
123
      d[i] = s[i];
 
124
      i++;
 
125
      if (i == MaxLength) break;
 
126
    } // while
 
127
    d[i] = 0; // Null terminate.
 
128
    return d;
 
129
  } // safeStringCopy
 
130
};
 
131
 
 
132
// === Do not use directly: use one of the predefined sizes below ===
 
133
 
 
134
template<SQInteger MAXLENGTH> // MAXLENGTH is max printable characters (trailing NULL is accounted for in ScriptStringVarBase::s[1]).
 
135
struct ScriptStringVar : ScriptStringVarBase {
 
136
  SQChar ps[MAXLENGTH];
 
137
  ScriptStringVar() : ScriptStringVarBase(MAXLENGTH) {
 
138
    s[0] = 0;
 
139
  }
 
140
  ScriptStringVar(const SQChar * _s) : ScriptStringVarBase(MAXLENGTH) {
 
141
    *this = _s;
 
142
  }
 
143
  const SQChar * operator = (const SQChar * _s) {
 
144
    return safeStringCopy(s,_s,MaxLength);
 
145
  }
 
146
  const SQChar * operator = (const ScriptStringVar & _s) {
 
147
    return safeStringCopy(s,_s.s,MaxLength);
 
148
  }
 
149
  bool operator == (const ScriptStringVar & _s) {
 
150
    return _strcmp(s,_s.s) == 0;
 
151
  }
 
152
  bool compareCaseInsensitive(const ScriptStringVar & _s) {
 
153
    return _stricmp(s,_s.s) == 0;
 
154
  }
 
155
};
 
156
 
 
157
// === Fixed size strings for scripting ===
 
158
 
 
159
typedef ScriptStringVar<8>   ScriptStringVar8;
 
160
typedef ScriptStringVar<16>  ScriptStringVar16;
 
161
typedef ScriptStringVar<32>  ScriptStringVar32;
 
162
typedef ScriptStringVar<64>  ScriptStringVar64;
 
163
typedef ScriptStringVar<128> ScriptStringVar128;
 
164
typedef ScriptStringVar<256> ScriptStringVar256;
 
165
 
 
166
// === Script Variable Types ===
 
167
 
 
168
enum ScriptVarType {VAR_TYPE_NONE=-1,VAR_TYPE_INT=0,VAR_TYPE_FLOAT,VAR_TYPE_BOOL,VAR_TYPE_CONST_STRING,VAR_TYPE_STRING,VAR_TYPE_USER_POINTER,VAR_TYPE_INSTANCE};
 
169
 
 
170
template <typename T>
 
171
struct TypeInfo {
 
172
  const SQChar * typeName;
 
173
  enum {TypeID=VAR_TYPE_NONE,Size=0};
 
174
};
 
175
 
 
176
// === Common Variable Types ===
 
177
 
 
178
template<>
 
179
struct TypeInfo<INT_T> {
 
180
  const SQChar * typeName;
 
181
  TypeInfo() : typeName(sqT("int")) {}
 
182
  enum {TypeID=VAR_TYPE_INT,Size=sizeof(INT_T)};
 
183
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
184
};
 
185
 
 
186
template<>
 
187
struct TypeInfo<FLOAT_T> {
 
188
  const SQChar * typeName;
 
189
  TypeInfo() : typeName(sqT("float")) {}
 
190
  enum {TypeID=VAR_TYPE_FLOAT,Size=sizeof(FLOAT_T)};
 
191
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
192
};
 
193
 
 
194
template<>
 
195
struct TypeInfo<bool> {
 
196
  const SQChar * typeName;
 
197
  TypeInfo() : typeName(sqT("bool")) {}
 
198
  enum {TypeID=VAR_TYPE_BOOL,Size=sizeof(BOOL_T)};
 
199
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
200
};
 
201
 
 
202
template<>
 
203
struct TypeInfo<SQUserPointer> {
 
204
  const SQChar * typeName;
 
205
  TypeInfo() : typeName(sqT("SQUserPointer")) {}
 
206
  enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)};
 
207
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
208
};
 
209
 
 
210
template<>
 
211
struct TypeInfo<SQAnything> {
 
212
  const SQChar * typeName;
 
213
  TypeInfo() : typeName(sqT("SQUserPointer")) {}
 
214
  enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)};
 
215
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
216
};
 
217
 
 
218
template<>
 
219
struct TypeInfo<const SQChar *> {
 
220
  const SQChar * typeName;
 
221
  TypeInfo() : typeName(sqT("const SQChar *")) {}
 
222
  enum {TypeID=VAR_TYPE_CONST_STRING,Size=sizeof(const SQChar *)};
 
223
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
224
};
 
225
 
 
226
template<>
 
227
struct TypeInfo<ScriptStringVarBase> {
 
228
  const SQChar * typeName;
 
229
  TypeInfo() : typeName(sqT("ScriptStringVarBase")) {}
 
230
  enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVarBase)};
 
231
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
232
};
 
233
 
 
234
// === Fixed String Variants ===
 
235
 
 
236
template<>
 
237
struct TypeInfo<ScriptStringVar8> {
 
238
  const SQChar * typeName;
 
239
  TypeInfo() : typeName(sqT("ScriptStringVar8")) {}
 
240
  enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar8)};
 
241
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
242
};
 
243
 
 
244
template<>
 
245
struct TypeInfo<ScriptStringVar16> {
 
246
  const SQChar * typeName;
 
247
  TypeInfo() : typeName(sqT("ScriptStringVar16")) {}
 
248
  enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar16)};
 
249
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
250
};
 
251
 
 
252
template<>
 
253
struct TypeInfo<ScriptStringVar32> {
 
254
  const SQChar * typeName;
 
255
  TypeInfo() : typeName(sqT("ScriptStringVar32")) {}
 
256
  enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar32)};
 
257
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
258
};
 
259
 
 
260
template<>
 
261
struct TypeInfo<ScriptStringVar64> {
 
262
  const SQChar * typeName;
 
263
  TypeInfo() : typeName(sqT("ScriptStringVar64")) {}
 
264
  enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar64)};
 
265
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
266
};
 
267
 
 
268
template<>
 
269
struct TypeInfo<ScriptStringVar128> {
 
270
  const SQChar * typeName;
 
271
  TypeInfo() : typeName(sqT("ScriptStringVar128")) {}
 
272
  enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar128)};
 
273
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
274
};
 
275
 
 
276
template<>
 
277
struct TypeInfo<ScriptStringVar256> {
 
278
  const SQChar * typeName;
 
279
  TypeInfo() : typeName(sqT("ScriptStringVar256")) {}
 
280
  enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar256)};
 
281
  operator ScriptVarType() { return ScriptVarType(TypeID); }
 
282
};
 
283
 
 
284
enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2};
 
285
 
 
286
// See VarRef and ClassType<> below: for instance assignment.
 
287
typedef void (*CopyVarFunc)(void * dst,void * src);
 
288
 
 
289
// === Variable references for script access ===
 
290
 
 
291
#define SQ_PLUS_TYPE_TABLE sqT("__SqTypes")
 
292
 
 
293
struct VarRef {
 
294
  // In this case 'offsetOrAddrOrConst' is simpler than using an anonymous union.
 
295
  void * offsetOrAddrOrConst; // Instance member variable offset from 'this' pointer base (as size_t), or address if static variable (void *), or constant value.
 
296
  ScriptVarType type;         // Variable type (from enum above).
 
297
  SQUserPointer instanceType; // Unique ID for the containing class instance (for instance vars only). When the var is an instance, its type is encoded in copyFunc.
 
298
  CopyVarFunc copyFunc;       // Function pointer to copy variables (for instance variables only).
 
299
  //short size;                 // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
 
300
  SQInteger size;                 // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
 
301
  short access;               // VarAccessType.
 
302
  const SQChar * typeName;    // Type name string (to create instances by name).
 
303
  VarRef() : offsetOrAddrOrConst(0), type(VAR_TYPE_NONE), instanceType((SQUserPointer)-1), copyFunc(0), size(0), access(VAR_ACCESS_READ_WRITE) {}
 
304
  VarRef(void * _offsetOrAddrOrConst, ScriptVarType _type, SQUserPointer _instanceType, CopyVarFunc _copyFunc, SQInteger _size,VarAccessType _access,const SQChar * _typeName) :
 
305
         offsetOrAddrOrConst(_offsetOrAddrOrConst), type(_type), instanceType(_instanceType), copyFunc(_copyFunc), size(_size), access(_access), typeName(_typeName) {
 
306
#ifdef SQ_SUPPORT_INSTANCE_TYPE_INFO
 
307
    SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE);
 
308
    if (typeTable.IsNull()) {
 
309
      typeTable = SquirrelVM::CreateTable();
 
310
      SquirrelObject root = SquirrelVM::GetRootTable();
 
311
      root.SetValue(SQ_PLUS_TYPE_TABLE,typeTable);
 
312
    } // if
 
313
    typeTable.SetValue(INT_T((size_t)copyFunc),typeName);
 
314
#endif
 
315
  }
 
316
};
 
317
 
 
318
typedef VarRef * VarRefPtr;
 
319
 
 
320
// Internal use only.
 
321
inline void getVarNameTag(SQChar * buff,INT_T maxSize,const SQChar * scriptName) {
 
322
//  assert(maxSize > 3);
 
323
#if 1
 
324
  SQChar * d = buff;
 
325
  d[0] = '_';
 
326
  d[1] = 'v';
 
327
  d = &d[2];
 
328
  maxSize -= (2+1); // +1 = space for null.
 
329
  SQInteger pos=0;
 
330
  while (scriptName[pos] && pos < maxSize) {
 
331
    d[pos] = scriptName[pos];
 
332
    pos++;
 
333
  } // while
 
334
  d[pos] = 0; // null terminate.
 
335
#else
 
336
  SCSNPRINTF(buff,maxSize,sqT("_v%s"),scriptName);
 
337
#endif
 
338
} // getVarNameTag
 
339
 
 
340
// Internal use only.
 
341
SQInteger setVarFunc(HSQUIRRELVM v);
 
342
SQInteger getVarFunc(HSQUIRRELVM v);
 
343
SQInteger setInstanceVarFunc(HSQUIRRELVM v);
 
344
SQInteger getInstanceVarFunc(HSQUIRRELVM v);
 
345
 
 
346
// === BEGIN Helpers ===
 
347
 
 
348
inline void createTableSetGetHandlers(SquirrelObject & so) {
 
349
  SquirrelObject delegate = so.GetDelegate();
 
350
  if (!delegate.Exists(sqT("_set"))) {
 
351
    delegate = SquirrelVM::CreateTable();
 
352
    SquirrelVM::CreateFunction(delegate,setVarFunc,sqT("_set"),sqT("sn|b|s")); // String var name = number(SQInteger or float) or bool or string.
 
353
    SquirrelVM::CreateFunction(delegate,getVarFunc,sqT("_get"),sqT("s"));      // String var name.
 
354
    so.SetDelegate(delegate);
 
355
  } // if
 
356
} // createTableSetGetHandlers
 
357
 
 
358
inline VarRefPtr createVarRef(SquirrelObject & so,const SQChar * scriptVarName) {
 
359
  VarRefPtr pvr=0;
 
360
  ScriptStringVar256 scriptVarTagName; getVarNameTag(scriptVarTagName,sizeof(scriptVarTagName),scriptVarName);
 
361
  if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) {
 
362
    so.NewUserData(scriptVarTagName,sizeof(*pvr));
 
363
    if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) throw SquirrelError(sqT("Could not create UserData."));
 
364
  } // if
 
365
  return pvr;
 
366
} // createVarRef
 
367
 
 
368
template<typename T>
 
369
void validateConstantType(T /*constant*/) {
 
370
  switch(TypeInfo<T>()) {
 
371
  case VAR_TYPE_INT:
 
372
  case VAR_TYPE_FLOAT:
 
373
  case VAR_TYPE_BOOL:
 
374
  case VAR_TYPE_CONST_STRING:
 
375
    break;
 
376
  default:
 
377
    throw SquirrelError(sqT("validateConstantType(): type must be INT, FLOAT, BOOL, or CONST CHAR *."));
 
378
  } // case
 
379
} // validateConstantType
 
380
 
 
381
inline void createInstanceSetGetHandlers(SquirrelObject & so) {
 
382
  if (!so.Exists(sqT("_set"))) {
 
383
    SquirrelVM::CreateFunction(so,setInstanceVarFunc,sqT("_set"),sqT("sn|b|s|x")); // String var name = number(SQInteger or float) or bool or string or instance.
 
384
    SquirrelVM::CreateFunction(so,getInstanceVarFunc,sqT("_get"),sqT("s"));      // String var name.
 
385
  } // if
 
386
} // createInstanceSetGetHandlers
 
387
 
 
388
// === END Helpers ===
 
389
 
 
390
// === Class Type Helper class: returns a unique number for each class type ===
 
391
 
 
392
template<typename T>
 
393
struct ClassType {
 
394
  static SQUserPointer type(void) { return (SQUserPointer)&copy; }
 
395
  static CopyVarFunc getCopyFunc(void) { return (CopyVarFunc)&copy; }
 
396
  static void copy(T * dst,T * src) {
 
397
    *dst = *src;
 
398
  } // copy
 
399
};
 
400
 
 
401
// === Bind a global or pre-allocated (not instance) class member variable or constant (for tables only (not classes)) ===
 
402
 
 
403
template<typename T>
 
404
void BindVariable(SquirrelObject & so,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
 
405
  VarRefPtr pvr = createVarRef(so,scriptVarName);
 
406
  *pvr = VarRef(var,TypeInfo<T>(),0,ClassType<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
 
407
  createTableSetGetHandlers(so);
 
408
} // BindVariable
 
409
 
 
410
// === Bind a constant by value: INT_T, FLOAT_T, BOOL_T, or CONST CHAR * (for tables only (not classes)) ===
 
411
 
 
412
template<typename T>
 
413
void BindConstant(SquirrelObject & so,T constant,const SQChar * scriptVarName) {
 
414
  validateConstantType(constant);
 
415
  VarRefPtr pvr = createVarRef(so,scriptVarName);
 
416
#if __cplusplus>=201103L
 
417
  static_assert(sizeof(constant)<=sizeof(void*), "using larger type");
 
418
#endif
 
419
  void *ptr = reinterpret_cast<void*>(constant);
 
420
  *pvr = VarRef(ptr,TypeInfo<T>(),0,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo<T>().typeName);
 
421
  createTableSetGetHandlers(so);
 
422
} // BindConstant
 
423
 
 
424
template<typename T>
 
425
void BindVariable(T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
 
426
  SquirrelObject so = SquirrelVM::GetRootTable();
 
427
  BindVariable(so,var,scriptVarName,access);
 
428
} // BindVariable
 
429
 
 
430
template<typename T>
 
431
void BindConstant(T constant,const SQChar * scriptVarName) {
 
432
  SquirrelObject so = SquirrelVM::GetRootTable();
 
433
  BindConstant(so,constant,scriptVarName);
 
434
} // BindConstant
 
435
 
 
436
// === Register a class instance member variable or constant. var argument provides type and offset ( effectively &((ClassType *)0)->var ) ===
 
437
 
 
438
// classType is the type of the member variable's containing class.
 
439
template<typename T>
 
440
void RegisterInstanceVariable(SquirrelObject & so,SQUserPointer classType,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
 
441
  VarRef * pvr = createVarRef(so,scriptVarName);
 
442
  void * offsetOrAddrOrConst = (void *)var; // var must be passed in as &obj->var, where obj = 0 (the address is the offset), or as static/global address.
 
443
  *pvr = VarRef(offsetOrAddrOrConst,TypeInfo<T>(),classType,ClassType<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
 
444
  createInstanceSetGetHandlers(so);
 
445
} // RegisterInstanceVariable
 
446
 
 
447
template<typename T>
 
448
void RegisterInstanceConstant(SquirrelObject & so,SQUserPointer classType,T constant,const SQChar * scriptVarName) {
 
449
  validateConstantType(constant);
 
450
  VarRef * pvr = createVarRef(so,scriptVarName);
 
451
  struct CV {
 
452
    T var;
 
453
    size_t pad;
 
454
  } cv; // Cast Variable helper.
 
455
  cv.var = constant;
 
456
  *pvr = VarRef(*(void **)&cv,TypeInfo<T>(),classType,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo<T>().typeName);
 
457
  createInstanceSetGetHandlers(so);
 
458
} // RegisterInstanceConstant
 
459
 
 
460
//////////////////////////////////////////////////////////////////////////
 
461
/////////// BEGIN Generalized Class/Struct Instance Support //////////////
 
462
//////////////////////////////////////////////////////////////////////////
 
463
 
 
464
//BOOL_T CreateNativeClassInstance(HSQUIRRELVM v,const SQChar * classname,SQUserPointer ud,SQRELEASEHOOK hook); // In SquirrelBindingUtils.cpp.
 
465
 
 
466
// Create native class instance and leave on stack.
 
467
inline BOOL_T CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className) {
 
468
  SQInteger oldtop = sq_gettop(v);
 
469
  sq_pushroottable(v);
 
470
  sq_pushstring(v,className,-1);
 
471
  if (SQ_FAILED(sq_rawget(v,-2))) { // Get the class (created with sq_newclass()).
 
472
    sq_settop(v,oldtop);
 
473
    return FALSE;
 
474
  } // if
 
475
#if 0
 
476
  sq_remove(v,-3); // Remove the root table.
 
477
  sq_push(v,1);    // Push the 'this'.
 
478
#else // Kamaitati's change. 5/28/06 jcs.
 
479
  sq_remove(v,-2); // Remove the root table.
 
480
  sq_pushroottable(v); // Push the 'this'.
 
481
#endif
 
482
  if (SQ_FAILED(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR))) { // Call ClassName(): creates new instance and calls constructor (instead of sq_createinstance() where constructor is not called).
 
483
    sq_settop(v,oldtop);
 
484
    return FALSE;
 
485
  } // if
 
486
  sq_remove(v,-2); // Remove the class.
 
487
  //  SQInteger newtop = sq_gettop(v);
 
488
  return TRUE;
 
489
} // CreateConstructNativeClassInstance
 
490
 
 
491
// Create new instance, copy 'classToCopy', and store result on stack.
 
492
template<typename T>
 
493
inline BOOL_T CreateCopyInstance(const SQChar * className,const T & classToCopy) {
 
494
  HSQUIRRELVM v = SquirrelVM::GetVMPtr();
 
495
  if (!CreateConstructNativeClassInstance(v,className)) {
 
496
    return FALSE;
 
497
  } // if
 
498
  SQUserPointer up=0;
 
499
  sq_getinstanceup(v,-1,&up,ClassType<T>::type());
 
500
  if (!up) return FALSE;
 
501
  T * newClass = (T *)up;
 
502
  *newClass = classToCopy; // <TODO> Optimized version that uses the copy constructor.
 
503
  return TRUE;
 
504
} // CreateCopyInstance
 
505
 
 
506
// Create a new copy of type 'className' and copy 'classToCopy', return result via SquirrelObject.
 
507
template<typename T>
 
508
inline SquirrelObject NewClassCopy(const SQChar * className,const T & classToCopy) {
 
509
  SquirrelObject ret;
 
510
  if (CreateCopyInstance(className,classToCopy)) {
 
511
    ret.AttachToStackObject(-1);
 
512
    sq_poptop(SquirrelVM::GetVMPtr());
 
513
  } else {
 
514
    throw SquirrelError(sqT("NewClassCopy(): could not create class"));
 
515
  } // if
 
516
  return ret;
 
517
} // NewClassCopy
 
518
 
 
519
// Return a new class copy on the stack from a varArgs function call.
 
520
template<typename T>
 
521
inline SQInteger ReturnCopy(HSQUIRRELVM v,const T & classToCopy) {
 
522
  SquirrelObject so(NewClassCopy(GetTypeName(classToCopy),classToCopy));
 
523
  return StackHandler(v).Return(so);
 
524
} // ReturnCopy
 
525
 
 
526
// Katsuaki Kawachi's GetInstance<> exception change. 6/27/06 jcs
 
527
 
 
528
// Get an instance of type T from the stack at idx (for function calls).
 
529
template<typename T,bool ExceptionOnError>
 
530
T * GetInstance(HSQUIRRELVM v,SQInteger idx) {
 
531
  SQUserPointer up=0;
 
532
  sq_getinstanceup(v,idx,&up,ClassType<T>::type());
 
533
  if (ExceptionOnError) { // This code block should be compiled out when ExceptionOnError is false. In any case, the compiler should not generate a test condition (include or exclude the enclosed code block).
 
534
    if (!up) throw SquirrelError(sqT("GetInstance: Invalid argument type"));
 
535
  } // if
 
536
  return (T *)up;
 
537
} // GetInstance
 
538
 
 
539
// NAME and macro changes from Ben's (Project5) forum post. 2/26/06 jcs
 
540
// Kamaitati's NULL_INSTANCE support. 5/28/06 jcs
 
541
 
 
542
#ifdef SQPLUS_SUPPORT_NULL_INSTANCES
 
543
 
 
544
#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
 
545
  inline const SQChar * GetTypeName(const TYPE & /*n*/) { return sqT(#NAME); } \
 
546
  inline void Push(HSQUIRRELVM v,TYPE * value) { \
 
547
    if (!value)  sq_pushnull(v); \
 
548
    else if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) \
 
549
      throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \
 
550
  inline void Push(HSQUIRRELVM /*v*/,TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \
 
551
  inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,false>(v,idx) != NULL; } \
 
552
  inline bool Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { \
 
553
    return (sq_gettype(v,idx)==OT_NULL) || (GetInstance<TYPE,false>(v,idx) != NULL); } \
 
554
  inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return *GetInstance<TYPE,true>(v,idx); } \
 
555
  inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { \
 
556
    if (sq_gettype(v,idx)==OT_NULL) return NULL; \
 
557
    return GetInstance<TYPE,true>(v,idx); } \
 
558
  template<> \
 
559
  struct TypeInfo<TYPE> { \
 
560
    const SQChar * typeName; \
 
561
    TypeInfo() : typeName(sqT(#NAME)) {} \
 
562
    enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
 
563
    operator ScriptVarType() { return ScriptVarType(TypeID); } \
 
564
  }; \
 
565
} // nameSpace SqPlus
 
566
 
 
567
#else
 
568
 
 
569
#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
 
570
  inline const SQChar * GetTypeName(const TYPE & /*n*/)            { return sqT(#NAME); } \
 
571
  inline void Push(HSQUIRRELVM v,TYPE * value)                 { if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \
 
572
  inline void Push(HSQUIRRELVM /*v*/,TYPE & value)                 { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \
 
573
  inline bool   Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,false>(v,idx) != NULL; } \
 
574
  inline bool   Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,false>(v,idx) != NULL; } \
 
575
  inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return *GetInstance<TYPE,true>(v,idx); } \
 
576
  inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,true>(v,idx); } \
 
577
  template<> \
 
578
  struct TypeInfo<TYPE> { \
 
579
    const SQChar * typeName; \
 
580
    TypeInfo() : typeName(sqT(#NAME)) {} \
 
581
    enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
 
582
    operator ScriptVarType() { return ScriptVarType(TypeID); } \
 
583
  }; \
 
584
} // nameSpace SqPlus
 
585
 
 
586
#endif
 
587
 
 
588
// TYPE or NAME below must match the string name used in SqClassDef<>, otherwise name lookup won't match and Squirrel will throw a "can't create instance" error.
 
589
#ifndef SQPLUS_CONST_OPT
 
590
#define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_(TYPE,TYPE)
 
591
#define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME)
 
592
#else
 
593
#define SQPLUS_DECLARE_INSTANCE_TYPE_CONST
 
594
#include "SqPlusConst.h"
 
595
#endif
 
596
 
 
597
//////////////////////////////////////////////////////////////////////////
 
598
//////////// END Generalized Class/Struct Instance Support ///////////////
 
599
//////////////////////////////////////////////////////////////////////////
 
600
 
 
601
#ifndef SQ_SKIP_ARG_ASSERT
 
602
  #define sq_argassert(arg,_index_) if (!Match(TypeWrapper<P##arg>(),v,_index_)) return sq_throwerror(v,sqT("Incorrect function argument"))
 
603
#else
 
604
  #define sq_argassert(arg,_index_)
 
605
#endif
 
606
 
 
607
// === Return value variants ===
 
608
 
 
609
template<class RT>
 
610
struct ReturnSpecialization {
 
611
 
 
612
  // === Standard Function calls ===
 
613
 
 
614
  static SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
 
615
    RT ret = func();
 
616
    Push(v,ret);
 
617
    return 1;
 
618
  }
 
619
 
 
620
  template<typename P1>
 
621
  static SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) {
 
622
    sq_argassert(1,index + 0);
 
623
    RT ret = func(
 
624
      Get(TypeWrapper<P1>(),v,index + 0)
 
625
    );
 
626
    Push(v,ret);
 
627
    return 1;
 
628
  }
 
629
 
 
630
  template<typename P1,typename P2>
 
631
  static SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
 
632
    sq_argassert(1,index + 0);
 
633
    sq_argassert(2,index + 1);
 
634
    RT ret = func(
 
635
      Get(TypeWrapper<P1>(),v,index + 0),
 
636
      Get(TypeWrapper<P2>(),v,index + 1)
 
637
    );
 
638
    Push(v,ret);
 
639
    return 1;
 
640
  }
 
641
 
 
642
  template<typename P1,typename P2,typename P3>
 
643
  static SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
 
644
    sq_argassert(1,index + 0);
 
645
    sq_argassert(2,index + 1);
 
646
    sq_argassert(3,index + 2);
 
647
    RT ret = func(
 
648
      Get(TypeWrapper<P1>(),v,index + 0),
 
649
      Get(TypeWrapper<P2>(),v,index + 1),
 
650
      Get(TypeWrapper<P3>(),v,index + 2)
 
651
    );
 
652
    Push(v,ret);
 
653
    return 1;
 
654
  }
 
655
 
 
656
  template<typename P1,typename P2,typename P3,typename P4>
 
657
  static SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
 
658
    sq_argassert(1,index + 0);
 
659
    sq_argassert(2,index + 1);
 
660
    sq_argassert(3,index + 2);
 
661
    sq_argassert(4,index + 3);
 
662
    RT ret = func(
 
663
      Get(TypeWrapper<P1>(),v,index + 0),
 
664
      Get(TypeWrapper<P2>(),v,index + 1),
 
665
      Get(TypeWrapper<P3>(),v,index + 2),
 
666
      Get(TypeWrapper<P4>(),v,index + 3)
 
667
    );
 
668
    Push(v,ret);
 
669
    return 1;
 
670
  }
 
671
 
 
672
  template<typename P1,typename P2,typename P3,typename P4,typename P5>
 
673
  static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
 
674
    sq_argassert(1,index + 0);
 
675
    sq_argassert(2,index + 1);
 
676
    sq_argassert(3,index + 2);
 
677
    sq_argassert(4,index + 3);
 
678
    sq_argassert(5,index + 4);
 
679
    RT ret = func(
 
680
      Get(TypeWrapper<P1>(),v,index + 0),
 
681
      Get(TypeWrapper<P2>(),v,index + 1),
 
682
      Get(TypeWrapper<P3>(),v,index + 2),
 
683
      Get(TypeWrapper<P4>(),v,index + 3),
 
684
      Get(TypeWrapper<P5>(),v,index + 4)
 
685
    );
 
686
    Push(v,ret);
 
687
    return 1;
 
688
  }
 
689
 
 
690
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
 
691
  static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
 
692
    sq_argassert(1,index + 0);
 
693
    sq_argassert(2,index + 1);
 
694
    sq_argassert(3,index + 2);
 
695
    sq_argassert(4,index + 3);
 
696
    sq_argassert(5,index + 4);
 
697
    sq_argassert(6,index + 5);
 
698
    RT ret = func(
 
699
      Get(TypeWrapper<P1>(),v,index + 0),
 
700
      Get(TypeWrapper<P2>(),v,index + 1),
 
701
      Get(TypeWrapper<P3>(),v,index + 2),
 
702
      Get(TypeWrapper<P4>(),v,index + 3),
 
703
      Get(TypeWrapper<P5>(),v,index + 4),
 
704
      Get(TypeWrapper<P6>(),v,index + 5)
 
705
    );
 
706
    Push(v,ret);
 
707
    return 1;
 
708
  }
 
709
 
 
710
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
 
711
  static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
 
712
    sq_argassert(1,index + 0);
 
713
    sq_argassert(2,index + 1);
 
714
    sq_argassert(3,index + 2);
 
715
    sq_argassert(4,index + 3);
 
716
    sq_argassert(5,index + 4);
 
717
    sq_argassert(6,index + 5);
 
718
    sq_argassert(7,index + 6);
 
719
    RT ret = func(
 
720
      Get(TypeWrapper<P1>(),v,index + 0),
 
721
      Get(TypeWrapper<P2>(),v,index + 1),
 
722
      Get(TypeWrapper<P3>(),v,index + 2),
 
723
      Get(TypeWrapper<P4>(),v,index + 3),
 
724
      Get(TypeWrapper<P5>(),v,index + 4),
 
725
      Get(TypeWrapper<P6>(),v,index + 5),
 
726
      Get(TypeWrapper<P7>(),v,index + 6)
 
727
    );
 
728
    Push(v,ret);
 
729
    return 1;
 
730
  }
 
731
 
 
732
  // === Member Function calls ===
 
733
 
 
734
  template <typename Callee>
 
735
  static SQInteger Call(Callee & callee,RT (Callee::*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
 
736
    RT ret = (callee.*func)();
 
737
    Push(v,ret);
 
738
    return 1;
 
739
  }
 
740
 
 
741
  template <typename Callee,typename P1>
 
742
  static SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
 
743
    sq_argassert(1,index + 0);
 
744
    RT ret = (callee.*func)(
 
745
      Get(TypeWrapper<P1>(),v,index + 0)
 
746
    );
 
747
    Push(v,ret);
 
748
    return 1;
 
749
  }
 
750
 
 
751
  template<typename Callee,typename P1,typename P2>
 
752
  static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
 
753
    sq_argassert(1,index + 0);
 
754
    sq_argassert(2,index + 1);
 
755
    RT ret = (callee.*func)(
 
756
      Get(TypeWrapper<P1>(),v,index + 0),
 
757
      Get(TypeWrapper<P2>(),v,index + 1)
 
758
    );
 
759
    Push(v,ret);
 
760
    return 1;
 
761
  }
 
762
 
 
763
  template<typename Callee,typename P1,typename P2,typename P3>
 
764
  static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
 
765
    sq_argassert(1,index + 0);
 
766
    sq_argassert(2,index + 1);
 
767
    sq_argassert(3,index + 2);
 
768
    RT ret = (callee.*func)(
 
769
      Get(TypeWrapper<P1>(),v,index + 0),
 
770
      Get(TypeWrapper<P2>(),v,index + 1),
 
771
      Get(TypeWrapper<P3>(),v,index + 2)
 
772
    );
 
773
    Push(v,ret);
 
774
    return 1;
 
775
  }
 
776
 
 
777
  template<typename Callee,typename P1,typename P2,typename P3,typename P4>
 
778
  static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
 
779
    sq_argassert(1,index + 0);
 
780
    sq_argassert(2,index + 1);
 
781
    sq_argassert(3,index + 2);
 
782
    sq_argassert(4,index + 3);
 
783
    RT ret = (callee.*func)(
 
784
      Get(TypeWrapper<P1>(),v,index + 0),
 
785
      Get(TypeWrapper<P2>(),v,index + 1),
 
786
      Get(TypeWrapper<P3>(),v,index + 2),
 
787
      Get(TypeWrapper<P4>(),v,index + 3)
 
788
    );
 
789
    Push(v,ret);
 
790
    return 1;
 
791
  }
 
792
 
 
793
  template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
 
794
  static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
 
795
    sq_argassert(1,index + 0);
 
796
    sq_argassert(2,index + 1);
 
797
    sq_argassert(3,index + 2);
 
798
    sq_argassert(4,index + 3);
 
799
    sq_argassert(5,index + 4);
 
800
    RT ret = (callee.*func)(
 
801
      Get(TypeWrapper<P1>(),v,index + 0),
 
802
      Get(TypeWrapper<P2>(),v,index + 1),
 
803
      Get(TypeWrapper<P3>(),v,index + 2),
 
804
      Get(TypeWrapper<P4>(),v,index + 3),
 
805
      Get(TypeWrapper<P5>(),v,index + 4)
 
806
    );
 
807
    Push(v,ret);
 
808
    return 1;
 
809
  }
 
810
 
 
811
  template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
 
812
  static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
 
813
    sq_argassert(1,index + 0);
 
814
    sq_argassert(2,index + 1);
 
815
    sq_argassert(3,index + 2);
 
816
    sq_argassert(4,index + 3);
 
817
    sq_argassert(5,index + 4);
 
818
    sq_argassert(6,index + 5);
 
819
    RT ret = (callee.*func)(
 
820
      Get(TypeWrapper<P1>(),v,index + 0),
 
821
      Get(TypeWrapper<P2>(),v,index + 1),
 
822
      Get(TypeWrapper<P3>(),v,index + 2),
 
823
      Get(TypeWrapper<P4>(),v,index + 3),
 
824
      Get(TypeWrapper<P5>(),v,index + 4),
 
825
      Get(TypeWrapper<P6>(),v,index + 5)
 
826
    );
 
827
    Push(v,ret);
 
828
    return 1;
 
829
  }
 
830
 
 
831
  template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
 
832
  static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
 
833
    sq_argassert(1,index + 0);
 
834
    sq_argassert(2,index + 1);
 
835
    sq_argassert(3,index + 2);
 
836
    sq_argassert(4,index + 3);
 
837
    sq_argassert(5,index + 4);
 
838
    sq_argassert(6,index + 5);
 
839
    sq_argassert(7,index + 6);
 
840
    RT ret = (callee.*func)(
 
841
      Get(TypeWrapper<P1>(),v,index + 0),
 
842
      Get(TypeWrapper<P2>(),v,index + 1),
 
843
      Get(TypeWrapper<P3>(),v,index + 2),
 
844
      Get(TypeWrapper<P4>(),v,index + 3),
 
845
      Get(TypeWrapper<P5>(),v,index + 4),
 
846
      Get(TypeWrapper<P6>(),v,index + 5),
 
847
      Get(TypeWrapper<P7>(),v,index + 6)
 
848
    );
 
849
    Push(v,ret);
 
850
    return 1;
 
851
  }
 
852
 
 
853
#ifdef SQPLUS_CONST_OPT
 
854
#define SQPLUS_CALL_CONST_MFUNC_RET0
 
855
#include "SqPlusConst.h"
 
856
#endif
 
857
};
 
858
 
 
859
// === No return value variants ===
 
860
 
 
861
template<>
 
862
struct ReturnSpecialization<void> {
 
863
 
 
864
  // === Standard function calls ===
 
865
 
 
866
  static SQInteger Call(void (*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
 
867
                (void)v;
 
868
                func();
 
869
                return 0;
 
870
        }
 
871
 
 
872
        template<typename P1>
 
873
        static SQInteger Call(void (*func)(P1),HSQUIRRELVM v,SQInteger index) {
 
874
    sq_argassert(1,index + 0);
 
875
                func(
 
876
                        Get(TypeWrapper<P1>(),v,index + 0)
 
877
                );
 
878
                return 0;
 
879
        }
 
880
 
 
881
        template<typename P1,typename P2>
 
882
        static SQInteger Call(void (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
 
883
    sq_argassert(1,index + 0);
 
884
    sq_argassert(2,index + 1);
 
885
                func(
 
886
                        Get(TypeWrapper<P1>(),v,index + 0),
 
887
                        Get(TypeWrapper<P2>(),v,index + 1)
 
888
                );
 
889
                return 0;
 
890
        }
 
891
 
 
892
  template<typename P1,typename P2,typename P3>
 
893
  static SQInteger Call(void (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
 
894
    sq_argassert(1,index + 0);
 
895
    sq_argassert(2,index + 1);
 
896
    sq_argassert(3,index + 2);
 
897
    func(
 
898
      Get(TypeWrapper<P1>(),v,index + 0),
 
899
      Get(TypeWrapper<P2>(),v,index + 1),
 
900
      Get(TypeWrapper<P3>(),v,index + 2)
 
901
    );
 
902
    return 0;
 
903
  }
 
904
 
 
905
  template<typename P1,typename P2,typename P3,typename P4>
 
906
  static SQInteger Call(void (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
 
907
    sq_argassert(1,index + 0);
 
908
    sq_argassert(2,index + 1);
 
909
    sq_argassert(3,index + 2);
 
910
    sq_argassert(4,index + 3);
 
911
    func(
 
912
      Get(TypeWrapper<P1>(),v,index + 0),
 
913
      Get(TypeWrapper<P2>(),v,index + 1),
 
914
      Get(TypeWrapper<P3>(),v,index + 2),
 
915
      Get(TypeWrapper<P4>(),v,index + 3)
 
916
    );
 
917
    return 0;
 
918
  }
 
919
 
 
920
  template<typename P1,typename P2,typename P3,typename P4,typename P5>
 
921
  static SQInteger Call(void (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
 
922
    sq_argassert(1,index + 0);
 
923
    sq_argassert(2,index + 1);
 
924
    sq_argassert(3,index + 2);
 
925
    sq_argassert(4,index + 3);
 
926
    sq_argassert(5,index + 4);
 
927
    func(
 
928
      Get(TypeWrapper<P1>(),v,index + 0),
 
929
      Get(TypeWrapper<P2>(),v,index + 1),
 
930
      Get(TypeWrapper<P3>(),v,index + 2),
 
931
      Get(TypeWrapper<P4>(),v,index + 3),
 
932
      Get(TypeWrapper<P5>(),v,index + 4)
 
933
    );
 
934
    return 0;
 
935
  }
 
936
 
 
937
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
 
938
  static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
 
939
    sq_argassert(1,index + 0);
 
940
    sq_argassert(2,index + 1);
 
941
    sq_argassert(3,index + 2);
 
942
    sq_argassert(4,index + 3);
 
943
    sq_argassert(5,index + 4);
 
944
    sq_argassert(6,index + 5);
 
945
    func(
 
946
      Get(TypeWrapper<P1>(),v,index + 0),
 
947
      Get(TypeWrapper<P2>(),v,index + 1),
 
948
      Get(TypeWrapper<P3>(),v,index + 2),
 
949
      Get(TypeWrapper<P4>(),v,index + 3),
 
950
      Get(TypeWrapper<P5>(),v,index + 4),
 
951
      Get(TypeWrapper<P6>(),v,index + 5)
 
952
    );
 
953
    return 0;
 
954
  }
 
955
 
 
956
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
 
957
  static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
 
958
    sq_argassert(1,index + 0);
 
959
    sq_argassert(2,index + 1);
 
960
    sq_argassert(3,index + 2);
 
961
    sq_argassert(4,index + 3);
 
962
    sq_argassert(5,index + 4);
 
963
    sq_argassert(6,index + 5);
 
964
    sq_argassert(7,index + 6);
 
965
    func(
 
966
      Get(TypeWrapper<P1>(),v,index + 0),
 
967
      Get(TypeWrapper<P2>(),v,index + 1),
 
968
      Get(TypeWrapper<P3>(),v,index + 2),
 
969
      Get(TypeWrapper<P4>(),v,index + 3),
 
970
      Get(TypeWrapper<P5>(),v,index + 4),
 
971
      Get(TypeWrapper<P6>(),v,index + 5),
 
972
      Get(TypeWrapper<P7>(),v,index + 6)
 
973
    );
 
974
    return 0;
 
975
  }
 
976
 
 
977
  // === Member function calls ===
 
978
 
 
979
        template<typename Callee>
 
980
        static SQInteger Call(Callee & callee,void (Callee::*func)(),HSQUIRRELVM,SQInteger /*index*/) {
 
981
                (callee.*func)();
 
982
                return 0;
 
983
        }
 
984
 
 
985
        template<typename Callee,typename P1>
 
986
        static SQInteger Call(Callee & callee,void (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
 
987
    sq_argassert(1,index + 0);
 
988
                (callee.*func)(
 
989
                        Get(TypeWrapper<P1>(),v,index + 0)
 
990
                );
 
991
                return 0;
 
992
        }
 
993
 
 
994
        template<typename Callee,typename P1,typename P2>
 
995
        static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
 
996
    sq_argassert(1,index + 0);
 
997
    sq_argassert(2,index + 1);
 
998
                (callee.*func)(
 
999
                        Get(TypeWrapper<P1>(),v,index + 0),
 
1000
                        Get(TypeWrapper<P2>(),v,index + 1)
 
1001
                );
 
1002
                return 0;
 
1003
        }
 
1004
 
 
1005
        template<typename Callee,typename P1,typename P2,typename P3>
 
1006
        static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
 
1007
    sq_argassert(1,index + 0);
 
1008
    sq_argassert(2,index + 1);
 
1009
    sq_argassert(3,index + 2);
 
1010
                (callee.*func)(
 
1011
                        Get(TypeWrapper<P1>(),v,index + 0),
 
1012
                        Get(TypeWrapper<P2>(),v,index + 1),
 
1013
      Get(TypeWrapper<P3>(),v,index + 2)
 
1014
                );
 
1015
                return 0;
 
1016
        }
 
1017
 
 
1018
        template<typename Callee,typename P1,typename P2,typename P3,typename P4>
 
1019
        static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
 
1020
    sq_argassert(1,index + 0);
 
1021
    sq_argassert(2,index + 1);
 
1022
    sq_argassert(3,index + 2);
 
1023
    sq_argassert(4,index + 3);
 
1024
                (callee.*func)(
 
1025
                        Get(TypeWrapper<P1>(),v,index + 0),
 
1026
                        Get(TypeWrapper<P2>(),v,index + 1),
 
1027
      Get(TypeWrapper<P3>(),v,index + 2),
 
1028
      Get(TypeWrapper<P4>(),v,index + 3)
 
1029
                );
 
1030
                return 0;
 
1031
        }
 
1032
 
 
1033
        template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
 
1034
        static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
 
1035
    sq_argassert(1,index + 0);
 
1036
    sq_argassert(2,index + 1);
 
1037
    sq_argassert(3,index + 2);
 
1038
    sq_argassert(4,index + 3);
 
1039
    sq_argassert(5,index + 4);
 
1040
                (callee.*func)(
 
1041
                        Get(TypeWrapper<P1>(),v,index + 0),
 
1042
                        Get(TypeWrapper<P2>(),v,index + 1),
 
1043
      Get(TypeWrapper<P3>(),v,index + 2),
 
1044
      Get(TypeWrapper<P4>(),v,index + 3),
 
1045
      Get(TypeWrapper<P5>(),v,index + 4)
 
1046
                );
 
1047
                return 0;
 
1048
        }
 
1049
 
 
1050
        template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
 
1051
        static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
 
1052
    sq_argassert(1,index + 0);
 
1053
    sq_argassert(2,index + 1);
 
1054
    sq_argassert(3,index + 2);
 
1055
    sq_argassert(4,index + 3);
 
1056
    sq_argassert(5,index + 4);
 
1057
    sq_argassert(6,index + 5);
 
1058
                (callee.*func)(
 
1059
                        Get(TypeWrapper<P1>(),v,index + 0),
 
1060
                        Get(TypeWrapper<P2>(),v,index + 1),
 
1061
      Get(TypeWrapper<P3>(),v,index + 2),
 
1062
      Get(TypeWrapper<P4>(),v,index + 3),
 
1063
      Get(TypeWrapper<P5>(),v,index + 4),
 
1064
      Get(TypeWrapper<P6>(),v,index + 5)
 
1065
                );
 
1066
                return 0;
 
1067
        }
 
1068
 
 
1069
        template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
 
1070
        static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
 
1071
    sq_argassert(1,index + 0);
 
1072
    sq_argassert(2,index + 1);
 
1073
    sq_argassert(3,index + 2);
 
1074
    sq_argassert(4,index + 3);
 
1075
    sq_argassert(5,index + 4);
 
1076
    sq_argassert(6,index + 5);
 
1077
    sq_argassert(7,index + 6);
 
1078
                (callee.*func)(
 
1079
                        Get(TypeWrapper<P1>(),v,index + 0),
 
1080
                        Get(TypeWrapper<P2>(),v,index + 1),
 
1081
      Get(TypeWrapper<P3>(),v,index + 2),
 
1082
      Get(TypeWrapper<P4>(),v,index + 3),
 
1083
      Get(TypeWrapper<P5>(),v,index + 4),
 
1084
      Get(TypeWrapper<P6>(),v,index + 5),
 
1085
      Get(TypeWrapper<P7>(),v,index + 6)
 
1086
                );
 
1087
                return 0;
 
1088
        }
 
1089
 
 
1090
#ifdef SQPLUS_CONST_OPT
 
1091
#define SQPLUS_CALL_CONST_MFUNC_NORET
 
1092
#include "SqPlusConst.h"
 
1093
#endif
 
1094
 
 
1095
};
 
1096
 
 
1097
// === STANDARD Function return value specialized call handlers ===
 
1098
 
 
1099
template<typename RT>
 
1100
SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger index) {
 
1101
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1102
}
 
1103
 
 
1104
template<typename RT,typename P1>
 
1105
SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) {
 
1106
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1107
}
 
1108
 
 
1109
template<typename RT,typename P1,typename P2>
 
1110
SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
 
1111
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1112
}
 
1113
 
 
1114
template<typename RT,typename P1,typename P2,typename P3>
 
1115
SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
 
1116
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1117
}
 
1118
 
 
1119
template<typename RT,typename P1,typename P2,typename P3,typename P4>
 
1120
SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
 
1121
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1122
}
 
1123
 
 
1124
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
 
1125
SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
 
1126
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1127
}
 
1128
 
 
1129
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
 
1130
SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
 
1131
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1132
}
 
1133
 
 
1134
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
 
1135
SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
 
1136
  return ReturnSpecialization<RT>::Call(func,v,index);
 
1137
}
 
1138
 
 
1139
// === MEMBER Function return value specialized call handlers ===
 
1140
 
 
1141
template<typename Callee,typename RT>
 
1142
SQInteger Call(Callee & callee, RT (Callee::*func)(),HSQUIRRELVM v,SQInteger index) {
 
1143
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1144
}
 
1145
 
 
1146
template<typename Callee,typename RT,typename P1>
 
1147
SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
 
1148
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1149
}
 
1150
 
 
1151
template<typename Callee,typename RT,typename P1,typename P2>
 
1152
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
 
1153
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1154
}
 
1155
 
 
1156
template<typename Callee,typename RT,typename P1,typename P2,typename P3>
 
1157
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
 
1158
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1159
}
 
1160
 
 
1161
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4>
 
1162
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
 
1163
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1164
}
 
1165
 
 
1166
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
 
1167
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
 
1168
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1169
}
 
1170
 
 
1171
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
 
1172
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
 
1173
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1174
}
 
1175
 
 
1176
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
 
1177
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
 
1178
  return ReturnSpecialization<RT>::Call(callee,func,v,index);
 
1179
}
 
1180
 
 
1181
#ifdef SQPLUS_CONST_OPT
 
1182
#define SQPLUS_CALL_CONST_MFUNC_RET1
 
1183
#include "SqPlusConst.h"
 
1184
#endif
 
1185
 
 
1186
// === Direct Call Standard Function handler ===
 
1187
 
 
1188
template<typename Func>
 
1189
struct DirectCallFunction {
 
1190
  static inline SQInteger Dispatch(HSQUIRRELVM v) {
 
1191
    StackHandler sa(v);
 
1192
    SQInteger paramCount = sa.GetParamCount();
 
1193
    Func * func = (Func *)sa.GetUserData(paramCount);
 
1194
    return Call(*func,v,2);
 
1195
  } // Dispatch
 
1196
};
 
1197
 
 
1198
// === Direct Call Member Function handler ===
 
1199
 
 
1200
template<typename Callee,typename Func>
 
1201
class DirectCallMemberFunction {
 
1202
public:
 
1203
  static inline SQInteger Dispatch(HSQUIRRELVM v) {
 
1204
    StackHandler sa(v);
 
1205
    SQInteger paramCount = sa.GetParamCount();
 
1206
    unsigned char * ud = (unsigned char *)sa.GetUserData(paramCount);
 
1207
    // C::B patch: Handle invalid instance type here
 
1208
    if (!*(Callee**)ud) {
 
1209
      return sq_throwerror(v,sqT("Invalid Instance Type"));
 
1210
    } // if
 
1211
    return Call(**(Callee**)ud,*(Func*)(ud + sizeof(Callee*)),v,2);
 
1212
  } // Dispatch
 
1213
};
 
1214
 
 
1215
// === Direct Call Instance Member Function handler ===
 
1216
 
 
1217
#define SQ_CLASS_OBJECT_TABLE_NAME sqT("__ot")
 
1218
#define SQ_CLASS_HIER_ARRAY sqT("__ca")
 
1219
 
 
1220
template<typename Callee,typename Func>
 
1221
class DirectCallInstanceMemberFunction {
 
1222
public:
 
1223
  static inline SQInteger Dispatch(HSQUIRRELVM v) {
 
1224
    StackHandler sa(v);
 
1225
    Callee * instance = (Callee *)sa.GetInstanceUp(1,0);
 
1226
    SQInteger paramCount = sa.GetParamCount();
 
1227
    Func * func = (Func *)sa.GetUserData(paramCount);
 
1228
    // C::B patch: Let the compiler search (comment out the whole block)
 
1229
//#ifdef SQ_USE_CLASS_INHERITANCE
 
1230
//    SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
 
1231
//    SQUserPointer typetag; so.GetTypeTag(&typetag);
 
1232
//    SQUserPointer calleeType = ClassType<Callee>::type();
 
1233
//    if (typetag != calleeType) {
 
1234
//      SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
 
1235
//      instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType<Callee>::type())); // <TODO> 64-bit compatible version.
 
1236
//      if (!instance) {
 
1237
//        return sq_throwerror(v,sqT("Invalid Instance Type"));
 
1238
//      } // if
 
1239
//    } // if
 
1240
//#endif
 
1241
    // C::B patch: If not instance -> return Ok anyways
 
1242
    if (!instance)
 
1243
      return SQ_OK;
 
1244
    return Call(*instance,*func,v,2);
 
1245
  } // Dispatch
 
1246
};
 
1247
 
 
1248
// === Direct Call Instance Member Function Variable Argument handler ===
 
1249
 
 
1250
template<typename Callee>
 
1251
class DirectCallInstanceMemberFunctionVarArgs {
 
1252
public:
 
1253
  typedef SQInteger (Callee::*FuncType)(HSQUIRRELVM);
 
1254
  static inline SQInteger Dispatch(HSQUIRRELVM v) {
 
1255
    StackHandler sa(v);
 
1256
    Callee * instance = (Callee *)sa.GetInstanceUp(1,0);
 
1257
    SQInteger paramCount = sa.GetParamCount();
 
1258
    FuncType func = *(FuncType *)sa.GetUserData(paramCount);
 
1259
    // C::B patch: Let the compiler search (comment out the whole block)
 
1260
//#ifdef SQ_USE_CLASS_INHERITANCE
 
1261
//    SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
 
1262
//    SQUserPointer typetag; so.GetTypeTag(&typetag);
 
1263
//    SQUserPointer calleeType = ClassType<Callee>::type();
 
1264
//    if (typetag != calleeType) {
 
1265
//      SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
 
1266
//      instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType<Callee>::type())); // <TODO> 64-bit compatible version.
 
1267
//      if (!instance) {
 
1268
//        return sq_throwerror(v,sqT("Invalid Instance Type"));
 
1269
//      } // if
 
1270
//    } // if
 
1271
//#endif
 
1272
    sq_poptop(v); // Remove UserData from stack: so sa.GetParamCount() returns actual param count.
 
1273
    // C::B patch: If not instance -> return Ok anyways
 
1274
    if (!instance)
 
1275
      return SQ_OK;
 
1276
    return (instance->*func)(v);
 
1277
  } // Dispatch
 
1278
};
 
1279
 
 
1280
// Code fragment useful for debugging new implementations.
 
1281
#if 0
 
1282
HSQOBJECT ho = sa.GetObjectHandle(paramCount);
 
1283
SquirrelObject so(ho);
 
1284
SQObjectType sot = so.GetType();
 
1285
#endif
 
1286
 
 
1287
// === Standard function call ===
 
1288
 
 
1289
template<typename Func>
 
1290
inline void sq_pushdirectclosure(HSQUIRRELVM v,Func func,SQUnsignedInteger nupvalues) {
 
1291
  SQUserPointer up = sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
 
1292
  memcpy(up,&func,sizeof(func));
 
1293
  sq_newclosure(v,DirectCallFunction<Func>::Dispatch,nupvalues+1);
 
1294
} // sq_pushdirectclosure
 
1295
 
 
1296
// === Fixed Class pointer call (always calls with object pointer that was registered) ===
 
1297
 
 
1298
template<typename Callee,typename Func>
 
1299
inline void sq_pushdirectclosure(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
 
1300
  unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(Callee*)+sizeof(func));  // Also pushed on stack.
 
1301
  const SQUserPointer pCallee = (SQUserPointer)&callee;
 
1302
  memcpy(up,&pCallee,sizeof(Callee*));
 
1303
  memcpy(up + sizeof(Callee*),&func,sizeof(func));
 
1304
  sq_newclosure(v,DirectCallMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
 
1305
} // sq_pushdirectclosure
 
1306
 
 
1307
// === Class Instance call: class pointer retrieved from script class instance ===
 
1308
 
 
1309
template<typename Callee,typename Func>
 
1310
inline void sq_pushdirectinstanceclosure(HSQUIRRELVM v,const Callee & /*callee*/,Func func,SQUnsignedInteger nupvalues) {
 
1311
  unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func));  // Also pushed on stack.
 
1312
  memcpy(up,&func,sizeof(func));
 
1313
  sq_newclosure(v,DirectCallInstanceMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
 
1314
} // sq_pushdirectinstanceclosure
 
1315
 
 
1316
// === Class Instance call: class pointer retrieved from script class instance (variable arguments) ===
 
1317
 
 
1318
template<typename Callee>
 
1319
inline void sq_pushdirectinstanceclosurevarargs(HSQUIRRELVM v,const Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),SQUnsignedInteger nupvalues) {
 
1320
  unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
 
1321
  memcpy(up,&func,sizeof(func));
 
1322
  sq_newclosure(v,DirectCallInstanceMemberFunctionVarArgs<Callee>::Dispatch,nupvalues+1);
 
1323
} // sq_pushdirectinstanceclosurevarargs
 
1324
 
 
1325
// === Register a STANDARD function (table or class on stack) ===
 
1326
 
 
1327
template<typename Func>
 
1328
inline void Register(HSQUIRRELVM v,Func func,const SQChar * name) {
 
1329
  sq_pushstring(v,name,-1);
 
1330
  sq_pushdirectclosure(v,func,0);
 
1331
  sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
 
1332
} // Register
 
1333
 
 
1334
// === Register a MEMBER function (table or class on stack) ===
 
1335
 
 
1336
template<typename Callee,typename Func>
 
1337
inline void Register(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
 
1338
  sq_pushstring(v,name,-1);
 
1339
  sq_pushdirectclosure(v,callee,func,0);
 
1340
  sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
 
1341
} // Register
 
1342
 
 
1343
// === Register a STANDARD global function (root table) ===
 
1344
 
 
1345
template<typename Func>
 
1346
inline void RegisterGlobal(HSQUIRRELVM v,Func func,const SQChar * name) {
 
1347
  sq_pushroottable(v);
 
1348
  Register(v,func,name);
 
1349
  sq_poptop(v); // Remove root table.
 
1350
} // RegisterGlobal
 
1351
 
 
1352
template<typename Func>
 
1353
inline void RegisterGlobal(Func func,const SQChar * name) {
 
1354
  RegisterGlobal(SquirrelVM::GetVMPtr(),func,name);
 
1355
} // RegisterGlobal
 
1356
 
 
1357
// === Register a MEMBER global function (root table) ===
 
1358
 
 
1359
template<typename Callee,typename Func>
 
1360
inline void RegisterGlobal(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
 
1361
  sq_pushroottable(v);
 
1362
  Register(v,callee,func,name);
 
1363
  sq_poptop(v); // Remove root table.
 
1364
} // RegisterGlobal
 
1365
 
 
1366
template<typename Callee,typename Func>
 
1367
inline void RegisterGlobal(Callee & callee,Func func,const SQChar * name) {
 
1368
  RegisterGlobal(SquirrelVM::GetVMPtr(),callee,func,name);
 
1369
} // RegisterGlobal
 
1370
 
 
1371
// === Register a STANDARD function (hso is table or class) ===
 
1372
 
 
1373
template<typename Func>
 
1374
inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Func func,const SQChar * name) {
 
1375
  sq_pushobject(v,hso);
 
1376
  Register(v,func,name);
 
1377
  sq_poptop(v); // Remove hso.
 
1378
} // Register
 
1379
 
 
1380
// === Register a MEMBER function (hso is table or class) ===
 
1381
// === Fixed Class pointer call (always calls with object pointer that was registered) ===
 
1382
 
 
1383
template<typename Callee,typename Func>
 
1384
inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Callee & callee,Func func,const SQChar * name) {
 
1385
  sq_pushobject(v,hso);
 
1386
  Register(v,callee,func,name);
 
1387
  sq_poptop(v); // Remove hso.
 
1388
} // Register
 
1389
 
 
1390
// === Register an INSTANCE MEMBER function ===
 
1391
// === Class Instance call: class pointer retrieved from script class instance ===
 
1392
 
 
1393
template<typename Callee,typename Func>
 
1394
inline void RegisterInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Func func,const SQChar * name) {
 
1395
  sq_pushobject(v,hclass);
 
1396
  sq_pushstring(v,name,-1);
 
1397
  sq_pushdirectinstanceclosure(v,callee,func,0);
 
1398
  sq_createslot(v,-3);
 
1399
  sq_poptop(v); // Remove hclass.
 
1400
} // RegisterInstance
 
1401
 
 
1402
 
 
1403
#ifdef _MSC_VER
 
1404
#pragma warning(disable : 4995) // Deprecated _snprintf
 
1405
#endif
 
1406
 
 
1407
// === Register an INSTANCE MEMBER function Variable Arguments ===
 
1408
// typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
 
1409
// All the other Squirrel type-masks are passed normally.
 
1410
 
 
1411
template<typename Callee>
 
1412
inline void RegisterInstanceVarArgs(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),const SQChar * name,const SQChar * typeMask=sqT("*")) {
 
1413
  sq_pushobject(v,hclass);
 
1414
  sq_pushstring(v,name,-1);
 
1415
  sq_pushdirectinstanceclosurevarargs(v,callee,func,0);
 
1416
  SQChar tm[64];
 
1417
  SQChar * ptm = tm;
 
1418
  SQInteger numParams = SQ_MATCHTYPEMASKSTRING;
 
1419
  if (typeMask) {
 
1420
    if (typeMask[0] == '*') {
 
1421
      ptm       = 0; // Variable args: don't check parameters.
 
1422
//      numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()).
 
1423
    } else {
 
1424
      if (SCSNPRINTF(tm,sizeof(tm),sqT("x%s"),typeMask) < 0) { // Must be an instance.
 
1425
        throw SquirrelError(sqT("RegisterInstanceVarArgs: typeMask string too long."));
 
1426
      } // if
 
1427
    } // if
 
1428
  } else { // <TODO> Need to check object type on stack: table, class, instance, etc.
 
1429
//    _snprintf(tm,sizeof(tm),"x"); // instance.
 
1430
    tm[0] = 'x';
 
1431
    tm[1] = 0;
 
1432
  } // if
 
1433
  if (ptm) { // If ptm == 0, don't check type.
 
1434
    sq_setparamscheck(v,numParams,ptm); // Determine arg count from type string.
 
1435
  } // if
 
1436
#ifdef _DEBUG
 
1437
  sq_setnativeclosurename(v,-1,name); // For debugging only.
 
1438
#endif
 
1439
  sq_createslot(v,-3);
 
1440
  sq_poptop(v); // Remove hclass.
 
1441
} // RegisterInstanceVarArgs
 
1442
 
 
1443
#ifdef _MSC_VER
 
1444
#pragma warning(default : 4995)
 
1445
#endif
 
1446
 
 
1447
// === Call Squirrel Functions from C/C++ ===
 
1448
// No type checking is performed for Squirrel functions as Squirrel types are dynamic:
 
1449
// Incoming types are passed unchanged to Squirrel functions. The parameter count is checked: an exception is thrown if mismatched.
 
1450
// Return values must match the RT template argument type, else an exception can be thrown on return.
 
1451
 
 
1452
template<typename RT>
 
1453
struct SquirrelFunction {
 
1454
  HSQUIRRELVM v;
 
1455
  SquirrelObject object; // Table or class.
 
1456
  SquirrelObject func;
 
1457
  SquirrelFunction() : v(0) {}
 
1458
  SquirrelFunction(HSQUIRRELVM _v,const SquirrelObject & _object,const SquirrelObject & _func) : v(_v), object(_object), func(_func) {}
 
1459
  SquirrelFunction(const SquirrelObject & _object,const SquirrelObject & _func) : v(SquirrelVM::GetVMPtr()), object(_object), func(_func) {}
 
1460
  SquirrelFunction(const SquirrelObject & _object,const SQChar * name) {
 
1461
    v      = SquirrelVM::GetVMPtr();
 
1462
    object = _object;
 
1463
    func   = object.GetValue(name);
 
1464
  }
 
1465
  SquirrelFunction(const SQChar * name) {
 
1466
    v      = SquirrelVM::GetVMPtr();
 
1467
    object = SquirrelVM::GetRootTable();
 
1468
    func   = object.GetValue(name);
 
1469
  }
 
1470
 
 
1471
  // Release references and reset internal objects to null.
 
1472
  void reset(void) {
 
1473
    func.Reset();
 
1474
    object.Reset();
 
1475
  } // Reset
 
1476
 
 
1477
#define SQPLUS_CHECK_FNCALL(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("SquirrelFunction<> call failed"))
 
1478
 
 
1479
  RT operator()(void) {
 
1480
    sq_pushobject(v,func.GetObjectHandle());
 
1481
    sq_pushobject(v,object.GetObjectHandle());
 
1482
    SQPLUS_CHECK_FNCALL(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR));
 
1483
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1484
  }
 
1485
 
 
1486
  template<typename P1>
 
1487
  RT operator()(P1 p1) {
 
1488
    sq_pushobject(v,func.GetObjectHandle());
 
1489
    sq_pushobject(v,object.GetObjectHandle());
 
1490
    Push(v,p1);
 
1491
    SQPLUS_CHECK_FNCALL(sq_call(v,2,SQTrue,SQ_CALL_RAISE_ERROR));
 
1492
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1493
  }
 
1494
 
 
1495
  template<typename P1,typename P2>
 
1496
  RT operator()(P1 p1,P2 p2) {
 
1497
    sq_pushobject(v,func.GetObjectHandle());
 
1498
    sq_pushobject(v,object.GetObjectHandle());
 
1499
    Push(v,p1);
 
1500
    Push(v,p2);
 
1501
    SQPLUS_CHECK_FNCALL(sq_call(v,3,SQTrue,SQ_CALL_RAISE_ERROR));
 
1502
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1503
  }
 
1504
 
 
1505
  template<typename P1,typename P2,typename P3>
 
1506
  RT operator()(P1 p1,P2 p2,P3 p3) {
 
1507
    sq_pushobject(v,func.GetObjectHandle());
 
1508
    sq_pushobject(v,object.GetObjectHandle());
 
1509
    Push(v,p1);
 
1510
    Push(v,p2);
 
1511
    Push(v,p3);
 
1512
    SQPLUS_CHECK_FNCALL(sq_call(v,4,SQTrue,SQ_CALL_RAISE_ERROR));
 
1513
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1514
  }
 
1515
 
 
1516
  template<typename P1,typename P2,typename P3,typename P4>
 
1517
  RT operator()(P1 p1,P2 p2,P3 p3,P4 p4) {
 
1518
    sq_pushobject(v,func.GetObjectHandle());
 
1519
    sq_pushobject(v,object.GetObjectHandle());
 
1520
    Push(v,p1);
 
1521
    Push(v,p2);
 
1522
    Push(v,p3);
 
1523
    Push(v,p4);
 
1524
    SQPLUS_CHECK_FNCALL(sq_call(v,5,SQTrue,SQ_CALL_RAISE_ERROR));
 
1525
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1526
  }
 
1527
 
 
1528
  template<typename P1,typename P2,typename P3,typename P4,typename P5>
 
1529
  RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5) {
 
1530
    sq_pushobject(v,func.GetObjectHandle());
 
1531
    sq_pushobject(v,object.GetObjectHandle());
 
1532
    Push(v,p1);
 
1533
    Push(v,p2);
 
1534
    Push(v,p3);
 
1535
    Push(v,p4);
 
1536
    Push(v,p5);
 
1537
    SQPLUS_CHECK_FNCALL(sq_call(v,6,SQTrue,SQ_CALL_RAISE_ERROR));
 
1538
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1539
  }
 
1540
 
 
1541
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
 
1542
  RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6) {
 
1543
    sq_pushobject(v,func.GetObjectHandle());
 
1544
    sq_pushobject(v,object.GetObjectHandle());
 
1545
    Push(v,p1);
 
1546
    Push(v,p2);
 
1547
    Push(v,p3);
 
1548
    Push(v,p4);
 
1549
    Push(v,p5);
 
1550
    Push(v,p6);
 
1551
    SQPLUS_CHECK_FNCALL(sq_call(v,7,SQTrue,SQ_CALL_RAISE_ERROR));
 
1552
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1553
  }
 
1554
 
 
1555
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
 
1556
  RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7) {
 
1557
    sq_pushobject(v,func.GetObjectHandle());
 
1558
    sq_pushobject(v,object.GetObjectHandle());
 
1559
    Push(v,p1);
 
1560
    Push(v,p2);
 
1561
    Push(v,p3);
 
1562
    Push(v,p4);
 
1563
    Push(v,p5);
 
1564
    Push(v,p6);
 
1565
    Push(v,p7);
 
1566
    SQPLUS_CHECK_FNCALL(sq_call(v,8,SQTrue,SQ_CALL_RAISE_ERROR));
 
1567
    return GetRet(TypeWrapper<RT>(),v,-1);
 
1568
  }
 
1569
 
 
1570
};
 
1571
 
 
1572
// === Class/Struct registration ===
 
1573
 
 
1574
#define SQ_DELETE_CLASS(CLASSTYPE) if (up) { CLASSTYPE * self = (CLASSTYPE *)up; delete self;} return 0
 
1575
#define SQ_DECLARE_RELEASE(CLASSTYPE) \
 
1576
  static SQInteger release(SQUserPointer up, SQInteger /*size*/) { \
 
1577
    SQ_DELETE_CLASS(CLASSTYPE); \
 
1578
  }
 
1579
 
 
1580
template<typename T>
 
1581
struct ReleaseClassPtrPtr {
 
1582
  static SQInteger release(SQUserPointer up,SQInteger size) {
 
1583
    if (up) {
 
1584
      T ** self = (T **)up;
 
1585
      delete *self;
 
1586
    } // if
 
1587
    return 0;
 
1588
  } // release
 
1589
};
 
1590
 
 
1591
template<typename T>
 
1592
struct ReleaseClassPtr {
 
1593
  static SQInteger release(SQUserPointer up,SQInteger size) {
 
1594
    if (up) {
 
1595
      T * self = (T *)up;
 
1596
      delete self;
 
1597
    } // if
 
1598
    return 0;
 
1599
  } // release
 
1600
};
 
1601
 
 
1602
BOOL_T CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName=0);
 
1603
 
 
1604
#define SQ_ANCESTOR_CLASS_INDEX sqT("__ci")
 
1605
 
 
1606
// Call PostConstruct() at the end of custom constructors.
 
1607
template<typename T>
 
1608
inline SQInteger PostConstruct(HSQUIRRELVM v,T * newClass,SQRELEASEHOOK hook) {
 
1609
#ifdef SQ_USE_CLASS_INHERITANCE
 
1610
  StackHandler sa(v);
 
1611
  HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
 
1612
  SquirrelObject instance(ho);
 
1613
  INT_T classIndex = instance.GetValue(SQ_ANCESTOR_CLASS_INDEX).ToInteger();
 
1614
  if (classIndex == -1) { // Is this the most-derived C/C++ class? If so, create all ancestors (if present).
 
1615
 
 
1616
    SquirrelObject newObjectTable = SquirrelVM::CreateTable();                 // 11/2/05: Create a new table for this instance.
 
1617
    newObjectTable.SetUserPointer(INT_T((size_t)ClassType<T>::type()),newClass); // <TODO> 64-bit compatible version.
 
1618
    instance.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,newObjectTable);
 
1619
 
 
1620
    SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
 
1621
    INT_T count = classHierArray.Len();
 
1622
    if (count > 1) { // This will be true when more than one C/C++ class is in the hierarchy.
 
1623
      --count; // Skip the most-derived class.
 
1624
      for (INT_T i=0; i < count; i++) {
 
1625
#ifdef CPP_STYLE_INHERITANCE // Kamaitati's changes for C++ inheritance support. jcs 5/28/06
 
1626
        SquirrelObject so = classHierArray.GetValue(i);
 
1627
        sq_pushobject(v,so.GetObjectHandle());
 
1628
        SQUserPointer typeTag;
 
1629
        sq_gettypetag(v,-1,&typeTag);
 
1630
        newObjectTable.SetUserPointer(INT_T(size_t(typeTag)),newClass);
 
1631
        sq_poptop(v);
 
1632
#else
 
1633
        instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,i); // Store ancestor class index for recursive constructor calls to come.
 
1634
        INT_T top = sq_gettop(v);
 
1635
        SquirrelObject so = classHierArray.GetValue(i); // Need to create UserData struct: store pointer to class, set release hook.
 
1636
        SquirrelObject func = so.GetValue(sqT("constructor"));
 
1637
        sq_pushobject(v,func.GetObjectHandle());
 
1638
        sq_pushobject(v,instance.GetObjectHandle()); // The 'instance' is the real Squirrel 'this' for all ancestors (as opposed to an instance created from the defining class, which does not happen).
 
1639
        sq_call(v,1,SQFalse,SQ_CALL_RAISE_ERROR); // Call constructor: no arguments are passed other than the 'instance'.
 
1640
        sq_settop(v,top);
 
1641
#endif
 
1642
      } // for
 
1643
      instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,SquirrelObject()); // Store an OT_NULL object to free SQ_ANCESTOR_CLASS_INDEX var.
 
1644
    } // if
 
1645
  } else { // Ancestor: Construct class and set release hook.
 
1646
 
 
1647
    SquirrelObject objectTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); // 11/2/05: Get the existing object table.
 
1648
    objectTable.SetUserPointer(INT_T((size_t)ClassType<T>::type()),newClass);     // <TODO> 64-bit compatible version.
 
1649
 
 
1650
    INT_T top = sq_gettop(v);
 
1651
    T ** ud = (T **)sq_newuserdata(v,sizeof(T *)); // Create UserData and push onto stack.
 
1652
    *ud = newClass;
 
1653
    // C::B patch: Disable releasing of objects (due to private/protected dtors) (Note: This is evil, but no other possibility found.)
 
1654
//    sq_setreleasehook(v,-1,ReleaseClassPtrPtr<T>::release); // Set release hook for UserData on stack.
 
1655
    SquirrelObject userData;
 
1656
    userData.AttachToStackObject(-1);
 
1657
    SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
 
1658
    classHierArray.SetValue(classIndex,userData); // Replace the class entry with UserData: will be freed during most-derived class destruction.
 
1659
    sq_settop(v,top);
 
1660
    return TRUE;
 
1661
  } // if
 
1662
#endif
 
1663
  sq_setinstanceup(v,1,newClass);
 
1664
  sq_setreleasehook(v,1,hook);
 
1665
  return 1;
 
1666
} // PostConstruct
 
1667
 
 
1668
template<typename T>
 
1669
struct ConstructReleaseClass {
 
1670
  static SQInteger construct(HSQUIRRELVM v) {
 
1671
    return PostConstruct<T>(v,new T(),release);
 
1672
  } // construct
 
1673
  // C::B patch: Add empty constructor
 
1674
  static SQInteger no_construct(HSQUIRRELVM v) {
 
1675
    return PostConstruct<T>(v,0,0);
 
1676
  } // no_construct
 
1677
  SQ_DECLARE_RELEASE(T)
 
1678
};
 
1679
 
 
1680
template<typename T>
 
1681
inline SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,const SQChar * baseScriptClassName=0) {
 
1682
  SQInteger top = sq_gettop(v);
 
1683
  SquirrelObject newClass;
 
1684
  if (CreateClass(v,newClass,(SQUserPointer)ClassType<T>::type(),scriptClassName,baseScriptClassName)) {
 
1685
    SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<T>::no_construct,sqT("constructor"));
 
1686
#ifdef SQ_USE_CLASS_INHERITANCE
 
1687
    // <NOTE> New member vars cannot be added to instances (OT_INSTANCE): additions must occur on the defining class (OT_CLASS), before any instances are instantiated.
 
1688
    if (!newClass.Exists(SQ_CLASS_OBJECT_TABLE_NAME)) { // Will always get table from most-derived registered class.
 
1689
      SquirrelObject objectTable = SquirrelVM::CreateTable();
 
1690
      newClass.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable); // Constructors must add their 'this' pointer indexed by type to this table. See PostConstruct() above.
 
1691
                                                                 // 11/2/05: This table will behave as a static global for each instance unless overwritten during construction (see PostConstruct() above).
 
1692
    } // if
 
1693
    SquirrelObject classHierArray;
 
1694
    if (!newClass.Exists(SQ_CLASS_HIER_ARRAY)) {   // Will always get table from most-derived registered class.
 
1695
      classHierArray = SquirrelVM::CreateArray(0); // The only constructor called will be the most-derived class: this array contains all classes in the hierarchy to be constructed.
 
1696
      newClass.SetValue(SQ_CLASS_HIER_ARRAY,classHierArray);
 
1697
    } else {
 
1698
      classHierArray = newClass.GetValue(SQ_CLASS_HIER_ARRAY);
 
1699
    } // if
 
1700
    classHierArray.ArrayAppend(newClass);          // Add the class to the hierarchy array. The array values will be released and replaced with UserData to free created ancestor classes.
 
1701
    // C::B patch for 64bit builds
 
1702
    newClass.SetValue(SQ_ANCESTOR_CLASS_INDEX,(SQInteger)-1); // When the class hierarchy is created, this var will be used to help in recursively creating ancestor classes.
 
1703
#endif
 
1704
  } // if
 
1705
  sq_settop(v,top);
 
1706
  return newClass;
 
1707
} // RegisterClassType
 
1708
 
 
1709
// === Define and register a C++ class and its members for use with Squirrel ===
 
1710
// Constructors+destructors are automatically created. Custom constructors must use the
 
1711
// standard SQFUNCTION signature if variable argument types are required (overloads).
 
1712
// See testSqPlus2.cpp for examples.
 
1713
 
 
1714
template<typename TClassType>
 
1715
struct SQClassDef {
 
1716
  HSQUIRRELVM v;
 
1717
  const SQChar * name;
 
1718
  const SQChar * base;
 
1719
  SquirrelObject newClass;
 
1720
 
 
1721
#ifdef SQ_USE_CLASS_INHERITANCE
 
1722
  // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
 
1723
  SQClassDef(HSQUIRRELVM _v,const SQChar * _name,const SQChar * _base=0) : v(_v), name(_name), base(_base) {
 
1724
    newClass = RegisterClassType<TClassType>(v,name,base);
 
1725
  }
 
1726
  // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
 
1727
  SQClassDef(const SQChar * _name,const SQChar * _base=0) : name(_name), base(_base) {
 
1728
    v = SquirrelVM::GetVMPtr();
 
1729
    newClass = RegisterClassType<TClassType>(v,name,base);
 
1730
  }
 
1731
#else
 
1732
  SQClassDef(HSQUIRRELVM _v,const SQChar * _name) : v(_v), name(_name) {
 
1733
    newClass = RegisterClassType<TClassType>(v,name);
 
1734
  }
 
1735
 
 
1736
  SQClassDef(const SQChar * _name) : name(_name) {
 
1737
    v = SquirrelVM::GetVMPtr();
 
1738
    newClass = RegisterClassType<TClassType>(v,name);
 
1739
  }
 
1740
#endif
 
1741
 
 
1742
  // C::B patch: Add empty constructor
 
1743
  SQClassDef & emptyCtor() {
 
1744
    SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<TClassType>::construct,sqT("constructor"));
 
1745
    return *this;
 
1746
  } // emptyCtor
 
1747
 
 
1748
  // Register a member function.
 
1749
  template<typename Func>
 
1750
  SQClassDef & func(Func pfunc,const SQChar * name_) {
 
1751
    RegisterInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_);
 
1752
    return *this;
 
1753
  } // func
 
1754
 
 
1755
  // Register a variable-argument member function (supports variable+multiple return values).
 
1756
  // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
 
1757
  // All the other Squirrel type-masks are passed normally.
 
1758
  template<typename Func>
 
1759
  SQClassDef & funcVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) {
 
1760
    RegisterInstanceVarArgs(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_,typeMask);
 
1761
    return *this;
 
1762
  } // funcVarArgs
 
1763
 
 
1764
  // === BEGIN static-member+global function registration ===
 
1765
 
 
1766
  // === This version is for static member functions only, such as custom constructors where 'this' is not yet valid ===
 
1767
  // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
 
1768
  // All the other Squirrel type-masks are passed normally.
 
1769
 
 
1770
  template<typename Func>
 
1771
  SQClassDef & staticFuncVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) {
 
1772
    SquirrelVM::PushObject(newClass);
 
1773
    SquirrelVM::CreateFunction(pfunc,name_,typeMask);
 
1774
    SquirrelVM::Pop(1);
 
1775
    return *this;
 
1776
  } // staticFuncVarArgs
 
1777
 
 
1778
  // Register a standard global function (effectively embedding a global function in TClassType's script namespace: does not need or use a 'this' pointer).
 
1779
  template<typename Func>
 
1780
  SQClassDef & staticFunc(Func pfunc,const SQChar * name_) {
 
1781
    Register(v,newClass.GetObjectHandle(),pfunc,name_);
 
1782
    return *this;
 
1783
  } // staticFunc
 
1784
 
 
1785
  // Register a function to a pre-allocated class/struct member function: will use callee's 'this' (effectively embedding a global function in TClassType's script namespace).
 
1786
  template<typename Callee,typename Func>
 
1787
  SQClassDef & staticFunc(Callee & callee,Func pfunc,const SQChar * name_) {
 
1788
    Register(v,newClass.GetObjectHandle(),callee,pfunc,name_);
 
1789
    return *this;
 
1790
  } // staticFunc
 
1791
 
 
1792
  // === END static+global function registration ===
 
1793
 
 
1794
  // Register a member variable.
 
1795
  template<typename VarType>
 
1796
  SQClassDef & var(VarType TClassType::* pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) {
 
1797
    struct CV {
 
1798
      VarType TClassType::* var;
 
1799
    } cv; // Cast Variable helper.
 
1800
    cv.var = pvar;
 
1801
    RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name_,access);
 
1802
    return *this;
 
1803
  } // var
 
1804
 
 
1805
  // Register a member variable as a UserPointer (read only).
 
1806
  template<typename VarType>
 
1807
  SQClassDef & varAsUserPointer(VarType TClassType::* pvar,const SQChar * name_) {
 
1808
    struct CV {
 
1809
      VarType TClassType::* var;
 
1810
    } cv; // Cast Variable helper.
 
1811
    cv.var = pvar;
 
1812
    RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(SQAnything **)&cv,name_,VAR_ACCESS_READ_ONLY);
 
1813
    return *this;
 
1814
  } // varAsUserPointer
 
1815
 
 
1816
  template<typename VarType>
 
1817
  SQClassDef & staticVar(VarType * pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) {
 
1818
    struct CV {
 
1819
      VarType * var;
 
1820
    } cv; // Cast Variable helper.
 
1821
    cv.var = pvar;
 
1822
    RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name_,VarAccessType(access|VAR_ACCESS_STATIC));
 
1823
    return *this;
 
1824
  } // staticVar
 
1825
 
 
1826
#ifdef SQPLUS_CONST_OPT
 
1827
#define SQ_REG_CONST_STATIC_VAR
 
1828
#include "SqPlusConst.h"
 
1829
#endif
 
1830
 
 
1831
  // Register a constant (read-only in script, passed by value (only INT_T, FLOAT_T, or BOOL_T types)).
 
1832
  template<typename ConstantType>
 
1833
  SQClassDef & constant(ConstantType constant_,const SQChar * name_) {
 
1834
    RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant_,name_);
 
1835
    return *this;
 
1836
  } // constant
 
1837
 
 
1838
  // Register an enum as an integer (read-only in script).
 
1839
  SQClassDef & enumInt(SQInteger constant_,const SQChar * name_) {
 
1840
      RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant_,name_);
 
1841
      return *this;
 
1842
  } // enumInt
 
1843
 
 
1844
};
 
1845
 
 
1846
// === BEGIN Function Call Handlers ===
 
1847
 
 
1848
inline void Push(HSQUIRRELVM v,char value)               { sq_pushinteger(v,value); }
 
1849
inline void Push(HSQUIRRELVM v,unsigned char value)      { sq_pushinteger(v,value); }
 
1850
inline void Push(HSQUIRRELVM v,short value)              { sq_pushinteger(v,value); }
 
1851
inline void Push(HSQUIRRELVM v,unsigned short value)     { sq_pushinteger(v,value); }
 
1852
inline void Push(HSQUIRRELVM v,int value)                { sq_pushinteger(v,value); }
 
1853
inline void Push(HSQUIRRELVM v,unsigned int value)       { sq_pushinteger(v,value); }
 
1854
inline void Push(HSQUIRRELVM v,long value)               { sq_pushinteger(v,value); }
 
1855
inline void Push(HSQUIRRELVM v,long long value)          { sq_pushinteger(v,value); }
 
1856
inline void Push(HSQUIRRELVM v,unsigned long value)      { sq_pushinteger(v,value); }
 
1857
inline void Push(HSQUIRRELVM v,unsigned long long value) { sq_pushinteger(v,value); }
 
1858
inline void Push(HSQUIRRELVM v,double value)             { sq_pushfloat(v,(FLOAT_T)value); }
 
1859
inline void Push(HSQUIRRELVM v,float value)              { sq_pushfloat(v,(FLOAT_T)value); }
 
1860
inline void Push(HSQUIRRELVM v,const SQChar * value)     { sq_pushstring(v,value,-1); }
 
1861
inline void Push(HSQUIRRELVM v,const SquirrelNull &)     { sq_pushnull(v); }
 
1862
inline void Push(HSQUIRRELVM v,SQFUNCTION value)         { sq_pushuserpointer(v,(void*)value); }
 
1863
inline void Push(HSQUIRRELVM v,SQAnythingPtr value)      { sq_pushuserpointer(v,(void*)value); } // Cast to SQAnythingPtr instead of void * if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
 
1864
inline void Push(HSQUIRRELVM v,SquirrelObject & so)      { sq_pushobject(v,so.GetObjectHandle()); }
 
1865
 
 
1866
 
 
1867
#define USE_ARGUMENT_DEPENDANT_OVERLOADS
 
1868
#ifdef USE_ARGUMENT_DEPENDANT_OVERLOADS
 
1869
#ifdef _MSC_VER
 
1870
#pragma warning (disable:4675) // Disable warning: "resolved overload was found by argument-dependent lookup" when class/struct pointers are used as function arguments.
 
1871
#endif
 
1872
// === BEGIN Argument Dependent Overloads ===
 
1873
inline void Push(HSQUIRRELVM v,bool value)                  { sq_pushbool(v,value); }               // Pass bool as SQInteger if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
 
1874
inline void Push(HSQUIRRELVM v,const void * value)          { sq_pushuserpointer(v,(void*)value); } // Pass SQAnythingPtr instead of void * "                                             "
 
1875
inline void Push(HSQUIRRELVM v,const SQUserPointer & value) { sq_pushuserpointer(v,(void*)value); }
 
1876
// === END Argument Dependent Overloads ===
 
1877
#endif
 
1878
 
 
1879
#define SQPLUS_CHECK_GET(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("sq_get*() failed (type error)"))
 
1880
 
 
1881
inline bool     Match(TypeWrapper<bool>,HSQUIRRELVM v,SQInteger idx)               { return sq_gettype(v,idx) == OT_BOOL; }
 
1882
inline bool     Match(TypeWrapper<char>,HSQUIRRELVM v,SQInteger idx)               { return sq_gettype(v,idx) == OT_INTEGER; }
 
1883
inline bool     Match(TypeWrapper<unsigned char>,HSQUIRRELVM v, SQInteger idx)     { return sq_gettype(v,idx) == OT_INTEGER; }
 
1884
inline bool     Match(TypeWrapper<short>,HSQUIRRELVM v,SQInteger idx)              { return sq_gettype(v,idx) == OT_INTEGER; }
 
1885
inline bool     Match(TypeWrapper<unsigned short>,HSQUIRRELVM v,SQInteger idx)     { return sq_gettype(v,idx) == OT_INTEGER; }
 
1886
inline bool     Match(TypeWrapper<int>,HSQUIRRELVM v,SQInteger idx)                { return sq_gettype(v,idx) == OT_INTEGER; }
 
1887
inline bool     Match(TypeWrapper<unsigned int>,HSQUIRRELVM v,SQInteger idx)       { return sq_gettype(v,idx) == OT_INTEGER; }
 
1888
inline bool     Match(TypeWrapper<long>,HSQUIRRELVM v,SQInteger idx)               { return sq_gettype(v,idx) == OT_INTEGER; }
 
1889
inline bool Match(TypeWrapper<long long>,HSQUIRRELVM v,SQInteger idx)          { return sq_gettype(v,idx) == OT_INTEGER; }
 
1890
inline bool     Match(TypeWrapper<unsigned long>,HSQUIRRELVM v,SQInteger idx)      { return sq_gettype(v,idx) == OT_INTEGER; }
 
1891
inline bool Match(TypeWrapper<unsigned long long>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
 
1892
inline bool     Match(TypeWrapper<float>,HSQUIRRELVM v,SQInteger idx)              { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; }
 
1893
inline bool     Match(TypeWrapper<double>,HSQUIRRELVM v,SQInteger idx)             { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; }
 
1894
inline bool     Match(TypeWrapper<const SQChar *>,HSQUIRRELVM v,SQInteger idx)     { return sq_gettype(v,idx) == OT_STRING; }
 
1895
inline bool     Match(TypeWrapper<HSQUIRRELVM>,HSQUIRRELVM /*v*/,SQInteger /*idx*/){ return true; } // See Get() for HSQUIRRELVM below (v is always present).
 
1896
inline bool     Match(TypeWrapper<void*>,HSQUIRRELVM v,SQInteger idx)              { return sq_gettype(v,idx) == OT_USERPOINTER; }
 
1897
inline bool     Match(TypeWrapper<SquirrelObject>,HSQUIRRELVM /*v*/,SQInteger /*idx*/) { return true; } // See sq_getstackobj(): always returns true.
 
1898
 
 
1899
inline void               Get(TypeWrapper<void>,HSQUIRRELVM /*v*/,int)                      { ; }
 
1900
inline bool               Get(TypeWrapper<bool>,HSQUIRRELVM v,SQInteger idx)                { SQBool b; SQPLUS_CHECK_GET(sq_getbool(v,idx,&b)); return b != 0; }
 
1901
inline char               Get(TypeWrapper<char>,HSQUIRRELVM v,SQInteger idx)                { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<char>(i); }
 
1902
inline unsigned char      Get(TypeWrapper<unsigned char>,HSQUIRRELVM v,SQInteger idx)       { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned char>(i); }
 
1903
inline short              Get(TypeWrapper<short>,HSQUIRRELVM v,SQInteger idx)               { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<short>(i); }
 
1904
inline unsigned short     Get(TypeWrapper<unsigned short>,HSQUIRRELVM v,SQInteger idx)      { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned short>(i); }
 
1905
inline int                Get(TypeWrapper<int>,HSQUIRRELVM v,SQInteger idx)                 { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return i; }
 
1906
inline unsigned int       Get(TypeWrapper<unsigned int>,HSQUIRRELVM v,SQInteger idx)        { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned int>(i); }
 
1907
inline long               Get(TypeWrapper<long>,HSQUIRRELVM v,SQInteger idx)                { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<long>(i); }
 
1908
inline long long          Get(TypeWrapper<long long>,HSQUIRRELVM v,SQInteger idx)           { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<long long>(i); }
 
1909
inline unsigned long      Get(TypeWrapper<unsigned long>,HSQUIRRELVM v,SQInteger idx)       { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned long>(i); }
 
1910
inline unsigned long long Get(TypeWrapper<unsigned long long>, HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned long long>(i); }
 
1911
inline float              Get(TypeWrapper<float>,HSQUIRRELVM v,SQInteger idx)               { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return f; }
 
1912
inline double             Get(TypeWrapper<double>,HSQUIRRELVM v,SQInteger idx)              { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return static_cast<double>(f); }
 
1913
inline const SQChar *     Get(TypeWrapper<const SQChar *>,HSQUIRRELVM v,SQInteger idx)      { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return s; }
 
1914
inline SquirrelNull       Get(TypeWrapper<SquirrelNull>,HSQUIRRELVM v,SQInteger idx)        { (void)v, (void)idx; return SquirrelNull();  }
 
1915
inline void *             Get(TypeWrapper<void *>,HSQUIRRELVM v,SQInteger idx)              { SQUserPointer p; SQPLUS_CHECK_GET(sq_getuserpointer(v,idx,&p)); return p; }
 
1916
inline HSQUIRRELVM        Get(TypeWrapper<HSQUIRRELVM>,HSQUIRRELVM v,SQInteger /*idx*/)     { sq_poptop(v); return v; } // sq_poptop(v): remove UserData from stack so GetParamCount() matches normal behavior.
 
1917
inline SquirrelObject     Get(TypeWrapper<SquirrelObject>,HSQUIRRELVM v,SQInteger idx)      { HSQOBJECT o; SQPLUS_CHECK_GET(sq_getstackobj(v,idx,&o)); return SquirrelObject(o); }
 
1918
 
 
1919
#ifdef SQPLUS_SUPPORT_STD_STRING
 
1920
inline void Push(HSQUIRRELVM v,const std::string& value) { sq_pushstring(v,value.c_str(),-1); }
 
1921
inline bool Match(TypeWrapper<const std::string&>, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; }
 
1922
inline std::string Get(TypeWrapper<const std::string&>,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return std::string(s); }
 
1923
#endif
 
1924
 
 
1925
// Added jflanglois suggestion, 8/20/06. jcs
 
1926
#ifdef SQPLUS_SUPPORT_SQ_STD_STRING
 
1927
typedef std::basic_string<SQChar> sq_std_string;
 
1928
inline void Push(HSQUIRRELVM v,const sq_std_string & value) { sq_pushstring(v,value.c_str(),-1); }
 
1929
inline bool Match(TypeWrapper<const sq_std_string &>, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; }
 
1930
inline sq_std_string Get(TypeWrapper<const sq_std_string &>,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return sq_std_string(s); }
 
1931
#endif
 
1932
 
 
1933
// GetRet() restores the stack for SquirrelFunction<>() calls.
 
1934
template<typename RT>
 
1935
inline RT GetRet(TypeWrapper<RT>,HSQUIRRELVM v,SQInteger idx) { RT ret = Get(TypeWrapper<RT>(),v,idx); sq_pop(v,2); return ret; } // sq_pop(v,2): restore stack after function call.
 
1936
 
 
1937
// Specialization to support void return type.
 
1938
inline void GetRet(TypeWrapper<void>,HSQUIRRELVM v,SQInteger /*idx*/) { sq_pop(v,2); }
 
1939
 
 
1940
// === END Function Call Handlers ===
 
1941
 
 
1942
// === Example SQClassDef usage (see testSqPlus2.cpp): ===
 
1943
 
 
1944
#if 0
 
1945
  SQClassDef<NewTestObj> sqClass(sqT("NewTestObj");
 
1946
  sqClass.func(NewTestObj::newtestR1,sqT("newtestR1"));
 
1947
  sqClass.var(&NewTestObj::val,sqT("val"));
 
1948
  sqClass.var(&NewTestObj::s1,sqT("s1"));
 
1949
  sqClass.var(&NewTestObj::s2,sqT("s2"));
 
1950
  sqClass.funcVarArgs(&NewTestObj::multiArgs,sqT("multiArgs"));
 
1951
 
 
1952
// Shorthand form:
 
1953
 
 
1954
  SQClassDef<NewTestObj>(sqT("NewTestObj").
 
1955
    func(NewTestObj::newtestR1,sqT("newtestR1")).
 
1956
    var(&NewTestObj::val,sqT("val")).
 
1957
    var(&NewTestObj::s1,sqT("s1")).
 
1958
    var(&NewTestObj::s2,sqT("s2")).
 
1959
    funcVarArgs(NewTestObj::multiArgs,sqT("multiArgs"));
 
1960
#endif
 
1961
 
 
1962
// === Macros for old style registration. SQClassDef registration is now easier to use (SQ_DECLARE_CLASS() is not needed) ===
 
1963
 
 
1964
#define SQ_DECLARE_CLASS(CLASSNAME)                                  \
 
1965
static SQInteger _##CLASSNAME##_release(SQUserPointer up,SQInteger size) { \
 
1966
  if (up) {                                                          \
 
1967
    CLASSNAME * self = (CLASSNAME *)up;                              \
 
1968
    delete self;                                                     \
 
1969
  }                                                                  \
 
1970
  return 0;                                                          \
 
1971
}                                                                    \
 
1972
static SQInteger _##CLASSNAME##_constructor(HSQUIRRELVM v) {               \
 
1973
  CLASSNAME * pc = new CLASSNAME();                                  \
 
1974
  sq_setinstanceup(v,1,pc);                                          \
 
1975
  sq_setreleasehook(v,1,_##CLASSNAME##_release);                     \
 
1976
  return 1;                                                          \
 
1977
}
 
1978
 
 
1979
#define SQ_REGISTER_CLASS(CLASSNAME)                                 \
 
1980
  RegisterClassType(SquirrelVM::GetVMPtr(),sqT(#CLASSNAME),_##CLASSNAME##_constructor)
 
1981
 
 
1982
#define SQ_REGISTER_INSTANCE(NEWSQCLASS,CCLASS,FUNCNAME)             \
 
1983
  RegisterInstance(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME));
 
1984
 
 
1985
#define SQ_REGISTER_INSTANCE_VARARGS(NEWSQCLASS,CCLASS,FUNCNAME)     \
 
1986
  RegisterInstanceVarArgs(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME));
 
1987
 
 
1988
#define SQ_REGISTER_INSTANCE_VARIABLE(NEWSQCLASS,CCLASS,VARNAME)     \
 
1989
  RegisterInstanceVariable(NEWSQCLASS,&((CCLASS *)0)->VARNAME,sqT(#VARNAME));
 
1990
 
 
1991
#if defined(USE_ARGUMENT_DEPENDANT_OVERLOADS) && defined(_MSC_VER)
 
1992
#pragma warning (default:4675)
 
1993
#endif
 
1994
 
 
1995
}; // namespace SqPlus
 
1996
 
 
1997
#endif //_SQ_PLUS_H_