squirrel_helper.hpp

Go to the documentation of this file.
00001 /* $Id: squirrel_helper.hpp 20632 2010-08-26 22:01:16Z rubidium $ */
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     SQObject obj;
00122     sq_getstackobj(vm, index, &obj);
00123     sq_pushobject(vm, obj);
00124     sq_pushnull(vm);
00125 
00126     SmallVector<int32, 2> data;
00127 
00128     while (SQ_SUCCEEDED(sq_next(vm, -2))) {
00129       SQInteger tmp;
00130       if (SQ_SUCCEEDED(sq_getinteger(vm, -1, &tmp))) {
00131         *data.Append() = (int32)tmp;
00132       } else {
00133         sq_pop(vm, 4);
00134         throw sq_throwerror(vm, _SC("a member of an array used as parameter to a function is not numeric"));
00135       }
00136 
00137       sq_pop(vm, 2);
00138     }
00139     sq_pop(vm, 2);
00140 
00141     Array *arr = (Array*)MallocT<byte>(sizeof(Array) + sizeof(int32) * data.Length());
00142     arr->size = data.Length();
00143     memcpy(arr->array, data.Begin(), sizeof(int32) * data.Length());
00144 
00145     *ptr->Append() = arr;
00146     return arr;
00147   }
00148 
00154   template <typename Tfunc, bool Tis_void_retval = HasVoidReturnT<Tfunc>::Yes> struct HelperT;
00155 
00159   template <typename Tretval>
00160   struct HelperT<Tretval (*)(), false> {
00161     static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm)
00162     {
00163       return Return(vm, (*func)());
00164     }
00165   };
00166 
00170   template <typename Tretval>
00171   struct HelperT<Tretval (*)(), true> {
00172     static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm)
00173     {
00174       (*func)();
00175       return 0;
00176     }
00177   };
00178 
00182   template <class Tcls, typename Tretval>
00183   struct HelperT<Tretval (Tcls::*)(), false> {
00184     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm)
00185     {
00186       return Return(vm, (instance->*func)());
00187     }
00188   };
00189 
00193   template <class Tcls, typename Tretval>
00194   struct HelperT<Tretval (Tcls::*)(), true> {
00195     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm)
00196     {
00197       (instance->*func)();
00198       return 0;
00199     }
00200 
00201     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm)
00202     {
00203       return new Tcls();
00204     }
00205   };
00206 
00210   template <typename Tretval, typename Targ1>
00211   struct HelperT<Tretval (*)(Targ1), false> {
00212     static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm)
00213     {
00214       SQAutoFreePointers ptr;
00215       Tretval ret = (*func)(
00216         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00217       );
00218       sq_pop(vm, 1);
00219       return Return(vm, ret);
00220     }
00221   };
00222 
00226   template <typename Tretval, typename Targ1>
00227   struct HelperT<Tretval (*)(Targ1), true> {
00228     static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm)
00229     {
00230       SQAutoFreePointers ptr;
00231       (*func)(
00232         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00233       );
00234       sq_pop(vm, 1);
00235       return 0;
00236     }
00237   };
00238 
00242   template <class Tcls, typename Tretval, typename Targ1>
00243   struct HelperT<Tretval (Tcls::*)(Targ1), false> {
00244     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm)
00245     {
00246       SQAutoFreePointers ptr;
00247       Tretval ret = (instance->*func)(
00248         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00249       );
00250       sq_pop(vm, 1);
00251       return Return(vm, ret);
00252     }
00253   };
00254 
00258   template <class Tcls, typename Tretval, typename Targ1>
00259   struct HelperT<Tretval (Tcls::*)(Targ1), true> {
00260     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm)
00261     {
00262       SQAutoFreePointers ptr;
00263       (instance->*func)(
00264         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00265       );
00266       sq_pop(vm, 1);
00267       return 0;
00268     }
00269 
00270     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm)
00271     {
00272       SQAutoFreePointers ptr;
00273       Tcls *inst = new Tcls(
00274         GetParam(ForceType<Targ1>(), vm, 2, &ptr)
00275       );
00276 
00277       return inst;
00278     }
00279   };
00280 
00284   template <typename Tretval, typename Targ1, typename Targ2>
00285   struct HelperT<Tretval (*)(Targ1, Targ2), false> {
00286     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm)
00287     {
00288       SQAutoFreePointers ptr;
00289       Tretval ret = (*func)(
00290         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00291         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00292       );
00293       sq_pop(vm, 2);
00294       return Return(vm, ret);
00295     }
00296   };
00297 
00301   template <typename Tretval, typename Targ1, typename Targ2>
00302   struct HelperT<Tretval (*)(Targ1, Targ2), true> {
00303     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm)
00304     {
00305       SQAutoFreePointers ptr;
00306       (*func)(
00307         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00308         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00309       );
00310       sq_pop(vm, 2);
00311       return 0;
00312     }
00313   };
00314 
00318   template <class Tcls, typename Tretval, typename Targ1, typename Targ2>
00319   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2), false> {
00320     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm)
00321     {
00322       SQAutoFreePointers ptr;
00323       Tretval ret = (instance->*func)(
00324         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00325         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00326       );
00327       sq_pop(vm, 2);
00328       return Return(vm, ret);
00329     }
00330   };
00331 
00335   template <class Tcls, typename Tretval, typename Targ1, typename Targ2>
00336   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2), true> {
00337     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm)
00338     {
00339       SQAutoFreePointers ptr;
00340       (instance->*func)(
00341         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00342         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00343       );
00344       sq_pop(vm, 2);
00345       return 0;
00346     }
00347 
00348     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm)
00349     {
00350       SQAutoFreePointers ptr;
00351       Tcls *inst = new Tcls(
00352         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00353         GetParam(ForceType<Targ2>(), vm, 3, &ptr)
00354       );
00355 
00356       return inst;
00357     }
00358   };
00359 
00363   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00364   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3), false> {
00365     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00366     {
00367       SQAutoFreePointers ptr;
00368       Tretval ret = (*func)(
00369         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00370         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00371         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00372       );
00373       sq_pop(vm, 3);
00374       return Return(vm, ret);
00375     }
00376   };
00377 
00381   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00382   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3), true> {
00383     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00384     {
00385       SQAutoFreePointers ptr;
00386       (*func)(
00387         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00388         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00389         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00390       );
00391       sq_pop(vm, 3);
00392       return 0;
00393     }
00394   };
00395 
00399   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00400   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3), false> {
00401     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00402     {
00403       SQAutoFreePointers ptr;
00404       Tretval ret = (instance->*func)(
00405         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00406         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00407         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00408       );
00409       sq_pop(vm, 3);
00410       return Return(vm, ret);
00411     }
00412   };
00413 
00417   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3>
00418   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3), true> {
00419     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00420     {
00421       SQAutoFreePointers ptr;
00422       (instance->*func)(
00423         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00424         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00425         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00426       );
00427       sq_pop(vm, 3);
00428       return 0;
00429     }
00430 
00431     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm)
00432     {
00433       SQAutoFreePointers ptr;
00434       Tcls *inst = new Tcls(
00435         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00436         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00437         GetParam(ForceType<Targ3>(), vm, 4, &ptr)
00438       );
00439 
00440       return inst;
00441     }
00442   };
00443 
00447   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00448   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4), false> {
00449     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00450     {
00451       SQAutoFreePointers ptr;
00452       Tretval ret = (*func)(
00453         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00454         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00455         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00456         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00457       );
00458       sq_pop(vm, 4);
00459       return Return(vm, ret);
00460     }
00461   };
00462 
00466   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00467   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4), true> {
00468     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00469     {
00470       SQAutoFreePointers ptr;
00471       (*func)(
00472         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00473         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00474         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00475         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00476       );
00477       sq_pop(vm, 4);
00478       return 0;
00479     }
00480   };
00481 
00485   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00486   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4), false> {
00487     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00488     {
00489       SQAutoFreePointers ptr;
00490       Tretval ret = (instance->*func)(
00491         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00492         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00493         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00494         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00495       );
00496       sq_pop(vm, 4);
00497       return Return(vm, ret);
00498     }
00499   };
00500 
00504   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4>
00505   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4), true> {
00506     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00507     {
00508       SQAutoFreePointers ptr;
00509       (instance->*func)(
00510         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00511         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00512         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00513         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00514       );
00515       sq_pop(vm, 4);
00516       return 0;
00517     }
00518 
00519     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm)
00520     {
00521       SQAutoFreePointers ptr;
00522       Tcls *inst = new Tcls(
00523         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00524         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00525         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00526         GetParam(ForceType<Targ4>(), vm, 5, &ptr)
00527       );
00528 
00529       return inst;
00530     }
00531   };
00532 
00536   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00537   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5), false> {
00538     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00539     {
00540       SQAutoFreePointers ptr;
00541       Tretval ret = (*func)(
00542         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00543         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00544         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00545         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00546         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00547       );
00548       sq_pop(vm, 5);
00549       return Return(vm, ret);
00550     }
00551   };
00552 
00556   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00557   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5), true> {
00558     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00559     {
00560       SQAutoFreePointers ptr;
00561       (*func)(
00562         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00563         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00564         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00565         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00566         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00567       );
00568       sq_pop(vm, 5);
00569       return 0;
00570     }
00571   };
00572 
00576   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00577   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5), false> {
00578     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00579     {
00580       SQAutoFreePointers ptr;
00581       Tretval ret = (instance->*func)(
00582         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00583         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00584         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00585         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00586         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00587       );
00588       sq_pop(vm, 5);
00589       return Return(vm, ret);
00590     }
00591   };
00592 
00596   template <class Tcls, typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5>
00597   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5), true> {
00598     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00599     {
00600       SQAutoFreePointers ptr;
00601       (instance->*func)(
00602         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00603         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00604         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00605         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00606         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00607       );
00608       sq_pop(vm, 5);
00609       return 0;
00610     }
00611 
00612     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm)
00613     {
00614       SQAutoFreePointers ptr;
00615       Tcls *inst = new Tcls(
00616         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00617         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00618         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00619         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00620         GetParam(ForceType<Targ5>(), vm, 6, &ptr)
00621       );
00622 
00623       return inst;
00624     }
00625   };
00626 
00630   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10>
00631   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), false> {
00632     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00633     {
00634       SQAutoFreePointers ptr;
00635       Tretval ret = (*func)(
00636         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00637         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00638         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00639         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00640         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00641         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00642         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00643         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00644         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00645         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00646       );
00647       sq_pop(vm, 10);
00648       return Return(vm, ret);
00649     }
00650   };
00651 
00655   template <typename Tretval, typename Targ1, typename Targ2, typename Targ3, typename Targ4, typename Targ5, typename Targ6, typename Targ7, typename Targ8, typename Targ9, typename Targ10>
00656   struct HelperT<Tretval (*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), true> {
00657     static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00658     {
00659       SQAutoFreePointers ptr;
00660       (*func)(
00661         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00662         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00663         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00664         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00665         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00666         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00667         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00668         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00669         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00670         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00671       );
00672       sq_pop(vm, 10);
00673       return 0;
00674     }
00675   };
00676 
00680   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>
00681   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), false> {
00682     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00683     {
00684       SQAutoFreePointers ptr;
00685       Tretval ret = (instance->*func)(
00686         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00687         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00688         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00689         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00690         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00691         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00692         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00693         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00694         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00695         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00696       );
00697       sq_pop(vm, 10);
00698       return Return(vm, ret);
00699     }
00700   };
00701 
00705   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>
00706   struct HelperT<Tretval (Tcls::*)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), true> {
00707     static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00708     {
00709       SQAutoFreePointers ptr;
00710       (instance->*func)(
00711         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00712         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00713         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00714         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00715         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00716         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00717         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00718         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00719         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00720         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00721       );
00722       sq_pop(vm, 10);
00723       return 0;
00724     }
00725 
00726     static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm)
00727     {
00728       SQAutoFreePointers ptr;
00729       Tcls *inst = new Tcls(
00730         GetParam(ForceType<Targ1>(), vm, 2, &ptr),
00731         GetParam(ForceType<Targ2>(), vm, 3, &ptr),
00732         GetParam(ForceType<Targ3>(), vm, 4, &ptr),
00733         GetParam(ForceType<Targ4>(), vm, 5, &ptr),
00734         GetParam(ForceType<Targ5>(), vm, 6, &ptr),
00735         GetParam(ForceType<Targ6>(), vm, 7, &ptr),
00736         GetParam(ForceType<Targ7>(), vm, 8, &ptr),
00737         GetParam(ForceType<Targ8>(), vm, 9, &ptr),
00738         GetParam(ForceType<Targ9>(), vm, 10, &ptr),
00739         GetParam(ForceType<Targ10>(), vm, 11, &ptr)
00740       );
00741 
00742       return inst;
00743     }
00744   };
00745 
00746 
00752   template <typename Tcls, typename Tmethod>
00753   inline SQInteger DefSQNonStaticCallback(HSQUIRRELVM vm)
00754   {
00755     /* Find the amount of params we got */
00756     int nparam = sq_gettop(vm);
00757     SQUserPointer ptr = NULL;
00758     SQUserPointer real_instance = NULL;
00759     HSQOBJECT instance;
00760 
00761     /* Get the 'SQ' instance of this class */
00762     Squirrel::GetInstance(vm, &instance);
00763 
00764     /* Protect against calls to a non-static method in a static way */
00765     sq_pushroottable(vm);
00766     sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1);
00767     sq_get(vm, -2);
00768     sq_pushobject(vm, instance);
00769     if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static"));
00770     sq_pop(vm, 3);
00771 
00772     /* Get the 'real' instance of this class */
00773     sq_getinstanceup(vm, 1, &real_instance, 0);
00774     /* Get the real function pointer */
00775     sq_getuserdata(vm, nparam, &ptr, 0);
00776     if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call"));
00777     /* Remove the userdata from the stack */
00778     sq_pop(vm, 1);
00779 
00780     try {
00781       /* Delegate it to a template that can handle this specific function */
00782       return HelperT<Tmethod>::SQCall((Tcls *)real_instance, *(Tmethod *)ptr, vm);
00783     } catch (SQInteger e) {
00784       sq_pop(vm, nparam);
00785       return e;
00786     }
00787   }
00788 
00794   template <typename Tcls, typename Tmethod>
00795   inline SQInteger DefSQAdvancedNonStaticCallback(HSQUIRRELVM vm)
00796   {
00797     /* Find the amount of params we got */
00798     int nparam = sq_gettop(vm);
00799     SQUserPointer ptr = NULL;
00800     SQUserPointer real_instance = NULL;
00801     HSQOBJECT instance;
00802 
00803     /* Get the 'SQ' instance of this class */
00804     Squirrel::GetInstance(vm, &instance);
00805 
00806     /* Protect against calls to a non-static method in a static way */
00807     sq_pushroottable(vm);
00808     sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1);
00809     sq_get(vm, -2);
00810     sq_pushobject(vm, instance);
00811     if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static"));
00812     sq_pop(vm, 3);
00813 
00814     /* Get the 'real' instance of this class */
00815     sq_getinstanceup(vm, 1, &real_instance, 0);
00816     /* Get the real function pointer */
00817     sq_getuserdata(vm, nparam, &ptr, 0);
00818     if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call"));
00819     /* Remove the userdata from the stack */
00820     sq_pop(vm, 1);
00821 
00822     /* Call the function, which its only param is always the VM */
00823     return (SQInteger)(((Tcls *)real_instance)->*(*(Tmethod *)ptr))(vm);
00824   }
00825 
00831   template <typename Tcls, typename Tmethod>
00832   inline SQInteger DefSQStaticCallback(HSQUIRRELVM vm)
00833   {
00834     /* Find the amount of params we got */
00835     int nparam = sq_gettop(vm);
00836     SQUserPointer ptr = NULL;
00837 
00838     /* Get the real function pointer */
00839     sq_getuserdata(vm, nparam, &ptr, 0);
00840 
00841     try {
00842       /* Delegate it to a template that can handle this specific function */
00843       return HelperT<Tmethod>::SQCall((Tcls *)NULL, *(Tmethod *)ptr, vm);
00844     } catch (SQInteger e) {
00845       sq_pop(vm, nparam);
00846       return e;
00847     }
00848   }
00849 
00854   template <typename Tcls>
00855   static SQInteger DefSQDestructorCallback(SQUserPointer p, SQInteger size)
00856   {
00857     /* Remove the real instance too */
00858     if (p != NULL) ((Tcls *)p)->Release();
00859     return 0;
00860   }
00861 
00867   template <typename Tcls, typename Tmethod, int Tnparam>
00868   inline SQInteger DefSQConstructorCallback(HSQUIRRELVM vm)
00869   {
00870     /* Find the amount of params we got */
00871     int nparam = sq_gettop(vm);
00872 
00873     try {
00874       /* Create the real instance */
00875       Tcls *instance = HelperT<Tmethod>::SQConstruct((Tcls *)NULL, (Tmethod)NULL, vm);
00876       sq_setinstanceup(vm, -Tnparam, instance);
00877       sq_setreleasehook(vm, -Tnparam, DefSQDestructorCallback<Tcls>);
00878       instance->AddRef();
00879       return 0;
00880     } catch (SQInteger e) {
00881       sq_pop(vm, nparam);
00882       return e;
00883     }
00884   }
00885 
00886 } // namespace SQConvert
00887 
00888 #endif /* SQUIRREL_HELPER_HPP */