Added new typeinfo for method and event

Dieser Commit ist enthalten in:
Reinder Feenstra 2022-03-22 23:39:59 +01:00
Ursprung 6bb930b2f2
Commit f159668406
8 geänderte Dateien mit 100 neuen und 64 gelöschten Zeilen

Datei anzeigen

@ -3,7 +3,7 @@
* *
* This file is part of the traintastic source code. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -25,8 +25,10 @@
#include "interfaceitem.hpp" #include "interfaceitem.hpp"
#include <list> #include <list>
#include <tcb/span.hpp>
#include "eventflags.hpp" #include "eventflags.hpp"
#include "argument.hpp" #include "argument.hpp"
#include "typeinfo.hpp"
class AbstractEventHandler; class AbstractEventHandler;
@ -40,8 +42,6 @@ class AbstractEvent : public InterfaceItem
void fire(const Arguments& args); void fire(const Arguments& args);
public: public:
using ArgumentInfo = std::pair<ValueType, std::string_view>;
AbstractEvent(Object& object, std::string_view name, EventFlags m_flags); AbstractEvent(Object& object, std::string_view name, EventFlags m_flags);
inline bool isScriptable() const { return (m_flags & EventFlags::Scriptable) == EventFlags::Scriptable; } 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; } inline EventFlags flags() const { return m_flags; }
/// @todo C++20 -> std::span ?? virtual tcb::span<const TypeInfo> argumentTypeInfo() const = 0;
virtual std::pair<const ArgumentInfo*, size_t> argumentInfo() const = 0;
void connect(std::shared_ptr<AbstractEventHandler> handler); void connect(std::shared_ptr<AbstractEventHandler> handler);
bool disconnect(const std::shared_ptr<AbstractEventHandler>& handler); bool disconnect(const std::shared_ptr<AbstractEventHandler>& handler);

Datei anzeigen

@ -3,7 +3,7 @@
* *
* This file is part of the traintastic source code. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -28,7 +28,9 @@
#include <vector> #include <vector>
#include <variant> #include <variant>
#include <stdexcept> #include <stdexcept>
#include <tcb/span.hpp>
#include "argument.hpp" #include "argument.hpp"
#include "typeinfo.hpp"
class AbstractMethod : public InterfaceItem class AbstractMethod : public InterfaceItem
{ {
@ -111,9 +113,8 @@ class AbstractMethod : public InterfaceItem
inline MethodFlags flags() const { return m_flags; } inline MethodFlags flags() const { return m_flags; }
virtual std::size_t argumentCount() const = 0; virtual tcb::span<const TypeInfo> argumentTypeInfo() const = 0;
virtual std::vector<ValueType> argumentTypes() const = 0; virtual TypeInfo resultTypeInfo() const = 0;
virtual ValueType resultType() const = 0;
virtual Result call(const Arguments& args) = 0; virtual Result call(const Arguments& args) = 0;
}; };

Datei anzeigen

@ -3,7 +3,7 @@
* *
* This file is part of the traintastic source code. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -34,7 +34,7 @@ class Event : public AbstractEvent
template<class T, class... Tn> template<class T, class... Tn>
inline void addArguments(Arguments& args, T value, Tn... others) inline void addArguments(Arguments& args, T value, Tn... others)
{ {
if constexpr(value_type_v<T> == ValueType::Enum || value_type_v<T> == ValueType::Set) if constexpr(value_type_v<T> == ValueType::Enum || value_type_v<T> == ValueType::Set || value_type_v<T> == ValueType::Integer)
args.emplace_back(static_cast<int64_t>(value)); args.emplace_back(static_cast<int64_t>(value));
else else
args.emplace_back(value); args.emplace_back(value);
@ -43,18 +43,7 @@ class Event : public AbstractEvent
addArguments(args, others...); addArguments(args, others...);
} }
template<class T> //static constexpr std::array<ArgumentInfo, sizeof...(Args)> s_argumentInfo = {{getArgumentInfo<Args>()...}};
static constexpr std::pair<ValueType, std::string_view> getArgumentInfo()
{
if constexpr(is_set_v<T>)
return {ValueType::Set, set_name_v<T>};
else if constexpr(std::is_enum_v<T>)
return {ValueType::Enum, EnumName<T>::value};
else
return {value_type_v<T>, {}};
}
static constexpr std::array<ArgumentInfo, sizeof...(Args)> s_argumentInfo = {{getArgumentInfo<Args>()...}};
protected: protected:
void fire(Args... args) void fire(Args... args)
@ -74,9 +63,9 @@ class Event : public AbstractEvent
{ {
} }
std::pair<const ArgumentInfo*, size_t> argumentInfo() const final tcb::span<const TypeInfo> argumentTypeInfo() const final
{ {
return {s_argumentInfo.data(), s_argumentInfo.size()}; return {typeInfoArray<Args...>};//.data(), typeInfoArray<Args...>.size()};
} }
}; };

