From cf664d8143a3c5bcf2ec66fa05c9087e51ec5ec9 Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Wed, 6 Mar 2024 08:55:49 +0800 Subject: [PATCH] feat update --- .clang-format | 2 +- CMakeLists.txt | 4 ++ runtime/meta_object.h | 12 ++++++ runtime/meta_object_register.h | 38 ++++++++++++++++++ runtime/meta_registry.h | 70 ++++++++++++++++++++++++++++++++++ runtime/meta_utils.h | 68 +++++++++++++++++++++++++++++++++ test/main.cc | 21 ++++++++++ 7 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 runtime/meta_object.h create mode 100644 runtime/meta_object_register.h create mode 100644 runtime/meta_registry.h create mode 100644 runtime/meta_utils.h create mode 100644 test/main.cc diff --git a/.clang-format b/.clang-format index 8f51be9..87fa808 100644 --- a/.clang-format +++ b/.clang-format @@ -37,7 +37,7 @@ BreakBeforeTernaryOperators: true BreakConstructorInitializers: BeforeColon ConstructorInitializerAllOnOneLineOrOnePerLine: true BreakInheritanceList: BeforeColon -ColumnLimit: 100 +ColumnLimit: 120 CompactNamespaces: false ContinuationIndentWidth: 4 EmptyLineBeforeAccessModifier: LogicalBlock diff --git a/CMakeLists.txt b/CMakeLists.txt index e8b5372..49f8fc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,10 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin") endif() endif() +add_executable(test test/main.cc) +target_include_directories(test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(test PRIVATE sled) + target_include_directories(meta PRIVATE ${CLANG_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src diff --git a/runtime/meta_object.h b/runtime/meta_object.h new file mode 100644 index 0000000..6e1e0e3 --- /dev/null +++ b/runtime/meta_object.h @@ -0,0 +1,12 @@ +#pragma once +#ifndef META_RUNTIME_META_OBJECT_H +#define META_RUNTIME_META_OBJECT_H + +namespace meta { + +class MetaObject { +public: + virtual ~MetaObject() = default; +}; +}// namespace meta +#endif// META_RUNTIME_META_OBJECT_H diff --git a/runtime/meta_object_register.h b/runtime/meta_object_register.h new file mode 100644 index 0000000..41ded65 --- /dev/null +++ b/runtime/meta_object_register.h @@ -0,0 +1,38 @@ +#pragma once +#ifndef META_RUNTIME_META_OBJECT_REGISTER_H +#define META_RUNTIME_META_OBJECT_REGISTER_H +#include "meta_registry.h" +#include "meta_utils.h" + +namespace meta { +template +class MetaObjectRegister { +public: + MetaObjectRegister() { register_.DoNothing(); } + + virtual ~MetaObjectRegister() = default; + + static T *CreateMetaObject(Args &&...args) + { + T *ptr = nullptr; + try { + ptr = new T(std::forward(args)...); + } catch (const std::bad_alloc &) { + return nullptr; + } + return ptr; + } + +private: + struct Register { + Register() { MetaRegistry::Register(GetMetaName(), CreateMetaObject); } + + ~Register() { MetaRegistry::Unregister(GetMetaName()); } + + void DoNothing(); + }; + + static Register register_; +}; +}// namespace meta +#endif// META_RUNTIME_META_OBJECT_REGISTER_H diff --git a/runtime/meta_registry.h b/runtime/meta_registry.h new file mode 100644 index 0000000..f9cb6b7 --- /dev/null +++ b/runtime/meta_registry.h @@ -0,0 +1,70 @@ +#pragma once +#ifndef META_RUNTIME_META_REGISTRY_H +#define META_RUNTIME_META_REGISTRY_H + +#include "meta_object.h" +#include +#include + +namespace meta { + +/** + * Registry + **/ + +template +class MetaRegistry { +public: + static MetaRegistry *Instance(); + static bool Register(const std::string &obj_name, + std::function creator); + static bool Unregister(const std::string &obj_name); + +private: + bool RegisterImpl(const std::string &obj_name, std::function creator); + bool UnregisterImpl(const std::string &obj_name); + + std::unordered_map> creators_; +}; + +template +MetaRegistry * +MetaRegistry::Instance() +{ + static MetaRegistry instance; + return &instance; +} + +template +bool +MetaRegistry::Register(const std::string &obj_name, + std::function creator) +{ + return Instance()->RegisterImpl(obj_name, creator); +} + +template +bool +MetaRegistry::Unregister(const std::string &obj_name) +{ + return Instance()->UnregisterImpl(obj_name); +} + +template +bool +MetaRegistry::RegisterImpl(const std::string &obj_name, + std::function creator) +{ + return creators_.insert({obj_name, creator}).second; +} + +template +bool +MetaRegistry::UnregisterImpl(const std::string &obj_name) +{ + return creators_.erase(obj_name) > 0; +} + +}// namespace meta + +#endif// META_RUNTIME_META_REGISTRY_H diff --git a/runtime/meta_utils.h b/runtime/meta_utils.h new file mode 100644 index 0000000..f2e1baa --- /dev/null +++ b/runtime/meta_utils.h @@ -0,0 +1,68 @@ +#pragma once +#ifndef META_RUNTIME_META_UTILS_H +#define META_RUNTIME_META_UTILS_H + +#include +#include + +namespace meta { +namespace { +template +inline std::string +GetDemangleName() +{ + const std::string name = typeid(T).name(); + std::string pretty_name = name; + int status = -4; + char *res = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status); + if (status == 0) { pretty_name = std::string(res); } + free(res); + return pretty_name; +} + +inline std::string +RemoveWhiteSpace(const std::string &name, const std::string &chars = "[]<>,&* ") +{ + // trim left and right + std::string compact_name = name.substr(name.find_first_not_of(' ')); + compact_name = compact_name.substr(0, compact_name.find_last_not_of(' ') + 1); + + // remove white space + for (int i = 0; i < compact_name.size(); ++i) { + if (compact_name[i] == ' ') { + if (i > 0 && chars.find(compact_name[i - 1]) != std::string::npos) { + compact_name.erase(i, 1); + } else if (i + 1 < compact_name.size() + && chars.find(compact_name[i + 1]) != std::string::npos) { + compact_name.erase(i, 1); + } + } + } + return compact_name; +} + +inline std::string +RemoveInnerNamespace(const std::string &name) +{ + std::string new_name = name; + auto iter = name.find("::__1"); + while (iter != std::string::npos) { + new_name.replace(iter, 5, ""); + iter = new_name.find("::__1"); + } + return new_name; +} + +}// namespace + +template +std::string +GetMetaName() +{ + static std::string name = RemoveInnerNamespace(RemoveWhiteSpace(GetDemangleName())); + return name; +} + +}// namespace meta + +#endif// META_RUNTIME_META_UTILS_H diff --git a/test/main.cc b/test/main.cc new file mode 100644 index 0000000..45734be --- /dev/null +++ b/test/main.cc @@ -0,0 +1,21 @@ +#include "runtime/meta_object_register.h" +#include "runtime/meta_utils.h" +#include + +class Object : public meta::MetaObject { +public: +}; + +class ObjectRegister : public meta::MetaObjectRegister {}; + +int +main(int argc, char *argv[]) +{ + ObjectRegister register; + LOGV("", "{}", meta::GetMetaName()); + LOGV("", "{}", meta::GetMetaName()); + LOGV("", "{}", meta::GetMetaName>()); + LOGV("", "{}", meta::GetMetaName>()); + LOGV("", "{}", meta::GetMetaName>()); + return 0; +}