#pragma once #ifndef __FILE_Detail_CP_Typen_Hpp #define __FILE_Detail_CP_Typen_Hpp #include "detail/CP/CHash.hpp" template constexpr bool TIsBaseOf = std::is_base_of_v; template constexpr bool TAreSame = std::is_same_v; namespace Internal { template struct TConditionalTool { }; template struct TConditionalTool { using Type = typename TConditionalTool::Type; }; template struct TConditionalTool { using Type = First; }; template struct TConditionalTool { using Type = First; }; template struct TConditionalTool { using Type = std::conditional_t; }; } template using TChoose = typename Internal::TConditionalTool::Type; template using TConditional = typename Internal::TConditionalTool::Type; template using TDecay = std::decay_t; template constexpr bool TIsP = std::is_pointer_v; template constexpr bool TIsC = std::is_const_v; template constexpr bool TIsV = std::is_volatile_v; template constexpr bool TIsR = std::is_reference_v; template constexpr bool TIsF = std::is_function_v; template constexpr bool TIsLR = std::is_lvalue_reference_v; template constexpr bool TIsRR = std::is_rvalue_reference_v; template constexpr bool TIsCV = TIsC && TIsV; template constexpr bool TIsIt = TIsP || TIsLR())>; template constexpr bool TIsVoid = std::is_same_v; template constexpr bool THasVirtual = std::has_virtual_destructor_v; template constexpr bool TIsCStr = TAreSame&& TAreSame; template using TRemoveP = std::remove_pointer_t; template using TRemoveC = std::remove_const_t; template using TRemoveV = std::remove_volatile_t; template using TRemoveR = std::remove_reference_t; template using TRemoveCV = std::remove_cv_t; template using TEnableIf = std::enable_if_t; namespace Internal { template struct StringAbleTool { template ()))> static constexpr bool check_std_to_string(U*) { return true; } template static constexpr bool check_std_to_string(...) { return false; } template ()))> static constexpr bool check_to_string(U*) { return true; } template static constexpr bool check_to_string(...) { return false; } template ().ToString)> static constexpr bool check_self_to_string(U*) { return true; } template static constexpr bool check_self_to_string(...) { return false; } static constexpr bool Value = check_std_to_string(nullptr) || check_to_string(nullptr) || check_self_to_string(nullptr); template ()))> static constexpr bool check_atoi_parse(U*) { return true; } template static constexpr bool check_atoi_parse(...) { return true; } template ()))> static constexpr bool check_atof_parse(U*) { return true; } template static constexpr bool check_atof_parse(...) { return true; } template ()))> static constexpr bool check_atol_parse(U*) { return true; } template static constexpr bool check_atol_parse(...) { return true; } template ()))> static constexpr bool check_atoll_parse(U*) { return true; } template static constexpr bool check_atoll_parse(...) { return true; } template (),(const char*const)nullptr,0))> static constexpr bool check_parse_string(U*) { return true; } template static constexpr bool check_parse_string(...) { return false; } template ().Parse((const char* const)nullptr, 0))> static constexpr bool check_self_parse(U*) { return true; } template static constexpr bool check_self_parse(...) { return false; } }; } template constexpr bool THasToString = Internal::StringAbleTool::Value; namespace Internal { template struct TIsConvertibleImpl { private: static uint_fast8_t Test(...); static uint_fast16_t Test(To); public: enum { Value = sizeof(Test((From)std::declval())) - 1 }; }; } template constexpr bool TIsConvertible = Internal::TIsConvertibleImpl::Value; template constexpr bool TIsPointerConvertible = TIsConvertible; template constexpr bool TIsReferenceConvertible = TIsConvertible; namespace Internal { /** * Copies the cv-qualifiers from one type to another, e.g.: * * TCopyQualifiers::Type == const T2 * TCopyQualifiers::Type == const volatile T2 */ template struct TCopyQualifiersTool { typedef To Type; }; template struct TCopyQualifiersTool { typedef const To Type; }; template struct TCopyQualifiersTool< volatile From, To> { typedef volatile To Type; }; template struct TCopyQualifiersTool { typedef const volatile To Type; }; } template using TCopyQualifiers = typename Internal::TCopyQualifiersTool::Type; template constexpr bool TLosesQualifiers = !TAreSame, To>; namespace Internal { struct PrettyFunctionTag {}; template constexpr std::string_view PrettyFunction() { return __FUNCSIG__; } template constexpr std::string_view PrettyFunction() { return __FUNCSIG__; } constexpr size_t GetPrettyFunctionPrefix() { auto a = PrettyFunction(); auto b = PrettyFunction(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(0, result) != b.substr(0, result)) return result; } return result; } constexpr size_t GetPrettyFunctionSuffix() { auto a = PrettyFunction(); auto b = PrettyFunction(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(a.size() - result - 1, end) != b.substr(b.size() - result - 1, end)) return result; } return result; } template constexpr size_t GetPrettyFunctionWithValuePrefix() { auto a = PrettyFunction(0)>(); auto b = PrettyFunction(1)>(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(0, result) != b.substr(0, result)) return result; } return result; } template constexpr size_t GetPrettyFunctionWithValueSuffix() { auto a = PrettyFunction(0)>(); auto b = PrettyFunction(1)>(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(a.size() - result - 1, end) != b.substr(b.size() - result - 1, end)) return result; } return result; } template constexpr std::string_view SymbolNameTool() { auto name = PrettyFunction(); name.remove_prefix(GetPrettyFunctionPrefix() - 1); name.remove_suffix(GetPrettyFunctionSuffix()); return name; } template constexpr std::string_view ValueNameTool() { auto name = PrettyFunction(); name.remove_prefix(GetPrettyFunctionWithValuePrefix() - 1); name.remove_suffix(GetPrettyFunctionWithValueSuffix()); return name; } template struct TraitTool; template struct TraitTool { template static constexpr bool Is() { return (TAreSame || (Derived && TIsBaseOf)); } template static constexpr bool Is(P) { return (TAreSame || (Derived && TIsBaseOf)); } template static constexpr bool Is(P from, T& to) { to = static_cast(from); return (TAreSame || (Derived && TIsBaseOf)); } static bool Is(void* ptr) { using TSymbol = decltype(Symbol()); return Symbol() == *reinterpret_cast(reinterpret_cast(ptr) - sizeof(TSymbol)); } static intptr_t Symbol() { static auto symbol = typeid(T).hash_code(); return (intptr_t)&symbol; } static T* New(void* memory, size_t capacity) { using TSymbol = decltype(Symbol()); constexpr auto size = sizeof(TSymbol) + sizeof(T); if (capacity < size || memory == nullptr) return nullptr; char* ptr = new(memory) char[size]; auto&& head = reinterpret_cast(*ptr); head = Symbol(); T* result = reinterpret_cast(&(ptr[sizeof(TSymbol)])); return result; } static void Delete(T* ptr) { using TSymbol = decltype(Symbol()); *reinterpret_cast(reinterpret_cast(ptr) - sizeof(TSymbol)) = 0; ptr->~T(); } static T* FirstInMemory(void* memory, size_t capacity) { for (char* head = (char*)memory, *end = (char*)memory + capacity; head != end; head++) { if (Is(head)) return (T*)head; } return nullptr; } static bool WriteBinary(T* object, char* buffer, size_t capacity) { if (sizeof(T) + sizeof(decltype(Symbol())) > capacity) return false; *reinterpret_cast(&buffer[0]) = Symbol(); memcpy_s(&buffer[sizeof(decltype(Symbol()))], capacity, object, sizeof(T)); return true; } static bool Write(T* object, char* buffer, size_t capacity, bool is_allow_binary_write = false) { if constexpr (StringAbleTool::check_self_to_string(nullptr)) { auto str = object->ToString(); size_t strCsize = 0; if constexpr (TIsCStr) { constexpr auto _strCsize = sizeof(decltype(*str[0])); strCsize = _strCsize; } else { constexpr auto _strCsize = sizeof(decltype(*str.begin())); strCsize = _strCsize; } if (strCsize == 0) return false; if (str.size() * strCsize > capacity) return false; memcpy_s(buffer, capacity, str.c_str(), str.size() * strCsize); } else if constexpr (StringAbleTool::check_to_string(nullptr)) { auto str = to_string(*object); size_t strCsize = 0; if constexpr (TIsCStr) { constexpr auto _strCsize = sizeof(decltype(*str[0])); strCsize = _strCsize; } else { constexpr auto _strCsize = sizeof(decltype(*str.begin())); strCsize = _strCsize; } if (strCsize == 0) return false; if (str.size() * strCsize > capacity) return false; memcpy_s(buffer, capacity, str.c_str(), str.size() * strCsize); } else if constexpr (StringAbleTool::check_std_to_string(nullptr)) { std::string str = std::to_string(*object); if (str.size() > capacity) return false; memcpy_s(buffer, capacity, str.c_str(), str.size()); } else { if (is_allow_binary_write == false) return false; WriteBinary(object, buffer, capacity); } return true; } static T* ReadBinaryWithoutToken(T* object, char* buffer, size_t capacity) { constexpr auto offset = sizeof(decltype(Symbol())); if (capacity > sizeof(T) + offset && *reinterpret_cast(&buffer[0]) == Symbol()) memcpy(object, &buffer[offset], capacity); else { if (capacity > sizeof(T)) memcpy(object, buffer, capacity); else return nullptr; } return object; } static T* ReadBinary(void* memory, size_t capacity, char* buffer, size_t buffer_capacity) { constexpr auto size = sizeof(T) + sizeof(decltype(Symbol())); if (size > buffer_capacity) return nullptr; if (size > capacity) return nullptr; if (*reinterpret_cast(&buffer[0]) != Symbol()) return nullptr; T* object = reinterpret_cast(&buffer[sizeof(decltype(Symbol()))]); memcpy(memory, buffer, size); return object; } static bool Parse(T* object, const char* const buffer, size_t capacity) { if constexpr (StringAbleTool::check_self_parse(nullptr)) { object->Parse(buffer, capacity); } else if constexpr (StringAbleTool::check_parse_string(nullptr)) { from_string(object, buffer, capacity); } else if constexpr (TAreSame) { if (strcmp(buffer, "true") == 0) *object = true; else if (strcmp(buffer, "false") == 0) *object = false; else return false; } else if constexpr (StringAbleTool::check_atoll_parse(nullptr)) { *object = static_cast(atoll(buffer)); } else if constexpr (StringAbleTool::check_atol_parse(nullptr)) { *object = static_cast(atol(buffer)); } else if constexpr (StringAbleTool::check_atoi_parse(nullptr)) { *object = static_cast(atoi(buffer)); } else if constexpr (StringAbleTool::check_atof_parse(nullptr)) { *object = static_cast(atof(buffer)); } else { return false; } return true; } constexpr static std::string_view SymbolName() { return SymbolNameTool(); } static uint32_t Hash(const T& v) { if constexpr (std::is_integral_v) return GetTypeHash(v); else return GetTypeHash(&v); } private: constexpr static uint32_t InjectTypeHash() { auto str = SymbolName(); return CHash(str.data()); } public: constexpr static int TypeHash = InjectTypeHash(); }; template struct TraitTool : public TraitTool { template constexpr static std::string_view ValueName() { return ValueNameTool(); } }; template struct TraitTool : public TraitTool {}; template struct TraitTool< volatile T, IsIntegral> : public TraitTool {}; template struct TraitTool : public TraitTool {}; } template using TTrait = Internal::TraitTool>; namespace Internal { template class ValueClass : public TTrait { private: T value; using _Mybase = TTrait; public: ValueClass(const T& value) : value(value) {} ValueClass(T& value) : value(value) {} ValueClass(T&& value) : value(std::move(value)) {} ValueClass& operator=(const T& value) noexcept { this->value = value; } ValueClass& operator=(T& value) noexcept { this->value = value; } ValueClass& operator=(T&& value) noexcept { this->value = std::move(value); } constexpr operator T& () { return value; } constexpr operator const T& () const { return value; } uint32_t Hash() { return _Mybase::Hash(value); } }; } using Bool = Internal::ValueClass; using Int = Internal::ValueClass; using Float = Internal::ValueClass; using Double = Internal::ValueClass; using Long = Internal::ValueClass; using UInt = Internal::ValueClass; using Int8 = Internal::ValueClass; using Int16 = Internal::ValueClass; using Int32 = Internal::ValueClass; using Int64 = Internal::ValueClass; using UInt8 = Internal::ValueClass; using UInt16 = Internal::ValueClass; using UInt32 = Internal::ValueClass; using UInt64 = Internal::ValueClass; using LongDouble = Internal::ValueClass; #if !defined(nameofT)&&!defined(nameofEnum) template constexpr auto __Inject_nameof() { return TTrait::SymbolName(); } template constexpr auto __Inject_nameof() { return TTrait::ValueName(); } #define nameofT(x) __Inject_nameof(); #define nameofEnum(x) __Inject_nameof(); #else template constexpr auto nameof() { return TTrait::SymbolName(); } template constexpr auto nameof() { return TTrait::ValueName(); } #endif // !nameof template using TUnwrapped = TEnableIf, TConditional, TRemoveP, decltype(*std::declval())>>; template > decltype(auto) Unwrapping(T from) { return *from; } template > || TIsConvertible> To Cast(From data) { if constexpr (TIsConvertible) return static_cast(data); return static_cast(Unwrapping(data)); } #endif // !__FILE_Detail_CP_Typen_Hpp