serde refl rebuild
This commit is contained in:
parent
0a5cb27b27
commit
5b5c35a5ef
@ -4,6 +4,7 @@
|
|||||||
#include "json/serde.inl"
|
#include "json/serde.inl"
|
||||||
namespace api {
|
namespace api {
|
||||||
using meta::result;
|
using meta::result;
|
||||||
|
using std::string_view;
|
||||||
enum class SerializeError : char
|
enum class SerializeError : char
|
||||||
{
|
{
|
||||||
EMPTY,
|
EMPTY,
|
||||||
@ -11,11 +12,13 @@ namespace api {
|
|||||||
};
|
};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool JsonDeserialize(string_view text, T* obj) {
|
inline bool JsonDeserialize(string_view text, T* obj) {
|
||||||
|
if (text.empty()) return false;
|
||||||
yyjson_alc alc = JsonAllocatorAdapter();
|
yyjson_alc alc = JsonAllocatorAdapter();
|
||||||
yyjson_doc* doc = yyjson_read_opts((char*)text.data(), text.size(), YYJSON_READ_INSITU, &alc, nullptr);
|
yyjson_doc* doc = yyjson_read_opts((char*)text.data(), text.size(), YYJSON_READ_INSITU, &alc, nullptr);
|
||||||
|
if (!doc) return false;
|
||||||
yyjson_val* root = yyjson_doc_get_root(doc);
|
yyjson_val* root = yyjson_doc_get_root(doc);
|
||||||
if constexpr (has_json_specialization_v<T>) {
|
if constexpr (has_json_specialization_v<T>) {
|
||||||
return JsonSerde<T>::Read(root, obj);
|
return gen::JsonSerde<T>::Read(root, obj);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return JsonArchive::Deserialize(root, obj);
|
return JsonArchive::Deserialize(root, obj);
|
||||||
@ -35,7 +38,7 @@ namespace api {
|
|||||||
inline string_view JsonSerialize(const T& t) {
|
inline string_view JsonSerialize(const T& t) {
|
||||||
yyjson_alc alc = JsonAllocatorAdapter();
|
yyjson_alc alc = JsonAllocatorAdapter();
|
||||||
yyjson_mut_doc* doc = yyjson_mut_doc_new(&alc);
|
yyjson_mut_doc* doc = yyjson_mut_doc_new(&alc);
|
||||||
yyjson_mut_val* root = JsonSerde<T>::Write(doc, Any{t});
|
yyjson_mut_val* root = gen::JsonSerde<T>::Write(doc, &t);
|
||||||
yyjson_mut_doc_set_root(doc, root);
|
yyjson_mut_doc_set_root(doc, root);
|
||||||
size_t len;
|
size_t len;
|
||||||
const char* json_str = yyjson_mut_write_opts(doc, 0, &alc, &len, NULL);
|
const char* json_str = yyjson_mut_write_opts(doc, 0, &alc, &len, NULL);
|
||||||
|
|||||||
@ -1,57 +1,58 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "../type.h"
|
||||||
#include "refl/pch.h"
|
#include "refl/pch.h"
|
||||||
#include <format>
|
namespace gen {
|
||||||
#include <string_view>
|
template<typename T>
|
||||||
namespace api {
|
struct Meta {};
|
||||||
namespace archive {
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept is_string_v = requires(T t) {
|
concept is_string_v = requires(T t) {
|
||||||
{ static_cast<std::string>(t) } -> std::convertible_to<std::string>;
|
{ static_cast<std::string>(t) } -> std::convertible_to<std::string>;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
using std::string_view;
|
|
||||||
using refl::Any;
|
|
||||||
using refl::UClass;
|
|
||||||
using refl::type_name;
|
|
||||||
using refl::TypeInfo;
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct JsonSerde {
|
concept is_serde_v = std::is_same_v<T, bool> || std::is_integral_v<T> || std::is_floating_point_v<T> || is_string_v<T> || std::is_enum_v<T>;
|
||||||
inline static bool Read(yyjson_val* val, Any any) {
|
template<typename T, typename = void>
|
||||||
|
struct JsonSerde {};
|
||||||
|
template<typename T>
|
||||||
|
struct JsonSerde<T, std::enable_if_t<is_serde_v<T>>>{
|
||||||
|
inline static bool Read(yyjson_val* val, const void* ptr) {
|
||||||
if constexpr (std::is_same_v<T, bool>) {
|
if constexpr (std::is_same_v<T, bool>) {
|
||||||
*any.CastTo<T*>() = (T)yyjson_get_bool(val);
|
*(T*)(ptr) = (T)yyjson_get_bool(val);
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_integral_v<T>) {
|
else if constexpr (std::is_integral_v<T>) {
|
||||||
*any.CastTo<T*>() = (T)yyjson_get_uint(val);
|
*(T*)(ptr) = (T)yyjson_get_uint(val);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_enum_v<T>) {
|
||||||
|
*(T*)(ptr) = (T)yyjson_get_uint(val);
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_floating_point_v<T>) {
|
else if constexpr (std::is_floating_point_v<T>) {
|
||||||
*any.CastTo<T*>() = (T)yyjson_get_real(val);
|
*(T*)(ptr) = (T)yyjson_get_real(val);
|
||||||
}
|
}
|
||||||
else if constexpr (archive::is_string_v<T>) {
|
else if constexpr (is_string_v<T>) {
|
||||||
*any.CastTo<T*>() = yyjson_get_str(val);
|
*(T*)(ptr) = yyjson_get_str(val);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw std::runtime_error(std::format("unknown json read type {}", type_name<T>().View()));
|
static_assert(false, "unknown json read type");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, Any any) {
|
inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, const void* ptr) {
|
||||||
if constexpr (std::is_same_v<T, bool>) {
|
if constexpr (std::is_same_v<T, bool>) {
|
||||||
return yyjson_mut_bool(doc, *any.CastTo<T*>());
|
return yyjson_mut_bool(doc, *(T*)(ptr));
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_integral_v<T>) {
|
else if constexpr (std::is_integral_v<T>) {
|
||||||
return yyjson_mut_uint(doc, *any.CastTo<T*>());
|
return yyjson_mut_uint(doc, *(T*)(ptr));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_enum_v<T>) {
|
||||||
|
return yyjson_mut_uint(doc, (std::underlying_type_t<T>)*(T*)(ptr));
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_floating_point_v<T>) {
|
else if constexpr (std::is_floating_point_v<T>) {
|
||||||
return yyjson_mut_real(doc, *any.CastTo<T*>());
|
return yyjson_mut_real(doc, *(T*)(ptr));
|
||||||
}
|
}
|
||||||
else if constexpr (archive::is_string_v<T>) {
|
else if constexpr (is_string_v<T>) {
|
||||||
auto c = (any.CastTo<T*>())->data();
|
return yyjson_mut_str(doc, ((T*)ptr)->data());
|
||||||
return yyjson_mut_str(doc, "");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw std::runtime_error(std::format("unknown json write type {}", type_name<T>().View()));
|
static_assert(false, "unknown json write type");
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,38 @@
|
|||||||
#include "serde.h"
|
#include "serde.h"
|
||||||
|
namespace gen {
|
||||||
|
#ifdef API_DEBUG
|
||||||
|
template<typename T>
|
||||||
|
inline bool JsonRead(yyjson_val* node, const T& t) {
|
||||||
|
if (!node) return false;
|
||||||
|
return JsonSerde<T>::Read(node, &t);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
inline yyjson_mut_val* JsonWrite(yyjson_mut_doc* doc, const T& t) {
|
||||||
|
return JsonSerde<T>::Write(doc, &t);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define JsonRead(node, t) if(node)JsonSerde<decltype(t)>::Read(node, &t)
|
||||||
|
#define JsonWrite(doc, t) JsonSerde<decltype(t)>::Write(doc, &t)
|
||||||
|
#endif
|
||||||
|
template<typename T>
|
||||||
|
struct JsonSerde<T, std::enable_if_t<refl::is_meta_v<T>>> {
|
||||||
|
inline static bool Read(yyjson_val* val, const void* ptr) {
|
||||||
|
T& v = *(T*)ptr;
|
||||||
|
for_each_field([=](std::string_view name, auto&& value) {
|
||||||
|
JsonRead(yyjson_obj_get(val, name.data()), value);
|
||||||
|
}, v);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, const void* ptr) {
|
||||||
|
T& v = *(T*)ptr;
|
||||||
|
yyjson_mut_val* obj = yyjson_mut_obj(doc);
|
||||||
|
for_each_field([=](std::string_view name, auto&& value) {
|
||||||
|
yyjson_mut_obj_add_val(doc, obj, name.data(), JsonWrite(doc, value));
|
||||||
|
}, v);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
namespace api {
|
namespace api {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
// 辅助结构体,用于检查特化版本
|
// 辅助结构体,用于检查特化版本
|
||||||
@ -6,21 +40,8 @@ namespace api {
|
|||||||
struct has_json_specialization : std::false_type {};
|
struct has_json_specialization : std::false_type {};
|
||||||
// 特化辅助结构体,匹配特化版本
|
// 特化辅助结构体,匹配特化版本
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_json_specialization<T, std::void_t<decltype(&JsonSerde<T>::Read) >> : std::true_type {};
|
struct has_json_specialization<T, std::void_t<decltype(gen::JsonSerde<T>::Read)>> : std::true_type {};
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept has_json_specialization_v = detail::has_json_specialization<T>::value;
|
concept has_json_specialization_v = detail::has_json_specialization<T>::value;
|
||||||
|
|
||||||
#ifdef API_DEBUG
|
|
||||||
template<typename T>
|
|
||||||
inline bool JsonRead(yyjson_val* node, const T& t) {
|
|
||||||
return JsonSerde<T>::Read(node, t);
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
inline yyjson_mut_val* JsonWrite(yyjson_mut_doc* doc, const T& t) {
|
|
||||||
return JsonSerde<T>::Write(doc, t);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define JsonRead(node, t) JsonSerde<decltype(t)>::Read(node, t)
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
@ -2,12 +2,15 @@
|
|||||||
#include "yyjson.h"
|
#include "yyjson.h"
|
||||||
#include "serde.h"
|
#include "serde.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
|
using refl::Any;
|
||||||
|
using refl::UClass;
|
||||||
|
using refl::TypeInfo;
|
||||||
struct JsonVTable {
|
struct JsonVTable {
|
||||||
bool(*Read)(yyjson_val*, Any) = nullptr;
|
bool(*Read)(yyjson_val*, const void*) = nullptr;
|
||||||
yyjson_mut_val*(*Write)(yyjson_mut_doc*, Any) = nullptr;
|
yyjson_mut_val*(*Write)(yyjson_mut_doc*, const void*) = nullptr;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static JsonVTable Make() {
|
static JsonVTable Make() {
|
||||||
return { &JsonSerde<T>::Read, &JsonSerde<T>::Write };
|
return { &gen::JsonSerde<T>::Read, &gen::JsonSerde<T>::Write };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
using JsonFuncTable = std::pmr::unordered_map<const UClass*, JsonVTable>;
|
using JsonFuncTable = std::pmr::unordered_map<const UClass*, JsonVTable>;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
#include "serde.h"
|
#include "serde.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
// 定义 yyjson_alc 适配器类
|
// 定义 yyjson_alc 适配器类
|
||||||
yyjson_alc JsonAllocatorAdapter(std::pmr::memory_resource* mr = &FramePool) {
|
inline yyjson_alc JsonAllocatorAdapter(std::pmr::memory_resource* mr = &FramePool) {
|
||||||
// 初始化 yyjson_alc 结构体
|
// 初始化 yyjson_alc 结构体
|
||||||
yyjson_alc alc;
|
yyjson_alc alc;
|
||||||
alc.malloc = [](void* ctx, size_t size) -> void* {
|
alc.malloc = [](void* ctx, size_t size) -> void* {
|
||||||
@ -30,6 +30,7 @@ namespace api {
|
|||||||
inline JsonFuncTable JsonArchive::BuildFuncTable()
|
inline JsonFuncTable JsonArchive::BuildFuncTable()
|
||||||
{
|
{
|
||||||
JsonFuncTable funcTable{ &MemPool };
|
JsonFuncTable funcTable{ &MemPool };
|
||||||
|
using std::string_view;
|
||||||
#define RegisterAny(T) funcTable.emplace(&TypeInfo<T>::StaticClass,JsonVTable::Make<T>())
|
#define RegisterAny(T) funcTable.emplace(&TypeInfo<T>::StaticClass,JsonVTable::Make<T>())
|
||||||
#include "../register.inl"
|
#include "../register.inl"
|
||||||
#undef RegisterAny
|
#undef RegisterAny
|
||||||
@ -47,7 +48,7 @@ namespace api {
|
|||||||
}
|
}
|
||||||
auto it = FuncTable.find(any.cls);
|
auto it = FuncTable.find(any.cls);
|
||||||
if (it != FuncTable.end()) {
|
if (it != FuncTable.end()) {
|
||||||
return it->second.Write(doc, any);
|
return it->second.Write(doc, any.ptr);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -58,7 +59,7 @@ namespace api {
|
|||||||
}
|
}
|
||||||
auto it = FuncTable.find(any.cls);
|
auto it = FuncTable.find(any.cls);
|
||||||
if (it != FuncTable.end()) {
|
if (it != FuncTable.end()) {
|
||||||
return it->second.Read(res, any);
|
return it->second.Read(res, any.ptr);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
0
engine/modules/engine/core/include/archive/type.h
Normal file
0
engine/modules/engine/core/include/archive/type.h
Normal file
@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "pmr/name.h"
|
#include "pmr/name.h"
|
||||||
#include "macro.h"
|
#include "enum_macro.h"
|
||||||
#include "os/shared_library.h"
|
#include "os/shared_library.h"
|
||||||
|
#include "refl/pch.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
using pmr::Name;
|
using pmr::Name;
|
||||||
enum class EModuleFlag : uint32_t {
|
enum class EModuleFlag : uint32_t {
|
||||||
@ -9,14 +10,23 @@ namespace api {
|
|||||||
};
|
};
|
||||||
ENABLE_BITMASK_OPERATORS(EModuleFlag);
|
ENABLE_BITMASK_OPERATORS(EModuleFlag);
|
||||||
struct ModuleInfo {
|
struct ModuleInfo {
|
||||||
EModuleFlag flag;
|
UPROPERTY()
|
||||||
|
EModuleFlag flag{0};
|
||||||
|
UPROPERTY()
|
||||||
Name name; //!< name of the plugin
|
Name name; //!< name of the plugin
|
||||||
|
UPROPERTY()
|
||||||
Name prettyname; //!< formatted name of the plugin
|
Name prettyname; //!< formatted name of the plugin
|
||||||
|
UPROPERTY()
|
||||||
Name core_version; //!< version of the engine
|
Name core_version; //!< version of the engine
|
||||||
|
UPROPERTY()
|
||||||
Name version; // !< version of the plugin
|
Name version; // !< version of the plugin
|
||||||
|
UPROPERTY()
|
||||||
Name linking; // !< linking of the plugin
|
Name linking; // !< linking of the plugin
|
||||||
|
UPROPERTY()
|
||||||
Name license; //!< license of the plugin
|
Name license; //!< license of the plugin
|
||||||
|
UPROPERTY()
|
||||||
Name url; //!< url of the plugin
|
Name url; //!< url of the plugin
|
||||||
|
UPROPERTY()
|
||||||
Name copyright; //!< copyright of the plugin
|
Name copyright; //!< copyright of the plugin
|
||||||
public:
|
public:
|
||||||
bool IsReload() {
|
bool IsReload() {
|
||||||
@ -56,3 +66,4 @@ namespace api {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
#include "module.inl"
|
#include "module.inl"
|
||||||
|
#include "module_gen.inl"
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "moudle.h"
|
#include "module.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
template<typename T1, typename T2, typename Hasher = std::hash<T1>>
|
template<typename T1, typename T2, typename Hasher = std::hash<T1>>
|
||||||
using table = std::pmr::unordered_map<T1, T2, Hasher>;
|
using table = std::pmr::unordered_map<T1, T2, Hasher>;
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
static_component("core","engine")
|
static_component("core","engine")
|
||||||
|
add_rules("c++.codegen",{
|
||||||
|
files = {"include/module/module.h"}
|
||||||
|
})
|
||||||
add_includedirs("include", "include/3rdparty", {public = true})
|
add_includedirs("include", "include/3rdparty", {public = true})
|
||||||
add_headerfiles("include/**.h","include/**.inl")
|
add_headerfiles("include/**.h","include/**.inl")
|
||||||
add_files("src/**.cpp")
|
add_files("src/**.cpp")
|
||||||
|
|||||||
@ -3,53 +3,53 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
namespace pmr
|
namespace pmr
|
||||||
{
|
{
|
||||||
|
static consteval inline size_t InvalidValue() noexcept { return static_cast<size_t>(-1); }
|
||||||
constexpr inline size_t string_hash(std::string_view str) noexcept;
|
constexpr inline size_t string_hash(std::string_view str) noexcept;
|
||||||
class NameID {
|
|
||||||
public:
|
|
||||||
static consteval size_t InvalidValue() noexcept { return static_cast<size_t>(-1); }
|
|
||||||
|
|
||||||
constexpr NameID() noexcept : hash{ InvalidValue() } {}
|
|
||||||
explicit constexpr NameID(size_t value) noexcept : hash{ value } {}
|
|
||||||
constexpr NameID(std::string_view str) noexcept : hash{ string_hash(str) } {}
|
|
||||||
template<size_t N>
|
|
||||||
constexpr NameID(const char(&str)[N]) noexcept : hash{ string_hash(str) } {}
|
|
||||||
|
|
||||||
constexpr size_t GetValue() const noexcept { return hash; }
|
|
||||||
|
|
||||||
constexpr bool Valid() const noexcept { return hash != InvalidValue(); }
|
|
||||||
|
|
||||||
constexpr bool Is(std::string_view str) const noexcept { return hash == NameID{ str }.GetValue(); }
|
|
||||||
|
|
||||||
explicit constexpr operator bool() const noexcept { return Valid(); }
|
|
||||||
|
|
||||||
constexpr std::strong_ordering operator<=>(const NameID& rhs) const noexcept = default;
|
|
||||||
std::string ToString() const;
|
|
||||||
const std::pmr::string& ToStringRef() const;
|
|
||||||
operator std::string() const { return ToString(); }
|
|
||||||
private:
|
|
||||||
size_t hash;
|
|
||||||
};
|
|
||||||
struct Name {
|
struct Name {
|
||||||
|
private:
|
||||||
size_t hash;
|
size_t hash;
|
||||||
#ifdef API_DEBUG
|
#ifdef API_DEBUG
|
||||||
std::string_view value;
|
std::string_view value;
|
||||||
#endif // API_DEBUG
|
#endif // API_DEBUG
|
||||||
public:
|
public:
|
||||||
Name():hash(NameID::InvalidValue()) {};
|
Name():hash(InvalidValue()) {};
|
||||||
Name(const char* str)noexcept;
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
constexpr Name(const char(&str)[N]) noexcept;
|
Name(const char(&str)[N]) noexcept;
|
||||||
|
Name(const char* str)noexcept;
|
||||||
Name(const std::string& str)noexcept;
|
Name(const std::string& str)noexcept;
|
||||||
Name(std::string_view str)noexcept;
|
Name(std::string_view str)noexcept;
|
||||||
auto operator<=>(const Name& other) const noexcept { return hash <=> other.hash; };
|
auto operator<=>(const Name& other) const noexcept { return hash <=> other.hash; };
|
||||||
bool operator==(const Name& other) const {
|
bool operator==(const Name& other) const {return hash == other.hash;}
|
||||||
return hash == other.hash;
|
const char* data()const { return ToStringView().data(); }
|
||||||
}
|
constexpr size_t Hash() const noexcept { return hash; }
|
||||||
constexpr size_t GetValue() const noexcept { return hash; }
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
const std::string_view ToStringView() const;
|
const std::string_view ToStringView() const;
|
||||||
operator std::string() const { return ToString(); }
|
operator std::string() const { return ToString(); }
|
||||||
};
|
};
|
||||||
|
class CName {
|
||||||
|
private:
|
||||||
|
size_t hash;
|
||||||
|
std::string_view value;
|
||||||
|
public:
|
||||||
|
constexpr CName() noexcept : hash{ InvalidValue() } {}
|
||||||
|
constexpr CName(std::string_view str) noexcept : hash{ string_hash(str) } ,value(str) {}
|
||||||
|
template<size_t N>
|
||||||
|
constexpr CName(const char(&str)[N]) noexcept : hash{ string_hash(str) }, value(str) {}
|
||||||
|
const char* data()const { return Value().data(); }
|
||||||
|
constexpr size_t Hash() const noexcept { return hash; }
|
||||||
|
constexpr std::string_view Value() const noexcept { return value; }
|
||||||
|
constexpr bool Valid() const noexcept { return hash != InvalidValue(); }
|
||||||
|
|
||||||
|
explicit constexpr operator bool() const noexcept { return Valid(); }
|
||||||
|
|
||||||
|
constexpr auto operator<=>(const CName& rhs) const noexcept { return hash <=> rhs.hash; };
|
||||||
|
bool operator==(const CName& other) const { return hash == other.hash; }
|
||||||
|
std::string ToString() const { return std::string(value); };
|
||||||
|
operator std::string() const { return ToString(); }
|
||||||
|
};
|
||||||
|
bool operator==(const CName& cname, const Name& name) {
|
||||||
|
return cname.Hash() == name.Hash();
|
||||||
|
}
|
||||||
constexpr inline size_t string_hash(std::string_view str) noexcept
|
constexpr inline size_t string_hash(std::string_view str) noexcept
|
||||||
{
|
{
|
||||||
constexpr size_t fnv_offset_basis = 0xcbf29ce484222325;
|
constexpr size_t fnv_offset_basis = 0xcbf29ce484222325;
|
||||||
@ -66,22 +66,23 @@ namespace pmr
|
|||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
consteval static CName FName(std::string_view view) { return CName{ view }; };
|
||||||
}
|
}
|
||||||
namespace std {
|
namespace std {
|
||||||
template<>
|
template<>
|
||||||
struct hash<::pmr::NameID>
|
struct hash<::pmr::CName>
|
||||||
{
|
{
|
||||||
size_t operator()(const ::pmr::NameID& ID) const noexcept
|
size_t operator()(const ::pmr::CName& name) const noexcept
|
||||||
{
|
{
|
||||||
return ID.GetValue();
|
return name.Hash();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<>
|
template<>
|
||||||
struct hash<::pmr::Name>
|
struct hash<::pmr::Name>
|
||||||
{
|
{
|
||||||
size_t operator()(const ::pmr::Name& ID) const noexcept
|
size_t operator()(const ::pmr::Name& name) const noexcept
|
||||||
{
|
{
|
||||||
return ID.GetValue();
|
return name.Hash();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,14 +32,6 @@ namespace pmr {
|
|||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
inline std::string NameID::ToString() const
|
|
||||||
{
|
|
||||||
return std::string(NameTable::Find(hash));
|
|
||||||
}
|
|
||||||
inline const std::pmr::string& NameID::ToStringRef() const
|
|
||||||
{
|
|
||||||
return NameTable::Find(hash);
|
|
||||||
}
|
|
||||||
#ifdef API_DEBUG
|
#ifdef API_DEBUG
|
||||||
#define MAKE_NAME_PAIR(hash, str) value = NameTable::MakePair(hash, str)
|
#define MAKE_NAME_PAIR(hash, str) value = NameTable::MakePair(hash, str)
|
||||||
#define NAME_TO_STRING value
|
#define NAME_TO_STRING value
|
||||||
@ -60,7 +52,7 @@ namespace pmr {
|
|||||||
MAKE_NAME_PAIR(hash, str);
|
MAKE_NAME_PAIR(hash, str);
|
||||||
}
|
}
|
||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
inline constexpr Name::Name(const char(&str)[N]) noexcept : hash(string_hash(str))
|
inline Name::Name(const char(&str)[N]) noexcept : hash(string_hash(str))
|
||||||
{
|
{
|
||||||
MAKE_NAME_PAIR(hash, str);
|
MAKE_NAME_PAIR(hash, str);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "any.h"
|
#include "any.h"
|
||||||
#include "uclass.h"
|
#include "uclass.h"
|
||||||
namespace refl{
|
namespace refl{
|
||||||
bool Any::Check(const UClass* parent)const
|
inline bool Any::Check(const UClass* parent)const
|
||||||
{
|
{
|
||||||
if (cls == parent) {
|
if (cls == parent) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -4,6 +4,9 @@
|
|||||||
#include <span>
|
#include <span>
|
||||||
namespace refl {
|
namespace refl {
|
||||||
using pmr::Name;
|
using pmr::Name;
|
||||||
|
using pmr::CName;
|
||||||
|
using pmr::FName;
|
||||||
|
using pmr::string_hash;
|
||||||
using std::span;
|
using std::span;
|
||||||
using Offset = uint32_t;
|
using Offset = uint32_t;
|
||||||
using Method = void*;
|
using Method = void*;
|
||||||
|
|||||||
44
engine/modules/engine/zlib/include/refl/detail/meta.h
Normal file
44
engine/modules/engine/zlib/include/refl/detail/meta.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "field.h"
|
||||||
|
namespace gen {
|
||||||
|
using pmr::CName;
|
||||||
|
using pmr::FName;
|
||||||
|
using pmr::string_hash;
|
||||||
|
template<typename T, size_t hash>
|
||||||
|
struct MetaImpl {};
|
||||||
|
template<typename T>
|
||||||
|
struct Property {
|
||||||
|
std::string_view name;
|
||||||
|
T ptr;
|
||||||
|
constexpr Property(T ptr, std::string_view name) noexcept:name(name), ptr(ptr) {}
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
consteval Property<T> FProperty(T ptr, std::string_view name) { return { ptr, name }; }
|
||||||
|
|
||||||
|
// 遍历所有字段值
|
||||||
|
template <typename Func, typename T, size_t hash = string_hash("Meta")>
|
||||||
|
inline void for_each_field(Func&& func, T& obj) {
|
||||||
|
constexpr auto props = MetaImpl<T, hash>::Fields();
|
||||||
|
std::apply([&](auto... field) {
|
||||||
|
((func(field.name, obj.*(field.ptr))), ...);
|
||||||
|
}, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace refl {
|
||||||
|
struct MetaHelp{
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
static FieldPtr CtorField(T(*ptr)(Args...), const MethodData& data = {});
|
||||||
|
|
||||||
|
template<typename T, typename Obj>
|
||||||
|
static FieldPtr MemberField(T Obj::* ptr, CName name, const MemberData& data = {});
|
||||||
|
|
||||||
|
template<typename R, typename ...Args>
|
||||||
|
static FieldPtr MethodField(R(*ptr)(Args...), CName name, const MethodData& data = {});
|
||||||
|
|
||||||
|
template<typename T, typename R, typename ...Args>
|
||||||
|
static FieldPtr MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data = {});
|
||||||
|
|
||||||
|
template<typename T, typename R, typename ...Args>
|
||||||
|
static FieldPtr MethodField(R(T::* ptr)(Args...)const, CName name, const MethodData& data = {});
|
||||||
|
};
|
||||||
|
}
|
||||||
1
engine/modules/engine/zlib/include/refl/detail/meta.inl
Normal file
1
engine/modules/engine/zlib/include/refl/detail/meta.inl
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "meta.h"
|
||||||
@ -95,6 +95,20 @@ namespace refl {
|
|||||||
using args_type_t = detail::args_type<std::remove_cv_t<T>>::type;
|
using args_type_t = detail::args_type<std::remove_cv_t<T>>::type;
|
||||||
};
|
};
|
||||||
namespace refl {
|
namespace refl {
|
||||||
|
template<class T>
|
||||||
|
struct Meta {};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
concept is_meta_v = requires { typename Meta<T>::Impl; };
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
concept has_parent_v = requires { typename Meta<T>::Parent; };
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using meta_t = Meta<T>::Impl;
|
||||||
|
template<class T>
|
||||||
|
using parent_t = typename Meta<T>::Parent;
|
||||||
|
|
||||||
//类型接口
|
//类型接口
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct TypeInfoImpl;
|
struct TypeInfoImpl;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
#include "uclass.h"
|
#include "uclass.h"
|
||||||
#include "name.h"
|
#include "name.h"
|
||||||
|
#include "type.h"
|
||||||
namespace refl{
|
namespace refl{
|
||||||
template <class T>
|
template <class T>
|
||||||
concept is_metas_v = false;//requires(const Name & name) { MetaImpl<T>::MyMetas::GetMeta(name); };
|
concept is_metas_v = requires(const Name & name) { Meta<T>::GetMeta(name); };
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class UClass_Auto : public UClass {
|
class UClass_Auto : public UClass {
|
||||||
public:
|
public:
|
||||||
@ -29,13 +30,29 @@ namespace refl{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<>
|
template<typename T, typename MetaImpl>
|
||||||
struct TypeInfoImpl<void> {
|
class UClass_Meta : public UClass {
|
||||||
inline static UClass StaticClass{ type_name<void>().View(), 0 };
|
using FieldsType = decltype(MetaImpl::MakeFields());
|
||||||
|
FieldsType Fields{ MetaImpl::MakeFields() };
|
||||||
|
UClass_Meta() : UClass(type_name<T>().View(), sizeof(T)) {
|
||||||
|
if constexpr (has_parent_v<T>) {
|
||||||
|
parent = &TypeInfo<parent_t<T>>::StaticClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct TypeInfoImpl {
|
struct TypeInfoImpl {
|
||||||
using MyUClass = UClass_Auto<T>;
|
using MyUClass = UClass_Auto<T>;
|
||||||
inline static MyUClass StaticClass{};
|
inline static MyUClass StaticClass{};
|
||||||
};
|
};
|
||||||
|
template<>
|
||||||
|
struct TypeInfoImpl<void> {
|
||||||
|
inline static UClass StaticClass{ type_name<void>().View(), 0 };
|
||||||
|
};
|
||||||
|
template<is_meta_v T>
|
||||||
|
struct TypeInfoImpl<T> {
|
||||||
|
using MyUClass = UClass_Meta<T, meta_t<T>>;
|
||||||
|
inline static MyUClass StaticClass{};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
39
engine/modules/engine/zlib/include/refl/macro.h
Normal file
39
engine/modules/engine/zlib/include/refl/macro.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#if !defined(__cppast)
|
||||||
|
#define __cppast(...)
|
||||||
|
#endif
|
||||||
|
#define __Meta(...) __cppast(Meta=__VA_ARGS__)
|
||||||
|
#define UPROPERTY(...) __Meta(__VA_ARGS__)
|
||||||
|
#define UFUNCTION(...) __Meta(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define __vkMeta(...) __cppast(vkMeta=__VA_ARGS__)
|
||||||
|
#define UPROPERTY_vk(...) __vkMeta(__VA_ARGS__)
|
||||||
|
#define UFUNCTION_vk(...) __vkMeta(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define __dxMeta(...) __cppast(dxMeta=__VA_ARGS__)
|
||||||
|
#define UPROPERTY_dx(...) __dxMeta(__VA_ARGS__)
|
||||||
|
#define UFUNCTION_dx(...) __dxMeta(__VA_ARGS__)
|
||||||
|
|
||||||
|
// 辅助宏,用于实际拼接
|
||||||
|
#define CONCATENATE(arg1, arg2) CONCATENATE_IMPL(arg1, arg2)
|
||||||
|
#define CONCATENATE_IMPL(arg1, arg2) arg1##arg2
|
||||||
|
#define MY_UNIQUE_NAME(base) CONCATENATE(base, __LINE__)
|
||||||
|
|
||||||
|
#define USING_CTOR_NAME MY_UNIQUE_NAME(__Ctor)
|
||||||
|
#define USING_FUNC_NAME MY_UNIQUE_NAME(__Func)
|
||||||
|
|
||||||
|
#define USING_OVERLOAD_CTOR(Class, ...) using USING_CTOR_NAME = Class(*)(__VA_ARGS__);
|
||||||
|
#define USING_OVERLOAD_FUNC(R, ...) using USING_FUNC_NAME = R(*)(__VA_ARGS__);
|
||||||
|
#define USING_OVERLOAD_CLASS_FUNC(R, Class, ...) using USING_FUNC_NAME = R(Class::*)(__VA_ARGS__);
|
||||||
|
|
||||||
|
#define REGISTER_META_TABLE(Class) refl::UClass::MetaTable.emplace(type_name<Class>().View(), &refl::TypeInfo<Class>::StaticClass);
|
||||||
|
|
||||||
|
#define GENERATED_BODY() template <typename T, size_t hash>\
|
||||||
|
friend class gen::MetaImpl;
|
||||||
|
/*
|
||||||
|
struct vec3{
|
||||||
|
USING_OVERLOAD_CTOR(vec3)
|
||||||
|
UFUNCTION({},ref = USING_CTOR_NAME)
|
||||||
|
vec3(){}
|
||||||
|
}
|
||||||
|
*/
|
||||||
@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "detail/name.inl"
|
#include "detail/name.inl"
|
||||||
#include "detail/any.inl"
|
#include "detail/any.inl"
|
||||||
|
#include "detail/meta.inl"
|
||||||
#include "detail/uclass.inl"
|
#include "detail/uclass.inl"
|
||||||
|
#include "macro.h"
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "module/moudle.h"
|
#include "module/module.h"
|
||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
class VulkanModule : public api::IDynamicModule
|
class VulkanModule : public api::IDynamicModule
|
||||||
{
|
{
|
||||||
|
|||||||
1
engine/modules/render/vulkan/vulkan.plugin
Normal file
1
engine/modules/render/vulkan/vulkan.plugin
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"flag":0,"name":"vulkan"}
|
||||||
@ -3,4 +3,3 @@ shared_component("vulkan","engine")
|
|||||||
add_headerfiles("include/**.h")
|
add_headerfiles("include/**.h")
|
||||||
add_files("src/**.cpp")
|
add_files("src/**.cpp")
|
||||||
add_rules("engine.plugin", {file = "include/vulkan/module.h"})
|
add_rules("engine.plugin", {file = "include/vulkan/module.h"})
|
||||||
--add_deps("core", "asset", {public = true})
|
|
||||||
94
engine/tools/make_plugin/src/macro_parse.cpp
Normal file
94
engine/tools/make_plugin/src/macro_parse.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include "macro_parse.h"
|
||||||
|
#include <string>
|
||||||
|
#include <stack>
|
||||||
|
#include <optional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
std::string_view module_macro[] = { MODULE_DEPENDENCY , IMPLEMENT_DYNAMIC_MODULE , IMPLEMENT_STATIC_MODULE };
|
||||||
|
pmr::vector<pmr::string> parseArgs(std::string_view& str) {
|
||||||
|
pmr::vector<pmr::string> args(&pool);
|
||||||
|
std::stack<char> stack;
|
||||||
|
enum EParseState {
|
||||||
|
EEmpty,
|
||||||
|
EBody,
|
||||||
|
};
|
||||||
|
EParseState state = EEmpty;
|
||||||
|
int n = 0;
|
||||||
|
char segment[1024];
|
||||||
|
for (char c : str) {
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case EEmpty:
|
||||||
|
{
|
||||||
|
if (c == ' ' || c == '\t')
|
||||||
|
break;
|
||||||
|
state = EBody;
|
||||||
|
if (c == '(' && stack.empty()) {
|
||||||
|
stack.push(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case EBody:
|
||||||
|
{
|
||||||
|
if (c == '(' || c == '{' || c == '[' || (c == '"' && stack.top() != '"')) {
|
||||||
|
stack.push(c);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char t = stack.top();
|
||||||
|
if ((t == '(' && c == ')') || (t == '[' && c == ']') || (t == '{' && c == '}') || (t == '"' && c == '"')) {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stack.empty()) {
|
||||||
|
std::string_view view(segment, n);
|
||||||
|
args.push_back(pmr::string(view, &pool));
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
if (c == ',' && stack.size() == 1) {
|
||||||
|
std::string_view view(segment, n);
|
||||||
|
args.push_back(pmr::string(view, &pool));
|
||||||
|
n = 0;
|
||||||
|
state = EEmpty;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
segment[n++] = c;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
std::optional<MacroData> parseLine(std::string_view line) {
|
||||||
|
for (auto macro : module_macro) {
|
||||||
|
size_t pos = line.find(macro);
|
||||||
|
if (pos != std::string_view::npos) {
|
||||||
|
line = line.substr(pos + macro.size());
|
||||||
|
MacroData md{ parseArgs(line) };
|
||||||
|
md.macro = macro.data();
|
||||||
|
//std::cout << line << std::endl;
|
||||||
|
return md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::optional<MacroData>{};
|
||||||
|
}
|
||||||
|
// 读取文件并返回每一行内容
|
||||||
|
pmr::vector<MacroData> readMacroFile(const char* file_path) {
|
||||||
|
pmr::vector<MacroData> lines(&pool);
|
||||||
|
std::ifstream file(file_path);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
//std::cerr << "Failed to open file: " << file_path << std::endl;
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
std::string_view line_view(line);
|
||||||
|
if (auto md = parseLine(line_view)) {
|
||||||
|
lines.push_back(md.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
17
engine/tools/make_plugin/src/macro_parse.h
Normal file
17
engine/tools/make_plugin/src/macro_parse.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <memory_resource>
|
||||||
|
namespace pmr {
|
||||||
|
using std::pmr::monotonic_buffer_resource;
|
||||||
|
using std::pmr::vector;
|
||||||
|
using std::pmr::string;
|
||||||
|
}
|
||||||
|
inline pmr::monotonic_buffer_resource pool;
|
||||||
|
inline const char* MODULE_DEPENDENCY = "MODULE_DEPENDENCY";
|
||||||
|
inline const char* IMPLEMENT_DYNAMIC_MODULE = "IMPLEMENT_DYNAMIC_MODULE";
|
||||||
|
inline const char* IMPLEMENT_STATIC_MODULE = "IMPLEMENT_STATIC_MODULE";
|
||||||
|
struct MacroData {
|
||||||
|
const char* macro{ nullptr };
|
||||||
|
pmr::vector<pmr::string> args;
|
||||||
|
MacroData() :args(&pool) {}
|
||||||
|
MacroData(const pmr::vector<pmr::string>& args) :args(args) {}
|
||||||
|
};
|
||||||
|
pmr::vector<MacroData> readMacroFile(const char* file_path);
|
||||||
@ -1,113 +1,19 @@
|
|||||||
#include <fstream>
|
#include "macro_parse.h"
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <memory_resource>
|
|
||||||
#include <stack>
|
|
||||||
#include <optional>
|
|
||||||
#include <sstream>
|
|
||||||
#include "archive/json.h"
|
#include "archive/json.h"
|
||||||
namespace pmr {
|
#include "module/module.h"
|
||||||
using std::pmr::monotonic_buffer_resource;
|
#include <iostream>
|
||||||
using std::pmr::vector;
|
#include <fstream>
|
||||||
using std::pmr::string;
|
#include <sstream>
|
||||||
}
|
std::string_view readFile(const char* file_path) {
|
||||||
pmr::monotonic_buffer_resource pool;
|
std::ifstream file(file_path, std::ios::ate);
|
||||||
const char* MODULE_DEPENDENCY = "MODULE_DEPENDENCY";
|
|
||||||
const char* IMPLEMENT_DYNAMIC_MODULE = "IMPLEMENT_DYNAMIC_MODULE";
|
|
||||||
const char* IMPLEMENT_STATIC_MODULE = "IMPLEMENT_STATIC_MODULE";
|
|
||||||
std::string_view module_macro[] = { MODULE_DEPENDENCY , IMPLEMENT_DYNAMIC_MODULE , IMPLEMENT_STATIC_MODULE };
|
|
||||||
struct MacroData{
|
|
||||||
const char* macro{nullptr};
|
|
||||||
pmr::vector<pmr::string> args;
|
|
||||||
MacroData() :args(&pool) {}
|
|
||||||
MacroData(const pmr::vector<pmr::string>& args):args(args) {}
|
|
||||||
};
|
|
||||||
pmr::vector<pmr::string> parseArgs(std::string_view& str) {
|
|
||||||
pmr::vector<pmr::string> args(&pool);
|
|
||||||
std::stack<char> stack;
|
|
||||||
enum EParseState {
|
|
||||||
EEmpty,
|
|
||||||
EBody,
|
|
||||||
};
|
|
||||||
EParseState state = EEmpty;
|
|
||||||
int n = 0;
|
|
||||||
char segment[1024];
|
|
||||||
for (char c : str) {
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case EEmpty:
|
|
||||||
{
|
|
||||||
if (c == ' ' || c == '\t')
|
|
||||||
break;
|
|
||||||
state = EBody;
|
|
||||||
if (c == '(' && stack.empty()) {
|
|
||||||
stack.push(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case EBody:
|
|
||||||
{
|
|
||||||
if (c == '(' || c == '{' || c == '[' || (c == '"' && stack.top() != '"')) {
|
|
||||||
stack.push(c);
|
|
||||||
}else{
|
|
||||||
char t = stack.top();
|
|
||||||
if ((t == '(' && c == ')') || (t == '[' && c == ']') || (t == '{' && c == '}') || (t == '"' && c == '"')) {
|
|
||||||
stack.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stack.empty()) {
|
|
||||||
std::string_view view(segment, n);
|
|
||||||
args.push_back(pmr::string(view, &pool));
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
if (c == ',' && stack.size() == 1) {
|
|
||||||
std::string_view view(segment, n);
|
|
||||||
args.push_back(pmr::string(view, &pool));
|
|
||||||
n = 0;
|
|
||||||
state = EEmpty;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
segment[n++] = c;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
std::optional<MacroData> parseLine(std::string_view line) {
|
|
||||||
for (auto macro : module_macro) {
|
|
||||||
size_t pos = line.find(macro);
|
|
||||||
if (pos != std::string_view::npos) {
|
|
||||||
line = line.substr(pos + macro.size());
|
|
||||||
MacroData md{ parseArgs(line) };
|
|
||||||
md.macro = macro.data();
|
|
||||||
std::cout << line << std::endl;
|
|
||||||
return md;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::optional<MacroData>{};
|
|
||||||
}
|
|
||||||
// 读取文件并返回每一行内容
|
|
||||||
pmr::vector<MacroData> readFile(const char* file_path) {
|
|
||||||
pmr::vector<MacroData> lines(&pool);
|
|
||||||
std::ifstream file(file_path);
|
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
//std::cerr << "Failed to open file: " << file_path << std::endl;
|
return "";
|
||||||
return lines;
|
|
||||||
}
|
}
|
||||||
std::string line;
|
size_t size = file.tellg();
|
||||||
while (std::getline(file, line)) {
|
file.seekg(0);
|
||||||
std::string_view line_view(line);
|
char* ptr = new(FramePool)char[size];
|
||||||
if (auto md = parseLine(line_view)) {
|
file.read(ptr, size);
|
||||||
lines.push_back(md.value());
|
return std::string_view(ptr, size);
|
||||||
}
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
return lines;
|
|
||||||
}
|
}
|
||||||
void writeFile(const char* file_path, std::string_view data) {
|
void writeFile(const char* file_path, std::string_view data) {
|
||||||
std::ofstream file(file_path, 0);
|
std::ofstream file(file_path, 0);
|
||||||
@ -134,43 +40,40 @@ void genLua(const char* file_path, const pmr::vector<MacroData>& mdList) {
|
|||||||
oss << '}';
|
oss << '}';
|
||||||
writeFile(file_path, oss.str());
|
writeFile(file_path, oss.str());
|
||||||
}
|
}
|
||||||
namespace api {
|
|
||||||
struct Guid {
|
|
||||||
int a;
|
|
||||||
float b;
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct JsonSerde<Guid> {
|
|
||||||
inline static bool Read(yyjson_val* node, Any any) {
|
|
||||||
Guid& v = *any.CastTo<Guid*>();
|
|
||||||
JsonRead(yyjson_obj_get(node, "a"), v.a);
|
|
||||||
JsonRead(yyjson_obj_get(node, "b"), v.b);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, Any any) {
|
|
||||||
Guid& v = *any.CastTo<Guid*>();
|
|
||||||
auto obj = yyjson_mut_obj(doc);
|
|
||||||
yyjson_mut_obj_add_val(doc, obj, "a", JsonWrite(doc, v.a));
|
|
||||||
yyjson_mut_obj_add_val(doc, obj, "b", JsonWrite(doc, v.b));
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
void genPlugin(const char* file_path, const pmr::vector<MacroData>& mdList) {
|
void genPlugin(const char* file_path, const pmr::vector<MacroData>& mdList) {
|
||||||
api::Guid guid;
|
std::string_view text = readFile(file_path);
|
||||||
guid.a = 1243;
|
api::ModuleInfo info;
|
||||||
std::string_view data = api::JsonSerialize(guid);
|
api::JsonDeserialize<api::ModuleInfo>(text, &info);
|
||||||
auto res = api::JsonDeserialize<api::Guid>(data);
|
bool bchange = false;
|
||||||
if (res) {
|
for (auto& md : mdList) {
|
||||||
api::Guid g2 = res.value();
|
if (md.macro == IMPLEMENT_DYNAMIC_MODULE || md.macro == IMPLEMENT_STATIC_MODULE) {
|
||||||
int a = g2.a;
|
api::Name name = md.args[1].c_str();
|
||||||
int b = g2.b;
|
bchange = info.name != name;
|
||||||
|
info.name = name;
|
||||||
|
}
|
||||||
|
else if (md.macro == MODULE_DEPENDENCY) {
|
||||||
|
for (auto& args : md.args) {
|
||||||
|
if (args[0] != '{') {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int main() {
|
}
|
||||||
const char* file_path = R"(F:\engine\zengine\engine\modules\render\vulkan\include\vulkan\module.h)";
|
}
|
||||||
auto mdList = readFile(file_path);
|
if (bchange) {
|
||||||
genLua(R"(F:\engine\zengine\build\.gens\vulkan\windows\xmake.lua)", mdList);
|
writeFile(file_path, api::JsonSerialize(info));
|
||||||
genPlugin(R"(F:\engine\zengine\build\.gens\vulkan\windows\xmake.lua)", mdList);
|
}
|
||||||
|
}
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc < 6) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
std::string project_dir = argv[1];
|
||||||
|
std::string lua_file = project_dir + "\\" + argv[2];
|
||||||
|
std::string script_dir = argv[3];
|
||||||
|
std::string module_file = script_dir + "\\" + argv[4];
|
||||||
|
std::string plugin_file = script_dir + "\\" + argv[5];
|
||||||
|
auto mdList = readMacroFile(module_file.c_str());
|
||||||
|
genLua(lua_file.c_str(), mdList);
|
||||||
|
genPlugin(plugin_file.c_str(), mdList);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1,3 +1,8 @@
|
|||||||
tool_target("make_plugin")
|
tool_target("make_plugin")
|
||||||
add_files("src/main.cpp")
|
add_includedirs("src")
|
||||||
|
add_files("src/*.cpp")
|
||||||
|
add_headerfiles("src/*.h")
|
||||||
|
add_rules("engine.tool")
|
||||||
add_deps("core")
|
add_deps("core")
|
||||||
|
set_runargs([[F:\engine\zengine]], [[build\.gens\vulkan\windows\xmake.lua]],
|
||||||
|
[[F:\engine\zengine\engine\modules\render\vulkan]], [[include/vulkan/module.h]], [[vulkan.plugin]])
|
||||||
@ -1,12 +1,21 @@
|
|||||||
|
function find_exe_dir()
|
||||||
|
local os_name = os.host()
|
||||||
|
local arch_name = os.arch()
|
||||||
|
local mode_name = is_mode("debug") and "debug" or "release"
|
||||||
|
|
||||||
|
-- 构建生成目录路径
|
||||||
|
return path.join(os.projectdir(), "build", os_name, arch_name, mode_name)
|
||||||
|
end
|
||||||
function find_my_program(name, sdkdir, use_next)
|
function find_my_program(name, sdkdir, use_next)
|
||||||
import("lib.detect.find_file")
|
import("lib.detect.find_file")
|
||||||
import("lib.detect.find_program")
|
import("lib.detect.find_program")
|
||||||
import("lib.detect.find_tool")
|
import("lib.detect.find_tool")
|
||||||
|
|
||||||
local sdkdir = sdkdir or path.join(os.projectdir(), "tools")
|
local sdkdir = sdkdir or path.join(os.projectdir(), "tools")
|
||||||
local tool = find_tool(name, {pathes = {sdkdir, "/usr/local/bin"}})
|
local exedir = find_exe_dir()
|
||||||
local prog = tool and tool.program or find_program(name, {pathes = {sdkdir, "/usr/local/bin"}})
|
local tool = find_tool(name, {pathes = {sdkdir, exedir, "/usr/local/bin"}})
|
||||||
prog = prog or find_file(name, {sdkdir})
|
local prog = tool and tool.program or find_program(name, {pathes = {sdkdir,exedir, "/usr/local/bin"}})
|
||||||
|
prog = prog or find_file(name, {sdkdir, exedir})
|
||||||
if (prog == nil) then
|
if (prog == nil) then
|
||||||
if os.host() ~= "windows" then
|
if os.host() ~= "windows" then
|
||||||
local outdata, errdata = os.iorun("which " .. name)
|
local outdata, errdata = os.iorun("which " .. name)
|
||||||
@ -21,7 +30,7 @@ function find_my_program(name, sdkdir, use_next)
|
|||||||
if not use_next then
|
if not use_next then
|
||||||
return find_my_program(name, path.join(sdkdir, name), true)
|
return find_my_program(name, path.join(sdkdir, name), true)
|
||||||
end
|
end
|
||||||
print(name .. "_f not found! under " .. sdkdir)
|
print(name .. " not found! under " .. sdkdir, exedir)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
return {program = prog, sdkdir = sdkdir}
|
return {program = prog, sdkdir = sdkdir}
|
||||||
66
engine/xmake/rule_gen/make_gen.lua
Normal file
66
engine/xmake/rule_gen/make_gen.lua
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import("core.project.depend")
|
||||||
|
local genList = {}
|
||||||
|
function cmd_compile(genfile, sourcefile, template, macro, define)
|
||||||
|
if genList[genfile] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
import("find_sdk")
|
||||||
|
local meta = find_sdk.find_my_program("refl")
|
||||||
|
template = template or path.join(meta.sdkdir, "template")
|
||||||
|
if not macro then --优先使用库定义
|
||||||
|
macro = path.join(os.projectdir(), "engine/modules/engine/zlib/include/refl/macro.h")
|
||||||
|
if not os.exists(macro) then
|
||||||
|
macro = path.join(os.curdir(), "macro.h")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
argv = {"build", sourcefile, "-o", genfile, "-t", template, "-m", macro}
|
||||||
|
if define then
|
||||||
|
table.insert(argv, "-d")
|
||||||
|
table.insert(argv, define)
|
||||||
|
end
|
||||||
|
genList[genfile] = true
|
||||||
|
print("cmd_meta_compile", genfile)
|
||||||
|
os.execv(meta.program, argv)
|
||||||
|
return argv
|
||||||
|
end
|
||||||
|
|
||||||
|
function _listen_gen_file(target, batch, template, macro, define)
|
||||||
|
genfile, sourcefile = batch[1], batch[2]
|
||||||
|
local dependfile = target:dependfile(genfile)
|
||||||
|
depend.on_changed(
|
||||||
|
function()
|
||||||
|
cmd_compile(batch[1], batch[2], template, macro, define)
|
||||||
|
end,
|
||||||
|
{dependfile = dependfile, files = sourcefile}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
function gen(target)
|
||||||
|
local gen_batch = target:data("codegen.batch")
|
||||||
|
if not gen_batch then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local template = target:extraconf("rules", "c++.codegen", "template")
|
||||||
|
local macro = target:extraconf("rules", "c++.codegen", "macro")
|
||||||
|
local define = target:extraconf("rules", "c++.codegen", "define")
|
||||||
|
for _, batch in ipairs(gen_batch) do
|
||||||
|
if batch[2] then
|
||||||
|
_listen_gen_file(target, batch, template, macro, define)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function main(target, headerfiles)
|
||||||
|
local sourcedir = path.join(target:autogendir({root = true}), target:plat(), "inl")
|
||||||
|
if not os.isdir(sourcedir) then
|
||||||
|
os.mkdir(sourcedir)
|
||||||
|
end
|
||||||
|
target:add("includedirs", sourcedir, {public = true})
|
||||||
|
local gen_batch = {}
|
||||||
|
for idx, headerfile in pairs(headerfiles) do
|
||||||
|
-- batch
|
||||||
|
sourcefile = path.join(sourcedir, path.basename(headerfile) .. "_gen.inl")
|
||||||
|
table.insert(gen_batch, {sourcefile, headerfile})
|
||||||
|
end
|
||||||
|
-- save unit batch
|
||||||
|
target:data_set("codegen.batch", gen_batch)
|
||||||
|
end
|
||||||
19
engine/xmake/rule_gen/xmake.lua
Normal file
19
engine/xmake/rule_gen/xmake.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
rule("c++.codegen")
|
||||||
|
set_extensions(".inl")
|
||||||
|
after_load(function (target)
|
||||||
|
if not is_mode("debug") then return end
|
||||||
|
import("make_gen")
|
||||||
|
local headerfiles = {}
|
||||||
|
local files = target:extraconf("rules", "c++.codegen", "files")
|
||||||
|
for _, file in ipairs(files) do
|
||||||
|
local p = path.join(target:scriptdir(), file)
|
||||||
|
for __, filepath in ipairs(os.files(p)) do
|
||||||
|
table.insert(headerfiles, filepath)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
make_gen(target, headerfiles)
|
||||||
|
end)
|
||||||
|
on_config(function (target)
|
||||||
|
if not is_mode("debug") then return end
|
||||||
|
import("make_gen").gen(target)
|
||||||
|
end)
|
||||||
@ -1,28 +1,30 @@
|
|||||||
import("core.project.depend")
|
import("core.project.depend")
|
||||||
function cmd_compile(target, genfile, file)
|
function cmd_compile(target, genfile, file)
|
||||||
local res = [[
|
import("find_sdk")
|
||||||
{
|
print("find make_plugin", is_mode("debug"))
|
||||||
{"core", { public = true}},
|
local plugin = find_sdk.find_my_program("make_plugin")
|
||||||
{"asset", { public = true}},
|
if not plugin then return end
|
||||||
}
|
print("cmd_compile plugin", genfile, file)
|
||||||
]]
|
argv = { os.projectdir() , genfile, target:scriptdir(), file, target:name() .. ".plugin"}
|
||||||
io.writefile(genfile, res)
|
os.execv(plugin.program, argv)
|
||||||
local dependency = io.load(genfile)
|
|
||||||
for k,v in ipairs(dependency) do
|
|
||||||
--target:add("deps", v[1], v[2])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
function main(target, file)
|
function main(target, file)
|
||||||
local sourcedir = path.join(target:autogendir({root = true}), target:plat())
|
local sourcedir = path.join(target:autogendir({root = true}), target:plat())
|
||||||
if not os.isdir(sourcedir) then
|
if not os.isdir(sourcedir) then
|
||||||
os.mkdir(sourcedir)
|
os.mkdir(sourcedir)
|
||||||
end
|
end
|
||||||
local genfile = sourcedir .. "\\xmake.lua"
|
local genfile = path.join(sourcedir,"xmake.lua")
|
||||||
local dependfile = target:dependfile(genfile)
|
local dependfile = target:dependfile(genfile)
|
||||||
depend.on_changed(
|
depend.on_changed(
|
||||||
function()
|
function()
|
||||||
cmd_compile(target, genfile, file)
|
cmd_compile(target, genfile, file)
|
||||||
end,
|
end,
|
||||||
{dependfile = dependfile, files = {file}}
|
{dependfile = dependfile, files = {path.join(target:scriptdir(), file)}}
|
||||||
)
|
)
|
||||||
|
if os.exists(genfile) then
|
||||||
|
local dependency = io.load(genfile)
|
||||||
|
for k,v in ipairs(dependency) do
|
||||||
|
target:add("deps", v[1], v[2])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@ -1,6 +1,7 @@
|
|||||||
rule("engine.plugin")
|
rule("engine.plugin")
|
||||||
set_extensions(".h")
|
set_extensions(".h")
|
||||||
on_load(function (target)
|
on_load(function (target)
|
||||||
|
if not is_mode("debug") then return end
|
||||||
import("make_plugin")
|
import("make_plugin")
|
||||||
local file = target:extraconf("rules", "engine.plugin", "file")
|
local file = target:extraconf("rules", "engine.plugin", "file")
|
||||||
make_plugin(target, file or "module.h")
|
make_plugin(target, file or "module.h")
|
||||||
|
|||||||
5
engine/xmake/rule_tool/xmake.lua
Normal file
5
engine/xmake/rule_tool/xmake.lua
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
rule("engine.tool")
|
||||||
|
-- after_build(function (target)
|
||||||
|
-- -- do nothing
|
||||||
|
-- --print("after_install", target:targetfile())
|
||||||
|
-- end)
|
||||||
Loading…
Reference in New Issue
Block a user