/* * Copyright (c) 2010-2012 OTClient * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef LUAVALUECASTS_H #define LUAVALUECASTS_H // this file is and must be included only from luainterface.h #include "declarations.h" #include // bool void push_luavalue(bool b); bool luavalue_cast(int index, bool& b); // int void push_luavalue(int i); bool luavalue_cast(int index, int& i); // double void push_luavalue(double d); bool luavalue_cast(int index, double& d); // float inline void push_luavalue(float f) { push_luavalue((double)f); } inline bool luavalue_cast(int index, float& f) { double d; bool r = luavalue_cast(index, d); f = d; return r; } // int8 inline void push_luavalue(int8 v) { push_luavalue((int)v); } inline bool luavalue_cast(int index, int8& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint8 inline void push_luavalue(uint8 v) { push_luavalue((int)v); } inline bool luavalue_cast(int index, uint8& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // int16 inline void push_luavalue(int16 v) { push_luavalue((int)v); } inline bool luavalue_cast(int index, int16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint16 inline void push_luavalue(uint16 v) { push_luavalue((int)v); } inline bool luavalue_cast(int index, uint16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint32 inline void push_luavalue(uint32 v) { push_luavalue((double)v); } inline bool luavalue_cast(int index, uint32& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // int64 inline void push_luavalue(int64 v) { push_luavalue((double)v); } inline bool luavalue_cast(int index, int64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // uint64 inline void push_luavalue(uint64 v) { push_luavalue((double)v); } inline bool luavalue_cast(int index, uint64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // string void push_luavalue(const char* cstr); void push_luavalue(const std::string& str); bool luavalue_cast(int index, std::string& str); // lua cpp function void push_luavalue(const LuaCppFunction& func); // color void push_luavalue(const Color& color); bool luavalue_cast(int index, Color& color); // rect void push_luavalue(const Rect& rect); bool luavalue_cast(int index, Rect& rect); // point void push_luavalue(const Point& point); bool luavalue_cast(int index, Point& point); // size void push_luavalue(const Size& size); bool luavalue_cast(int index, Size& size); // otml nodes void push_luavalue(const OTMLNodePtr& node); bool luavalue_cast(int index, OTMLNodePtr& node); // enum template typename std::enable_if::value, bool>::type luavalue_cast(int index, T& myenum); // LuaObject pointers template typename std::enable_if::value, void>::type push_luavalue(const T& obj); bool luavalue_cast(int index, LuaObjectPtr& obj); template typename std::enable_if::value, bool>::type luavalue_cast(int index, std::shared_ptr& ptr); // std::function template void push_luavalue(const std::function& func); template bool luavalue_cast(int index, std::function& func); template typename std::enable_if::value, bool>::type luavalue_cast(int index, std::function& func); // vector template void push_luavalue(const std::vector& vec); // deque template void push_luavalue(const std::deque& vec); // tuple template void push_luavalue(const std::tuple& tuple); // start definitions #include "luaexception.h" #include "luainterface.h" template typename std::enable_if::value, bool>::type luavalue_cast(int index, T& myenum) { return luavalue_cast(index, (int&)myenum); } template typename std::enable_if::value, void>::type push_luavalue(const T& obj) { if(obj) return g_lua.pushObject(obj); return g_lua.pushNil(); } template typename std::enable_if::value, bool>::type luavalue_cast(int index, std::shared_ptr& ptr) { LuaObjectPtr obj; if(!luavalue_cast(index, obj)) return false; ptr = std::dynamic_pointer_cast(obj); return true; } template void push_luavalue(const std::function& func) { if(func) { LuaCppFunction f = luabinder::bind_fun(func); g_lua.pushCppFunction(f); } else g_lua.pushNil(); } template bool luavalue_cast(int index, std::function& func) { if(g_lua.isFunction(index)) { g_lua.pushValue(index); // weak references are used here, this means that the script must hold another reference // to this function, otherwise it will expire int funcWeakRef = g_lua.weakRef(); func = [=](Args... args) { // note that we must catch exceptions, because this lambda can be called from anywhere // and most of them won't catch exceptions (e.g. dispatcher) g_lua.getWeakRef(funcWeakRef); try { if(g_lua.isFunction()) { g_lua.polymorphicPush(args...); assert(g_lua.safeCall(sizeof...(Args)) == 0); } else { throw LuaException("attempt to call an expired lua function from C++," "did you forget to hold a reference for that function?", 0); } } catch(LuaException& e) { logError("lua function callback failed: ", e.what()); } }; return true; } else if(g_lua.isNil(index)) { func = std::function(); return true; } return false; } template typename std::enable_if::value, bool>::type luavalue_cast(int index, std::function& func) { if(g_lua.isFunction(index)) { g_lua.pushValue(index); // weak references are used here, this means that the script must hold another reference // to this function, otherwise it will expire int funcWeakRef = g_lua.weakRef(); func = [=](Args... args) -> Ret { // note that we must catch exceptions, because this lambda can be called from anywhere // and most of them won't catch exceptions (e.g. dispatcher) try { g_lua.getWeakRef(funcWeakRef); if(g_lua.isFunction()) { g_lua.polymorphicPush(args...); if(g_lua.safeCall(sizeof...(Args)) != 1) throw LuaException("a function from lua didn't retrieve the expected number of results", 0); return g_lua.polymorphicPop(); } else { throw LuaException("attempt to call an expired lua function from C++," "did you forget to hold a reference for that function?", 0); } } catch(LuaException& e) { logError("lua function callback failed: ", e.what()); } return Ret(); }; return true; } else if(g_lua.isNil(index)) { func = std::function(); return true; } return false; } template void push_luavalue(const std::vector& vec) { g_lua.newTable(); int i = 1; for(const T& v : vec) { push_luavalue(v); g_lua.rawSeti(i); i++; } } template void push_luavalue(const std::deque& vec) { g_lua.newTable(); int i = 1; for(const T& v : vec) { push_luavalue(v); g_lua.rawSeti(i); i++; } } template struct push_tuple_luavalue { template static void call(const Tuple& tuple) { push_luavalue(std::get(tuple)); g_lua.rawSeti(N); push_tuple_luavalue::call(tuple); } }; template<> struct push_tuple_luavalue<0> { template static void call(const Tuple& tuple) { } }; template void push_luavalue(const std::tuple& tuple) { g_lua.newTable(); push_tuple_luavalue::call(tuple); } #endif