diff --git a/processor/pc/BinaryBuffer.cpp b/processor/pc/BinaryBuffer.cpp index c2cbdca..cf08968 100644 --- a/processor/pc/BinaryBuffer.cpp +++ b/processor/pc/BinaryBuffer.cpp @@ -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); +} + diff --git a/processor/pc/BinaryBuffer.h b/processor/pc/BinaryBuffer.h index a3304f3..12e4f95 100644 --- a/processor/pc/BinaryBuffer.h +++ b/processor/pc/BinaryBuffer.h @@ -35,6 +35,7 @@ static_assert(IsTupleLike>); class BinaryBuffer { public: BinaryBuffer(); + BinaryBuffer(std::size_t n, const byte *buf); template requires IsBasicType @@ -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 &); diff --git a/processor/pc/ProcedureManager.cpp b/processor/pc/ProcedureManager.cpp new file mode 100644 index 0000000..e48456f --- /dev/null +++ b/processor/pc/ProcedureManager.cpp @@ -0,0 +1,24 @@ +#include "ProcedureManager.h" + +ProcedureManager::ProcedureManager() {} + +void ProcedureManager::handleCall(FILE *in, FILE *out) const { + ProcedureCallHeader header; + auto ptr = reinterpret_cast(&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); + } +} + diff --git a/processor/pc/ProcedureManager.h b/processor/pc/ProcedureManager.h index f706714..db87424 100644 --- a/processor/pc/ProcedureManager.h +++ b/processor/pc/ProcedureManager.h @@ -1,41 +1,65 @@ #ifndef OGPC_PMANAGER_H_ #define OGPC_PMANAGER_H_ +#include "BinaryBuffer.h" +#include +#include +#include +#include +#include + inline namespace { template struct FuncArgTraits; -template -struct FuncArgTraits { - using type = T; +template +struct FuncArgTraits { + using type = std::tuple; +}; + +template +struct FuncArgTraits> { + using type = std::tuple; +}; + +template +struct FuncArgTraits : FuncArgTraits {}; + +template +struct FuncArgTraits { + using type = std::tuple; +}; + +struct ProcedureCallHeader { + uint64_t rd; + int32_t method; + uint32_t len; }; } -#include -#include -#include - class ProcedureManager { public: ProcedureManager(); template - void registerProcedure(const std::string &name, T&& func) { - procedures[name] = [&func](BinraryBuffer &b) -> BinaryBuffer { - using Arg = typename FuncArgTraits::type; + void registerProcedure(const std::uint32_t &id, T&& func) { + procedures[id] = [&func](BinaryBuffer &b) -> BinaryBuffer { + using Arg = typename FuncArgTraits::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> procedures; + std::map> procedures; }; #endif diff --git a/processor/test/cases/pmanager.cpp b/processor/test/cases/pmanager.cpp new file mode 100644 index 0000000..d1afebc --- /dev/null +++ b/processor/test/cases/pmanager.cpp @@ -0,0 +1,50 @@ +#include "pc/ProcedureManager.h" +#include "pc/BinaryBuffer.h" +#include "test/u.hpp" +#include +#include + +inline namespace { + +using Void = std::tuple<>; + +AddTestCase _(20, "ProcedureManager", [](TestCase& t) { + t.expectEq([] { + 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); +}); + +} +