PenetrateBase/PenetrateBasic/cmds_basic.h

174 lines
4.4 KiB
C++

#pragma once
#include <functional>
#include <QString>
#include "data_types.h"
#include "validation.h"
namespace Inlet {
template<typename... Types> struct SignatureImpl;
template<> struct SignatureImpl<> {
public:
SignatureImpl() { }
void execute(std::function<void(void)> unit) {
unit();
}
void result() const { }
void saveTo(int index, datas::IDataObject& object) { }
void loadFrom(int index, datas::IDataObject& object) { }
};
template<typename Ret> struct SignatureImpl<Ret> {
private:
Ret _result;
public:
SignatureImpl() : _result(Ret()) { }
Ret execute(std::function<Ret(void)> unit) {
_result = unit();
return _result;
}
Ret result() const {
return _result;
}
void saveTo(int index, datas::IDataObject& object) {
datas::dataSet<Ret>(object, u8"RetValue", _result);
}
void loadFrom(int index, datas::IDataObject& object) {
_result = datas::dataGet<Ret>(object, u8"RetValue");
}
};
template<typename Ret, typename First, typename... Args>
struct SignatureImpl<Ret, First, Args...> : public SignatureImpl<Ret, Args...> {
private:
First _args_value;
public:
SignatureImpl() : SignatureImpl<Ret, Args...>(), _args_value(First()) { }
SignatureImpl(First a0, Args... args) :SignatureImpl<Ret, Args...>(args...), _args_value(a0) { }
First getArgs0() {
return _args_value;
}
Ret execute(std::function<Ret(First, Args...)> unit) {
auto unit_wrap = [&](Args... args) {
return unit(_args_value, args...);
};
return SignatureImpl<Ret, Args...>::execute(unit_wrap);
}
void saveTo(int index, datas::IDataObject& object) {
datas::dataSet<First>(object, QString(u8"Args_%1").arg(index), _args_value);
SignatureImpl<Ret, Args...>::saveTo(index + 1, object);
}
void loadFrom(int index, datas::IDataObject& object) {
_args_value = datas::dataGet<First>(object, QString(u8"Args_%1").arg(index));
SignatureImpl<Ret, Args...>::loadFrom(index + 1, object);
}
};
class IRunbase {
public:
virtual ~IRunbase() = default;
virtual quint64 address() const = 0;
virtual void run() = 0;
virtual void saveTo(datas::IDataObject& object) = 0;
virtual void loadFrom(datas::IDataObject& object) = 0;
};
template<typename Ret, typename... Args> using Callable = Ret(*)(Args...);
template<void* addr, typename Ret, typename... Args> struct CmdsImpl : public IRunbase {
private:
Callable<Ret, Args...> _func = (Callable<Ret, Args...>)addr;
SignatureImpl<Ret, Args...> _args_value;
static CmdsImpl<addr, Ret, Args...>* _global_inst;
public:
CmdsImpl() : _args_value() { }
CmdsImpl(Args... args) :_args_value(args...) { }
static CmdsImpl<addr, Ret, Args...>* global() {
if (!_global_inst) {
_global_inst = new CmdsImpl<addr, Ret, Args...>();
}
return _global_inst;
}
Ret execute(Args... args) {
_args_value = SignatureImpl<Ret, Args...>(args...);
return _args_value.execute(_func);
}
Ret result() const {
return _args_value.result();
}
// IRunbase
quint64 address() const {
return (quint64) addr;
}
void run() {
_args_value.execute(_func);
}
virtual void saveTo(datas::IDataObject& object) {
_args_value.saveTo(0, object);
}
virtual void loadFrom(datas::IDataObject& object) {
_args_value.loadFrom(0, object);
}
};
template<void* addr, typename Ret, typename... Args> CmdsImpl<addr, Ret, Args...>* CmdsImpl<addr, Ret, Args...>::_global_inst = nullptr;
template<void* addr, typename Ret, typename... Args> struct EventsImpl : public IRunbase {
private:
Callable<Ret, Args...> _func = (Callable<Ret, Args...>)addr;
SignatureImpl<Ret, Args...> _args_value;
static EventsImpl<addr, Ret, Args...>* _global_inst;
public:
EventsImpl() : _args_value() { }
EventsImpl(Args... args) : _args_value(args...) { }
static EventsImpl<addr, Ret, Args...>* global() {
if (!_global_inst) {
_global_inst = new EventsImpl<addr, Ret, Args...>();
}
return _global_inst;
}
void execute(Args... args) {
_args_value = SignatureImpl<Ret, Args...>(args...);
}
// IRunbase
quint64 address() const {
return (quint64) addr;
}
void run() {
_args_value.execute(_func);
}
virtual void saveTo(datas::IDataObject& object) {
_args_value.saveTo(0, object);
}
virtual void loadFrom(datas::IDataObject& object) {
_args_value.loadFrom(0, object);
}
};
template<void* addr, typename Ret, typename... Args> EventsImpl<addr, Ret, Args...>* EventsImpl<addr, Ret, Args...>::_global_inst = nullptr;
}