Datei anzeigen

@ -3,7 +3,7 @@
* *
* This file is part of the traintastic source code. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -32,14 +32,14 @@
template<class T> template<class T>
class Method; class Method;
/*
template<class... A> template<class... A>
struct args struct args
{ {
static constexpr std::size_t count = sizeof...(A); static constexpr std::size_t count = sizeof...(A);
static constexpr std::array<ValueType, count> types = {{value_type_v<A>...}}; static constexpr std::array<ValueType, count> types = {{value_type_v<std::remove_const_t<std::remove_reference_t<A>>>...}};
}; };
*/
template<std::size_t N, class... A> template<std::size_t N, class... A>
using getArgumentType = typename std::tuple_element<N, std::tuple<A...>>::type; using getArgumentType = typename std::tuple_element<N, std::tuple<A...>>::type;
@ -90,8 +90,6 @@ inline AbstractMethod::Result toResult(const T& value)
template<class R, class... A> template<class R, class... A>
class Method<R(A...)> : public AbstractMethod class Method<R(A...)> : public AbstractMethod
{ {
private:
protected: protected:
std::function<R(A...)> m_function; std::function<R(A...)> m_function;
@ -113,34 +111,20 @@ class Method<R(A...)> : public AbstractMethod
return m_function(args...); return m_function(args...);
} }
std::size_t argumentCount() const final tcb::span<const TypeInfo> argumentTypeInfo() const final
{ {
return sizeof...(A); //return {typeInfoArray<A...>.data(), typeInfoArray<A...>.size()};
return {typeInfoArray<A...>};
} }
std::vector<ValueType> argumentTypes() const final TypeInfo resultTypeInfo() const final
{ {
if constexpr(sizeof...(A) == 0) return getTypeInfo<R>();
return {};
else
return std::vector<ValueType>(args<A...>::types.begin(), args<A...>::types.end());
}
ValueType resultType() const final
{
if constexpr(std::is_same_v<R, void>)
return ValueType::Invalid;
else if constexpr(value_type_v<R> != ValueType::Invalid)
return value_type_v<R>;
else if constexpr(is_shared_ptr_v<R> && std::is_base_of_v<Object, typename R::element_type>)
return ValueType::Object;
else
static_assert(sizeof(R) != sizeof(R));
} }
Result call(const std::vector<Argument>& args) final Result call(const std::vector<Argument>& args) final
{ {
if(args.size() != argumentCount()) if(args.size() != sizeof...(A))
throw InvalidNumberOfArgumentsError(); throw InvalidNumberOfArgumentsError();
if constexpr(std::is_same_v<R, void>) if constexpr(std::is_same_v<R, void>)

59
server/src/core/typeinfo.hpp Normale Datei
Datei anzeigen

@ -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 <array>
#include <string_view>
#include <traintastic/enum/valuetype.hpp>
#include <traintastic/set/set.hpp>
struct TypeInfo
{
ValueType type;
std::string_view enumName;
std::string_view setName;
};
template<class T>
static constexpr TypeInfo getTypeInfo()
{
using A = std::remove_const_t<std::remove_reference_t<T>>;
if constexpr(value_type_v<A> == ValueType::Set)
return {ValueType::Set, {}, set_name_v<A>};
else if constexpr(value_type_v<A> == ValueType::Enum)
return {ValueType::Enum, EnumName<A>::value, {}};
else
return {value_type_v<A>, {}, {}};
}
template<class... A>
struct TypeInfoArray
{
static constexpr std::array<TypeInfo, sizeof...(A)> value = {{getTypeInfo<A>()...}};
};
template<class... A>
inline constexpr auto typeInfoArray = TypeInfoArray<A...>::value;
#endif

Datei anzeigen

@ -3,7 +3,7 @@
* *
* This file is part of the traintastic source code. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -55,8 +55,11 @@ EventHandler::~EventHandler()
void EventHandler::execute(const Arguments& args) void EventHandler::execute(const Arguments& args)
{ {
const auto argumentInfo = m_event.argumentInfo(); const auto argumentTypeInfo = m_event.argumentTypeInfo();
assert(args.size() == argumentInfo.second); assert(args.size() == argumentTypeInfo.size());
if(args.size() != argumentTypeInfo.size())
return;
lua_rawgeti(m_L, LUA_REGISTRYINDEX, m_function); 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++) for(size_t i = 0; i < nargs; i++)
{ {
const auto& arg = args[i]; const auto& arg = args[i];
switch(argumentInfo.first[i].first) switch(argumentTypeInfo[i].type)
{ {
case ValueType::Boolean: case ValueType::Boolean:
push(m_L, std::get<bool>(arg)); push(m_L, std::get<bool>(arg));
break; break;
case ValueType::Enum: case ValueType::Enum:
pushEnum(m_L, argumentInfo.first[i].second.data(), std::get<int64_t>(arg)); pushEnum(m_L, argumentTypeInfo[i].enumName.data(), std::get<int64_t>(arg));
break; break;
case ValueType::Integer: case ValueType::Integer:
@ -91,7 +94,7 @@ void EventHandler::execute(const Arguments& args)
break; break;
case ValueType::Set: case ValueType::Set:
pushSet(m_L, argumentInfo.first[i].second.data(), std::get<int64_t>(arg)); pushSet(m_L, argumentTypeInfo[i].setName.data(), std::get<int64_t>(arg));
break; break;
case ValueType::Invalid: case ValueType::Invalid:

Datei anzeigen

@ -86,7 +86,7 @@ int Method::__gc(lua_State* L)
int Method::__call(lua_State* L) int Method::__call(lua_State* L)
{ {
AbstractMethod& method = check(L, 1); AbstractMethod& method = check(L, 1);
const int argc = static_cast<int>(method.argumentCount()); const int argc = static_cast<int>(method.argumentTypeInfo().size());
if(lua_gettop(L) - 1 != argc) if(lua_gettop(L) - 1 != argc)
errorExpectedNArgumentsGotN(L, argc, lua_gettop(L) - 1); errorExpectedNArgumentsGotN(L, argc, lua_gettop(L) - 1);
@ -101,7 +101,8 @@ int Method::__call(lua_State* L)
{ {
AbstractMethod::Result result = method.call(args); AbstractMethod::Result result = method.call(args);
switch(method.resultType()) const auto& typeInfo = method.resultTypeInfo();
switch(typeInfo.type)
{ {
case ValueType::Invalid: case ValueType::Invalid:
return 0; // no return value return 0; // no return value

Datei anzeigen

@ -280,7 +280,7 @@ bool Session::processMessage(const Message& message)
case ValueType::String: case ValueType::String:
{ {
std::string arg = message.read<std::string>(); std::string arg = message.read<std::string>();
if(i < method->argumentCount() && method->argumentTypes()[i] == ValueType::Object) if(i < method->argumentTypeInfo().size() && method->argumentTypeInfo()[i].type == ValueType::Object)
{ {
if(arg.empty()) if(arg.empty())
args.push_back(ObjectPtr()); args.push_back(ObjectPtr());
@ -671,10 +671,10 @@ void Session::writeObject(Message& message, const ObjectPtr& object)
else if(const AbstractMethod* method = dynamic_cast<const AbstractMethod*>(&item)) else if(const AbstractMethod* method = dynamic_cast<const AbstractMethod*>(&item))
{ {
message.write(InterfaceItemType::Method); message.write(InterfaceItemType::Method);
message.write(method->resultType()); message.write(method->resultTypeInfo().type);
message.write(static_cast<uint8_t>(method->argumentCount())); message.write(static_cast<uint8_t>(method->argumentTypeInfo().size()));
for(auto type : method->argumentTypes()) for(const auto& info : method->argumentTypeInfo())
message.write(type); message.write(info.type);
} }
message.writeBlock(); // attributes message.writeBlock(); // attributes