Added new typeinfo for method and event
Dieser Commit ist enthalten in:
Ursprung
6bb930b2f2
Commit
f159668406
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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()};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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
59
server/src/core/typeinfo.hpp
Normale Datei
@ -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
|
||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren