From f159668406543e9ee45b07017fbf471bf407544b Mon Sep 17 00:00:00 2001 From: Reinder Feenstra Date: Tue, 22 Mar 2022 23:39:59 +0100 Subject: [PATCH] Added new typeinfo for method and event --- server/src/core/abstractevent.hpp | 9 ++--- server/src/core/abstractmethod.hpp | 9 +++-- server/src/core/event.hpp | 21 +++-------- server/src/core/method.hpp | 36 +++++------------- server/src/core/typeinfo.hpp | 59 ++++++++++++++++++++++++++++++ server/src/lua/eventhandler.cpp | 15 +++++--- server/src/lua/method.cpp | 5 ++- server/src/network/session.cpp | 10 ++--- 8 files changed, 100 insertions(+), 64 deletions(-) create mode 100644 server/src/core/typeinfo.hpp diff --git a/server/src/core/abstractevent.hpp b/server/src/core/abstractevent.hpp index 453283c7..d75f480c 100644 --- a/server/src/core/abstractevent.hpp +++ b/server/src/core/abstractevent.hpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2021 Reinder Feenstra + * Copyright (C) 2021-2022 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,8 +25,10 @@ #include "interfaceitem.hpp" #include +#include #include "eventflags.hpp" #include "argument.hpp" +#include "typeinfo.hpp" class AbstractEventHandler; @@ -40,8 +42,6 @@ class AbstractEvent : public InterfaceItem void fire(const Arguments& args); public: - using ArgumentInfo = std::pair; - AbstractEvent(Object& object, std::string_view name, EventFlags m_flags); inline bool isScriptable() const { return (m_flags & EventFlags::Scriptable) == EventFlags::Scriptable; } @@ -53,8 +53,7 @@ class AbstractEvent : public InterfaceItem inline EventFlags flags() const { return m_flags; } - /// @todo C++20 -> std::span ?? - virtual std::pair argumentInfo() const = 0; + virtual tcb::span argumentTypeInfo() const = 0; void connect(std::shared_ptr handler); bool disconnect(const std::shared_ptr& handler); diff --git a/server/src/core/abstractmethod.hpp b/server/src/core/abstractmethod.hpp index 63209805..18889924 100644 --- a/server/src/core/abstractmethod.hpp +++ b/server/src/core/abstractmethod.hpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2019-2021 Reinder Feenstra + * Copyright (C) 2019-2022 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,7 +28,9 @@ #include #include #include +#include #include "argument.hpp" +#include "typeinfo.hpp" class AbstractMethod : public InterfaceItem { @@ -111,9 +113,8 @@ class AbstractMethod : public InterfaceItem inline MethodFlags flags() const { return m_flags; } - virtual std::size_t argumentCount() const = 0; - virtual std::vector argumentTypes() const = 0; - virtual ValueType resultType() const = 0; + virtual tcb::span argumentTypeInfo() const = 0; + virtual TypeInfo resultTypeInfo() const = 0; virtual Result call(const Arguments& args) = 0; }; diff --git a/server/src/core/event.hpp b/server/src/core/event.hpp index 2a7f28fc..ce8a4087 100644 --- a/server/src/core/event.hpp +++ b/server/src/core/event.hpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2021 Reinder Feenstra + * Copyright (C) 2021-2022 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,7 +34,7 @@ class Event : public AbstractEvent template inline void addArguments(Arguments& args, T value, Tn... others) { - if constexpr(value_type_v == ValueType::Enum || value_type_v == ValueType::Set) + if constexpr(value_type_v == ValueType::Enum || value_type_v == ValueType::Set || value_type_v == ValueType::Integer) args.emplace_back(static_cast(value)); else args.emplace_back(value); @@ -43,18 +43,7 @@ class Event : public AbstractEvent addArguments(args, others...); } - template - static constexpr std::pair getArgumentInfo() - { - if constexpr(is_set_v) - return {ValueType::Set, set_name_v}; - else if constexpr(std::is_enum_v) - return {ValueType::Enum, EnumName::value}; - else - return {value_type_v, {}}; - } - - static constexpr std::array s_argumentInfo = {{getArgumentInfo()...}}; + //static constexpr std::array s_argumentInfo = {{getArgumentInfo()...}}; protected: void fire(Args... args) @@ -74,9 +63,9 @@ class Event : public AbstractEvent { } - std::pair argumentInfo() const final + tcb::span argumentTypeInfo() const final { - return {s_argumentInfo.data(), s_argumentInfo.size()}; + return {typeInfoArray};//.data(), typeInfoArray.size()}; } }; diff --git a/server/src/core/method.hpp b/server/src/core/method.hpp index 0bc71809..5a1495f4 100644 --- a/server/src/core/method.hpp +++ b/server/src/core/method.hpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2019-2021 Reinder Feenstra + * Copyright (C) 2019-2022 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,14 +32,14 @@ template class Method; - +/* template struct args { static constexpr std::size_t count = sizeof...(A); - static constexpr std::array types = {{value_type_v...}}; + static constexpr std::array types = {{value_type_v>>...}}; }; - +*/ template using getArgumentType = typename std::tuple_element>::type; @@ -90,8 +90,6 @@ inline AbstractMethod::Result toResult(const T& value) template class Method : public AbstractMethod { - private: - protected: std::function m_function; @@ -113,34 +111,20 @@ class Method : public AbstractMethod return m_function(args...); } - std::size_t argumentCount() const final + tcb::span argumentTypeInfo() const final { - return sizeof...(A); + //return {typeInfoArray.data(), typeInfoArray.size()}; + return {typeInfoArray}; } - std::vector argumentTypes() const final + TypeInfo resultTypeInfo() const final { - if constexpr(sizeof...(A) == 0) - return {}; - else - return std::vector(args::types.begin(), args::types.end()); - } - - ValueType resultType() const final - { - if constexpr(std::is_same_v) - return ValueType::Invalid; - else if constexpr(value_type_v != ValueType::Invalid) - return value_type_v; - else if constexpr(is_shared_ptr_v && std::is_base_of_v) - return ValueType::Object; - else - static_assert(sizeof(R) != sizeof(R)); + return getTypeInfo(); } Result call(const std::vector& args) final { - if(args.size() != argumentCount()) + if(args.size() != sizeof...(A)) throw InvalidNumberOfArgumentsError(); if constexpr(std::is_same_v) diff --git a/server/src/core/typeinfo.hpp b/server/src/core/typeinfo.hpp new file mode 100644 index 00000000..8503648f --- /dev/null +++ b/server/src/core/typeinfo.hpp @@ -0,0 +1,59 @@ +/** + * server/src/core/typeinfo.hpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2022 Reinder Feenstra + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TRAINTASTIC_SERVER_CORE_TYPEINFO_HPP +#define TRAINTASTIC_SERVER_CORE_TYPEINFO_HPP + +#include +#include +#include +#include + +struct TypeInfo +{ + ValueType type; + std::string_view enumName; + std::string_view setName; +}; + +template +static constexpr TypeInfo getTypeInfo() +{ + using A = std::remove_const_t>; + if constexpr(value_type_v == ValueType::Set) + return {ValueType::Set, {}, set_name_v}; + else if constexpr(value_type_v == ValueType::Enum) + return {ValueType::Enum, EnumName::value, {}}; + else + return {value_type_v, {}, {}}; +} + +template +struct TypeInfoArray +{ + static constexpr std::array value = {{getTypeInfo()...}}; +}; + +template +inline constexpr auto typeInfoArray = TypeInfoArray::value; + +#endif diff --git a/server/src/lua/eventhandler.cpp b/server/src/lua/eventhandler.cpp index c8a571a9..8ca2d415 100644 --- a/server/src/lua/eventhandler.cpp +++ b/server/src/lua/eventhandler.cpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2021 Reinder Feenstra + * Copyright (C) 2021-2022 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -55,8 +55,11 @@ EventHandler::~EventHandler() void EventHandler::execute(const Arguments& args) { - const auto argumentInfo = m_event.argumentInfo(); - assert(args.size() == argumentInfo.second); + const auto argumentTypeInfo = m_event.argumentTypeInfo(); + assert(args.size() == argumentTypeInfo.size()); + + if(args.size() != argumentTypeInfo.size()) + return; lua_rawgeti(m_L, LUA_REGISTRYINDEX, m_function); @@ -64,14 +67,14 @@ void EventHandler::execute(const Arguments& args) for(size_t i = 0; i < nargs; i++) { const auto& arg = args[i]; - switch(argumentInfo.first[i].first) + switch(argumentTypeInfo[i].type) { case ValueType::Boolean: push(m_L, std::get(arg)); break; case ValueType::Enum: - pushEnum(m_L, argumentInfo.first[i].second.data(), std::get(arg)); + pushEnum(m_L, argumentTypeInfo[i].enumName.data(), std::get(arg)); break; case ValueType::Integer: @@ -91,7 +94,7 @@ void EventHandler::execute(const Arguments& args) break; case ValueType::Set: - pushSet(m_L, argumentInfo.first[i].second.data(), std::get(arg)); + pushSet(m_L, argumentTypeInfo[i].setName.data(), std::get(arg)); break; case ValueType::Invalid: diff --git a/server/src/lua/method.cpp b/server/src/lua/method.cpp index 4960ef57..fcb55ae9 100644 --- a/server/src/lua/method.cpp +++ b/server/src/lua/method.cpp @@ -86,7 +86,7 @@ int Method::__gc(lua_State* L) int Method::__call(lua_State* L) { AbstractMethod& method = check(L, 1); - const int argc = static_cast(method.argumentCount()); + const int argc = static_cast(method.argumentTypeInfo().size()); if(lua_gettop(L) - 1 != argc) errorExpectedNArgumentsGotN(L, argc, lua_gettop(L) - 1); @@ -101,7 +101,8 @@ int Method::__call(lua_State* L) { AbstractMethod::Result result = method.call(args); - switch(method.resultType()) + const auto& typeInfo = method.resultTypeInfo(); + switch(typeInfo.type) { case ValueType::Invalid: return 0; // no return value diff --git a/server/src/network/session.cpp b/server/src/network/session.cpp index be6fcf59..c62955aa 100644 --- a/server/src/network/session.cpp +++ b/server/src/network/session.cpp @@ -280,7 +280,7 @@ bool Session::processMessage(const Message& message) case ValueType::String: { std::string arg = message.read(); - if(i < method->argumentCount() && method->argumentTypes()[i] == ValueType::Object) + if(i < method->argumentTypeInfo().size() && method->argumentTypeInfo()[i].type == ValueType::Object) { if(arg.empty()) args.push_back(ObjectPtr()); @@ -671,10 +671,10 @@ void Session::writeObject(Message& message, const ObjectPtr& object) else if(const AbstractMethod* method = dynamic_cast(&item)) { message.write(InterfaceItemType::Method); - message.write(method->resultType()); - message.write(static_cast(method->argumentCount())); - for(auto type : method->argumentTypes()) - message.write(type); + message.write(method->resultTypeInfo().type); + message.write(static_cast(method->argumentTypeInfo().size())); + for(const auto& info : method->argumentTypeInfo()) + message.write(info.type); } message.writeBlock(); // attributes