From a3dd7506d377b1434f913bd65c019eed52b64b6e Mon Sep 17 00:00:00 2001 From: truebrain Date: Mon, 12 Jan 2009 17:11:45 +0000 Subject: (svn r15027) -Merge: tomatos and bananas left to be, here is NoAI for all to see. NoAI is an API (a framework) to build your own AIs in. See: http://wiki.openttd.org/wiki/index.php/AI:Main_Page With many thanks to: - glx and Rubidium for their syncing, feedback and hard work - Yexo for his feedback, patches, and AIs which tested the system very deep - Morloth for his feedback and patches - TJIP for hosting a challenge which kept NoAI on track - All AI authors for testing our AI API, and all other people who helped in one way or another -Remove: all old AIs and their cheats/hacks --- src/script/squirrel_helper.hpp | 870 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 870 insertions(+) create mode 100644 src/script/squirrel_helper.hpp (limited to 'src/script/squirrel_helper.hpp') diff --git a/src/script/squirrel_helper.hpp b/src/script/squirrel_helper.hpp new file mode 100644 index 000000000..67baf7c51 --- /dev/null +++ b/src/script/squirrel_helper.hpp @@ -0,0 +1,870 @@ +/* $Id$ */ + +/** @file squirrel_helper.hpp declarations and parts of the implementation of the class for convert code */ + +#ifndef SQUIRREL_HELPER_HPP +#define SQUIRREL_HELPER_HPP + +#include +#include "../core/math_func.hpp" +#include "../core/smallvec_type.hpp" +#include "../economy_type.h" +#include "squirrel_helper_type.hpp" + +/** + * The Squirrel convert routines + */ +namespace SQConvert { + /** + * Pointers assigned to this class will be free'd when this instance + * comes out of scope. Useful to make sure you can use strdup(), + * without leaking memory. + */ + struct SQAutoFreePointers : SmallVector { + ~SQAutoFreePointers() + { + for (uint i = 0; i < this->items; i++) free(this->data[i]); + } + }; + + template struct YesT { + static const bool Yes = Y; + static const bool No = !Y; + }; + + /** + * Helper class to recognize if the given type is void. Usage: 'IsVoidT::Yes' + */ + template struct IsVoidT : YesT {}; + template <> struct IsVoidT : YesT {}; + + /** + * Helper class to recognize if the function/method return type is void. + */ + template struct HasVoidReturnT; + /* functions */ + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + /* methods */ + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + template struct HasVoidReturnT : IsVoidT {}; + + + /** + * Special class to make it possible for the compiler to pick the correct GetParam(). + */ + template class ForceType { }; + + /** + * To return a value to squirrel, we call this function. It converts to the right format. + */ + template static int Return(HSQUIRRELVM vm, T t); + + template <> inline int Return (HSQUIRRELVM vm, uint8 res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline int Return (HSQUIRRELVM vm, uint16 res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline int Return (HSQUIRRELVM vm, uint32 res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline int Return (HSQUIRRELVM vm, int8 res) { sq_pushinteger(vm, res); return 1; } + template <> inline int Return (HSQUIRRELVM vm, int16 res) { sq_pushinteger(vm, res); return 1; } + template <> inline int Return (HSQUIRRELVM vm, int32 res) { sq_pushinteger(vm, res); return 1; } + template <> inline int Return (HSQUIRRELVM vm, int64 res) { sq_pushinteger(vm, ClampToI32(res)); return 1; } + template <> inline int Return (HSQUIRRELVM vm, Money res) { sq_pushinteger(vm, ClampToI32(res)); return 1; } + template <> inline int Return (HSQUIRRELVM vm, bool res) { sq_pushbool (vm, res); return 1; } + template <> inline int Return (HSQUIRRELVM vm, char *res) { if (res == NULL) sq_pushnull(vm); else sq_pushstring (vm, OTTD2FS(res), strlen(res)); free(res); return 1; } + template <> inline int Return(HSQUIRRELVM vm, const char *res) { if (res == NULL) sq_pushnull(vm); else sq_pushstring (vm, OTTD2FS(res), strlen(res)); return 1; } + template <> inline int Return (HSQUIRRELVM vm, void *res) { sq_pushuserpointer(vm, res); return 1; } + + /** + * To get a param from squirrel, we call this function. It converts to the right format. + */ + template static T GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr); + + template <> inline uint8 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } + template <> inline uint16 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } + template <> inline uint32 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } + template <> inline int8 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } + template <> inline int16 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } + template <> inline int32 GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; } + template <> inline bool GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQBool tmp; sq_getbool (vm, index, &tmp); return tmp != 0; } + template <> inline const char *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { const SQChar *tmp; sq_getstring (vm, index, &tmp); char *tmp_str = strdup(FS2OTTD(tmp)); *ptr->Append() = (void *)tmp_str; return tmp_str; } + template <> inline void *GetParam(ForceType , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer tmp; sq_getuserpointer(vm, index, &tmp); return tmp; } + + template <> inline Array *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) + { + SQObject obj; + sq_getstackobj(vm, index, &obj); + sq_pushobject(vm, obj); + sq_pushnull(vm); + + SmallVector data; + + while (SQ_SUCCEEDED(sq_next(vm, -2))) { + SQInteger tmp; + if (SQ_SUCCEEDED(sq_getinteger(vm, -1, &tmp))) { + *data.Append() = (int32)tmp; + } else { + sq_pop(vm, 4); + throw sq_throwerror(vm, _SC("a member of an array used as parameter to a function is not numeric")); + } + + sq_pop(vm, 2); + } + sq_pop(vm, 2); + + Array *arr = (Array*)MallocT(sizeof(Array) + sizeof(int32) * data.Length()); + arr->size = data.Length(); + memcpy(arr->array, data.Begin(), sizeof(int32) * data.Length()); + + *ptr->Append() = arr; + return arr; + } + + /** + * Helper class to recognize the function type (retval type, args) and use the proper specialization + * for SQ callback. The partial specializations for the second arg (Tis_void_retval) are not possible + * on the function. Therefore the class is used instead. + */ + template ::Yes> struct HelperT; + + /** + * The real C++ caller for function with return value and 0 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm) + { + return Return(vm, (*func)()); + } + }; + + /** + * The real C++ caller for function with no return value and 0 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(), HSQUIRRELVM vm) + { + (*func)(); + return 0; + } + }; + + /** + * The real C++ caller for method with return value and 0 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm) + { + return Return(vm, (instance->*func)()); + } + }; + + /** + * The real C++ caller for method with no return value and 0 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm) + { + (instance->*func)(); + return 0; + } + + static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(), HSQUIRRELVM vm) + { + return new Tcls(); + } + }; + + /** + * The real C++ caller for function with return value and 1 param. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (*func)( + GetParam(ForceType(), vm, 2, &ptr) + ); + sq_pop(vm, 1); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for function with no return value and 1 param. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (*func)( + GetParam(ForceType(), vm, 2, &ptr) + ); + sq_pop(vm, 1); + return 0; + } + }; + + /** + * The real C++ caller for method with return value and 1 param. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr) + ); + sq_pop(vm, 1); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for method with no return value and 1 param. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr) + ); + sq_pop(vm, 1); + return 0; + } + + static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tcls *inst = new Tcls( + GetParam(ForceType(), vm, 2, &ptr) + ); + + return inst; + } + }; + + /** + * The real C++ caller for function with return value and 2 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr) + ); + sq_pop(vm, 2); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for function with no return value and 2 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr) + ); + sq_pop(vm, 2); + return 0; + } + }; + + /** + * The real C++ caller for method with return value and 2 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr) + ); + sq_pop(vm, 2); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for method with no return value and 2 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr) + ); + sq_pop(vm, 2); + return 0; + } + + static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tcls *inst = new Tcls( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr) + ); + + return inst; + } + }; + + /** + * The real C++ caller for function with return value and 3 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr) + ); + sq_pop(vm, 3); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for function with no return value and 3 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr) + ); + sq_pop(vm, 3); + return 0; + } + }; + + /** + * The real C++ caller for method with return value and 3 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr) + ); + sq_pop(vm, 3); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for method with no return value and 3 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr) + ); + sq_pop(vm, 3); + return 0; + } + + static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tcls *inst = new Tcls( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr) + ); + + return inst; + } + }; + + /** + * The real C++ caller for function with return value and 4 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr) + ); + sq_pop(vm, 4); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for function with no return value and 4 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr) + ); + sq_pop(vm, 4); + return 0; + } + }; + + /** + * The real C++ caller for method with return value and 4 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr) + ); + sq_pop(vm, 4); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for method with no return value and 4 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr) + ); + sq_pop(vm, 4); + return 0; + } + + static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tcls *inst = new Tcls( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr) + ); + + return inst; + } + }; + + /** + * The real C++ caller for function with return value and 5 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr) + ); + sq_pop(vm, 5); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for function with no return value and 5 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr) + ); + sq_pop(vm, 5); + return 0; + } + }; + + /** + * The real C++ caller for method with return value and 5 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr) + ); + sq_pop(vm, 5); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for method with no return value and 5 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr) + ); + sq_pop(vm, 5); + return 0; + } + + static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tcls *inst = new Tcls( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr) + ); + + return inst; + } + }; + + /** + * The real C++ caller for function with return value and 10 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr), + GetParam(ForceType(), vm, 7, &ptr), + GetParam(ForceType(), vm, 8, &ptr), + GetParam(ForceType(), vm, 9, &ptr), + GetParam(ForceType(), vm, 10, &ptr), + GetParam(ForceType(), vm, 11, &ptr) + ); + sq_pop(vm, 10); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for function with no return value and 10 params. + */ + template + struct HelperT { + static int SQCall(void *instance, Tretval (*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr), + GetParam(ForceType(), vm, 7, &ptr), + GetParam(ForceType(), vm, 8, &ptr), + GetParam(ForceType(), vm, 9, &ptr), + GetParam(ForceType(), vm, 10, &ptr), + GetParam(ForceType(), vm, 11, &ptr) + ); + sq_pop(vm, 10); + return 0; + } + }; + + /** + * The real C++ caller for method with return value and 10 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tretval ret = (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr), + GetParam(ForceType(), vm, 7, &ptr), + GetParam(ForceType(), vm, 8, &ptr), + GetParam(ForceType(), vm, 9, &ptr), + GetParam(ForceType(), vm, 10, &ptr), + GetParam(ForceType(), vm, 11, &ptr) + ); + sq_pop(vm, 10); + return Return(vm, ret); + } + }; + + /** + * The real C++ caller for method with no return value and 10 params. + */ + template + struct HelperT { + static int SQCall(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + (instance->*func)( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr), + GetParam(ForceType(), vm, 7, &ptr), + GetParam(ForceType(), vm, 8, &ptr), + GetParam(ForceType(), vm, 9, &ptr), + GetParam(ForceType(), vm, 10, &ptr), + GetParam(ForceType(), vm, 11, &ptr) + ); + sq_pop(vm, 10); + return 0; + } + + static Tcls *SQConstruct(Tcls *instance, Tretval (Tcls::*func)(Targ1, Targ2, Targ3, Targ4, Targ5, Targ6, Targ7, Targ8, Targ9, Targ10), HSQUIRRELVM vm) + { + SQAutoFreePointers ptr; + Tcls *inst = new Tcls( + GetParam(ForceType(), vm, 2, &ptr), + GetParam(ForceType(), vm, 3, &ptr), + GetParam(ForceType(), vm, 4, &ptr), + GetParam(ForceType(), vm, 5, &ptr), + GetParam(ForceType(), vm, 6, &ptr), + GetParam(ForceType(), vm, 7, &ptr), + GetParam(ForceType(), vm, 8, &ptr), + GetParam(ForceType(), vm, 9, &ptr), + GetParam(ForceType(), vm, 10, &ptr), + GetParam(ForceType(), vm, 11, &ptr) + ); + + return inst; + } + }; + + + /** + * A general template for all non-static method callbacks from Squirrel. + * In here the function_proc is recovered, and the SQCall is called that + * can handle this exact amount of params. + */ + template + inline SQInteger DefSQNonStaticCallback(HSQUIRRELVM vm) + { + /* Find the amount of params we got */ + int nparam = sq_gettop(vm); + SQUserPointer ptr = NULL; + SQUserPointer real_instance = NULL; + HSQOBJECT instance; + + /* Get the 'SQ' instance of this class */ + Squirrel::GetInstance(vm, &instance); + + /* Protect against calls to a non-static method in a static way */ + sq_pushroottable(vm); + sq_pushstring(vm, OTTD2FS(Tcls::GetClassName()), -1); + sq_get(vm, -2); + sq_pushobject(vm, instance); + if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); + sq_pop(vm, 3); + + /* Get the 'real' instance of this class */ + sq_getinstanceup(vm, 1, &real_instance, 0); + /* Get the real function pointer */ + sq_getuserdata(vm, nparam, &ptr, 0); + if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); + /* Remove the userdata from the stack */ + sq_pop(vm, 1); + + try { + /* Delegate it to a template that can handle this specific function */ + return HelperT::SQCall((Tcls *)real_instance, *(Tmethod *)ptr, vm); + } catch (SQInteger e) { + sq_pop(vm, nparam); + return e; + } + } + + /** + * A general template for all non-static advanced method callbacks from Squirrel. + * In here the function_proc is recovered, and the SQCall is called that + * can handle this exact amount of params. + */ + template + inline SQInteger DefSQAdvancedNonStaticCallback(HSQUIRRELVM vm) + { + /* Find the amount of params we got */ + int nparam = sq_gettop(vm); + SQUserPointer ptr = NULL; + SQUserPointer real_instance = NULL; + HSQOBJECT instance; + + /* Get the 'SQ' instance of this class */ + Squirrel::GetInstance(vm, &instance); + + /* Protect against calls to a non-static method in a static way */ + sq_pushroottable(vm); + sq_pushstring(vm, OTTD2FS(Tcls::GetClassName()), -1); + sq_get(vm, -2); + sq_pushobject(vm, instance); + if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); + sq_pop(vm, 3); + + /* Get the 'real' instance of this class */ + sq_getinstanceup(vm, 1, &real_instance, 0); + /* Get the real function pointer */ + sq_getuserdata(vm, nparam, &ptr, 0); + if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); + /* Remove the userdata from the stack */ + sq_pop(vm, 1); + + /* Call the function, which its only param is always the VM */ + return (SQInteger)(((Tcls *)real_instance)->*(*(Tmethod *)ptr))(vm); + } + + /** + * A general template for all function/static method callbacks from Squirrel. + * In here the function_proc is recovered, and the SQCall is called that + * can handle this exact amount of params. + */ + template + inline SQInteger DefSQStaticCallback(HSQUIRRELVM vm) + { + /* Find the amount of params we got */ + int nparam = sq_gettop(vm); + SQUserPointer ptr = NULL; + + /* Get the real function pointer */ + sq_getuserdata(vm, nparam, &ptr, 0); + + try { + /* Delegate it to a template that can handle this specific function */ + return HelperT::SQCall((Tcls *)NULL, *(Tmethod *)ptr, vm); + } catch (SQInteger e) { + sq_pop(vm, nparam); + return e; + } + } + + /** + * A general template for the destructor of SQ instances. This is needed + * here as it has to be in the same scope as DefSQConstructorCallback. + */ + template + static SQInteger DefSQDestructorCallback(SQUserPointer p, SQInteger size) + { + /* Remove the real instance too */ + if (p != NULL) ((Tcls *)p)->Release(); + return 0; + } + + /** + * A general template to handle creating of instance with any amount of + * params. It creates the instance in C++, and it sets all the needed + * settings in SQ to register the instance. + */ + template + inline SQInteger DefSQConstructorCallback(HSQUIRRELVM vm) + { + /* Find the amount of params we got */ + int nparam = sq_gettop(vm); + + try { + /* Create the real instance */ + Tcls *instance = HelperT::SQConstruct((Tcls *)NULL, (Tmethod)NULL, vm); + sq_setinstanceup(vm, -Tnparam, instance); + sq_setreleasehook(vm, -Tnparam, DefSQDestructorCallback); + instance->AddRef(); + return 0; + } catch (SQInteger e) { + sq_pop(vm, nparam); + return e; + } + } + +}; // namespace SQConvert + +#endif /* SQUIRREL_HELPER_HPP */ -- cgit v1.2.3-54-g00ecf