/* * Copyright (c) 2010-2013 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 template int push_internal_luavalue(T v); // bool int push_luavalue(bool b); bool luavalue_cast(int index, bool& b); // int int push_luavalue(int i); bool luavalue_cast(int index, int& i); // double int push_luavalue(double d); bool luavalue_cast(int index, double& d); // float inline int push_luavalue(float f) { push_luavalue((double)f); return 1; } inline bool luavalue_cast(int index, float& f) { double d; bool r = luavalue_cast(index, d); f = d; return r; } // int8 inline int push_luavalue(int8 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, int8& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint8 inline int push_luavalue(uint8 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, uint8& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // int16 inline int push_luavalue(int16 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, int16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint16 inline int push_luavalue(uint16 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, uint16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint32 inline int push_luavalue(uint32 v) { push_luavalue((double)v); return 1; } inline bool luavalue_cast(int index, uint32& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // int64 inline int push_luavalue(int64 v) { push_luavalue((double)v); return 1; } inline bool luavalue_cast(int index, int64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // uint64 inline int push_luavalue(uint64 v) { push_luavalue((double)v); return 1; } inline bool luavalue_cast(int index, uint64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // string int push_luavalue(const char* cstr); int push_luavalue(const std::string& str); bool luavalue_cast(int index, std::string& str); // lua cpp function int push_luavalue(const LuaCppFunction& func); // color int push_luavalue(const Color& color); bool luavalue_cast(int index, Color& color); // rect int push_luavalue(const Rect& rect); bool luavalue_cast(int index, Rect& rect); // point int push_luavalue(const Point& point); bool luavalue_cast(int index, Point& point); // size int push_luavalue(const Size& size); bool luavalue_cast(int index, Size& size); // otml nodes int push_luavalue(const OTMLNodePtr& node); bool luavalue_cast(int index, OTMLNodePtr& node); // enum template typename std::enable_if::value, int>::type push_luavalue(T e) { return push_luavalue((int)e); } template typename std::enable_if::value, bool>::type luavalue_cast(int index, T& myenum); // LuaObject pointers template typename std::enable_if::value, int>::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, stdext::shared_object_ptr& ptr); // std::function template int 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); // list template int push_luavalue(const std::list& list); template bool luavalue_cast(int index, std::list& list); // vector template int push_luavalue(const std::vector& vec); template bool luavalue_cast(int index, std::vector& vec); // deque template int push_luavalue(const std::deque& vec); template bool luavalue_cast(int index, std::deque& vec); // map template int push_luavalue(const std::map& map); template bool luavalue_cast(int index, std::map& map); // tuple template int push_luavalue(const std::tuple& tuple); template int push_internal_luavalue(const std::tuple& tuple); // start definitions #include "luaexception.h" #include "luainterface.h" #include "luaobject.h" template int push_internal_luavalue(T v) { return push_luavalue(v); } template typename std::enable_if::value, bool>::type luavalue_cast(int index, T& myenum) { int i; if(luavalue_cast(index, i)) { myenum = (T)i; return true; } return false; } template typename std::enable_if::value, int>::type push_luavalue(const T& obj) { if(obj) g_lua.pushObject(obj); else g_lua.pushNil(); return 1; } template typename std::enable_if::value, bool>::type luavalue_cast(int index, stdext::shared_object_ptr& ptr) { LuaObjectPtr obj; if(!luavalue_cast(index, obj)) return false; if(obj) ptr = obj->dynamic_self_cast(); else ptr = nullptr; return true; } template int push_luavalue(const std::function& func) { if(func) { LuaCppFunction f = luabinder::bind_fun(func); g_lua.pushCppFunction(f); } else g_lua.pushNil(); return 1; } 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()) { int numArgs = g_lua.polymorphicPush(args...); int rets = g_lua.safeCall(numArgs); g_lua.pop(rets); } 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) { g_logger.error(stdext::format("lua function callback failed: %s", 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()) { int numArgs = g_lua.polymorphicPush(args...); if(g_lua.safeCall(numArgs) != 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) { g_logger.error(stdext::format("lua function callback failed: %s", e.what())); } return Ret(); }; return true; } else if(g_lua.isNil(index)) { func = std::function(); return true; } return false; } template int push_luavalue(const std::list& list) { g_lua.newTable(); int i = 1; for(const T& v : list) { push_internal_luavalue(v); g_lua.rawSeti(i); i++; } return 1; } template bool luavalue_cast(int index, std::list& list) { if(g_lua.isTable(index)) { g_lua.pushNil(); while(g_lua.next(index < 0 ? index-1 : index)) { T value; if(luavalue_cast(-1, value)) list.push_back(value); g_lua.pop(); } return true; } return false; } template int push_luavalue(const std::vector& vec) { g_lua.newTable(); int i = 1; for(const T& v : vec) { push_internal_luavalue(v); g_lua.rawSeti(i); i++; } return 1; } template bool luavalue_cast(int index, std::vector& vec) { if(g_lua.isTable(index)) { g_lua.pushNil(); while(g_lua.next(index < 0 ? index-1 : index)) { T value; if(luavalue_cast(-1, value)) vec.push_back(value); g_lua.pop(); } return true; } return false; } template int push_luavalue(const std::deque& vec) { g_lua.newTable(); int i = 1; for(const T& v : vec) { push_internal_luavalue(v); g_lua.rawSeti(i); i++; } return 1; } template bool luavalue_cast(int index, std::deque& vec) { if(g_lua.isTable(index)) { g_lua.pushNil(); while(g_lua.next(index < 0 ? index-1 : index)) { T value; if(luavalue_cast(-1, value)) vec.push_back(value); g_lua.pop(); } return true; } return false; } template int push_luavalue(const std::map& map) { g_lua.newTable(); for(auto& it : map) { push_internal_luavalue(it.first); push_internal_luavalue(it.second); g_lua.rawSet(); } return 1; } template bool luavalue_cast(int index, std::map& map) { if(g_lua.isTable(index)) { g_lua.pushNil(); while(g_lua.next(index < 0 ? index-1 : index)) { K key; V value; if(luavalue_cast(-1, value) && luavalue_cast(-2, key)) map[key] = value; g_lua.pop(); } return true; } return false; } template struct push_tuple_internal_luavalue { template static void call(const Tuple& tuple) { push_internal_luavalue(std::get(tuple)); g_lua.rawSeti(N); push_tuple_internal_luavalue::call(tuple); } }; template<> struct push_tuple_internal_luavalue<0> { template static void call(const Tuple& tuple) { } }; template int push_internal_luavalue(const std::tuple& tuple) { g_lua.newTable(); push_tuple_internal_luavalue::call(tuple); return 1; } template struct push_tuple_luavalue { template static void call(const Tuple& tuple) { push_internal_luavalue(std::get::value - N>(tuple)); push_tuple_luavalue::call(tuple); } }; template<> struct push_tuple_luavalue<0> { template static void call(const Tuple& tuple) { } }; template int push_luavalue(const std::tuple& tuple) { push_tuple_luavalue::call(tuple); return sizeof...(Args); } #endif