squirrel_helper.hpp

Go to the documentation of this file.
00001 /* $Id: squirrel_helper.hpp 22886 2011-09-03 18:56:34Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef SQUIRREL_HELPER_HPP
00013 #define SQUIRREL_HELPER_HPP
00014 
00015 #include "squirrel.hpp"
00016 #include "../core/math_func.hpp"
00017 #include "../core/smallvec_type.hpp"
00018 #include "../economy_type.h"
00019 #include "../string_func.h"
00020 #include "squirrel_helper_type.hpp"
00021 
00025 namespace SQConvert {
00031   struct SQAutoFreePointers : SmallVector<void *, 1> {
00032     ~SQAutoFreePointers()
00033     {
00034       for (uint i = 0; i < this->items; i++) free(this->data[i]);
00035     }
00036   };
00037 
00038   template <bool Y> struct YesT {
00039     static const bool Yes = Y;
00040     static const bool No = !Y;
00041   };
00042 
00046   template <typename T> struct IsVoidT : YesT<false> {};
00047   template <> struct IsVoidT<void> : YesT<true> {};
00048 
00052   template <typename Tfunc> struct HasVoidReturnT;
00053   /* functions */
00054   template <typename Tretval> struct HasVoidReturnT<Tretval (*)()> : IsVoidT<Tretval> {};
00055   template <typename Tretval, typename Targ1> struct HasVoidReturnT<Tretval (*)(Targ1)> : IsVoidT<Tretval> {};
00056   template <typename Tretval, typename Targ1, typename Targ2> struct HasVoidReturnT<Tretval (*)(Targ1, Targ2)> : IsVoidT<Tretval> {};
00057   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3> struct HasVoidReturnT<Tretval (*)(Targ1, Targ2, Targ3)> : IsVoidT<Tretval> {};
00058   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4> struct HasVoidReturnT<Tretval (*)(Targ1, Targ2, Targ3, Targ4)> : IsVoidT<Tretval> {};
00059   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5> struct HasVoidReturnT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5)> : IsVoidT<Tretval> {};
00060   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10> struct HasVoidReturnT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10)> : IsVoidT<Tretval> {};
00061   /* methods */
00062   template <class Tcls, typename Tretval> struct HasVoidReturnT<Tretval (Tcls::*)()> : IsVoidT<Tretval> {};
00063   template <class Tcls, typename Tretval, typename Targ1> struct HasVoidReturnT<Tretval (Tcls::*)(Targ1)> : IsVoidT<Tretval> {};
00064   template <class Tcls, typename Tretval, typename Targ1, typename Targ2> struct HasVoidReturnT<Tretval (Tcls::*)(Targ1, Targ2)> : IsVoidT<Tretval> {};
00065   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3> struct HasVoidReturnT<Tretval (Tcls::*)(Targ1, Targ2, Targ3)> : IsVoidT<Tretval> {};
00066   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4> struct HasVoidReturnT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4)> : IsVoidT<Tretval> {};
00067   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5> struct HasVoidReturnT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5)> : IsVoidT<Tretval> {};
00068   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10> struct HasVoidReturnT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10)> : IsVoidT<Tretval> {};
00069 
00070 
00074   template <typename T> class ForceType { };
00075 
00079   template <typename T> static int Return(HSQUIRRELVM vm, T t);
00080 
00081   template <> inline int Return<uint8>       (HSQUIRRELVM vm, uint8 res)       { sq_pushinteger(vm, (int32)res); return 1; }
00082   template <> inline int Return<uint16>      (HSQUIRRELVM vm, uint16 res)      { sq_pushinteger(vm, (int32)res); return 1; }
00083   template <> inline int Return<uint32>      (HSQUIRRELVM vm, uint32 res)      { sq_pushinteger(vm, (int32)res); return 1; }
00084   template <> inline int Return<int8>        (HSQUIRRELVM vm, int8 res)        { sq_pushinteger(vm, res); return 1; }
00085   template <> inline int Return<int16>       (HSQUIRRELVM vm, int16 res)       { sq_pushinteger(vm, res); return 1; }
00086   template <> inline int Return<int32>       (HSQUIRRELVM vm, int32 res)       { sq_pushinteger(vm, res); return 1; }
00087   template <> inline int Return<int64>       (HSQUIRRELVM vm, int64 res)       { sq_pushinteger(vm, ClampToI32(res)); return 1; }
00088   template <> inline int Return<Money>       (HSQUIRRELVM vm, Money res)       { sq_pushinteger(vm, ClampToI32(res)); return 1; }
00089   template <> inline int Return<bool>        (HSQUIRRELVM vm, bool res)        { sq_pushbool   (vm, res); return 1; }
00090   template <> inline int Return<char *>      (HSQUIRRELVM vm, char *res)       { if (res == NULL) sq_pushnull(vm); else { sq_pushstring(vm, OTTD2SQ(res), -1); free(res); } return 1; }
00091   template <> inline int Return<const char *>(HSQUIRRELVM vm, const char *res) { if (res == NULL) sq_pushnull(vm); else { sq_pushstring(vm, OTTD2SQ(res), -1); } return 1; }
00092   template <> inline int Return<void *>      (HSQUIRRELVM vm, void *res)       { sq_pushuserpointer(vm, res); return 1; }
00093 
00097   template <typename T> static T GetParam(ForceType<T>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr);
00098 
00099   template <> inline uint8       GetParam(ForceType<uint8>       , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger     tmp; sq_getinteger    (vm, index, &tmp); return tmp; }
00100   template <> inline uint16      GetParam(ForceType<uint16>      , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger     tmp; sq_getinteger    (vm, index, &tmp); return tmp; }
00101   template <> inline uint32      GetParam(ForceType<uint32>      , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger     tmp; sq_getinteger    (vm, index, &tmp); return tmp; }
00102   template <> inline int8        GetParam(ForceType<int8>        , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger     tmp; sq_getinteger    (vm, index, &tmp); return tmp; }
00103   template <> inline int16       GetParam(ForceType<int16>       , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger     tmp; sq_getinteger    (vm, index, &tmp); return tmp; }
00104   template <> inline int32       GetParam(ForceType<int32>       , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger     tmp; sq_getinteger    (vm, index, &tmp); return tmp; }
00105   template <> inline bool        GetParam(ForceType<bool>        , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQBool        tmp; sq_getbool       (vm, index, &tmp); return tmp != 0; }
00106   template <> inline void       *GetParam(ForceType<void *>      , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer tmp; sq_getuserpointer(vm, index, &tmp); return tmp; }
00107   template <> inline const char *GetParam(ForceType<const char *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr)
00108   {
00109     sq_tostring(vm, index);
00110     const SQChar *tmp;
00111     sq_getstring(vm, -1, &tmp);
00112     char *tmp_str = strdup(SQ2OTTD(tmp));
00113     sq_poptop(vm);
00114     *ptr->Append() = (void *)tmp_str;
00115     str_validate(tmp_str, tmp_str + strlen(tmp_str));
00116     return tmp_str;
00117   }
00118 
00119   template <> inline Array      *GetParam(ForceType<Array *>,      HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr)
00120   {
00121     /* Sanity check of the size. */
00122     if (sq_getsize(vm, index) > UINT16_MAX) throw sq_throwerror(vm, _SC("an array used as parameter to a function is too large"));
00123 
00124     SQObject obj;
00125     sq_getstackobj(vm, index, &obj);
00126     sq_pushobject(vm, obj);
00127     sq_pushnull(vm);
00128 
00129     SmallVector<int32, 2> data;
00130 
00131     while (SQ_SUCCEEDED(sq_next(vm, -2))) {
00132       SQInteger tmp;
00133       if (SQ_SUCCEEDED(sq_getinteger(vm, -1, &tmp))) {
00134         *data.Append() = (int32)tmp;
00135       } else {
00136         sq_pop(vm, 4);
00137         throw sq_throwerror(vm, _SC("a member of an array used as parameter to a function is not numeric"));
00138       }
00139 
00140       sq_pop(vm, 2);
00141     }
00142     sq_pop(vm, 2);
00143 
00144     Array *arr = (Array*)MallocT<byte>(sizeof(Array) + sizeof(int32) * data.Length());
00145     arr->size = data.Length();
00146     memcpy(arr->array, data.Begin(), sizeof(int32) * data.Length());
00147 
00148     *ptr->Append() = arr;
00149     return arr;
00150   }
00151 
00157   template <typename Tfunc, bool Tis_void_retval = HasVoidReturnT<Tfunc>::Yes> struct HelperT;
00158 
00162   template <typename Tretval>
00163   struct HelperT<Tretval (*)(), false> {
00164     static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm)
00165     {
00166       return Return(vm, (*func)());
00167     }
00168   };
00169 
00173   template <typename Tretval>
00174   struct HelperT<Tretval (*)(), true> {
00175     static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm)
00176     {
00177       (*func)();
00178       return 0;
00179     }
00180   };
00181 
00185   template <class Tcls, typename Tretval>
00186   struct HelperT<Tretval (Tcls::*)(), false> {
00187     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm)
00188     {
00189       return Return(vm, (instance->*func)());
00190     }
00191   };
00192 
00196   template <class Tcls, typename Tretval>
00197   struct HelperT<Tretval (Tcls::*)(), true> {
00198     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm)
00199     {
00200       (instance->*func)();
00201       return 0;
00202     }
00203 
00204     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm)
00205     {
00206       return new Tcls();
00207     }
00208   };
00209 
00213   template <typename Tretval, typename Targ1>
00214   struct HelperT<Tretval (*)(Targ1), false> {
00215     static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm)
00216     {
00217       SQAutoFreePointers ptr;
00218       Tretval ret = (*func)(
00219         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00220       );
00221       sq_pop(vm, 1);
00222       return Return(vm, ret);
00223     }
00224   };
00225 
00229   template <typename Tretval, typename Targ1>
00230   struct HelperT<Tretval (*)(Targ1), true> {
00231     static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm)
00232     {
00233       SQAutoFreePointers ptr;
00234       (*func)(
00235         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00236       );
00237       sq_pop(vm, 1);
00238       return 0;
00239     }
00240   };
00241 
00245   template <class Tcls, typename Tretval, typename Targ1>
00246   struct HelperT<Tretval (Tcls::*)(Targ1), false> {
00247     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm)
00248     {
00249       SQAutoFreePointers ptr;
00250       Tretval ret = (instance->*func)(
00251         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00252       );
00253       sq_pop(vm, 1);
00254       return Return(vm, ret);
00255     }
00256   };
00257 
00261   template <class Tcls, typename Tretval, typename Targ1>
00262   struct HelperT<Tretval (Tcls::*)(Targ1), true> {
00263     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm)
00264     {
00265       SQAutoFreePointers ptr;
00266       (instance->*func)(
00267         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00268       );
00269       sq_pop(vm, 1);
00270       return 0;
00271     }
00272 
00273     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm)
00274     {
00275       SQAutoFreePointers ptr;
00276       Tcls *inst = new Tcls(
00277         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00278       );
00279 
00280       return inst;
00281     }
00282   };
00283 
00287   template <typename Tretval, typename Targ1, typename Targ2>
00288   struct HelperT<Tretval (*)(Targ1, Targ2), false> {
00289     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm)
00290     {
00291       SQAutoFreePointers ptr;
00292       Tretval ret = (*func)(
00293         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00294         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00295       );
00296       sq_pop(vm, 2);
00297       return Return(vm, ret);
00298     }
00299   };
00300 
00304   template <typename Tretval, typename Targ1, typename Targ2>
00305   struct HelperT<Tretval (*)(Targ1, Targ2), true> {
00306     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm)
00307     {
00308       SQAutoFreePointers ptr;
00309       (*func)(
00310         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00311         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00312       );
00313       sq_pop(vm, 2);
00314       return 0;
00315     }
00316   };
00317 
00321   template <class Tcls, typename Tretval, typename Targ1, typename Targ2>
00322   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2), false> {
00323     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm)
00324     {
00325       SQAutoFreePointers ptr;
00326       Tretval ret = (instance->*func)(
00327         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00328         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00329       );
00330       sq_pop(vm, 2);
00331       return Return(vm, ret);
00332     }
00333   };
00334 
00338   template <class Tcls, typename Tretval, typename Targ1, typename Targ2>
00339   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2), true> {
00340     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm)
00341     {
00342       SQAutoFreePointers ptr;
00343       (instance->*func)(
00344         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00345         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00346       );
00347       sq_pop(vm, 2);
00348       return 0;
00349     }
00350 
00351     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm)
00352     {
00353       SQAutoFreePointers ptr;
00354       Tcls *inst = new Tcls(
00355         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00356         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00357       );
00358 
00359       return inst;
00360     }
00361   };
00362 
00366   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00367   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3), false> {
00368     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00369     {
00370       SQAutoFreePointers ptr;
00371       Tretval ret = (*func)(
00372         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00373         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00374         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00375       );
00376       sq_pop(vm, 3);
00377       return Return(vm, ret);
00378     }
00379   };
00380 
00384   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00385   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3), true> {
00386     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00387     {
00388       SQAutoFreePointers ptr;
00389       (*func)(
00390         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00391         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00392         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00393       );
00394       sq_pop(vm, 3);
00395       return 0;
00396     }
00397   };
00398 
00402   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00403   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3), false> {
00404     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00405     {
00406       SQAutoFreePointers ptr;
00407       Tretval ret = (instance->*func)(
00408         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00409         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00410         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00411       );
00412       sq_pop(vm, 3);
00413       return Return(vm, ret);
00414     }
00415   };
00416 
00420   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00421   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3), true> {
00422     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00423     {
00424       SQAutoFreePointers ptr;
00425       (instance->*func)(
00426         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00427         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00428         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00429       );
00430       sq_pop(vm, 3);
00431       return 0;
00432     }
00433 
00434     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00435     {
00436       SQAutoFreePointers ptr;
00437       Tcls *inst = new Tcls(
00438         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00439         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00440         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00441       );
00442 
00443       return inst;
00444     }
00445   };
00446 
00450   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00451   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4), false> {
00452     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00453     {
00454       SQAutoFreePointers ptr;
00455       Tretval ret = (*func)(
00456         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00457         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00458         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00459         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00460       );
00461       sq_pop(vm, 4);
00462       return Return(vm, ret);
00463     }
00464   };
00465 
00469   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00470   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4), true> {
00471     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00472     {
00473       SQAutoFreePointers ptr;
00474       (*func)(
00475         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00476         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00477         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00478         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00479       );
00480       sq_pop(vm, 4);
00481       return 0;
00482     }
00483   };
00484 
00488   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00489   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4), false> {
00490     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00491     {
00492       SQAutoFreePointers ptr;
00493       Tretval ret = (instance->*func)(
00494         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00495         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00496         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00497         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00498       );
00499       sq_pop(vm, 4);
00500       return Return(vm, ret);
00501     }
00502   };
00503 
00507   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00508   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4), true> {
00509     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00510     {
00511       SQAutoFreePointers ptr;
00512       (instance->*func)(
00513         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00514         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00515         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00516         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00517       );
00518       sq_pop(vm, 4);
00519       return 0;
00520     }
00521 
00522     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00523     {
00524       SQAutoFreePointers ptr;
00525       Tcls *inst = new Tcls(
00526         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00527         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00528         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00529         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00530       );
00531 
00532       return inst;
00533     }
00534   };
00535 
00539   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00540   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5), false> {
00541     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00542     {
00543       SQAutoFreePointers ptr;
00544       Tretval ret = (*func)(
00545         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00546         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00547         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00548         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00549         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00550       );
00551       sq_pop(vm, 5);
00552       return Return(vm, ret);
00553     }
00554   };
00555 
00559   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00560   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5), true> {
00561     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00562     {
00563       SQAutoFreePointers ptr;
00564       (*func)(
00565         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00566         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00567         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00568         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00569         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00570       );
00571       sq_pop(vm, 5);
00572       return 0;
00573     }
00574   };
00575 
00579   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00580   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5), false> {
00581     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00582     {
00583       SQAutoFreePointers ptr;
00584       Tretval ret = (instance->*func)(
00585         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00586         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00587         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00588         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00589         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00590       );
00591       sq_pop(vm, 5);
00592       return Return(vm, ret);
00593     }
00594   };
00595 
00599   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00600   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5), true> {
00601     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00602     {
00603       SQAutoFreePointers ptr;
00604       (instance->*func)(
00605         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00606         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00607         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00608         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00609         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00610       );
00611       sq_pop(vm, 5);
00612       return 0;
00613     }
00614 
00615     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00616     {
00617       SQAutoFreePointers ptr;
00618       Tcls *inst = new Tcls(
00619         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00620         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00621         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00622         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00623         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00624       );
00625 
00626       return inst;
00627     }
00628   };
00629 
00633   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10>
00634   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), false> {
00635     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00636     {
00637       SQAutoFreePointers ptr;
00638       Tretval ret = (*func)(
00639         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00640         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00641         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00642         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00643         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00644         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00645         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00646         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00647         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00648         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00649       );
00650       sq_pop(vm, 10);
00651       return Return(vm, ret);
00652     }
00653   };
00654 
00658   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10>
00659   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), true> {
00660     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00661     {
00662       SQAutoFreePointers ptr;
00663       (*func)(
00664         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00665         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00666         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00667         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00668         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00669         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00670         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00671         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00672         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00673         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00674       );
00675       sq_pop(vm, 10);
00676       return 0;
00677     }
00678   };
00679 
00683   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10>
00684   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), false> {
00685     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00686     {
00687       SQAutoFreePointers ptr;
00688       Tretval ret = (instance->*func)(
00689         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00690         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00691         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00692         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00693         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00694         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00695         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00696         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00697         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00698         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00699       );
00700       sq_pop(vm, 10);
00701       return Return(vm, ret);
00702     }
00703   };
00704 
00708   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10>
00709   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), true> {
00710     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00711     {
00712       SQAutoFreePointers ptr;
00713       (instance->*func)(
00714         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00715         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00716         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00717         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00718         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00719         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00720         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00721         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00722         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00723         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00724       );
00725       sq_pop(vm, 10);
00726       return 0;
00727     }
00728 
00729     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00730     {
00731       SQAutoFreePointers ptr;
00732       Tcls *inst = new Tcls(
00733         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00734         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00735         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00736         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00737         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00738         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00739         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00740         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00741         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00742         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00743       );
00744 
00745       return inst;
00746     }
00747   };
00748 
00749 
00755   template <typename Tcls, typename Tmethod>
00756   inline SQInteger DefSQNonStaticCallback(HSQUIRRELVM vm)
00757   {
00758     /* Find the amount of params we got */
00759     int nparam = sq_gettop(vm);
00760     SQUserPointer ptr = NULL;
00761     SQUserPointer real_instance = NULL;
00762     HSQOBJECT instance;
00763 
00764     /* Get the 'SQ' instance of this class */
00765     Squirrel::GetInstance(vm, &instance);
00766 
00767     /* Protect against calls to a non-static method in a static way */
00768     sq_pushroottable(vm);
00769     sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1);
00770     sq_get(vm, -2);
00771     sq_pushobject(vm, instance);
00772     if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static"));
00773     sq_pop(vm, 3);
00774 
00775     /* Get the 'real' instance of this class */
00776     sq_getinstanceup(vm, 1, &real_instance, 0);
00777     /* Get the real function pointer */
00778     sq_getuserdata(vm, nparam, &ptr, 0);
00779     if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call"));
00780     /* Remove the userdata from the stack */
00781     sq_pop(vm, 1);
00782 
00783     try {
00784       /* Delegate it to a template that can handle this specific function */
00785       return HelperT<Tmethod>::SQCall((Tcls *)real_instance, *(Tmethod *)ptr, vm);
00786     } catch (SQInteger e) {
00787       sq_pop(vm, nparam);
00788       return e;
00789     }
00790   }
00791 
00797   template <typename Tcls, typename Tmethod>
00798   inline SQInteger DefSQAdvancedNonStaticCallback(HSQUIRRELVM vm)
00799   {
00800     /* Find the amount of params we got */
00801     int nparam = sq_gettop(vm);
00802     SQUserPointer ptr = NULL;
00803     SQUserPointer real_instance = NULL;
00804     HSQOBJECT instance;
00805 
00806     /* Get the 'SQ' instance of this class */
00807     Squirrel::GetInstance(vm, &instance);
00808 
00809     /* Protect against calls to a non-static method in a static way */
00810     sq_pushroottable(vm);
00811     sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1);
00812     sq_get(vm, -2);
00813     sq_pushobject(vm, instance);
00814     if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static"));
00815     sq_pop(vm, 3);
00816 
00817     /* Get the 'real' instance of this class */
00818     sq_getinstanceup(vm, 1, &real_instance, 0);
00819     /* Get the real function pointer */
00820     sq_getuserdata(vm, nparam, &ptr, 0);
00821     if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call"));
00822     /* Remove the userdata from the stack */
00823     sq_pop(vm, 1);
00824 
00825     /* Call the function, which its only param is always the VM */
00826     return (SQInteger)(((Tcls *)real_instance)->*(*(Tmethod *)ptr))(vm);
00827   }
00828 
00834   template <typename Tcls, typename Tmethod>
00835   inline SQInteger DefSQStaticCallback(HSQUIRRELVM vm)
00836   {
00837     /* Find the amount of params we got */
00838     int nparam = sq_gettop(vm);
00839     SQUserPointer ptr = NULL;
00840 
00841     /* Get the real function pointer */
00842     sq_getuserdata(vm, nparam, &ptr, 0);
00843 
00844     try {
00845       /* Delegate it to a template that can handle this specific function */
00846       return HelperT<Tmethod>::SQCall((Tcls *)NULL, *(Tmethod *)ptr, vm);
00847     } catch (SQInteger e) {
00848       sq_pop(vm, nparam);
00849       return e;
00850     }
00851   }
00852 
00857   template <typename Tcls>
00858   static SQInteger DefSQDestructorCallback(SQUserPointer p, SQInteger size)
00859   {
00860     /* Remove the real instance too */
00861     if (p != NULL) ((Tcls *)p)->Release();
00862     return 0;
00863   }
00864 
00870   template <typename Tcls, typename Tmethod, int Tnparam>
00871   inline SQInteger DefSQConstructorCallback(HSQUIRRELVM vm)
00872   {
00873     /* Find the amount of params we got */
00874     int nparam = sq_gettop(vm);
00875 
00876     try {
00877       /* Create the real instance */
00878       Tcls *instance = HelperT<Tmethod>::SQConstruct((Tcls *)NULL, (Tmethod)NULL, vm);
00879       sq_setinstanceup(vm, -Tnparam, instance);
00880       sq_setreleasehook(vm, -Tnparam, DefSQDestructorCallback<Tcls>);
00881       instance->AddRef();
00882       return 0;
00883     } catch (SQInteger e) {
00884       sq_pop(vm, nparam);
00885       return e;
00886     }
00887   }
00888 
00889 } // namespace SQConvert
00890 
00891 #endif /* SQUIRREL_HELPER_HPP */