From 480052c058f3a8ebc70f024933ba5deb6baf0b08 Mon Sep 17 00:00:00 2001 From: tycho Date: Tue, 19 May 2015 15:25:18 +0100 Subject: Added LuaState support for all integral types All so added error handling for out of range values --- .gitignore | 1 + src/Bindings/BindingsProcessor.lua | 12 ++++---- src/Bindings/LuaState.cpp | 51 ++++++++++++-------------------- src/Bindings/LuaState.h | 52 ++++++++++++++++++++++++--------- src/Bindings/ManualBindings.cpp | 4 +-- src/Bindings/ManualBindings.h | 2 +- src/Bindings/ManualBindings_Network.cpp | 7 ++--- src/Bindings/ManualBindings_World.cpp | 2 +- src/Bindings/PluginLua.cpp | 10 ------- 9 files changed, 72 insertions(+), 69 deletions(-) diff --git a/.gitignore b/.gitignore index 8dc90910c..97b2e93d5 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ src/MCServer lib/tolua++/tolua src/Bindings/Bindings.* src/Bindings/BindingDependencies.txt +src/Bindings/LuaState_Call.inc MCServer.dir/ src/AllFiles.lst diff --git a/src/Bindings/BindingsProcessor.lua b/src/Bindings/BindingsProcessor.lua index f86be6c6d..fba992082 100644 --- a/src/Bindings/BindingsProcessor.lua +++ b/src/Bindings/BindingsProcessor.lua @@ -101,7 +101,7 @@ local function OutputLuaStateHelpers(a_Package) f:write("void Push(" .. item.name .. " * a_Value);\n") end for _, item in ipairs(types) do - f:write("void GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n") + f:write("bool GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n") end f:write("\n\n\n\n\n") f:close() @@ -125,15 +125,17 @@ local function OutputLuaStateHelpers(a_Package) end end for _, item in ipairs(types) do - f:write("void cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n") + f:write("bool cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n") f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n") - f:write("\t a_ReturnedVal = nullptr;\n") - f:write("\t return;\n\t}\n") + f:write("\t\ta_ReturnedVal = nullptr;\n") + f:write("\t\treturn false;\n\t}\n") f:write("\ttolua_Error err;\n") f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"" .. item.name .. "\", false, &err))\n") f:write("\t{\n") - f:write("\t a_ReturnedVal = *(reinterpret_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n") + f:write("\t\ta_ReturnedVal = *(reinterpret_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n") + f:write("\t\treturn true;\n"); f:write("\t}\n") + f:write("\treturn false;\n") f:write("}\n\n\n\n\n\n") end f:close() diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 08c7e19d7..232432a99 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -701,108 +701,95 @@ void cLuaState::PushUserType(void * a_Object, const char * a_Type) -void cLuaState::GetStackValue(int a_StackPos, AString & a_Value) +bool cLuaState::GetStackValue(int a_StackPos, AString & a_Value) { size_t len = 0; const char * data = lua_tolstring(m_LuaState, a_StackPos, &len); if (data != nullptr) { a_Value.assign(data, len); + return true; } + return false; } -void cLuaState::GetStackValue(int a_StackPos, BLOCKTYPE & a_ReturnedVal) -{ - if (lua_isnumber(m_LuaState, a_StackPos)) - { - a_ReturnedVal = static_cast(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); - } -} - - - - - -void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal) { a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0); + return true; } -void cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result) +bool cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_Result = static_cast(static_cast((tolua_tonumber(m_LuaState, a_StackPos, a_Result)))); + return true; } + return false; } -void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref) +bool cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref) { a_Ref.RefStack(*this, a_StackPos); + return true; } -void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_ReturnedVal = tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal); + return true; } + return false; } -void cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_ReturnedVal = static_cast(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); + return true; } + return false; } -void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal) { if (!lua_isnumber(m_LuaState, a_StackPos)) { - return; + return false; } a_ReturnedVal = static_cast(Clamp( static_cast(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)), static_cast(wSunny), static_cast(wThunderstorm)) ); -} - - - - - -void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal) -{ - if (lua_isnumber(m_LuaState, a_StackPos)) - { - a_ReturnedVal = static_cast(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); - } + return true; } diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 5b4ec3ae4..bbd0294ef 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -187,16 +187,37 @@ public: void Push(cLuaUDPEndpoint * a_UDPEndpoint); // GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged. + // Returns whether value was changed // Enum values are clamped to their allowed range. - void GetStackValue(int a_StackPos, AString & a_Value); - void GetStackValue(int a_StackPos, BLOCKTYPE & a_Value); - void GetStackValue(int a_StackPos, bool & a_Value); - void GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result); - void GetStackValue(int a_StackPos, cRef & a_Ref); - void GetStackValue(int a_StackPos, double & a_Value); - void GetStackValue(int a_StackPos, eWeather & a_Value); - void GetStackValue(int a_StackPos, float & a_ReturnedVal); - void GetStackValue(int a_StackPos, int & a_Value); + bool GetStackValue(int a_StackPos, AString & a_Value); + bool GetStackValue(int a_StackPos, bool & a_Value); + bool GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result); + bool GetStackValue(int a_StackPos, cRef & a_Ref); + bool GetStackValue(int a_StackPos, double & a_Value); + bool GetStackValue(int a_StackPos, eWeather & a_Value); + bool GetStackValue(int a_StackPos, float & a_ReturnedVal); + + // template to catch all of the various c++ integral types without overload conflicts + template + bool GetStackValue(int a_StackPos, T & a_ReturnedVal, typename std::enable_if::value>::type * unused = nullptr) + { + UNUSED(unused); + if (lua_isnumber(m_LuaState, a_StackPos)) + { + lua_Number Val = tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal); + if (Val > std::numeric_limits::max()) + { + return false; + } + if (Val < std::numeric_limits::min()) + { + return false; + } + a_ReturnedVal = static_cast(Val); + return true; + } + return false; + } // Include the auto-generated Push and GetStackValue() functions: #include "LuaState_Declaration.inc" @@ -218,10 +239,13 @@ public: /** Retrieves a list of values from the Lua stack, starting at the specified index. */ template - inline void GetStackValues(int a_StartStackPos, T & a_Ret, Args &&... args) + inline bool GetStackValues(int a_StartStackPos, T & a_Ret, Args &&... args) { - GetStackValue(a_StartStackPos, a_Ret); - GetStackValues(a_StartStackPos + 1, args...); + if (!GetStackValue(a_StartStackPos, a_Ret)) + { + return false; + } + return GetStackValues(a_StartStackPos + 1, args...); } /** Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions */ @@ -349,9 +373,9 @@ protected: /** Variadic template terminator: If there are no more values to get, bail out. This function is not available in the public API, because it's an error to request no values directly; only internal functions can do that. If you get a compile error saying this function is not accessible, check your calling code, you aren't reading any stack values. */ - void GetStackValues(int a_StartingStackPos) + bool GetStackValues(int a_StartingStackPos) { - // Do nothing + return true; } /** Pushes the function of the specified name onto the stack. diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index ff904d74a..bce1891e2 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -158,7 +158,7 @@ static int tolua_UncompressStringZLIB(lua_State * tolua_S) // Get the params: AString ToUncompress; - int UncompressedSize; + size_t UncompressedSize; S.GetStackValues(1, ToUncompress, UncompressedSize); // Compress the string: @@ -1801,7 +1801,7 @@ static int tolua_cMojangAPI_GetUUIDsFromPlayerNames(lua_State * L) // Convert the input table into AStringVector: AStringVector PlayerNames; int NumNames = luaL_getn(L, 2); - PlayerNames.reserve(NumNames); + PlayerNames.reserve(static_cast(NumNames)); for (int i = 1; i <= NumNames; i++) { lua_rawgeti(L, 2, i); diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h index e7a576588..83b960058 100644 --- a/src/Bindings/ManualBindings.h +++ b/src/Bindings/ManualBindings.h @@ -199,7 +199,7 @@ public: // Get parameters: Ty1 * Self = nullptr; - int ItemID; + UInt32 ItemID; cLuaState::cRef FnRef; L.GetStackValues(1, Self, ItemID, FnRef); if (Self == nullptr) diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp index df97d60b3..7d6ff95a7 100644 --- a/src/Bindings/ManualBindings_Network.cpp +++ b/src/Bindings/ManualBindings_Network.cpp @@ -101,13 +101,12 @@ static int tolua_cNetwork_CreateUDPEndpoint(lua_State * L) } // Read the params: - int Port; - S.GetStackValues(2, Port); + UInt16 Port; // Check validity: - if ((Port < 0) || (Port > 65535)) + if (S.GetStackValues(2, Port)) { - LOGWARNING("cNetwork:CreateUDPEndpoint() called with invalid port (%d), failing the request.", Port); + LOGWARNING("cNetwork:CreateUDPEndpoint() called with invalid port, failing the request."); S.Push(false); return 1; } diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp index 3ee5ca498..cda1518d2 100644 --- a/src/Bindings/ManualBindings_World.cpp +++ b/src/Bindings/ManualBindings_World.cpp @@ -50,7 +50,7 @@ static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S) std::array data; for (int i = 0; (i < 2) && L.IsParamNumber(11 + i); i++) { - L.GetStackValue(11 + i, data[i]); + L.GetStackValue(11 + i, data[static_cast(i)]); } World->GetBroadcaster().BroadcastParticleEffect(Name, Vector3f(PosX, PosY, PosZ), Vector3f(OffX, OffY, OffZ), ParticleData, ParticleAmmount, ExcludeClient); diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index a8be26f71..83466ab84 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -629,11 +629,6 @@ bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_Can case esWitherSkullBlue: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; case esWitherBirth: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; case esPlugin: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; - default: - { - ASSERT(!"Unhandled ExplosionSource"); - return false; - } } if (res) { @@ -670,11 +665,6 @@ bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool & case esWitherSkullBlue: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esWitherBirth: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esPlugin: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - default: - { - ASSERT(!"Unhandled ExplosionSource"); - return false; - } } if (res) { -- cgit v1.2.3