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.
|
||||
*
|
||||
* 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 <list>
|
||||
#include <tcb/span.hpp>
|
||||
#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<ValueType, std::string_view>;
|
||||
|
||||
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<const ArgumentInfo*, size_t> argumentInfo() const = 0;
|
||||
virtual tcb::span<const TypeInfo> argumentTypeInfo() const = 0;
|
||||
|
||||
void connect(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.
|
||||
*
|
||||
* 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 <vector>
|
||||
#include <variant>
|
||||
#include <stdexcept>
|
||||
#include <tcb/span.hpp>
|
||||
#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<ValueType> argumentTypes() const = 0;
|
||||
virtual ValueType resultType() const = 0;
|
||||
virtual tcb::span<const TypeInfo> argumentTypeInfo() const = 0;
|
||||
virtual TypeInfo resultTypeInfo() const = 0;
|
||||
virtual Result call(const Arguments& args) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -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<class T, class... Tn>
|
||||
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));
|
||||
else
|
||||
args.emplace_back(value);
|
||||
@ -43,18 +43,7 @@ class Event : public AbstractEvent
|
||||
addArguments(args, others...);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
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>()...}};
|
||||
//static constexpr std::array<ArgumentInfo, sizeof...(Args)> s_argumentInfo = {{getArgumentInfo<Args>()...}};
|
||||
|
||||
protected:
|
||||
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.
|
||||
*
|
||||
* 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 T>
|
||||
class Method;
|
||||
|
||||
/*
|
||||
template<class... A>
|
||||
struct args
|
||||
{
|
||||
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>
|
||||
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>
|
||||
class Method<R(A...)> : public AbstractMethod
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
std::function<R(A...)> m_function;
|
||||
|
||||
@ -113,34 +111,20 @@ class Method<R(A...)> : public AbstractMethod
|
||||
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 {};
|
||||
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));
|
||||
return getTypeInfo<R>();
|
||||
}
|
||||
|
||||
Result call(const std::vector<Argument>& args) final
|
||||
{
|
||||
if(args.size() != argumentCount())
|
||||
if(args.size() != sizeof...(A))
|
||||
throw InvalidNumberOfArgumentsError();
|
||||
|
||||
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.
|
||||
*
|
||||
* 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<bool>(arg));
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
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<int64_t>(arg));
|
||||
pushSet(m_L, argumentTypeInfo[i].setName.data(), std::get<int64_t>(arg));
|
||||
break;
|
||||
|
||||
case ValueType::Invalid:
|
||||
|
||||
@ -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<int>(method.argumentCount());
|
||||
const int argc = static_cast<int>(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
|
||||
|
||||
@ -280,7 +280,7 @@ bool Session::processMessage(const Message& message)
|
||||
case ValueType::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())
|
||||
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))
|
||||
{
|
||||
message.write(InterfaceItemType::Method);
|
||||
message.write(method->resultType());
|
||||
message.write(static_cast<uint8_t>(method->argumentCount()));
|
||||
for(auto type : method->argumentTypes())
|
||||
message.write(type);
|
||||
message.write(method->resultTypeInfo().type);
|
||||
message.write(static_cast<uint8_t>(method->argumentTypeInfo().size()));
|
||||
for(const auto& info : method->argumentTypeInfo())
|
||||
message.write(info.type);
|
||||
}
|
||||
|
||||
message.writeBlock(); // attributes
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren