#ifndef LUA_ARGS_H #define LUA_ARGS_H #pragma once #include "LuaHeaders.h" #include "LuaException.h" #include "LuaConvert.h" #include namespace luacpp { namespace args { class ArgumentException: public LuaException { public: ArgumentException(const std::string& message = "Argument Error!") noexcept : LuaException(message) { } ~ArgumentException() noexcept override = default; }; class opt {}; extern opt optional; inline int getArgsInternal(lua_State* /*L*/, bool, int, int) { return 0; } template inline int popArgumentValue(lua_State* L, T& target, bool& /*optionalOut*/, int& stackIndexOut) { convert::popValue(L, target, stackIndexOut, false); stackIndexOut = stackIndexOut + 1; return 1; } template<> inline int popArgumentValue(lua_State* /*L*/, opt& /*target*/, bool& optionalOut, int& /*stackIndexOut*/) { optionalOut = true; return 0; } template inline int getArgsInternal(lua_State* L, bool optional_arg, int stackIndex, int numArgs, T& target, Args& ... args) { if (!std::is_same::value) { if (stackIndex > numArgs) { // No more arguments there if (optional_arg) { // Everything is fine, this argument is optional return 0; } else { // No good, no more arguments but no optional throw ArgumentException("Not enough arguments!"); } } } return popArgumentValue(L, target, optional_arg, stackIndex) + getArgsInternal(L, optional_arg, stackIndex, numArgs, args...); } template int getArgs(lua_State* L, T& target, Args& ... args) { return getArgsInternal(L, false, 1, lua_gettop(L), target, args...); } } } #endif