Add procedure call impl
Signed-off-by: szdytom <szdytom@qq.com>
This commit is contained in:
commit
f0445542ce
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
build
|
||||
*.zip
|
||||
|
||||
# Executables
|
||||
*.pch
|
||||
*.out
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
|
||||
# Node.JS
|
||||
package-lock.json
|
||||
node_modules
|
||||
|
||||
# Editor
|
||||
*.swp
|
||||
.vscode
|
||||
|
||||
# Xmake
|
||||
.xmake
|
||||
|
36
processor/pc/BinaryBuffer.cpp
Normal file
36
processor/pc/BinaryBuffer.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "BinaryBuffer.h"
|
||||
#include <cstdint>
|
||||
|
||||
BinaryBuffer::BinaryBuffer() {}
|
||||
|
||||
BinaryBuffer& BinaryBuffer::operator<<(const std::string_view& x) {
|
||||
std::uint32_t len = x.size();
|
||||
*this << len;
|
||||
for (char c : x)
|
||||
*this << c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BinaryBuffer& BinaryBuffer::operator>>(std::string& x) {
|
||||
std::uint32_t len;
|
||||
*this >> len;
|
||||
x.resize(len);
|
||||
for (char& c : x)
|
||||
*this >> c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::size_t BinaryBuffer::size() const {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
bool BinaryBuffer::empty() const {
|
||||
return data.empty();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &out, const BinaryBuffer &x) {
|
||||
for (auto v : x.data)
|
||||
out.put(v);
|
||||
return out;
|
||||
}
|
||||
|
128
processor/pc/BinaryBuffer.h
Normal file
128
processor/pc/BinaryBuffer.h
Normal file
@ -0,0 +1,128 @@
|
||||
#ifndef OG_BINARY_BUFFER_H_
|
||||
#define OG_BINARY_BUFFER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <concepts>
|
||||
#include <string_view>
|
||||
#include <iostream>
|
||||
|
||||
using byte = unsigned char;
|
||||
|
||||
inline namespace {
|
||||
|
||||
template <typename T>
|
||||
concept IsTupleLike = requires(T t) {
|
||||
std::tuple_size<T>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept IsBasicType = std::integral<T> || std::is_enum<T>::value
|
||||
|| std::same_as<T, float> || std::same_as<T, double>;
|
||||
|
||||
template <typename T>
|
||||
concept IsTupleConvertable = requires(T t) {
|
||||
IsTupleLike<decltype(t.asTuple())>;
|
||||
};
|
||||
|
||||
static_assert(IsTupleLike<std::tuple<int, int, int>>);
|
||||
|
||||
}
|
||||
|
||||
class BinaryBuffer {
|
||||
public:
|
||||
BinaryBuffer();
|
||||
|
||||
template <typename T>
|
||||
requires IsBasicType<T>
|
||||
BinaryBuffer& operator>>(T& x) {
|
||||
if (sizeof(T) <= data.size()) {
|
||||
auto ptr = reinterpret_cast<byte*>(&x);
|
||||
for (std::size_t i = 0; i < sizeof(T); ++i) {
|
||||
ptr[i] = data.front();
|
||||
data.pop_front();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires IsBasicType<T>
|
||||
BinaryBuffer& operator<<(const T& x) {
|
||||
auto ptr = reinterpret_cast<const byte*>(&x);
|
||||
for (std::size_t i = 0; i < sizeof(T); ++i) {
|
||||
data.push_back(ptr[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BinaryBuffer& operator<<(const std::vector<T>& x) {
|
||||
uint32_t len = x.size();
|
||||
*this << len;
|
||||
for (const T& element : x)
|
||||
*this << element;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BinaryBuffer& operator>>(std::vector<T>& x) {
|
||||
uint32_t len;
|
||||
*this >> len;
|
||||
x.resize(len);
|
||||
for (std::uint32_t i = 0; i < len; ++i)
|
||||
*this >> x[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires IsTupleLike<T>
|
||||
BinaryBuffer& operator<<(const T& x) {
|
||||
std::apply([this](const auto&... elements) {
|
||||
(*this << ... << elements);
|
||||
}, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires IsTupleLike<T>
|
||||
BinaryBuffer& operator>>(T& x) {
|
||||
std::apply([this](auto&... elements) {
|
||||
(*this >> ... >> elements);
|
||||
}, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires IsTupleConvertable<T>
|
||||
BinaryBuffer& operator<<(const T &x) {
|
||||
*this << x.asTuple();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires IsTupleConvertable<T>
|
||||
BinaryBuffer& operator>>(T &x) {
|
||||
*this >> x.asTuple();
|
||||
return *this;
|
||||
}
|
||||
|
||||
BinaryBuffer& operator<<(const std::string_view &);
|
||||
BinaryBuffer& operator>>(std::string&);
|
||||
|
||||
std::size_t size() const;
|
||||
bool empty() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream &, const BinaryBuffer &);
|
||||
|
||||
private:
|
||||
std::deque<byte> data;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream &, const BinaryBuffer &);
|
||||
|
||||
#endif
|
||||
|
42
processor/pc/ProcedureManager.h
Normal file
42
processor/pc/ProcedureManager.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef OGPC_PMANAGER_H_
|
||||
#define OGPC_PMANAGER_H_
|
||||
|
||||
inline namespace {
|
||||
|
||||
template <typename T>
|
||||
struct FuncArgTraits;
|
||||
|
||||
template <typename R, typename T>
|
||||
struct FuncArgTraits<R(T)> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#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;
|
||||
Arg x;
|
||||
b >> x;
|
||||
auto y = func(std::move(x));
|
||||
BinaryBuffer res;
|
||||
res << y;
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, std::function<BinaryBuffer(BinaryBuffer&)>> procedures;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
53
processor/pc/astuple.h
Normal file
53
processor/pc/astuple.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef OGPC_ASTUPLE_H_
|
||||
#define OGPC_ASTUPLE_H_
|
||||
|
||||
#include "utility/macros.h"
|
||||
|
||||
#define OGPC_T__AS_DECLARETYPE_1(x) decltype(x)&
|
||||
#define OGPC_T__AS_DECLARETYPE_2(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_1(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_3(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_2(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_4(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_3(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_5(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_4(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_6(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_5(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_7(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_6(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_8(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_7(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_9(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_8(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_10(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_9(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_11(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_10(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_12(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_11(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_13(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_12(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_14(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_13(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_15(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_14(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE_16(x, ...) decltype(x)&, OGPC_T__AS_DECLARETYPE_15(__VA_ARGS__)
|
||||
#define OGPC_T__AS_DECLARETYPE(...) OG_M_CONCAT(OGPC_T__AS_DECLARETYPE_, OG_M_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_1(x) const decltype(x)&
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_2(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_1(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_3(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_2(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_4(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_3(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_5(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_4(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_6(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_5(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_7(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_6(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_8(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_7(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_9(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_8(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_10(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_9(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_11(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_10(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_12(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_11(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_13(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_12(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_14(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_13(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_15(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_14(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE_16(x, ...) const decltype(x)&, OGPC_T__AS_CONST_DECLARETYPE_15(__VA_ARGS__)
|
||||
#define OGPC_T__AS_CONST_DECLARETYPE(...) OG_M_CONCAT(OGPC_T__AS_CONST_DECLARETYPE_, OG_M_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#define OGPC_DECLARE_ASTUPLE(...) \
|
||||
std::tuple<OGPC_T__AS_DECLARETYPE(__VA_ARGS__)> asTuple() { \
|
||||
return {__VA_ARGS__}; \
|
||||
}\
|
||||
std::tuple<OGPC_T__AS_CONST_DECLARETYPE(__VA_ARGS__)> asTuple() const { \
|
||||
return {__VA_ARGS__}; \
|
||||
}\
|
||||
|
||||
#endif
|
||||
|
50
processor/pc/pctypes.h
Normal file
50
processor/pc/pctypes.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef OGPC_PCTYPES_H_
|
||||
#define OGPC_PCTYPES_H_
|
||||
|
||||
#include <cctypes>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "astuple.h"
|
||||
|
||||
using Player = std::uint8_t;
|
||||
using Team = std::uint8_t;
|
||||
|
||||
struct uuid {
|
||||
std::uint64_t low, high;
|
||||
|
||||
OGPC_DECLARE_ASTUPLE(low, high)
|
||||
};
|
||||
|
||||
struct ImportTerrainConfig {
|
||||
std::uint8_t w, h;
|
||||
std::string value;
|
||||
|
||||
OGPC_DECLARE_ASTUPLE(w, h, value)
|
||||
};
|
||||
|
||||
struct RandomTerrainConfig {
|
||||
std::uint8_t w, h;
|
||||
std::uint8_t city_dense, mountain_dense, swamp_dense, light_dense;
|
||||
|
||||
OGPC_DECLARE_ASTUPLE(w, h, city_dense, mountain_dense, swamp_dense, light_dense)
|
||||
};
|
||||
|
||||
struct PlayerMove {
|
||||
Player player;
|
||||
std::uint8_t x, y, dir;
|
||||
bool half;
|
||||
|
||||
OGPC_DECLARE_ASTUPLE(player, x, y, dir, half)
|
||||
};
|
||||
|
||||
struct PlayerRanking {
|
||||
Player player;
|
||||
bool is_defeated;
|
||||
std::uint16_t land;
|
||||
std::int32_t unit;
|
||||
|
||||
OGPC_DECLARE_ASTUPLE(player, is_defeated, land, unit)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
32
processor/test/cases/bbuffer.cpp
Normal file
32
processor/test/cases/bbuffer.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "pc/BinaryBuffer.h"
|
||||
#include "pc/astuple.h"
|
||||
#include "test/u.hpp"
|
||||
|
||||
inline namespace {
|
||||
|
||||
struct Point {
|
||||
int x, y, z;
|
||||
OGPC_DECLARE_ASTUPLE(x, y, z);
|
||||
};
|
||||
|
||||
AddTestCase _(10, "BinaryBuffer", [](TestCase& t) {
|
||||
t.expectEq<int>([] {
|
||||
BinaryBuffer bb;
|
||||
int x, y = 10;
|
||||
bb << y;
|
||||
bb >> x;
|
||||
return x;
|
||||
}, 10);
|
||||
|
||||
t.expectEq<std::tuple<int, int, int>>([] {
|
||||
BinaryBuffer bb;
|
||||
Point x{1, 2, 4};
|
||||
std::tuple<int, int, int> y;
|
||||
bb << x;
|
||||
bb >> y;
|
||||
return y;
|
||||
}, {1, 2, 4});
|
||||
});
|
||||
|
||||
}
|
||||
|
19
processor/test/cases/provider.cpp
Normal file
19
processor/test/cases/provider.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "test/u.hpp"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
|
||||
AddTestCase _(0, "tester", [](TestCase& t) {
|
||||
t.expectTrue([] { return true; });
|
||||
t.expectFalse([] { return false; });
|
||||
t.expectTrue([] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
return true;
|
||||
});
|
||||
|
||||
t.expectEq<int>([] { return 42; }, 42);
|
||||
t.expectEq<float>([] { return 10 + 1e-7; }, 10);
|
||||
t.expectEq<double>([] { return 10 + 1e-10; }, 10);
|
||||
});
|
||||
}
|
5
processor/test/main.cpp
Normal file
5
processor/test/main.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "test/u.hpp"
|
||||
|
||||
int main() {
|
||||
return TestSuit::getInstance()->evalTestCases();
|
||||
}
|
205
processor/test/u.hpp
Normal file
205
processor/test/u.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
#ifndef HEADER_TEST_U_HPP
|
||||
#define HEADER_TEST_U_HPP
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
template<typename T>
|
||||
struct TestDefaultEps {};
|
||||
|
||||
template<>
|
||||
struct TestDefaultEps<float> {
|
||||
static constexpr float value = 1e-6;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TestDefaultEps<double> {
|
||||
static constexpr double value = 1e-9;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TestDefaultEps<long double> {
|
||||
static constexpr long double value = 1e-12;
|
||||
};
|
||||
|
||||
class TestCase {
|
||||
public:
|
||||
TestCase(int id, const char* title): ok(0), fail(0), n(0), ended(false), time_used(0) {
|
||||
std::printf("[%02d]Testing %s:\n", id, title);
|
||||
}
|
||||
|
||||
void expectTrue(std::function<bool()> func) noexcept {
|
||||
expectEq<bool>(func, true);
|
||||
}
|
||||
|
||||
void expectFalse(std::function<bool()> func) noexcept {
|
||||
expectEq<bool>(func, false);
|
||||
}
|
||||
|
||||
template<typename T, typename EPS = TestDefaultEps<T>>
|
||||
typename std::enable_if<std::is_floating_point<T>::value>::type expectEq(
|
||||
std::function<T()> func,
|
||||
T&& answer) noexcept {
|
||||
auto res = runTask(func);
|
||||
if (!res.has_value()) {
|
||||
return onError();
|
||||
}
|
||||
|
||||
if (std::abs(res.value() - answer) < EPS::value) {
|
||||
onPass();
|
||||
} else {
|
||||
onFail();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<!std::is_floating_point<T>::value>::type expectEq(
|
||||
std::function<T()> func,
|
||||
T&& answer) noexcept {
|
||||
auto res = runTask(func);
|
||||
if (!res.has_value()) {
|
||||
return onError();
|
||||
}
|
||||
|
||||
if (res.value() == answer) {
|
||||
onPass();
|
||||
} else {
|
||||
onFail();
|
||||
}
|
||||
}
|
||||
|
||||
void end() noexcept {
|
||||
if (ended) {
|
||||
return;
|
||||
}
|
||||
ended = true;
|
||||
|
||||
std::putchar('\n');
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
std::putchar('-');
|
||||
}
|
||||
std::putchar('\n');
|
||||
if (fail) {
|
||||
if (fail == 1) {
|
||||
std::puts("1 test failed.");
|
||||
} else {
|
||||
std::printf("%d tests failed.\n", fail);
|
||||
}
|
||||
} else {
|
||||
if (ok == 1) {
|
||||
std::printf("OK. 1 test passed");
|
||||
} else {
|
||||
std::printf("OK. %d tests passed", ok);
|
||||
}
|
||||
std::printf(" in %lldms.\n", static_cast<long long>(time_used.count()));
|
||||
}
|
||||
}
|
||||
|
||||
bool hasFail() const noexcept {
|
||||
return fail > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void putchar(char c) noexcept {
|
||||
n += 1;
|
||||
if (n > 1 && n % 15 == 1) {
|
||||
std::putchar('\n');
|
||||
}
|
||||
std::putchar(c);
|
||||
}
|
||||
|
||||
void onPass() noexcept {
|
||||
ok += 1;
|
||||
putchar('.');
|
||||
}
|
||||
|
||||
void onFail() noexcept {
|
||||
fail += 1;
|
||||
putchar('F');
|
||||
}
|
||||
|
||||
void onError() noexcept {
|
||||
fail += 1;
|
||||
putchar('E');
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> runTask(std::function<T()> func) noexcept {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
try {
|
||||
T res = func();
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto dt = end - start;
|
||||
time_used += std::chrono::duration_cast<std::chrono::milliseconds>(dt);
|
||||
return {res};
|
||||
} catch (...) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
int ok, fail, n;
|
||||
bool ended;
|
||||
std::chrono::milliseconds time_used;
|
||||
};
|
||||
|
||||
class TestSuit {
|
||||
TestSuit(const TestSuit&) = delete;
|
||||
TestSuit(TestSuit&&) = delete;
|
||||
|
||||
public:
|
||||
static TestSuit* getInstance() {
|
||||
if (!instance) {
|
||||
instance = new TestSuit();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
void addTestCase(int id, const char* title, std::function<void(TestCase&)> f) {
|
||||
tc.emplace_back(id, title, f);
|
||||
}
|
||||
|
||||
int evalTestCases() {
|
||||
std::sort(tc.begin(), tc.end(), [](const auto &x, const auto &y) {
|
||||
return std::get<0>(x) < std::get<0>(y);
|
||||
});
|
||||
|
||||
for (auto [id, title, func] : tc) {
|
||||
TestCase t(id, title);
|
||||
func(t);
|
||||
t.end();
|
||||
std::putchar('\n');
|
||||
if (t.hasFail()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
tc.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
static inline TestSuit* instance = nullptr;
|
||||
TestSuit() {}
|
||||
|
||||
std::vector<std::tuple<int, const char*, std::function<void(TestCase&)>>> tc;
|
||||
};
|
||||
|
||||
class AddTestCase {
|
||||
AddTestCase() = delete;
|
||||
AddTestCase(const AddTestCase&) = delete;
|
||||
AddTestCase(AddTestCase&&) = delete;
|
||||
|
||||
public:
|
||||
AddTestCase(int id, const char* tilte, std::function<void(TestCase&)> func) {
|
||||
TestSuit::getInstance()->addTestCase(id, tilte, func);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // HEADER_TEST_U_HPP
|
||||
|
27
processor/utility/macros.h
Normal file
27
processor/utility/macros.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef OG_MACROS_H_
|
||||
#define OG_MACROS_H_
|
||||
|
||||
#define OG_M_ARG_COUNT__( \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
|
||||
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
|
||||
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
|
||||
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
|
||||
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
|
||||
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
|
||||
_61, _62, _63, N, ...) \
|
||||
N
|
||||
|
||||
#define OG_M_ARG_COUNT(...) OG_M_ARG_COUNT__(__VA_ARGS__ \
|
||||
, 63, 62, 61, 60, \
|
||||
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
|
||||
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
|
||||
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
|
||||
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
|
||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
|
||||
#define OG_M_CONCAT__(a, b) a##b
|
||||
#define OG_M_CONCAT(a, b) OG_M_CONCAT__(a, b)
|
||||
|
||||
#endif
|
||||
|
28
processor/xmake.lua
Normal file
28
processor/xmake.lua
Normal file
@ -0,0 +1,28 @@
|
||||
set_project("opengenerals-processor")
|
||||
set_basename("ogprocessor")
|
||||
set_version("0.1.0")
|
||||
set_languages("c++20")
|
||||
set_targetdir("build")
|
||||
|
||||
add_includedirs(".")
|
||||
|
||||
add_files("pc/*.cpp", "utility/*.cpp")
|
||||
target("main")
|
||||
set_default(true)
|
||||
set_kind("binary")
|
||||
add_files("main.cpp")
|
||||
set_warnings("allextra")
|
||||
|
||||
target("test")
|
||||
set_default(false)
|
||||
set_kind("binary")
|
||||
set_prefixname("test-")
|
||||
|
||||
add_files("test/**/*.cpp")
|
||||
add_files("test/main.cpp")
|
||||
|
||||
set_warnings("allextra")
|
||||
set_optimize("none")
|
||||
set_symbols("debug")
|
||||
add_defines("DEBUG")
|
||||
|
Loading…
x
Reference in New Issue
Block a user