diff options
Diffstat (limited to 'Sluift/Lua')
-rw-r--r-- | Sluift/Lua/Check.cpp | 74 | ||||
-rw-r--r-- | Sluift/Lua/Check.h | 27 | ||||
-rw-r--r-- | Sluift/Lua/Debug.h | 37 | ||||
-rw-r--r-- | Sluift/Lua/Exception.cpp | 6 | ||||
-rw-r--r-- | Sluift/Lua/Exception.h | 23 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistration.cpp | 8 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistration.h | 57 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistry.cpp | 62 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistry.h | 71 | ||||
-rw-r--r-- | Sluift/Lua/LuaUtils.cpp | 221 | ||||
-rw-r--r-- | Sluift/Lua/LuaUtils.h | 66 | ||||
-rw-r--r-- | Sluift/Lua/Value.cpp | 80 | ||||
-rw-r--r-- | Sluift/Lua/Value.h | 92 |
13 files changed, 499 insertions, 325 deletions
diff --git a/Sluift/Lua/Check.cpp b/Sluift/Lua/Check.cpp index cfb726a..b956623 100644 --- a/Sluift/Lua/Check.cpp +++ b/Sluift/Lua/Check.cpp @@ -1,60 +1,68 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/Lua/Check.h> -#include <boost/numeric/conversion/cast.hpp> -#include <iostream> #include <sstream> + +#include <boost/numeric/conversion/cast.hpp> + #include <lua.hpp> +#include <Swiften/Base/ByteArray.h> + #include <Sluift/Lua/Exception.h> using namespace Swift; static std::string getArgTypeError(lua_State* L, int arg, int tag) { - std::ostringstream s; - s << "Arg " << arg << ": expected " << lua_typename(L, tag) << ", got " << luaL_typename(L, arg); - return s.str(); + std::ostringstream s; + s << "Arg " << arg << ": expected " << lua_typename(L, tag) << ", got " << luaL_typename(L, arg); + return s.str(); } void Lua::checkType(lua_State* L, int arg, int type) { - if (lua_type(L, arg) != type) { - throw Lua::Exception(getArgTypeError(L, arg, type)); - } + if (lua_type(L, arg) != type) { + throw Lua::Exception(getArgTypeError(L, arg, type)); + } } int Lua::checkIntNumber(lua_State* L, int arg) { - if (!lua_isnumber(L, arg)) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TNUMBER)); - } - return boost::numeric_cast<int>(lua_tonumber(L, arg)); + if (!lua_isnumber(L, arg)) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TNUMBER)); + } + return boost::numeric_cast<int>(lua_tonumber(L, arg)); } std::string Lua::checkString(lua_State* L, int arg) { - const char *s = lua_tolstring(L, arg, NULL); - if (!s) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); - } - return std::string(s); + const char *s = lua_tolstring(L, arg, nullptr); + if (!s) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); + } + return std::string(s); +} + +ByteArray Lua::checkByteArray(lua_State* L, int arg) { + size_t len; + const char *s = lua_tolstring(L, arg, &len); + if (!s) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); + } + return createByteArray(s, len); } -void* Lua::checkUserDataRaw(lua_State* L, int arg, const char* tableName) { - void* userData = lua_touserdata(L, arg); - if (!userData) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); - } - if (!lua_getmetatable(L, arg)) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); - } - lua_getfield(L, LUA_REGISTRYINDEX, tableName); - if (!lua_rawequal(L, -1, -2)) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); - } - lua_pop(L, 2); - return userData; +void* Lua::checkUserDataRaw(lua_State* L, int arg) { + void* userData = lua_touserdata(L, arg); + if (!userData) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); + } + if (!lua_getmetatable(L, arg)) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); + } + lua_pop(L, 1); + return userData; } diff --git a/Sluift/Lua/Check.h b/Sluift/Lua/Check.h index a569826..61658a6 100644 --- a/Sluift/Lua/Check.h +++ b/Sluift/Lua/Check.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2014 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,19 +8,22 @@ #include <string> +#include <Swiften/Base/ByteArray.h> + struct lua_State; namespace Swift { - namespace Lua { - void checkType(lua_State* L, int arg, int type); - int checkIntNumber(lua_State* L, int arg); - std::string checkString(lua_State* L, int arg); + namespace Lua { + void checkType(lua_State* L, int arg, int type); + int checkIntNumber(lua_State* L, int arg); + std::string checkString(lua_State* L, int arg); + ByteArray checkByteArray(lua_State* L, int arg); - void* checkUserDataRaw(lua_State* L, int arg, const char* tableName); + void* checkUserDataRaw(lua_State* L, int arg); - template<typename T> - T** checkUserData(lua_State* L, int arg, const char* tableName) { - return reinterpret_cast<T**>(checkUserDataRaw(L, arg, tableName)); - } - } + template<typename T> + T** checkUserData(lua_State* L, int arg) { + return reinterpret_cast<T**>(checkUserDataRaw(L, arg)); + } + } } diff --git a/Sluift/Lua/Debug.h b/Sluift/Lua/Debug.h index 8e86b89..5f141e1 100644 --- a/Sluift/Lua/Debug.h +++ b/Sluift/Lua/Debug.h @@ -1,28 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <lua.hpp> #include <iostream> +#include <lua.hpp> + namespace Swift { - namespace Lua { - inline void dumpStack(lua_State *L) { - for (int i = 1; i <= lua_gettop(L); i++) { - int type = lua_type(L, i); - std::cout << i << ": [" << lua_typename(L, type) << "] "; - switch (type) { - case LUA_TSTRING: std::cout << lua_tostring(L, i); break; - case LUA_TNUMBER: std::cout << lua_tonumber(L, i); break; - case LUA_TBOOLEAN: std::cout << lua_toboolean(L, i); break; - default: break; - } - std::cout << std::endl; - } - } - } + namespace Lua { + inline void dumpStack(lua_State *L) { + for (int i = 1; i <= lua_gettop(L); i++) { + int type = lua_type(L, i); + std::cout << i << ": [" << lua_typename(L, type) << "] "; + switch (type) { + case LUA_TSTRING: std::cout << lua_tostring(L, i); break; + case LUA_TNUMBER: std::cout << lua_tonumber(L, i); break; + case LUA_TBOOLEAN: std::cout << lua_toboolean(L, i); break; + default: break; + } + std::cout << std::endl; + } + } + } } diff --git a/Sluift/Lua/Exception.cpp b/Sluift/Lua/Exception.cpp index d80b9fb..a51ad10 100644 --- a/Sluift/Lua/Exception.cpp +++ b/Sluift/Lua/Exception.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -11,5 +11,5 @@ using namespace Swift::Lua; Exception::Exception(const std::string& what) : std::runtime_error(what) { } -Exception::~Exception() throw() { +Exception::~Exception() SWIFTEN_NOEXCEPT { } diff --git a/Sluift/Lua/Exception.h b/Sluift/Lua/Exception.h index 6d00d01..a8ecc5f 100644 --- a/Sluift/Lua/Exception.h +++ b/Sluift/Lua/Exception.h @@ -1,20 +1,23 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <stdexcept> +#include <Swiften/Base/API.h> + namespace Swift { - namespace Lua { - class Exception : public std::runtime_error { - public: - Exception(const std::string& what); - virtual ~Exception() throw(); - }; - } + namespace Lua { + class Exception : public std::runtime_error { + public: + Exception(const std::string& what); + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Exception) + virtual ~Exception() SWIFTEN_NOEXCEPT; + }; + } } diff --git a/Sluift/Lua/FunctionRegistration.cpp b/Sluift/Lua/FunctionRegistration.cpp index b773952..5a6d43e 100644 --- a/Sluift/Lua/FunctionRegistration.cpp +++ b/Sluift/Lua/FunctionRegistration.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,8 +8,8 @@ using namespace Swift::Lua; -FunctionRegistration::FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type) { - FunctionRegistry::getInstance().addFunction(name, function, type); +FunctionRegistration::FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type, const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { + FunctionRegistry::getInstance().addFunction(name, function, type, helpDescription, helpParameters, helpOptions); } FunctionRegistration::~FunctionRegistration() { diff --git a/Sluift/Lua/FunctionRegistration.h b/Sluift/Lua/FunctionRegistration.h index 0df1da1..285c3d0 100644 --- a/Sluift/Lua/FunctionRegistration.h +++ b/Sluift/Lua/FunctionRegistration.h @@ -1,36 +1,45 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <string> + +#include <lua.hpp> + #include <Swiften/Base/API.h> + #include <Sluift/Lua/FunctionRegistry.h> -#include <lua.hpp> -#include <string> namespace Swift { - namespace Lua { - class FunctionRegistration { - public: - FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type); - ~FunctionRegistration(); - }; - } + namespace Lua { + class FunctionRegistration { + public: + FunctionRegistration( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); + ~FunctionRegistration(); + }; + } } + + +#define SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS) \ + static int TYPE##_##NAME(lua_State* L); \ + static int TYPE##_##NAME##_wrapper(lua_State* L); \ + static ::Swift::Lua::FunctionRegistration TYPE##_##NAME##_registration( #NAME , TYPE##_##NAME##_wrapper, #TYPE, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS); \ + static int TYPE##_##NAME##_wrapper(lua_State* L) { \ + try { \ + return TYPE ## _ ## NAME (L); \ + } \ + catch (const std::exception& e) { \ + return luaL_error(L, e.what()); \ + } \ + } \ + static int TYPE ## _ ## NAME (lua_State* L) + #define SLUIFT_LUA_FUNCTION(TYPE, NAME) \ - static int TYPE##_##NAME(lua_State* L); \ - static int TYPE##_##NAME##_wrapper(lua_State* L); \ - static ::Swift::Lua::FunctionRegistration TYPE##_##NAME##_registration( #NAME , TYPE##_##NAME##_wrapper, #TYPE); \ - static int TYPE##_##NAME##_wrapper(lua_State* L) { \ - try { \ - return TYPE ## _ ## NAME (L); \ - } \ - catch (const std::exception& e) { \ - return luaL_error(L, e.what()); \ - } \ - } \ - static int TYPE ## _ ## NAME (lua_State* L) + SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, "", "", "") diff --git a/Sluift/Lua/FunctionRegistry.cpp b/Sluift/Lua/FunctionRegistry.cpp index 99ea096..46c6d18 100644 --- a/Sluift/Lua/FunctionRegistry.cpp +++ b/Sluift/Lua/FunctionRegistry.cpp @@ -1,12 +1,14 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/Lua/FunctionRegistry.h> -#include <Swiften/Base/foreach.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/globals.h> using namespace Swift::Lua; @@ -17,39 +19,39 @@ FunctionRegistry::~FunctionRegistry() { } FunctionRegistry& FunctionRegistry::getInstance() { - static FunctionRegistry instance; - return instance; + static FunctionRegistry instance; + return instance; } -void FunctionRegistry::addFunction(const std::string& name, lua_CFunction function, const std::string& type) { - Registration registration; - registration.name = name; - registration.function = function; - registration.type = type; - registrations.push_back(registration); -} - -std::string FunctionRegistry::getMetaTableNameForType(const std::string& type) { - return "Sluift_" + type; -} - -void FunctionRegistry::registerTypeMetaTable(lua_State* L, const std::string& type) { - luaL_newmetatable(L, getMetaTableNameForType(type).c_str()); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - addFunctionsToTable(L, type); +void FunctionRegistry::addFunction( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { + Registration registration; + registration.name = name; + registration.function = function; + registration.type = type; + registration.helpDescription = helpDescription; + registration.helpParameters = helpParameters; + registration.helpOptions = helpOptions; + registrations.push_back(registration); } void FunctionRegistry::createFunctionTable(lua_State* L, const std::string& type) { - lua_newtable(L); - addFunctionsToTable(L, type); + lua_newtable(L); + addFunctionsToTable(L, type); } void FunctionRegistry::addFunctionsToTable(lua_State* L, const std::string& type) { - foreach(const Registration& registration, registrations) { - if (registration.type == type) { - lua_pushcclosure(L, registration.function, 0); - lua_setfield(L, -2, registration.name.c_str()); - } - } + for (const auto& registration : registrations) { + if (registration.type == type) { + lua_pushcclosure(L, registration.function, 0); + if (!registration.helpDescription.empty()) { + Lua::registerHelp(L, -1, registration.helpDescription, registration.helpParameters, registration.helpOptions); + } + else { + Lua::registerExtraHelp(L, -1, registration.type + "." + registration.name); + } + lua_setfield(L, -2, registration.name.c_str()); + } + } } diff --git a/Sluift/Lua/FunctionRegistry.h b/Sluift/Lua/FunctionRegistry.h index e3ad620..88e15d5 100644 --- a/Sluift/Lua/FunctionRegistry.h +++ b/Sluift/Lua/FunctionRegistry.h @@ -1,46 +1,47 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <lua.hpp> #include <string> #include <vector> -namespace Swift { - namespace Lua { - class FunctionRegistry { - public: - ~FunctionRegistry(); - static FunctionRegistry& getInstance(); - - void addFunction(const std::string& name, lua_CFunction function, const std::string& type); - - static std::string getMetaTableNameForType(const std::string& type); - void registerTypeMetaTable(lua_State* L, const std::string& type); - - void createFunctionTable(lua_State* L, const std::string& type); - - /** - * Adds the functions to the table on the top of the stack. - */ - void addFunctionsToTable(lua_State* L, const std::string& type); - - private: - FunctionRegistry(); - +#include <lua.hpp> - private: - struct Registration { - std::string name; - lua_CFunction function; - std::string type; - }; - std::vector<Registration> registrations; - }; - } +namespace Swift { + namespace Lua { + class FunctionRegistry { + public: + ~FunctionRegistry(); + static FunctionRegistry& getInstance(); + + void addFunction(const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); + + void createFunctionTable(lua_State* L, const std::string& type); + + /** + * Adds the functions to the table on the top of the stack. + */ + void addFunctionsToTable(lua_State* L, const std::string& type); + + private: + FunctionRegistry(); + + + private: + struct Registration { + std::string name; + lua_CFunction function; + std::string type; + std::string helpDescription; + std::string helpParameters; + std::string helpOptions; + }; + std::vector<Registration> registrations; + }; + } } diff --git a/Sluift/Lua/LuaUtils.cpp b/Sluift/Lua/LuaUtils.cpp index 7052abe..c677381 100644 --- a/Sluift/Lua/LuaUtils.cpp +++ b/Sluift/Lua/LuaUtils.cpp @@ -1,19 +1,21 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/Lua/LuaUtils.h> -#include <lua.hpp> - -#include <boost/scope_exit.hpp> -#include <Sluift/Lua/Exception.h> -#include <iostream> #include <cassert> #include <sstream> + +#include <boost/algorithm/string/trim.hpp> #include <boost/numeric/conversion/cast.hpp> +#include <boost/scope_exit.hpp> + +#include <lua.hpp> + +#include <Sluift/Lua/Exception.h> #include <Sluift/globals.h> using namespace Swift::Lua; @@ -21,59 +23,178 @@ using namespace Swift::Lua; static const std::string INDENT = " "; void Swift::Lua::registerTableToString(lua_State* L, int index) { - index = Lua::absoluteOffset(L, index); - lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex); - lua_getfield(L, -1, "register_table_tostring"); - lua_pushvalue(L, index); - if (lua_pcall(L, 1, 0, 0) != 0) { - throw Lua::Exception(lua_tostring(L, -1)); - } - lua_pop(L, 1); + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_table_tostring"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerTableEquals(lua_State* L, int index) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_table_equals"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); } void Swift::Lua::registerGetByTypeIndex(lua_State* L, int index) { - index = Lua::absoluteOffset(L, index); - lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex); - lua_getfield(L, -1, "register_get_by_type_index"); - lua_pushvalue(L, index); - if (lua_pcall(L, 1, 0, 0) != 0) { - throw Lua::Exception(lua_tostring(L, -1)); - } - lua_pop(L, 1); + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_get_by_type_index"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); } boost::optional<std::string> Swift::Lua::getStringField(lua_State* L, int index, const std::string& field) { - lua_getfield(L, index, field.c_str()); - // Seems to generate warnings with some versions of CLang that i can't turn off. - // Leaving the more elegant code here, hoping we can re-enable it later (newer boost? c++11?). - // The same applies to the other get*Field functions. - //BOOST_SCOPE_EXIT(&L) { lua_pop(L,1); } BOOST_SCOPE_EXIT_END - //return lua_isstring(L, -1) ? std::string(lua_tostring(L, -1)) : boost::optional<std::string>(); - - boost::optional<std::string> result; - if (lua_isstring(L, -1)) { - result = std::string(lua_tostring(L, -1)); - } - lua_pop(L, 1); - return result; + lua_getfield(L, index, field.c_str()); + // Seems to generate warnings with some versions of CLang that i can't turn off. + // Leaving the more elegant code here, hoping we can re-enable it later (newer boost? c++11?). + // The same applies to the other get*Field functions. + //BOOST_SCOPE_EXIT(&L) { lua_pop(L,1); } BOOST_SCOPE_EXIT_END + //return lua_isstring(L, -1) ? std::string(lua_tostring(L, -1)) : boost::optional<std::string>(); + + boost::optional<std::string> result; + if (lua_isstring(L, -1)) { + result = std::string(lua_tostring(L, -1)); + } + lua_pop(L, 1); + return result; } boost::optional<bool> Swift::Lua::getBooleanField(lua_State* L, int index, const std::string& field) { - lua_getfield(L, index, field.c_str()); - boost::optional<bool> result; - if (lua_isboolean(L, -1)) { - result = lua_toboolean(L, -1); - } - lua_pop(L, 1); - return result; + lua_getfield(L, index, field.c_str()); + boost::optional<bool> result; + if (lua_isboolean(L, -1)) { + result = lua_toboolean(L, -1); + } + lua_pop(L, 1); + return result; } boost::optional<int> Swift::Lua::getIntField(lua_State* L, int index, const std::string& field) { - lua_getfield(L, index, field.c_str()); - boost::optional<int> result; - if (lua_isnumber(L, -1)) { - result = boost::numeric_cast<int>(lua_tonumber(L, -1)); - } - lua_pop(L, 1); - return result; + lua_getfield(L, index, field.c_str()); + boost::optional<int> result; + if (lua_isnumber(L, -1)) { + result = boost::numeric_cast<int>(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + return result; +} + +void Swift::Lua::registerHelp(lua_State* L, int index, const std::string& description, const std::string& parameters, const std::string& options) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_help"); + lua_pushvalue(L, index); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (!parameters.empty()) { + std::istringstream s(parameters); + lua_newtable(L); + int i = 1; + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_createtable(L, 2, 0); + lua_pushstring(L, key.c_str()); + lua_rawseti(L, -2, 1); + lua_pushstring(L, value.c_str()); + lua_rawseti(L, -2, 2); + + lua_rawseti(L, -2, i++); + } + lua_setfield(L, -2, "parameters"); + } + if (!options.empty()) { + std::istringstream s(options); + lua_newtable(L); + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_pushstring(L, value.c_str()); + lua_setfield(L, -2, key.c_str()); + } + lua_setfield(L, -2, "options"); + } + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerClassHelp(lua_State* L, const std::string& name, const std::string& description) { + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_class_help"); + lua_pushstring(L, name.c_str()); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerExtraHelp(lua_State* L, int index, const std::string& name) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "extra_help"); + lua_getfield(L, -1, name.c_str()); + if (!lua_isnil(L, -1)) { + lua_getfield(L, -3, "register_help"); + lua_pushvalue(L, index); + lua_pushvalue(L, -3); + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + } + lua_pop(L, 3); +} + +void Swift::Lua::pushStringArray(lua_State* L, const std::vector<std::string>& strings) { + lua_createtable(L, boost::numeric_cast<int>(strings.size()), 0); + for (size_t i = 0; i < strings.size(); ++i) { + lua_pushstring(L, strings[i].c_str()); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } } diff --git a/Sluift/Lua/LuaUtils.h b/Sluift/Lua/LuaUtils.h index bad307c..b9f5bff 100644 --- a/Sluift/Lua/LuaUtils.h +++ b/Sluift/Lua/LuaUtils.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,25 +8,51 @@ #include <lua.hpp> #include <boost/optional.hpp> +#include <string> +#include <vector> -struct lua_State; +#if LUA_VERSION_NUM < 502 +#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) +#define lua_compare(L,idx1,idx2,LUA_OPEQ) lua_equal(L,(idx1),(idx2)) +#define lua_rawlen(L, i) lua_objlen(L,(i)) +#endif +#if LUA_VERSION_NUM >= 503 +#undef luaL_register +#define luaL_register(L, n, l) \ + lua_getglobal( L, n ); \ + if( lua_isnil( L, -1 ) ) \ + { \ + lua_pop( L, 1 ); \ + lua_newtable( L ); \ + } \ + luaL_setfuncs( L, (l), 0 ); \ + lua_pushvalue( L, -1 ); \ + lua_setglobal( L, n ); +#endif namespace Swift { - namespace Lua { - /** - * Can be used as __tostring metamethod on a table. - */ - int convertTableToString(lua_State* L); - - void registerTableToString(lua_State* L, int index); - void registerGetByTypeIndex(lua_State* L, int index); - - inline int absoluteOffset(lua_State* L, int index) { - return index > 0 ? index : lua_gettop(L) + index + 1; - } - - boost::optional<std::string> getStringField(lua_State* L, int index, const std::string&); - boost::optional<bool> getBooleanField(lua_State* L, int index, const std::string&); - boost::optional<int> getIntField(lua_State* L, int index, const std::string&); - } + namespace Lua { + /** + * Can be used as __tostring metamethod on a table. + */ + int convertTableToString(lua_State* L); + + void registerTableToString(lua_State* L, int index); + void registerTableEquals(lua_State* L, int index); + void registerGetByTypeIndex(lua_State* L, int index); + void registerHelp(lua_State* L, int index, + const std::string& description, const std::string& parameters, const std::string& options); + void registerClassHelp(lua_State* L, const std::string& name, const std::string& description); + void registerExtraHelp(lua_State* L, int index, const std::string& name); + + inline int absoluteOffset(lua_State* L, int index) { + return index > 0 ? index : lua_gettop(L) + index + 1; + } + + boost::optional<std::string> getStringField(lua_State* L, int index, const std::string&); + boost::optional<bool> getBooleanField(lua_State* L, int index, const std::string&); + boost::optional<int> getIntField(lua_State* L, int index, const std::string&); + + void pushStringArray(lua_State* L, const std::vector<std::string>& strings); + } } diff --git a/Sluift/Lua/Value.cpp b/Sluift/Lua/Value.cpp index 4f8078e..96d954c 100644 --- a/Sluift/Lua/Value.cpp +++ b/Sluift/Lua/Value.cpp @@ -1,66 +1,66 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include "Value.h" +#include <Sluift/Lua/Value.h> + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/variant/apply_visitor.hpp> extern "C" { - #include <lualib.h> + #include <lualib.h> } -#include <boost/variant/apply_visitor.hpp> -#include <boost/numeric/conversion/cast.hpp> -#include <Swiften/Base/foreach.h> using namespace Swift; using namespace Swift::Lua; namespace { - struct PushVisitor : public boost::static_visitor<> { - PushVisitor(lua_State* state) : state(state) { - } + struct PushVisitor : public boost::static_visitor<> { + PushVisitor(lua_State* state) : state(state) { + } - void operator()(const Nil&) const { - lua_pushnil(state); - } + void operator()(const Nil&) const { + lua_pushnil(state); + } - void operator()(const bool& b) const { - lua_pushboolean(state, b); - } + void operator()(const bool& b) const { + lua_pushboolean(state, b); + } - void operator()(const int& i) const { - lua_pushnumber(state, i); - } + void operator()(const int& i) const { + lua_pushnumber(state, i); + } - void operator()(const std::string& s) const { - lua_pushstring(state, s.c_str()); - } + void operator()(const std::string& s) const { + lua_pushstring(state, s.c_str()); + } - void operator()(const std::vector<Value>& values) const { - lua_createtable(state, boost::numeric_cast<int>(values.size()), 0); - for(size_t i = 0; i < values.size(); ++i) { - boost::apply_visitor(PushVisitor(state), values[i]); - lua_rawseti(state, -2, boost::numeric_cast<int>(i + 1)); - } - } + void operator()(const std::vector<Value>& values) const { + lua_createtable(state, boost::numeric_cast<int>(values.size()), 0); + for(size_t i = 0; i < values.size(); ++i) { + boost::apply_visitor(PushVisitor(state), values[i]); + lua_rawseti(state, -2, boost::numeric_cast<int>(i + 1)); + } + } - void operator()(const std::map<std::string, boost::shared_ptr<Value> >& table) const { - lua_createtable(state, 0, boost::numeric_cast<int>(table.size())); - for(std::map<std::string, boost::shared_ptr<Value> >::const_iterator i = table.begin(); i != table.end(); ++i) { - boost::apply_visitor(PushVisitor(state), *i->second); - lua_setfield(state, -2, i->first.c_str()); - } - } + void operator()(const std::map<std::string, std::shared_ptr<Value> >& table) const { + lua_createtable(state, 0, boost::numeric_cast<int>(table.size())); + for (const auto& i : table) { + boost::apply_visitor(PushVisitor(state), *i.second); + lua_setfield(state, -2, i.first.c_str()); + } + } - lua_State* state; - }; + lua_State* state; + }; } namespace Swift { namespace Lua { void pushValue(lua_State* state, const Value& value) { - boost::apply_visitor(PushVisitor(state), value); + boost::apply_visitor(PushVisitor(state), value); } }} diff --git a/Sluift/Lua/Value.h b/Sluift/Lua/Value.h index 55aa347..13c4a0c 100644 --- a/Sluift/Lua/Value.h +++ b/Sluift/Lua/Value.h @@ -1,60 +1,60 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> +#include <memory> #include <string> #include <vector> + #include <boost/variant.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> struct lua_State; namespace Swift { - namespace Lua { - struct Nil {}; - - typedef boost::make_recursive_variant< - Nil, - bool, - int, - std::string, - std::vector< boost::recursive_variant_ >, - std::map<std::string, boost::shared_ptr<boost::recursive_variant_> > - >::type Value; - - typedef std::map<std::string, boost::shared_ptr<Value> > Table; - typedef std::vector<Value> Array; - - inline boost::shared_ptr<Value> nilRef() { - return boost::make_shared<Value>(Nil()); - } - - inline boost::shared_ptr<Value> valueRef(const std::string& value) { - return boost::make_shared<Value>(value); - } - - inline boost::shared_ptr<Value> intRef(int value) { - return boost::make_shared<Value>(value); - } - - inline boost::shared_ptr<Value> boolRef(bool value) { - return boost::make_shared<Value>(value); - } - - inline boost::shared_ptr<Value> valueRef(const Table& table) { - return boost::make_shared<Value>(table); - } - - inline boost::shared_ptr<Value> valueRef(const Array& array) { - return boost::make_shared<Value>(array); - } - - void pushValue(lua_State* state, const Value& value); - } + namespace Lua { + struct Nil {}; + + typedef boost::make_recursive_variant< + Nil, + bool, + int, + std::string, + std::vector< boost::recursive_variant_ >, + std::map<std::string, std::shared_ptr<boost::recursive_variant_> > + >::type Value; + + typedef std::map<std::string, std::shared_ptr<Value> > Table; + typedef std::vector<Value> Array; + + inline std::shared_ptr<Value> nilRef() { + return std::make_shared<Value>(Nil()); + } + + inline std::shared_ptr<Value> valueRef(const std::string& value) { + return std::make_shared<Value>(value); + } + + inline std::shared_ptr<Value> intRef(int value) { + return std::make_shared<Value>(value); + } + + inline std::shared_ptr<Value> boolRef(bool value) { + return std::make_shared<Value>(value); + } + + inline std::shared_ptr<Value> valueRef(const Table& table) { + return std::make_shared<Value>(table); + } + + inline std::shared_ptr<Value> valueRef(const Array& array) { + return std::make_shared<Value>(array); + } + + void pushValue(lua_State* state, const Value& value); + } } |