complete ProcedureManager
Signed-off-by: szdytom <szdytom@qq.com>
This commit is contained in:
parent
d233589af0
commit
6b0875ee34
@ -3,6 +3,11 @@
|
||||
|
||||
BinaryBuffer::BinaryBuffer() {}
|
||||
|
||||
BinaryBuffer::BinaryBuffer(std::size_t n, const byte *buf) {
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
data.push_back(buf[i]);
|
||||
}
|
||||
|
||||
BinaryBuffer& BinaryBuffer::operator<<(const std::string_view& x) {
|
||||
std::uint32_t len = x.size();
|
||||
*this << len;
|
||||
@ -34,3 +39,9 @@ std::ostream& operator<<(std::ostream &out, const BinaryBuffer &x) {
|
||||
return out;
|
||||
}
|
||||
|
||||
void BinaryBuffer::writeTo(std::FILE *out) const {
|
||||
auto sz = size();
|
||||
for (std::size_t i = 0; i < sz; ++i)
|
||||
fputc(data[i], out);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ static_assert(IsTupleLike<std::tuple<int, int, int>>);
|
||||
class BinaryBuffer {
|
||||
public:
|
||||
BinaryBuffer();
|
||||
BinaryBuffer(std::size_t n, const byte *buf);
|
||||
|
||||
template <typename T>
|
||||
requires IsBasicType<T>
|
||||
@ -115,6 +116,7 @@ public:
|
||||
|
||||
std::size_t size() const;
|
||||
bool empty() const;
|
||||
void writeTo(std::FILE *out) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream &, const BinaryBuffer &);
|
||||
|
||||
|
24
processor/pc/ProcedureManager.cpp
Normal file
24
processor/pc/ProcedureManager.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "ProcedureManager.h"
|
||||
|
||||
ProcedureManager::ProcedureManager() {}
|
||||
|
||||
void ProcedureManager::handleCall(FILE *in, FILE *out) const {
|
||||
ProcedureCallHeader header;
|
||||
auto ptr = reinterpret_cast<byte*>(&header);
|
||||
std::size_t sz = 0;
|
||||
while (sz < sizeof(header))
|
||||
sz += fread(ptr + sz, 1, sizeof(header) - sz, in);
|
||||
|
||||
auto buf = new byte[header.len];
|
||||
sz = 0;
|
||||
while (sz < header.len)
|
||||
sz += fread(buf + sz, 1, header.len - sz, in);
|
||||
|
||||
BinaryBuffer bb(header.len, buf);
|
||||
delete[] buf;
|
||||
if (procedures.count(header.method)) {
|
||||
auto res = procedures.at(header.method)(bb);
|
||||
res.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +1,65 @@
|
||||
#ifndef OGPC_PMANAGER_H_
|
||||
#define OGPC_PMANAGER_H_
|
||||
|
||||
#include "BinaryBuffer.h"
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
inline namespace {
|
||||
|
||||
template <typename T>
|
||||
struct FuncArgTraits;
|
||||
|
||||
template <typename R, typename T>
|
||||
struct FuncArgTraits<R(T)> {
|
||||
using type = T;
|
||||
template <typename R, typename... T>
|
||||
struct FuncArgTraits<R(*)(T...)> {
|
||||
using type = std::tuple<T...>;
|
||||
};
|
||||
|
||||
template <typename R, typename... T>
|
||||
struct FuncArgTraits<std::function<R(T...)>> {
|
||||
using type = std::tuple<T...>;
|
||||
};
|
||||
|
||||
template <typename Callable>
|
||||
struct FuncArgTraits : FuncArgTraits<decltype(&Callable::operator())> {};
|
||||
|
||||
template <typename ReturnType, typename ClassType, typename... Args>
|
||||
struct FuncArgTraits<ReturnType(ClassType::*)(Args...) const> {
|
||||
using type = std::tuple<Args...>;
|
||||
};
|
||||
|
||||
struct ProcedureCallHeader {
|
||||
uint64_t rd;
|
||||
int32_t method;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
class ProcedureManager {
|
||||
public:
|
||||
ProcedureManager();
|
||||
|
||||
template <typename T>
|
||||
void registerProcedure(const std::string &name, T&& func) {
|
||||
procedures[name] = [&func](BinraryBuffer &b) -> BinaryBuffer {
|
||||
using Arg = typename FuncArgTraits<T::operator()>::type;
|
||||
void registerProcedure(const std::uint32_t &id, T&& func) {
|
||||
procedures[id] = [&func](BinaryBuffer &b) -> BinaryBuffer {
|
||||
using Arg = typename FuncArgTraits<typename std::decay<T>::type>::type;
|
||||
Arg x;
|
||||
b >> x;
|
||||
auto y = func(std::move(x));
|
||||
auto y = std::apply(func, std::move(x));
|
||||
BinaryBuffer res;
|
||||
res << y;
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
void handleCall(FILE *in, FILE *out) const;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::function<BinaryBuffer(BinaryBuffer&)>> procedures;
|
||||
std::map<std::uint32_t, std::function<BinaryBuffer(BinaryBuffer&)>> procedures;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
50
processor/test/cases/pmanager.cpp
Normal file
50
processor/test/cases/pmanager.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "pc/ProcedureManager.h"
|
||||
#include "pc/BinaryBuffer.h"
|
||||
#include "test/u.hpp"
|
||||
#include <tuple>
|
||||
#include <cstdint>
|
||||
|
||||
inline namespace {
|
||||
|
||||
using Void = std::tuple<>;
|
||||
|
||||
AddTestCase _(20, "ProcedureManager", [](TestCase& t) {
|
||||
t.expectEq<int>([] {
|
||||
std::int32_t x = 0;
|
||||
auto f1 = [&x] (std::int32_t d) -> Void {
|
||||
x += d;
|
||||
return {};
|
||||
};
|
||||
|
||||
auto f2 = [&x] (std::int32_t d) -> Void {
|
||||
x -= d;
|
||||
return {};
|
||||
};
|
||||
|
||||
ProcedureManager pm;
|
||||
pm.registerProcedure(1, f1);
|
||||
pm.registerProcedure(2, f2);
|
||||
|
||||
unsigned char ibuf[256] = {
|
||||
0x45, 0x27, 0xd1, 0xf2, 0x93, 0x43, 0xfc, 0xb1,
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00,
|
||||
0x45, 0x27, 0xd1, 0xf2, 0x93, 0x43, 0xfc, 0xb2,
|
||||
0x02, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
unsigned char obuf[256];
|
||||
|
||||
FILE *in = fmemopen(ibuf, 256, "r"),
|
||||
*out = fmemopen(obuf, 256, "w");
|
||||
pm.handleCall(in, out);
|
||||
pm.handleCall(in, out);
|
||||
return x;
|
||||
}, 1);
|
||||
});
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user