name 字符串优化
This commit is contained in:
parent
a6458a82c0
commit
f51befaff0
@ -1,4 +1,6 @@
|
|||||||
{
|
metadatas:
|
||||||
"metadatas": [],
|
- guid: 7dfa8412-3278-43f6-b332-ac09a132025f
|
||||||
"includes": []
|
name: ""
|
||||||
}
|
t_hash: "api::ShaderProgram\x06 mOwner!<21>/engine/assets/shader/simple.frag"
|
||||||
|
meta: ~
|
||||||
|
includes: ~
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
metadatas:
|
||||||
|
- guid: 47c28b8c-f2aa-4357-a12d-7212de6e3a9e
|
||||||
|
name: ""
|
||||||
|
t_hash: "api::ShaderProgram\x06 mOwner!<21>/engine/assets/shader/simple.frag"
|
||||||
|
meta: ~
|
||||||
|
includes: ~
|
||||||
@ -24,7 +24,7 @@ namespace api {
|
|||||||
for (auto& elem : bundle.GetAll())
|
for (auto& elem : bundle.GetAll())
|
||||||
std::visit([&](auto& handle) {
|
std::visit([&](auto& handle) {
|
||||||
using T = std::decay_t<decltype(*handle)>;
|
using T = std::decay_t<decltype(*handle)>;
|
||||||
SerializedMeta meta{ handle.guid, handle->Name(), meta_name<T>().view() };
|
SerializedMeta meta{ handle.guid, handle->Name(), meta_name<T>() };
|
||||||
if constexpr (is_meta_v<T>) {
|
if constexpr (is_meta_v<T>) {
|
||||||
meta.meta = handle->Meta();
|
meta.meta = handle->Meta();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ namespace api
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
const SerializedMeta* FetchMeta() const;
|
const SerializedMeta* FetchMeta() const;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const SerializedMeta* FetchMeta(string_view asset_name) const;
|
const SerializedMeta* FetchMeta(Name asset_name) const;
|
||||||
void Add(const SerializedMeta& meta) {
|
void Add(const SerializedMeta& meta) {
|
||||||
metadatas.push_back(meta);
|
metadatas.push_back(meta);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,7 +4,7 @@ namespace api
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline const SerializedMeta* MetaBundle::FetchMeta() const
|
inline const SerializedMeta* MetaBundle::FetchMeta() const
|
||||||
{
|
{
|
||||||
string_view name = meta_name<typename T::BaseResource>().view();
|
Name name = meta_name<typename T::BaseResource>();
|
||||||
for (auto& elem : metadatas)
|
for (auto& elem : metadatas)
|
||||||
{
|
{
|
||||||
if (elem.t_hash == name)
|
if (elem.t_hash == name)
|
||||||
@ -13,9 +13,9 @@ namespace api
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline const SerializedMeta* MetaBundle::FetchMeta(string_view asset_name) const
|
inline const SerializedMeta* MetaBundle::FetchMeta(Name asset_name) const
|
||||||
{
|
{
|
||||||
string_view name = meta_name<typename T::BaseResource>().view();
|
Name name = meta_name<typename T::BaseResource>();
|
||||||
for (auto& elem : metadatas)
|
for (auto& elem : metadatas)
|
||||||
{
|
{
|
||||||
if (elem.t_hash == name && asset_name == elem.name)
|
if (elem.t_hash == name && asset_name == elem.name)
|
||||||
|
|||||||
@ -45,19 +45,20 @@ namespace api {
|
|||||||
{
|
{
|
||||||
DestroyGraph();
|
DestroyGraph();
|
||||||
}
|
}
|
||||||
void ModuleManagerImpl::CreateModule(Name name, bool shared)
|
void ModuleManagerImpl::CreateModule(Name name, bool is_shared)
|
||||||
{
|
{
|
||||||
bool hotfix = true;
|
bool hotfix = true;
|
||||||
IModule* module = shared ?
|
IModule* module = is_shared ?
|
||||||
spawnDynamicModule(name, hotfix) :
|
spawnDynamicModule(name, hotfix) :
|
||||||
spawnStaticModule(name);
|
spawnStaticModule(name);
|
||||||
if (!module) { return; }
|
if (!module) { return; }
|
||||||
mModuleBlocks[name] = ModuleBlock{false, false};
|
mModuleBlocks[name] = ModuleBlock{false, false};
|
||||||
ModuleBlock& block = mModuleBlocks[name];
|
ModuleBlock& block = mModuleBlocks[name];
|
||||||
auto& moduleInfo = module->mInfo;
|
auto& moduleInfo = module->mInfo;
|
||||||
|
Name shared("shared");
|
||||||
for (auto& dep : moduleInfo.dependencies) {
|
for (auto& dep : moduleInfo.dependencies) {
|
||||||
if(auto it = mModuleBlocks.find(dep.name); it == mModuleBlocks.end())
|
if(auto it = mModuleBlocks.find(dep.name); it == mModuleBlocks.end())
|
||||||
CreateModule(dep.name, dep.kind == pmr::FName("shared"));
|
CreateModule(dep.name, dep.kind == shared);
|
||||||
}
|
}
|
||||||
module->OnLoad(mInfo.argc, mInfo.argv);
|
module->OnLoad(mInfo.argc, mInfo.argv);
|
||||||
block.isLoad = true;
|
block.isLoad = true;
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace gen {
|
|||||||
else if constexpr (std::is_floating_point_v<T>) {
|
else if constexpr (std::is_floating_point_v<T>) {
|
||||||
*(T*)(ptr) = (T)yyjson_get_real(val);
|
*(T*)(ptr) = (T)yyjson_get_real(val);
|
||||||
}
|
}
|
||||||
else if constexpr (is_string_v<T>) {
|
else if constexpr (is_string_view_v<T> || is_string_v<T>) {
|
||||||
*(T*)(ptr) = yyjson_get_str(val);
|
*(T*)(ptr) = yyjson_get_str(val);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -40,13 +40,11 @@ namespace gen {
|
|||||||
else if constexpr (std::is_floating_point_v<T>) {
|
else if constexpr (std::is_floating_point_v<T>) {
|
||||||
return yyjson_mut_real(doc, *(T*)(ptr));
|
return yyjson_mut_real(doc, *(T*)(ptr));
|
||||||
}
|
}
|
||||||
|
else if constexpr (is_string_view_v<T>) {
|
||||||
|
return yyjson_mut_str(doc, std::string_view(*(T*)ptr).data());
|
||||||
|
}
|
||||||
else if constexpr (is_string_v<T>) {
|
else if constexpr (is_string_v<T>) {
|
||||||
if constexpr (requires(T * t) { t->data(); }) {
|
return yyjson_mut_str(doc, std::string(*(T*)ptr).data());
|
||||||
return yyjson_mut_str(doc, ((T*)ptr)->data());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return yyjson_mut_str(doc, std::string(*(T*)ptr).data());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//static_assert(false, "unknown json write type");
|
//static_assert(false, "unknown json write type");
|
||||||
|
|||||||
@ -33,11 +33,11 @@ namespace api {
|
|||||||
#include "../register.inl"
|
#include "../register.inl"
|
||||||
#undef RegisterAny
|
#undef RegisterAny
|
||||||
}
|
}
|
||||||
inline consteval size_t VJsonSerdeRead() {
|
inline Name VJsonSerdeRead() {
|
||||||
return string_hash("JsonSerdeRead");
|
return Name("JsonSerdeRead");
|
||||||
}
|
}
|
||||||
inline consteval size_t VJsonSerdeWrite() {
|
inline Name VJsonSerdeWrite() {
|
||||||
return string_hash("JsonSerdeWrite");
|
return Name("JsonSerdeWrite");
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void JsonArchive::Register()
|
inline void JsonArchive::Register()
|
||||||
|
|||||||
@ -6,14 +6,20 @@ namespace gen {
|
|||||||
struct Meta {};
|
struct Meta {};
|
||||||
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::same_as<std::string>;
|
||||||
};
|
};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
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>;
|
concept is_string_view_v = requires(T t) {
|
||||||
|
{ static_cast<std::string_view>(t) } -> std::same_as<std::string_view>;
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
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>
|
||||||
|
|| is_string_view_v<T>;
|
||||||
}
|
}
|
||||||
namespace api {
|
namespace api {
|
||||||
using meta::result;
|
using meta::result;
|
||||||
using std::string_view;
|
using std::string_view;
|
||||||
|
using pmr::Name;
|
||||||
enum class SerializeError : char
|
enum class SerializeError : char
|
||||||
{
|
{
|
||||||
SERDE_EMPTY,
|
SERDE_EMPTY,
|
||||||
|
|||||||
@ -16,6 +16,9 @@ namespace gen {
|
|||||||
else if constexpr (std::is_enum_v<T>) {
|
else if constexpr (std::is_enum_v<T>) {
|
||||||
*(T*)(ptr) = (T)node.as<uint32_t>();
|
*(T*)(ptr) = (T)node.as<uint32_t>();
|
||||||
}
|
}
|
||||||
|
else if constexpr (is_string_view_v<T>) {
|
||||||
|
*(T*)(ptr) = node.as<std::string_view>();
|
||||||
|
}
|
||||||
else if constexpr (is_string_v<T>) {
|
else if constexpr (is_string_v<T>) {
|
||||||
*(T*)(ptr) = node.as<std::string>();
|
*(T*)(ptr) = node.as<std::string>();
|
||||||
}
|
}
|
||||||
@ -31,13 +34,11 @@ namespace gen {
|
|||||||
else if constexpr (std::is_enum_v<T>) {
|
else if constexpr (std::is_enum_v<T>) {
|
||||||
return YAML::Node{ *(uint32_t*)(T*)ptr };
|
return YAML::Node{ *(uint32_t*)(T*)ptr };
|
||||||
}
|
}
|
||||||
|
else if constexpr (is_string_view_v<T>) {
|
||||||
|
return YAML::Node{ std::string_view(*(T*)ptr).data() };
|
||||||
|
}
|
||||||
else if constexpr (is_string_v<T>) {
|
else if constexpr (is_string_v<T>) {
|
||||||
if constexpr (requires(T * t) { t->data(); }) {
|
return YAML::Node{ std::string(*(T*)ptr).data() };
|
||||||
return YAML::Node{ ((T*)ptr)->data()};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return YAML::Node{ std::string(*(T*)ptr).data() };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//static_assert(false, "unknown json write type");
|
//static_assert(false, "unknown json write type");
|
||||||
|
|||||||
@ -7,11 +7,11 @@ namespace api {
|
|||||||
#include "../register.inl"
|
#include "../register.inl"
|
||||||
#undef RegisterAny
|
#undef RegisterAny
|
||||||
}
|
}
|
||||||
inline consteval size_t VYamlSerdeRead() {
|
inline Name VYamlSerdeRead() {
|
||||||
return string_hash("YamlSerdeRead");
|
return Name("YamlSerdeRead");
|
||||||
}
|
}
|
||||||
inline consteval size_t VYamlSerdeWrite() {
|
inline Name VYamlSerdeWrite() {
|
||||||
return string_hash("YamlSerdeWrite");
|
return Name("YamlSerdeWrite");
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void YamlArchive::Register()
|
inline void YamlArchive::Register()
|
||||||
|
|||||||
@ -27,8 +27,8 @@ namespace api {
|
|||||||
void Execute(FRenderView& view);
|
void Execute(FRenderView& view);
|
||||||
void Clear();
|
void Clear();
|
||||||
TextureDesc Resource(Name name) {
|
TextureDesc Resource(Name name) {
|
||||||
constexpr size_t surface = string_hash("surface");
|
static Name surface("surface");
|
||||||
if (name.Hash() == surface) {
|
if (name == surface) {
|
||||||
return mSurface;
|
return mSurface;
|
||||||
}
|
}
|
||||||
auto it = mResourceTable.find(name);
|
auto it = mResourceTable.find(name);
|
||||||
|
|||||||
@ -29,15 +29,15 @@ namespace api
|
|||||||
}
|
}
|
||||||
shaderc_shader_kind GlslToSpirv::GetShaderKind(Name name)
|
shaderc_shader_kind GlslToSpirv::GetShaderKind(Name name)
|
||||||
{
|
{
|
||||||
switch (name.Hash())
|
static Name vert(".vert");
|
||||||
{
|
static Name frag(".frag");
|
||||||
case string_hash(".vert"): return shaderc_shader_kind::shaderc_vertex_shader;
|
if (name == vert) {
|
||||||
case string_hash(".geom"): return shaderc_shader_kind::shaderc_geometry_shader;
|
return shaderc_shader_kind::shaderc_vertex_shader;
|
||||||
case string_hash(".tese"): return shaderc_shader_kind::shaderc_tess_evaluation_shader;
|
|
||||||
case string_hash(".tesc"): return shaderc_shader_kind::shaderc_tess_control_shader;
|
|
||||||
case string_hash(".frag"): return shaderc_shader_kind::shaderc_fragment_shader;
|
|
||||||
default: return shaderc_shader_kind::shaderc_miss_shader;
|
|
||||||
}
|
}
|
||||||
|
if(name == frag) {
|
||||||
|
return shaderc_shader_kind::shaderc_fragment_shader;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("unsupport type");
|
||||||
}
|
}
|
||||||
ShaderStage GlslToSpirv::GetShaderStage(shaderc_shader_kind kind)
|
ShaderStage GlslToSpirv::GetShaderStage(shaderc_shader_kind kind)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory_resource>
|
#include <memory_resource>
|
||||||
namespace pmr {
|
namespace pmr {
|
||||||
using std::pmr::unsynchronized_pool_resource;
|
|
||||||
using std::pmr::memory_resource;
|
using std::pmr::memory_resource;
|
||||||
using std::pmr::vector;
|
using std::pmr::vector;
|
||||||
class ZLIB_API FrameAllocator : public memory_resource {
|
class ZLIB_API FrameAllocator : public memory_resource {
|
||||||
|
|||||||
@ -1,81 +1,217 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <mutex>
|
||||||
|
#include <array>
|
||||||
#include "singleton.h"
|
#include "singleton.h"
|
||||||
#include "frame_allocator.h"
|
#include "frame_allocator.h"
|
||||||
#include <unordered_map>
|
namespace pmr {
|
||||||
namespace pmr
|
|
||||||
{
|
|
||||||
template<typename T1, typename T2, typename Hasher = std::hash<T1>>
|
|
||||||
using table = std::pmr::unordered_map<T1, T2, Hasher>;
|
|
||||||
using std::pmr::string;
|
|
||||||
static consteval inline size_t InvalidValue() noexcept { return static_cast<size_t>(-1); }
|
|
||||||
struct Name {
|
|
||||||
private:
|
|
||||||
size_t hash;
|
|
||||||
#ifdef API_DEBUG
|
|
||||||
std::string_view value;
|
|
||||||
#endif // API_DEBUG
|
|
||||||
public:
|
|
||||||
Name():hash(InvalidValue()) {};
|
|
||||||
template<size_t N>
|
|
||||||
Name(const char(&str)[N]) noexcept;
|
|
||||||
Name(const char* str)noexcept;
|
|
||||||
Name(const std::string& str)noexcept;
|
|
||||||
Name(const string& str)noexcept;
|
|
||||||
Name(std::string_view str)noexcept;
|
|
||||||
auto operator<=>(const Name& other) const noexcept { return hash <=> other.hash; };
|
|
||||||
const char* data()const { return ToStringView().data(); }
|
|
||||||
constexpr size_t Hash() const noexcept { return hash; }
|
|
||||||
std::string ToString() const;
|
|
||||||
const std::string_view ToStringView() const;
|
|
||||||
operator size_t()const {return hash;}
|
|
||||||
operator std::string() const { return ToString(); }
|
|
||||||
};
|
|
||||||
class CName {
|
|
||||||
private:
|
|
||||||
size_t hash;
|
|
||||||
std::string_view value;
|
|
||||||
public:
|
|
||||||
constexpr CName() noexcept : hash{ InvalidValue() } {}
|
|
||||||
constexpr CName(string str) noexcept : hash{ string_hash(str) }, value(str) {}
|
|
||||||
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(); }
|
|
||||||
operator Name() {return Name(value);}
|
|
||||||
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(); }
|
|
||||||
};
|
|
||||||
inline bool operator==(const CName& cname, const Name& name) {
|
|
||||||
return cname.Hash() == name.Hash();
|
|
||||||
}
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr inline void hash_combine(size_t& seed, const T& v) noexcept
|
constexpr inline void hash_combine(size_t& seed, const T& v) noexcept
|
||||||
{
|
{
|
||||||
std::hash<T> hasher;
|
std::hash<T> hasher;
|
||||||
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||||
}
|
}
|
||||||
consteval static CName FName(std::string_view view) { return CName{ view }; };
|
template<typename T1, typename T2, typename Hasher = std::hash<T1>>
|
||||||
}
|
using table = std::pmr::unordered_map<T1, T2, Hasher>;
|
||||||
namespace std {
|
using std::pmr::string;
|
||||||
template<>
|
class Name {
|
||||||
struct hash<::pmr::CName>
|
static constexpr uint32_t IS_USED_MASK = 1u << 29u;
|
||||||
{
|
static constexpr uint32_t STRING_ENTRY_HANDLE_BITS = 29u;
|
||||||
size_t operator()(const ::pmr::CName& name) const noexcept
|
static constexpr uint32_t STRING_ENTRY_HANDLE_MASK = (1u << 29u) - 1u;
|
||||||
|
static constexpr uint32_t MAX_STRING_SIZE = 1023u;
|
||||||
|
static constexpr uint32_t MAX_SLOT_POOL_ARRAY_SIZE = 256u;
|
||||||
|
static constexpr uint32_t MAX_MEMORY_BLOCK_ARRAY_SIZE = 8192u;
|
||||||
|
struct StringEntryHandle
|
||||||
{
|
{
|
||||||
return name.Hash();
|
static constexpr uint16_t MEMORY_BLOCK_INDEX_MASK = (1u << 13u) - 1u;
|
||||||
|
private:
|
||||||
|
uint16_t empty3_memoryBlockIndex13;
|
||||||
|
uint16_t memoryBlockAlignedOffset16;
|
||||||
|
public:
|
||||||
|
StringEntryHandle()
|
||||||
|
: empty3_memoryBlockIndex13(0u), memoryBlockAlignedOffset16(0u){}
|
||||||
|
StringEntryHandle(uint32_t stringEntryHandleValue)
|
||||||
|
: StringEntryHandle(static_cast<uint16_t>(stringEntryHandleValue >> 16)& MEMORY_BLOCK_INDEX_MASK, static_cast<uint16_t>(stringEntryHandleValue)) {}
|
||||||
|
StringEntryHandle(uint16_t memoryBlockIndex, uint16_t memoryBlockAlignedOffset)
|
||||||
|
: empty3_memoryBlockIndex13(memoryBlockIndex), memoryBlockAlignedOffset16(memoryBlockAlignedOffset) {}
|
||||||
|
uint16_t GetMemoryBlockIndex() const {
|
||||||
|
return empty3_memoryBlockIndex13;
|
||||||
|
}
|
||||||
|
uint16_t GetMemoryBlockAlignedOffset() const {
|
||||||
|
return memoryBlockAlignedOffset16;
|
||||||
|
}
|
||||||
|
uint32_t GetStringEntryHandleValue() const {
|
||||||
|
return static_cast<uint32_t>(empty3_memoryBlockIndex13) << 16 | memoryBlockAlignedOffset16;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct StringEntryHeader
|
||||||
|
{
|
||||||
|
static constexpr uint16_t SIZE_MASK = (1u << 10u) - 1u;
|
||||||
|
static constexpr uint16_t STRING_HASH_PROBE_MASK = ((1u << 6u) - 1u) << 10u;
|
||||||
|
private:
|
||||||
|
uint16_t stringHashProbe6_size10;
|
||||||
|
public:
|
||||||
|
void Init(const uint8_t stringHashProbe, const uint16_t size) {
|
||||||
|
stringHashProbe6_size10 = (STRING_HASH_PROBE_MASK & (static_cast<uint16_t>(stringHashProbe) << 10u)) | (SIZE_MASK & size);
|
||||||
|
}
|
||||||
|
uint16_t GetSize() const { return SIZE_MASK & stringHashProbe6_size10; }
|
||||||
|
operator uint16_t() { return stringHashProbe6_size10; }
|
||||||
|
};
|
||||||
|
struct StringEntry
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
StringEntryHeader stringEntryHeader;
|
||||||
|
char data[MAX_STRING_SIZE];
|
||||||
|
public:
|
||||||
|
StringEntryHeader GetStringEntryHeader() const {
|
||||||
|
return stringEntryHeader;
|
||||||
|
}
|
||||||
|
void SetStringEntryHeader(StringEntryHeader _stringEntryHeader) {
|
||||||
|
stringEntryHeader = _stringEntryHeader;
|
||||||
|
}
|
||||||
|
const char* GetData() const { return data; };
|
||||||
|
};
|
||||||
|
struct HashInfo {
|
||||||
|
static constexpr uint32_t SLOT_POOL_INDEX_MASK = (1u << 8u) - 1u;
|
||||||
|
static constexpr uint32_t SLOT_HASH_PROBE_MASK = ((1u << 3u) - 1) << 13u;
|
||||||
|
static constexpr uint32_t STRING_HASH_PROBE_MASK = (1u << 6u) - 1;
|
||||||
|
const char* data;
|
||||||
|
StringEntryHeader stringEntryHeader;
|
||||||
|
uint16_t slotProbe3_empty21_slotPool8;
|
||||||
|
uint32_t slotIndex32;
|
||||||
|
HashInfo(std::string_view view) {
|
||||||
|
uint64_t hash = string_hash(view);
|
||||||
|
uint32_t Hi = static_cast<uint32_t>(hash >> 32);
|
||||||
|
uint32_t Lo = static_cast<uint32_t>(hash);
|
||||||
|
|
||||||
|
slotIndex32 = Lo;
|
||||||
|
slotProbe3_empty21_slotPool8 = (SLOT_HASH_PROBE_MASK & (Hi >> 16)) | (SLOT_POOL_INDEX_MASK & Hi);
|
||||||
|
stringEntryHeader.Init((Hi >> 8u) & STRING_HASH_PROBE_MASK, view.size());
|
||||||
|
data = view.data();
|
||||||
|
}
|
||||||
|
const char* GetData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
uint32_t GetSlotIndex() const{
|
||||||
|
return slotIndex32;
|
||||||
|
}
|
||||||
|
StringEntryHeader GetStringEntryHeader() const {
|
||||||
|
return stringEntryHeader;
|
||||||
|
}
|
||||||
|
uint32_t GetSlotPoolIndex() const {
|
||||||
|
return SLOT_POOL_INDEX_MASK & slotProbe3_empty21_slotPool8;
|
||||||
|
}
|
||||||
|
template<uint32_t mask>
|
||||||
|
uint32_t GetSlotHashProbe() const
|
||||||
|
{
|
||||||
|
return mask | (SLOT_HASH_PROBE_MASK & slotProbe3_empty21_slotPool8) << 16;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Slot
|
||||||
|
{
|
||||||
|
static constexpr uint32_t SLOT_HASH_PROBE_MASK = ((1u << 3u) - 1) << 29u;
|
||||||
|
static constexpr uint32_t STRING_ENTRY_HANDLE_MASK = (1u << 29u) - 1u;
|
||||||
|
static constexpr uint32_t MEMORY_BLOCK_ALIGNED_OFFSET_MASK = (1u << 16u) - 1u;
|
||||||
|
static constexpr uint32_t MEMORY_BLOCK_INDEX_MASK = ((1u << 13u) - 1u);
|
||||||
|
private:
|
||||||
|
uint32_t slotHashProbe3_stringEntryHandle29;
|
||||||
|
public:
|
||||||
|
bool IsTargetSlot(HashInfo hashInfo) const;
|
||||||
|
bool IsUsed() const{ return (slotHashProbe3_stringEntryHandle29 & IS_USED_MASK) == IS_USED_MASK; }
|
||||||
|
uint32_t GetSlotHashProbe() const { return SLOT_HASH_PROBE_MASK & slotHashProbe3_stringEntryHandle29; };
|
||||||
|
StringEntryHandle GetStringEntryHandle() const {
|
||||||
|
return StringEntryHandle((slotHashProbe3_stringEntryHandle29 >> 16) & MEMORY_BLOCK_INDEX_MASK, slotHashProbe3_stringEntryHandle29 & MEMORY_BLOCK_ALIGNED_OFFSET_MASK);
|
||||||
|
}
|
||||||
|
uint32_t GetStringEntryHandleValue() const { return slotHashProbe3_stringEntryHandle29 & STRING_ENTRY_HANDLE_BITS; };
|
||||||
|
uint32_t GetSlotValue() const { return slotHashProbe3_stringEntryHandle29; };
|
||||||
|
void Load(uint32_t slotHashProbeValue,StringEntryHandle stringEntryHandle) {
|
||||||
|
slotHashProbe3_stringEntryHandle29 = slotHashProbeValue | stringEntryHandle.GetStringEntryHandleValue();
|
||||||
|
}
|
||||||
|
void Load(Slot srcSlot) {slotHashProbe3_stringEntryHandle29 = srcSlot.slotHashProbe3_stringEntryHandle29;}
|
||||||
|
};
|
||||||
|
struct SlotPool
|
||||||
|
{
|
||||||
|
friend class Name;
|
||||||
|
static constexpr double SLOT_POOL_RESIZE_USAGE_RATE = 0.9;
|
||||||
|
static constexpr uint32_t SLOT_POOL_INITIALIZE_SIZE = 256u;
|
||||||
|
private:
|
||||||
|
uint32_t capcity;
|
||||||
|
uint32_t size;
|
||||||
|
Slot* slotArray;
|
||||||
|
std::mutex mutex;
|
||||||
|
public:
|
||||||
|
Slot& FindUnusedOrTargetSlot(HashInfo hashInfo);
|
||||||
|
Slot& FindUnusedSlot(HashInfo hashInfo);
|
||||||
|
void AutoResize();
|
||||||
|
void Resize();
|
||||||
|
};
|
||||||
|
struct StringEntryMemoryManager
|
||||||
|
{
|
||||||
|
friend class Name;
|
||||||
|
static constexpr uint32_t ALIGN_BYTES = 2u;
|
||||||
|
static constexpr uint32_t MAX_MEMORY_BLOCK_SIZE = (1u << 16u) * 2u;
|
||||||
|
private:
|
||||||
|
uint16_t currentMemoryBlockIndex;
|
||||||
|
uint16_t currentMemoryBlockAlignedCursor;
|
||||||
|
char* memoryBlockArray[MAX_MEMORY_BLOCK_ARRAY_SIZE];
|
||||||
|
std::mutex mutex;
|
||||||
|
public:
|
||||||
|
StringEntryMemoryManager();
|
||||||
|
StringEntry* GetStringEntry(StringEntryHandle stringEntryHandle) const;
|
||||||
|
StringEntryHandle AllocateStringEntry(StringEntryHeader stringEntryHeader, const char* data);
|
||||||
|
private:
|
||||||
|
void CreateNewMemoryBlock();
|
||||||
|
};
|
||||||
|
using tSlotPoolArray = std::array<SlotPool, MAX_SLOT_POOL_ARRAY_SIZE>;
|
||||||
|
inline UNIQUER_STATIC(tSlotPoolArray, slotPoolArray, "pmr::name::slotPoolArray")
|
||||||
|
inline UNIQUER_STATIC(StringEntryMemoryManager, stringEntryMemoryManager, "pmr::name::stringEntryMemoryManager")
|
||||||
|
uint32_t flag3_memory29;
|
||||||
|
public:
|
||||||
|
Name()noexcept : flag3_memory29(0) {};
|
||||||
|
Name(std::string view) noexcept : flag3_memory29(MakeInterned(view)) {};
|
||||||
|
Name(std::string_view view) noexcept : flag3_memory29(MakeInterned(view)) {};
|
||||||
|
template<size_t N>
|
||||||
|
Name(const char(&str)[N]) noexcept : Name(std::string_view(str)) {}
|
||||||
|
Name(const char* str)noexcept : Name(std::string_view(str)){};
|
||||||
|
auto operator<=>(const Name& other) const noexcept { return flag3_memory29 <=> other.flag3_memory29; };
|
||||||
|
uint32_t MakeInterned(std::string_view view);
|
||||||
|
uint32_t Hash() const{
|
||||||
|
return flag3_memory29;
|
||||||
|
}
|
||||||
|
operator uint32_t() const {
|
||||||
|
return flag3_memory29;
|
||||||
|
}
|
||||||
|
operator std::string_view()const {
|
||||||
|
return ToStringView();
|
||||||
|
}
|
||||||
|
operator std::string()const {
|
||||||
|
return ToString();
|
||||||
|
}
|
||||||
|
const char* data()const {
|
||||||
|
if (!flag3_memory29)return nullptr;
|
||||||
|
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(StringEntryHandle(flag3_memory29));
|
||||||
|
return stringEntry->GetData();
|
||||||
|
}
|
||||||
|
std::string_view ToStringView() const
|
||||||
|
{
|
||||||
|
if (!flag3_memory29)return "";
|
||||||
|
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(StringEntryHandle(flag3_memory29));
|
||||||
|
return std::string_view(stringEntry->GetData(), stringEntry->GetStringEntryHeader().GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToString() const
|
||||||
|
{
|
||||||
|
if (!flag3_memory29)return "";
|
||||||
|
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(StringEntryHandle(flag3_memory29));
|
||||||
|
return std::string(stringEntry->GetData(), stringEntry->GetStringEntryHeader().GetSize());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
namespace std {
|
||||||
template<>
|
template<>
|
||||||
struct hash<::pmr::Name>
|
struct hash<::pmr::Name>
|
||||||
{
|
{
|
||||||
size_t operator()(const ::pmr::Name& name) const noexcept
|
uint32_t operator()(const ::pmr::Name& name) const noexcept
|
||||||
{
|
{
|
||||||
return name.Hash();
|
return name.Hash();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,74 +1,151 @@
|
|||||||
|
#include "name.h"
|
||||||
|
constexpr inline size_t meta_align_size(size_t size, size_t alignment = 8) {
|
||||||
|
return (size + alignment - 1) / alignment * alignment;
|
||||||
|
}
|
||||||
|
XMALLOC_API void* xmalloc(size_t size);
|
||||||
namespace pmr {
|
namespace pmr {
|
||||||
using NameTable_t = table<size_t,const string>;
|
inline bool Name::Slot::IsTargetSlot(HashInfo hashInfo) const
|
||||||
inline NameTable_t& TableRef() {
|
|
||||||
UNIQUER_STATIC(NameTable_t, Table, "pmr::nametable")
|
|
||||||
return UNIQUER_VAL(Table);
|
|
||||||
}
|
|
||||||
struct NameTable {
|
|
||||||
static const string& Find(size_t id);
|
|
||||||
template<typename T>
|
|
||||||
static std::string_view MakePair(size_t id, T&& str);
|
|
||||||
};
|
|
||||||
template<typename T>
|
|
||||||
inline std::string_view NameTable::MakePair(size_t id, T&& str)
|
|
||||||
{
|
{
|
||||||
auto& Table = TableRef();
|
if (GetSlotHashProbe() == hashInfo.GetSlotHashProbe<IS_USED_MASK>())
|
||||||
auto it = Table.find(id);
|
{
|
||||||
if (it == Table.end()) {
|
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(GetStringEntryHandle());
|
||||||
auto it2 = Table.emplace(std::make_pair(id, string(str, Table.get_allocator())));
|
auto entryHeader = stringEntry->GetStringEntryHeader();
|
||||||
if (it2.second) {
|
if (entryHeader == hashInfo.GetStringEntryHeader() && 0 == strncmp(stringEntry->GetData(), hashInfo.GetData(), entryHeader.GetSize()))
|
||||||
return it2.first->second;
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
return it->second;
|
return false;
|
||||||
}
|
}
|
||||||
inline const string& NameTable::Find(size_t id)
|
inline Name::Slot& Name::SlotPool::FindUnusedOrTargetSlot(HashInfo hashInfo)
|
||||||
{
|
{
|
||||||
auto& Table = TableRef();
|
const uint32_t SLOT_POOL_CAPCITY_MASK = capcity - 1;
|
||||||
auto it = Table.find(id);
|
for (uint32_t slotIndex = hashInfo.GetSlotIndex() & SLOT_POOL_CAPCITY_MASK; true; slotIndex = (slotIndex + 1) & SLOT_POOL_CAPCITY_MASK)
|
||||||
if (it == Table.end()) {
|
{
|
||||||
static string empty("", Table.get_allocator());
|
Slot& slot = slotArray[slotIndex];
|
||||||
return empty;
|
|
||||||
|
if (!slot.IsUsed() || slot.IsTargetSlot(hashInfo))
|
||||||
|
{
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
#ifdef API_DEBUG
|
inline Name::Slot& Name::SlotPool::FindUnusedSlot(HashInfo hashInfo)
|
||||||
#define MAKE_NAME_PAIR(hash, str) value = NameTable::MakePair(hash, str)
|
|
||||||
#define NAME_TO_STRING value
|
|
||||||
#else
|
|
||||||
#define MAKE_NAME_PAIR(hash, str) NameTable::MakePair(hash, str)
|
|
||||||
#define NAME_TO_STRING NameTable::Find(hash)
|
|
||||||
#endif
|
|
||||||
inline std::string Name::ToString() const
|
|
||||||
{
|
{
|
||||||
return std::string(NAME_TO_STRING);
|
const uint32_t SLOT_POOL_CAPCITY_MASK = capcity - 1;
|
||||||
|
for (uint32_t slotIndex = hashInfo.GetSlotIndex() & SLOT_POOL_CAPCITY_MASK; true; slotIndex = (slotIndex + 1) & SLOT_POOL_CAPCITY_MASK)
|
||||||
|
{
|
||||||
|
Slot& slot = slotArray[slotIndex];
|
||||||
|
|
||||||
|
if (!slot.IsUsed())
|
||||||
|
{
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inline const std::string_view Name::ToStringView() const
|
inline void Name::SlotPool::AutoResize()
|
||||||
{
|
{
|
||||||
return std::string_view(NAME_TO_STRING);
|
if (size > SLOT_POOL_RESIZE_USAGE_RATE * capcity)
|
||||||
|
{
|
||||||
|
Resize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inline Name::Name(const char* str) noexcept: hash(string_hash(str))
|
inline void Name::SlotPool::Resize()
|
||||||
{
|
{
|
||||||
MAKE_NAME_PAIR(hash, str);
|
uint32_t oldCapcity = capcity;
|
||||||
|
Slot* oldSlotArray = slotArray;
|
||||||
|
|
||||||
|
capcity = oldCapcity * 2;
|
||||||
|
slotArray = reinterpret_cast<Slot*>(xmalloc(capcity * sizeof(Slot)));
|
||||||
|
//std::memset(slotArray, 0, capcity * sizeof(Slot));
|
||||||
|
auto& stringEntryMemoryManager = UNIQUER_VAL(stringEntryMemoryManager);
|
||||||
|
for (uint32_t slotIndex = 0; slotIndex < size; slotIndex++)
|
||||||
|
{
|
||||||
|
const Name::Slot& oldSlot = oldSlotArray[slotIndex];
|
||||||
|
|
||||||
|
StringEntry* stringEntry = stringEntryMemoryManager.GetStringEntry(oldSlotArray[slotIndex].GetStringEntryHandle());
|
||||||
|
const HashInfo hashInfo(std::string_view(stringEntry->GetData(), stringEntry->GetStringEntryHeader().GetSize()));
|
||||||
|
|
||||||
|
Name::Slot& slot = FindUnusedSlot(hashInfo);
|
||||||
|
|
||||||
|
slot.Load(oldSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::free(oldSlotArray);
|
||||||
}
|
}
|
||||||
template<std::size_t N>
|
inline Name::StringEntryMemoryManager::StringEntryMemoryManager()
|
||||||
inline Name::Name(const char(&str)[N]) noexcept : hash(string_hash(str))
|
|
||||||
{
|
{
|
||||||
MAKE_NAME_PAIR(hash, str);
|
auto& slotPoolArray = UNIQUER_VAL(slotPoolArray);
|
||||||
|
for (auto& slotPool : slotPoolArray)
|
||||||
|
{
|
||||||
|
slotPool.size = 0;
|
||||||
|
slotPool.capcity = SlotPool::SLOT_POOL_INITIALIZE_SIZE;
|
||||||
|
slotPool.slotArray = (Slot*)(xmalloc(SlotPool::SLOT_POOL_INITIALIZE_SIZE * sizeof(Slot)));
|
||||||
|
std::memset(slotPool.slotArray, 0, SlotPool::SLOT_POOL_INITIALIZE_SIZE);
|
||||||
|
}
|
||||||
|
currentMemoryBlockIndex = 0;
|
||||||
|
currentMemoryBlockAlignedCursor = 0;
|
||||||
|
memoryBlockArray[0] = (char*)(xmalloc(MAX_MEMORY_BLOCK_SIZE));
|
||||||
|
std::memset(memoryBlockArray[0], 0, MAX_MEMORY_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
inline Name::Name(const std::string& str) noexcept : hash(string_hash(str))
|
inline Name::StringEntry* Name::StringEntryMemoryManager::GetStringEntry(StringEntryHandle stringEntryHandle) const
|
||||||
{
|
{
|
||||||
MAKE_NAME_PAIR(hash, str);
|
return reinterpret_cast<Name::StringEntry*>(memoryBlockArray[stringEntryHandle.GetMemoryBlockIndex()] + stringEntryHandle.GetMemoryBlockAlignedOffset() * ALIGN_BYTES);
|
||||||
}
|
}
|
||||||
inline Name::Name(std::string_view str) noexcept : hash(string_hash(str))
|
inline Name::StringEntryHandle Name::StringEntryMemoryManager::AllocateStringEntry(StringEntryHeader stringEntryHeader, const char* data)
|
||||||
{
|
{
|
||||||
MAKE_NAME_PAIR(hash, str);
|
const uint32_t size = meta_align_size(sizeof(StringEntryHeader) + stringEntryHeader.GetSize(), ALIGN_BYTES);
|
||||||
|
const uint32_t alignedSize = size >> 1;
|
||||||
|
|
||||||
|
StringEntryHandle stringEntryHandle{};
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
if (((static_cast<uint32_t>(currentMemoryBlockAlignedCursor) + alignedSize) << 1) >= MAX_MEMORY_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
CreateNewMemoryBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
stringEntryHandle = StringEntryHandle(currentMemoryBlockIndex, currentMemoryBlockAlignedCursor);
|
||||||
|
currentMemoryBlockAlignedCursor += alignedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringEntry* stringEntry = GetStringEntry(stringEntryHandle);
|
||||||
|
stringEntry->SetStringEntryHeader(stringEntryHeader);
|
||||||
|
memcpy(const_cast<char*>(stringEntry->GetData()), data, stringEntryHeader.GetSize());
|
||||||
|
|
||||||
|
return stringEntryHandle;
|
||||||
}
|
}
|
||||||
inline Name::Name(const string& str)noexcept : hash(string_hash(str))
|
inline void Name::StringEntryMemoryManager::CreateNewMemoryBlock()
|
||||||
{
|
{
|
||||||
MAKE_NAME_PAIR(hash, str);
|
if (currentMemoryBlockIndex >= (MAX_MEMORY_BLOCK_ARRAY_SIZE - 1))
|
||||||
|
throw std::runtime_error("Interned string only supports a maximum of 1GB memory.");
|
||||||
|
|
||||||
|
currentMemoryBlockIndex += 1;
|
||||||
|
currentMemoryBlockAlignedCursor = 0;
|
||||||
|
memoryBlockArray[currentMemoryBlockIndex] = (char*)(xmalloc(MAX_MEMORY_BLOCK_SIZE));
|
||||||
|
std::memset(memoryBlockArray[currentMemoryBlockIndex], 0, MAX_MEMORY_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
inline uint32_t Name::MakeInterned(std::string_view view)
|
||||||
|
{
|
||||||
|
if (view.empty()) {
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
HashInfo hashInfo(view);
|
||||||
|
auto& slotPool = UNIQUER_VAL(slotPoolArray)[0];
|
||||||
|
uint32_t slotValue = 0u;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(slotPool.mutex);
|
||||||
|
slotPool.AutoResize();
|
||||||
|
Name::Slot& slot = slotPool.FindUnusedOrTargetSlot(hashInfo);
|
||||||
|
if (!slot.IsUsed())
|
||||||
|
{
|
||||||
|
slotPool.size++;
|
||||||
|
StringEntryHandle stringEntryHandle = UNIQUER_VAL(stringEntryMemoryManager).AllocateStringEntry(hashInfo.GetStringEntryHeader(), hashInfo.GetData());
|
||||||
|
slot.Load(hashInfo.GetSlotHashProbe<IS_USED_MASK>(), stringEntryHandle);
|
||||||
|
}
|
||||||
|
slotValue = slot.GetSlotValue();
|
||||||
|
}
|
||||||
|
return slotValue;
|
||||||
}
|
}
|
||||||
#undef MAKE_NAME_PAIR
|
|
||||||
#undef NAME_TO_STRING
|
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@ namespace refl {
|
|||||||
operator bool()const { return cls && ptr; }
|
operator bool()const { return cls && ptr; }
|
||||||
bool Check(const UClass* parent) const;
|
bool Check(const UClass* parent) const;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T FindVtable(size_t name)const;
|
T FindVtable(Name name)const;
|
||||||
bool Construct(span<Any> ArgsList) const;
|
bool Construct(span<Any> ArgsList) const;
|
||||||
Any New(pmr::memory_resource* pool)const;
|
Any New(pmr::memory_resource* pool)const;
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace refl{
|
|||||||
return any;
|
return any;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T Any::FindVtable(size_t name) const
|
inline T Any::FindVtable(Name name) const
|
||||||
{
|
{
|
||||||
return (T)cls->vtable.Find(name);
|
return (T)cls->vtable.Find(name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "field.h"
|
#include "field.h"
|
||||||
constexpr inline size_t meta_align_size(size_t size, size_t alignment = 8) {
|
|
||||||
return (size + alignment - 1) / alignment * alignment;
|
|
||||||
}
|
|
||||||
namespace gen {
|
namespace gen {
|
||||||
using refl::real_type_t;
|
using refl::real_type_t;
|
||||||
using pmr::CName;
|
|
||||||
using pmr::FName;
|
|
||||||
template<typename T, size_t hash>
|
template<typename T, size_t hash>
|
||||||
struct MetaImpl {};
|
struct MetaImpl {};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -38,16 +33,16 @@ namespace refl {
|
|||||||
static FieldPtr CtorField(T(*ptr)(Args...), const MethodData& data = {});
|
static FieldPtr CtorField(T(*ptr)(Args...), const MethodData& data = {});
|
||||||
|
|
||||||
template<typename T, typename Obj>
|
template<typename T, typename Obj>
|
||||||
static FieldPtr MemberField(T Obj::* ptr, CName name, const MemberData& data = {});
|
static FieldPtr MemberField(T Obj::* ptr, std::string_view name, const MemberData& data = {});
|
||||||
|
|
||||||
template<typename R, typename ...Args>
|
template<typename R, typename ...Args>
|
||||||
static FieldPtr MethodField(R(*ptr)(Args...), CName name, const MethodData& data = {});
|
static FieldPtr MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data = {});
|
||||||
|
|
||||||
template<typename T, typename R, typename ...Args>
|
template<typename T, typename R, typename ...Args>
|
||||||
static FieldPtr MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data = {});
|
static FieldPtr MethodField(R(T::* ptr)(Args...), std::string_view name, const MethodData& data = {});
|
||||||
|
|
||||||
template<typename T, typename R, typename ...Args>
|
template<typename T, typename R, typename ...Args>
|
||||||
static FieldPtr MethodField(R(T::* ptr)(Args...)const, CName name, const MethodData& data = {}) {
|
static FieldPtr MethodField(R(T::* ptr)(Args...)const, std::string_view name, const MethodData& data = {}) {
|
||||||
return MethodField(remove_const(ptr), name, data);
|
return MethodField(remove_const(ptr), name, data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -43,7 +43,7 @@ namespace refl {
|
|||||||
return FieldPtr{Name("Ctor"), cls, method, flag};
|
return FieldPtr{Name("Ctor"), cls, method, flag};
|
||||||
}
|
}
|
||||||
template<typename T, typename Obj>
|
template<typename T, typename Obj>
|
||||||
inline FieldPtr MetaHelp::MemberField(T Obj::* ptr, CName name, const MemberData& data)
|
inline FieldPtr MetaHelp::MemberField(T Obj::* ptr, std::string_view name, const MemberData& data)
|
||||||
{
|
{
|
||||||
const UClass* cls = meta_info<T>();
|
const UClass* cls = meta_info<T>();
|
||||||
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_CTOR_FLAG;
|
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_CTOR_FLAG;
|
||||||
@ -58,7 +58,7 @@ namespace refl {
|
|||||||
return FieldPtr{ name, cls, member, flag };
|
return FieldPtr{ name, cls, member, flag };
|
||||||
}
|
}
|
||||||
template<typename R, typename ...Args>
|
template<typename R, typename ...Args>
|
||||||
inline FieldPtr MetaHelp::MethodField(R(*ptr)(Args...), CName name, const MethodData& data)
|
inline FieldPtr MetaHelp::MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data)
|
||||||
{
|
{
|
||||||
MethodData method;
|
MethodData method;
|
||||||
uint32_t flag = FIELD_METHOD_FLAG;
|
uint32_t flag = FIELD_METHOD_FLAG;
|
||||||
@ -74,7 +74,7 @@ namespace refl {
|
|||||||
return { name, cls, method,flag };
|
return { name, cls, method,flag };
|
||||||
}
|
}
|
||||||
template<typename T, typename R, typename ...Args>
|
template<typename T, typename R, typename ...Args>
|
||||||
inline FieldPtr MetaHelp::MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data) {
|
inline FieldPtr MetaHelp::MethodField(R(T::* ptr)(Args...), std::string_view name, const MethodData& data) {
|
||||||
MethodData method;
|
MethodData method;
|
||||||
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
|
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
|
||||||
const UClass* cls = meta_info<real_type_t<R>(*)(const void*, real_type_t<Args>...)>();
|
const UClass* cls = meta_info<real_type_t<R>(*)(const void*, real_type_t<Args>...)>();
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "pmr/name.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
namespace refl {
|
namespace refl {
|
||||||
|
using pmr::Name;
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
struct TStr {
|
struct TStr {
|
||||||
std::array<char, N> value{}; // 确切长度的字符数组,不依赖 '\0'
|
std::array<char, N> value{}; // 确切长度的字符数组,不依赖 '\0'
|
||||||
@ -23,8 +25,6 @@ namespace refl {
|
|||||||
template <size_t N>
|
template <size_t N>
|
||||||
TStr(const char(&)[N]) -> TStr<N - 1>;
|
TStr(const char(&)[N]) -> TStr<N - 1>;
|
||||||
|
|
||||||
template<auto v>
|
template<typename T>
|
||||||
constexpr auto value_name() noexcept;
|
Name meta_name()noexcept;
|
||||||
template<typename T>
|
|
||||||
constexpr auto meta_name() noexcept;
|
|
||||||
}
|
}
|
||||||
@ -15,7 +15,7 @@ namespace refl {
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr auto raw_meta_name() noexcept {
|
constexpr auto raw_meta_tstr() noexcept {
|
||||||
constexpr std::string_view sign = func_signature<T>();
|
constexpr std::string_view sign = func_signature<T>();
|
||||||
constexpr size_t size = sign.size();
|
constexpr size_t size = sign.size();
|
||||||
return TStr<size>{ sign };
|
return TStr<size>{ sign };
|
||||||
@ -32,7 +32,7 @@ namespace refl {
|
|||||||
return num < 10 ? 1 : 1 + _num_digits(num / 10);
|
return num < 10 ? 1 : 1 + _num_digits(num / 10);
|
||||||
}
|
}
|
||||||
template <int N, int Digits = _num_digits(N)>
|
template <int N, int Digits = _num_digits(N)>
|
||||||
constexpr auto num_name() {
|
constexpr auto num_tstr() {
|
||||||
char data[Digits + 1];
|
char data[Digits + 1];
|
||||||
int n = N;
|
int n = N;
|
||||||
for (int i = Digits - 1; i >= 0; --i) {
|
for (int i = Digits - 1; i >= 0; --i) {
|
||||||
@ -42,7 +42,7 @@ namespace refl {
|
|||||||
return TStr{ data };
|
return TStr{ data };
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr auto num_prefix_name() {
|
constexpr auto num_prefix_tstr() {
|
||||||
if constexpr (std::is_integral_v<T>) {
|
if constexpr (std::is_integral_v<T>) {
|
||||||
if constexpr (std::is_signed_v<T>) {
|
if constexpr (std::is_signed_v<T>) {
|
||||||
return TStr{ "S" };
|
return TStr{ "S" };
|
||||||
@ -60,7 +60,7 @@ namespace refl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<auto v>
|
template<auto v>
|
||||||
constexpr auto value_name()noexcept {
|
constexpr auto value_tstr()noexcept {
|
||||||
using T = decltype(v);
|
using T = decltype(v);
|
||||||
if constexpr (std::is_null_pointer_v<T>)
|
if constexpr (std::is_null_pointer_v<T>)
|
||||||
return TStr{ "nullptr" };
|
return TStr{ "nullptr" };
|
||||||
@ -95,13 +95,13 @@ namespace refl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr auto meta_name() noexcept {
|
constexpr auto meta_tstr() noexcept {
|
||||||
if constexpr (std::is_same_v<T, void>) {
|
if constexpr (std::is_same_v<T, void>) {
|
||||||
return TStr{ "void" };
|
return TStr{ "void" };
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_arithmetic_v<T>) {
|
else if constexpr (std::is_arithmetic_v<T>) {
|
||||||
constexpr auto prefix = detail::num_prefix_name<T>();
|
constexpr auto prefix = detail::num_prefix_tstr<T>();
|
||||||
constexpr auto bit = detail::num_name<8 * sizeof(T)>();
|
constexpr auto bit = detail::num_tstr<8 * sizeof(T)>();
|
||||||
return concat_seq(prefix, bit);
|
return concat_seq(prefix, bit);
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_array_v<T>) {
|
else if constexpr (std::is_array_v<T>) {
|
||||||
@ -109,20 +109,26 @@ namespace refl {
|
|||||||
constexpr auto ex = std::extent_v<T, 0>;
|
constexpr auto ex = std::extent_v<T, 0>;
|
||||||
if constexpr (r == 1) {
|
if constexpr (r == 1) {
|
||||||
if constexpr (ex == 0)
|
if constexpr (ex == 0)
|
||||||
return concat_seq(TStr{"[]{"}, meta_name<std::remove_extent_t<T>>(), TStr{"}"});
|
return concat_seq(TStr{"[]{"}, meta_tstr<std::remove_extent_t<T>>(), TStr{"}"});
|
||||||
else
|
else
|
||||||
return concat_seq(TStr{"["}, detail::num_name<ex>(), TStr{"]{"}, meta_name<std::remove_extent_t<T>>(), TStr{"}"});
|
return concat_seq(TStr{"["}, detail::num_tstr<ex>(), TStr{"]{"}, meta_tstr<std::remove_extent_t<T>>(), TStr{"}"});
|
||||||
}
|
}
|
||||||
else { // r > 1
|
else { // r > 1
|
||||||
static_assert(r > 1);
|
static_assert(r > 1);
|
||||||
if constexpr (ex == 0)
|
if constexpr (ex == 0)
|
||||||
return concat_seq(TStr{"[]"}, type_name<std::remove_extent_t<T>>());
|
return concat_seq(TStr{"[]"}, type_name<std::remove_extent_t<T>>());
|
||||||
else
|
else
|
||||||
return concat_seq(TStr{"["}, detail::num_name<ex>(), TStr{"]"}, meta_name<std::remove_extent_t<T>>());
|
return concat_seq(TStr{"["}, detail::num_tstr<ex>(), TStr{"]"}, meta_tstr<std::remove_extent_t<T>>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return detail::raw_meta_name<T>();
|
return detail::raw_meta_tstr<T>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
Name meta_name() noexcept
|
||||||
|
{
|
||||||
|
auto view = meta_tstr<T>().view();
|
||||||
|
return Name(view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -7,8 +7,6 @@
|
|||||||
namespace refl {
|
namespace refl {
|
||||||
using std::span;
|
using std::span;
|
||||||
using pmr::Name;
|
using pmr::Name;
|
||||||
using pmr::CName;
|
|
||||||
using pmr::FName;
|
|
||||||
using pmr::table;
|
using pmr::table;
|
||||||
namespace detail {
|
namespace detail {
|
||||||
// 定义一个模板结构体用于检测是否为 数组
|
// 定义一个模板结构体用于检测是否为 数组
|
||||||
|
|||||||
@ -26,11 +26,11 @@ namespace refl {
|
|||||||
struct vtable_uclass
|
struct vtable_uclass
|
||||||
{
|
{
|
||||||
struct Node {
|
struct Node {
|
||||||
size_t name;
|
Name name;
|
||||||
void* method;
|
void* method;
|
||||||
Node* next;
|
Node* next;
|
||||||
Node(size_t name, void* ptr) :name(name), method(ptr), next(nullptr) {}
|
Node(Name name, void* ptr) :name(name), method(ptr), next(nullptr) {}
|
||||||
Node* Insert(size_t name, void* ptr) {
|
Node* Insert(Name name, void* ptr) {
|
||||||
Node* it = new Node(name, ptr);
|
Node* it = new Node(name, ptr);
|
||||||
next = it;
|
next = it;
|
||||||
return it;
|
return it;
|
||||||
@ -39,9 +39,6 @@ namespace refl {
|
|||||||
Node* header{nullptr};
|
Node* header{nullptr};
|
||||||
operator bool() { return header; }
|
operator bool() { return header; }
|
||||||
void Add(Name name, void* ptr) {
|
void Add(Name name, void* ptr) {
|
||||||
Add(name.Hash(), ptr);
|
|
||||||
}
|
|
||||||
void Add(size_t name, void* ptr) {
|
|
||||||
auto [bfind, it] = FindLast(name);
|
auto [bfind, it] = FindLast(name);
|
||||||
if (bfind) {
|
if (bfind) {
|
||||||
return;
|
return;
|
||||||
@ -50,7 +47,7 @@ namespace refl {
|
|||||||
Node** prev= it ? &(it->next) : &header;
|
Node** prev= it ? &(it->next) : &header;
|
||||||
*prev = next;
|
*prev = next;
|
||||||
}
|
}
|
||||||
std::pair<bool,Node*> FindLast(size_t name) const{
|
std::pair<bool,Node*> FindLast(Name name) const{
|
||||||
Node *prev = nullptr, *it = header;
|
Node *prev = nullptr, *it = header;
|
||||||
while (it) {
|
while (it) {
|
||||||
if (it->name == name) {
|
if (it->name == name) {
|
||||||
@ -61,7 +58,7 @@ namespace refl {
|
|||||||
}
|
}
|
||||||
return std::make_pair(false, prev);
|
return std::make_pair(false, prev);
|
||||||
}
|
}
|
||||||
void* Find(size_t name) const {
|
void* Find(Name name) const {
|
||||||
Node* it = header;
|
Node* it = header;
|
||||||
while (it) {
|
while (it) {
|
||||||
if (it->name == name) {
|
if (it->name == name) {
|
||||||
@ -81,25 +78,25 @@ namespace refl {
|
|||||||
using Construct_t = bool (*)(void* ptr, const UClass* cls,span<Any> ArgsList);
|
using Construct_t = bool (*)(void* ptr, const UClass* cls,span<Any> ArgsList);
|
||||||
using Destruct_t = void (*)(void*);
|
using Destruct_t = void (*)(void*);
|
||||||
void AddGetFields(GetFields_t func) {
|
void AddGetFields(GetFields_t func) {
|
||||||
Add(string_hash("GetFields"), (void*)func);
|
Add(Name("GetFields"), (void*)func);
|
||||||
}
|
}
|
||||||
void AddGetParams(GetParams_t func) {
|
void AddGetParams(GetParams_t func) {
|
||||||
Add(string_hash("GetParams"), (void*)func);
|
Add(Name("GetParams"), (void*)func);
|
||||||
}
|
}
|
||||||
void AddCall(Call_t func) {
|
void AddCall(Call_t func) {
|
||||||
Add(string_hash("Call"), (void*)func);
|
Add(Name("Call"), (void*)func);
|
||||||
}
|
}
|
||||||
void AddConstruct(Construct_t func) {
|
void AddConstruct(Construct_t func) {
|
||||||
Add(string_hash("Construct"), (void*)func);
|
Add(Name("Construct"), (void*)func);
|
||||||
}
|
}
|
||||||
void AddDestruct(Destruct_t func) {
|
void AddDestruct(Destruct_t func) {
|
||||||
Add(string_hash("Destruct"), (void*)func);
|
Add(Name("Destruct"), (void*)func);
|
||||||
}
|
}
|
||||||
GetFields_t GetFields() const { return (GetFields_t) Find(string_hash("GetFields")); }
|
GetFields_t GetFields() const { return (GetFields_t) Find(Name("GetFields")); }
|
||||||
GetParams_t GetParams() const { return (GetParams_t) Find(string_hash("GetParams")); }
|
GetParams_t GetParams() const { return (GetParams_t) Find(Name("GetParams")); }
|
||||||
Call_t Call() const { return (Call_t) Find(string_hash("Call")); }
|
Call_t Call() const { return (Call_t) Find(Name("Call")); }
|
||||||
Construct_t Construct() const { return (Construct_t) Find(string_hash("Construct")); }
|
Construct_t Construct() const { return (Construct_t) Find(Name("Construct")); }
|
||||||
Destruct_t Destruct() const { return (Destruct_t) Find(string_hash("Destruct")); }
|
Destruct_t Destruct() const { return (Destruct_t) Find(Name("Destruct")); }
|
||||||
};
|
};
|
||||||
class UClass {
|
class UClass {
|
||||||
public:
|
public:
|
||||||
@ -111,7 +108,7 @@ namespace refl {
|
|||||||
UClass(const UClass*) = delete;
|
UClass(const UClass*) = delete;
|
||||||
UClass& operator=(const UClass*) = delete;
|
UClass& operator=(const UClass*) = delete;
|
||||||
public:
|
public:
|
||||||
UClass(std::string_view name, uint32_t size, const UClass* parent = nullptr)
|
UClass(Name name, uint32_t size, const UClass* parent = nullptr)
|
||||||
:name(name), size(size), parent(parent) {}
|
:name(name), size(size), parent(parent) {}
|
||||||
Any New(pmr::memory_resource* pool, span<Any> ArgsList = {}) const {
|
Any New(pmr::memory_resource* pool, span<Any> ArgsList = {}) const {
|
||||||
void* ptr = pool->allocate(size);
|
void* ptr = pool->allocate(size);
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace refl {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class UClass_Auto : public UClass {
|
class UClass_Auto : public UClass {
|
||||||
public:
|
public:
|
||||||
UClass_Auto() : UClass(meta_name<T>().view(), sizeof(T)) {
|
UClass_Auto() : UClass(meta_name<T>(), sizeof(T)) {
|
||||||
if constexpr (std::is_pointer_v<T>) {
|
if constexpr (std::is_pointer_v<T>) {
|
||||||
using RT = std::remove_pointer_t<T>;
|
using RT = std::remove_pointer_t<T>;
|
||||||
flag |= CLASS_POINTER_FLAG;
|
flag |= CLASS_POINTER_FLAG;
|
||||||
@ -38,7 +38,7 @@ namespace refl {
|
|||||||
using MethodType = R(*)(Args...);
|
using MethodType = R(*)(Args...);
|
||||||
public:
|
public:
|
||||||
std::array<const UClass*, sizeof...(Args) + 1> UList{};
|
std::array<const UClass*, sizeof...(Args) + 1> UList{};
|
||||||
UMethod_Auto() : UClass(meta_name<MethodType>().view(), sizeof(MethodType)) {
|
UMethod_Auto() : UClass(meta_name<MethodType>(), sizeof(MethodType)) {
|
||||||
flag = CLASS_TRIVIAL_FLAG;
|
flag = CLASS_TRIVIAL_FLAG;
|
||||||
vtable.AddGetParams(&UMethod_Auto::GetParams);
|
vtable.AddGetParams(&UMethod_Auto::GetParams);
|
||||||
vtable.AddCall(&UMethod_Auto::Call);
|
vtable.AddCall(&UMethod_Auto::Call);
|
||||||
@ -137,7 +137,7 @@ namespace refl {
|
|||||||
memcpy(pit, &it, sizeof(it));
|
memcpy(pit, &it, sizeof(it));
|
||||||
pit->val = &*it;
|
pit->val = &*it;
|
||||||
}
|
}
|
||||||
UClass_Container() : UClass_Container_Impl(meta_name<T>().view(), sizeof(T)) {
|
UClass_Container() : UClass_Container_Impl(meta_name<T>(), sizeof(T)) {
|
||||||
parent = meta_info<value_type>();
|
parent = meta_info<value_type>();
|
||||||
flag = CLASS_CONTAINER_FLAG;
|
flag = CLASS_CONTAINER_FLAG;
|
||||||
vtable.AddConstruct(&UClass_Container::construct);
|
vtable.AddConstruct(&UClass_Container::construct);
|
||||||
@ -164,7 +164,7 @@ namespace refl {
|
|||||||
using FieldsType = decltype(MetaImpl::MakeFields());
|
using FieldsType = decltype(MetaImpl::MakeFields());
|
||||||
public:
|
public:
|
||||||
FieldsType Fields{ MetaImpl::MakeFields() };
|
FieldsType Fields{ MetaImpl::MakeFields() };
|
||||||
UClass_Meta() : UClass(meta_name<T>().view(), sizeof(T)) {
|
UClass_Meta() : UClass(meta_name<T>(), sizeof(T)) {
|
||||||
if constexpr (has_parent_v<T>) {
|
if constexpr (has_parent_v<T>) {
|
||||||
parent = meta_info<parent_t<T>>();
|
parent = meta_info<parent_t<T>>();
|
||||||
}
|
}
|
||||||
@ -281,8 +281,8 @@ namespace refl {
|
|||||||
inline const UClass* meta_info()
|
inline const UClass* meta_info()
|
||||||
{
|
{
|
||||||
using T = real_type_t<Type>;
|
using T = real_type_t<Type>;
|
||||||
constexpr auto name = meta_name<T>();
|
auto name = meta_name<T>();
|
||||||
if (auto cls = find_info(name.view())) {
|
if (auto cls = find_info(name)) {
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
UClass* cls;
|
UClass* cls;
|
||||||
@ -290,27 +290,27 @@ namespace refl {
|
|||||||
cls = new(MetaGlobalPool()) UClass_Meta<T, meta_t<T>>{};
|
cls = new(MetaGlobalPool()) UClass_Meta<T, meta_t<T>>{};
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<T, void>) {
|
else if constexpr (std::is_same_v<T, void>) {
|
||||||
cls = new(MetaGlobalPool()) UClass{ name.view(), 0 };
|
cls = new(MetaGlobalPool()) UClass{ name, 0 };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cls = meta_info_impl<T>::create();
|
cls = meta_info_impl<T>::create();
|
||||||
}
|
}
|
||||||
auto& ClassTable = UNIQUER_VAL(ClassTable);
|
auto& ClassTable = UNIQUER_VAL(ClassTable);
|
||||||
ClassTable[name.view()] = cls;
|
ClassTable[name] = cls;
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
template<typename T, size_t hash>
|
template<typename T, size_t hash>
|
||||||
inline const UClass* meta_info()
|
inline const UClass* meta_info()
|
||||||
{
|
{
|
||||||
if constexpr (have_meta_impl_v<T, hash>) {
|
if constexpr (have_meta_impl_v<T, hash>) {
|
||||||
constexpr auto name = meta_name<T>();
|
auto name = meta_name<T>();
|
||||||
const UClass* cls = find_info(name.view(), hash);
|
const UClass* cls = find_info(name, hash);
|
||||||
if (cls) {
|
if (cls) {
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
cls = new(MetaGlobalPool()) UClass_Meta<T, gen::MetaImpl<T, hash>>{};
|
cls = new(MetaGlobalPool()) UClass_Meta<T, gen::MetaImpl<T, hash>>{};
|
||||||
auto& MetaClassTable = UNIQUER_VAL(MetaClassTable);
|
auto& MetaClassTable = UNIQUER_VAL(MetaClassTable);
|
||||||
if (auto it = MetaClassTable.find(name.view()); it != MetaClassTable.end()) {
|
if (auto it = MetaClassTable.find(name); it != MetaClassTable.end()) {
|
||||||
auto meta = &it->second;
|
auto meta = &it->second;
|
||||||
while (meta) {
|
while (meta) {
|
||||||
if (!meta->next) {
|
if (!meta->next) {
|
||||||
@ -321,7 +321,7 @@ namespace refl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MetaClassTable.emplace(name.view(), MetaClasses{hash, cls});
|
MetaClassTable.emplace(name, MetaClasses{hash, cls});
|
||||||
}
|
}
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,4 +5,5 @@ header_component("zlib","engine")
|
|||||||
add_defines("API_DEBUG", {public = true})
|
add_defines("API_DEBUG", {public = true})
|
||||||
end
|
end
|
||||||
add_syslinks("kernel32")
|
add_syslinks("kernel32")
|
||||||
set_pcheader("include/refl/pch.h")
|
set_pcheader("include/refl/pch.h")
|
||||||
|
add_deps("xmalloc", {public = true})
|
||||||
@ -29,7 +29,7 @@ function shared_module(name, owner, opt)
|
|||||||
set_group("Engine/"..owner.."__dyn")
|
set_group("Engine/"..owner.."__dyn")
|
||||||
add_rules("engine.api")
|
add_rules("engine.api")
|
||||||
add_includedirs("include", {public = true})
|
add_includedirs("include", {public = true})
|
||||||
--add_rules("engine.plugin", {file = opt and opt.file or "include/" .. name .. "/module.h"})
|
add_rules("engine.plugin", {file = opt and opt.file or "include/" .. name .. "/module.h"})
|
||||||
end
|
end
|
||||||
function add_dependency(...)
|
function add_dependency(...)
|
||||||
add_deps(...)
|
add_deps(...)
|
||||||
|
|||||||
@ -12,7 +12,6 @@ target("engine")
|
|||||||
set_group("Engine")
|
set_group("Engine")
|
||||||
add_rules("engine.api")
|
add_rules("engine.api")
|
||||||
add_files("src/engine/*.cpp")
|
add_files("src/engine/*.cpp")
|
||||||
add_deps("xmalloc", {public = true})
|
|
||||||
includes("xmake/xmake.lua")
|
includes("xmake/xmake.lua")
|
||||||
includes("3rdparty/xmake.lua")
|
includes("3rdparty/xmake.lua")
|
||||||
includes("tools/xmake.lua")
|
includes("tools/xmake.lua")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user