From 74e6eec01d86c2adc8d607e71c1e7e645e4ad9de Mon Sep 17 00:00:00 2001 From: innerviewer Date: Mon, 28 Oct 2024 11:45:30 +0100 Subject: [PATCH] (Build) Fixed Linux build. Disabled litehtml, added new macros, etc. --- CMakeLists.txt | 12 ++ inc/Utils/Common/HashManager.h | 53 ++++- inc/Utils/Common/Hashes.h | 90 ++++++--- inc/Utils/Common/StringAtomLiterals.h | 10 + inc/Utils/ECS/Component.h | 30 ++- inc/Utils/ECS/GameObject.h | 1 + inc/Utils/TypeTraits/TypeTraits.h | 278 ++++++++++++++++++++++++++ inc/Utils/Types/SharedPtr.h | 6 +- inc/Utils/Types/StringAtom.h | 14 +- inc/Utils/Web/HTML/HTML.h | 239 +++++++--------------- inc/Utils/macros.h | 2 + py/ResourceEmbedder.py | 2 + src/Utils/Common/HashManager.cpp | 25 ++- src/Utils/Types/StringAtom.cpp | 12 +- src/Utils/Web/CSS/CSS.cpp | 175 +++++++++++++++- 15 files changed, 722 insertions(+), 227 deletions(-) create mode 100644 inc/Utils/TypeTraits/TypeTraits.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e22bbfe3..33f67795 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ option(SR_COMMON_SDL "" OFF) option(SR_COMMON_CURL "" OFF) option(SR_COMMON_JSON "" OFF) option(SR_COMMON_MYHTML "" ON) +option(SR_COMMON_LITEHTML "" OFF) option(SR_COMMON_DLL_EXPORTS "" ON) option(SR_COMMON_GIT_METADATA "" ON) @@ -21,6 +22,10 @@ if (SR_COMMON_SDL) add_compile_definitions(SR_COMMON_SDL) endif() +if (SR_COMMON_LITEHTML) + add_compile_definitions(SR_COMMON_LITEHTML) +endif() + if (SR_COMMON_EMBED_RESOURCES) add_compile_definitions(SR_COMMON_EMBED_RESOURCES) endif() @@ -215,6 +220,7 @@ SR_UTILS_INCLUDE_DIRECTORIES_APPEND(${CMAKE_CURRENT_SOURCE_DIR}/libs/cppcoro/inc SR_UTILS_INCLUDE_DIRECTORIES_APPEND(${CMAKE_CURRENT_SOURCE_DIR}/libs/cpptrace/include) SR_UTILS_INCLUDE_DIRECTORIES_APPEND(${CMAKE_CURRENT_SOURCE_DIR}/libs/rapidyaml/src) SR_UTILS_INCLUDE_DIRECTORIES_APPEND(${CMAKE_CURRENT_SOURCE_DIR}/libs/cssparser/cssparser) +SR_UTILS_INCLUDE_DIRECTORIES_APPEND(${SR_CMAKE_ROOT_BUILD_DIRECTORY}/Codegen) SR_UTILS_INCLUDE_DIRECTORIES_APPEND(${CMAKE_CURRENT_BINARY_DIR}/include/Utils/EmbedResources) @@ -266,6 +272,12 @@ if (SR_COMMON_MYHTML) target_link_libraries(Utils myhtml_static) endif() +if (SR_COMMON_LITEHTML) + add_subdirectory(libs/litehtml) + SR_UTILS_INCLUDE_DIRECTORIES_APPEND(${CMAKE_CURRENT_SOURCE_DIR}/libs/litehtml/include) + target_link_libraries(Utils litehtml) +endif() + if (SR_COMMON_SDL) target_link_libraries(Utils SDL3::SDL3) endif() diff --git a/inc/Utils/Common/HashManager.h b/inc/Utils/Common/HashManager.h index 25314ec1..309aafa4 100644 --- a/inc/Utils/Common/HashManager.h +++ b/inc/Utils/Common/HashManager.h @@ -12,6 +12,7 @@ namespace SR_UTILS_NS { struct StringHashInfo { std::string data; + std::string_view view; uint64_t hash = SR_ID_INVALID; uint64_t size = 0; /// TODO: remove }; @@ -27,7 +28,7 @@ namespace SR_UTILS_NS { SR_MAYBE_UNUSED static HashManager& Instance(); public: - SR_NODISCARD const std::string& HashToString(Hash hash) const; + SR_NODISCARD const std::string_view& HashToString(Hash hash) const; SR_NODISCARD StringAtom HashToStringAtom(Hash hash) const; SR_NODISCARD bool Exists(Hash hash) const; @@ -47,8 +48,58 @@ namespace SR_UTILS_NS { mutable std::recursive_mutex m_mutex; }; + + struct ConstexprStringHashEntry { + constexpr ConstexprStringHashEntry() = default; + constexpr ConstexprStringHashEntry(std::string_view str, uint64_t hash) + : str(str) + , hash(hash) + { } + std::string_view str; + uint64_t hash; + }; + + constexpr uint64_t ConstexprStringsMaxEntries = 512; + + struct GlobalStringRegistry { + constexpr GlobalStringRegistry() + : entries{} + , count(0) + { } + + mutable std::array entries; + mutable uint64_t count; + + constexpr uint64_t Register(std::string_view str, uint64_t hash) const { + if (count < ConstexprStringsMaxEntries) { + for (uint64_t i = 0; i < count; ++i) { + if (entries[i].hash == hash) { + return hash; + } + } + entries[++count] = ConstexprStringHashEntry(str, hash); + } + else { + throw std::runtime_error("GlobalStringRegistry() : max entries reached!"); + } + return hash; + } + + SR_NODISCARD constexpr std::optional FindConstexprStringByHash(uint64_t hash) const { + for (uint64_t i = 0; i < count; ++i) { + if (entries[i].hash == hash) { + return entries[i].str; + } + } + return std::nullopt; + } + }; + + /// TODO: может быть баг при использовании dll + //inline constexpr GlobalStringRegistry g_StringRegistry = GlobalStringRegistry(); } +#define SR_HASH_CONSTEXPR_STR_VIEW_REGISTER(x) (SR_UTILS_NS::g_StringRegistry.Register(x, SR_HASH_STR_VIEW(x))) #define SR_HASH_STR_REGISTER(x) (SR_UTILS_NS::HashManager::Instance().AddHash(x)) #define SR_HASH_TYPE_NAME_STR_REGISTER(x) (SR_UTILS_NS::HashManager::Instance().AddHash(SR_GET_TYPE_NAME(x))) #define SR_HASH_TO_STR(x) SR_UTILS_NS::HashManager::Instance().HashToString(x) diff --git a/inc/Utils/Common/Hashes.h b/inc/Utils/Common/Hashes.h index 7b546424..a0f4d571 100644 --- a/inc/Utils/Common/Hashes.h +++ b/inc/Utils/Common/Hashes.h @@ -92,65 +92,101 @@ namespace SR_UTILS_NS { std::constructible_from && requires(T type) { type.to_string(); } || requires(T type) { type.ToString(); }; + + static constexpr SRHashType InitialHash() noexcept { return 0xcbf29ce484222325; } + static constexpr SRHashType MagicPrime() noexcept { return 0x100000001b3; } + + template struct Encoder { + static constexpr SRHashType EncodeChar(SRHashType hash, const char (&text)[S]) noexcept { + hash = (hash ^ static_cast(static_cast(text[S - N - 1]))) * MagicPrime(); + return Encoder::EncodeChar(hash, text); + } + }; + + template struct Encoder { + static constexpr SRHashType EncodeChar(SRHashType hash, const char (&)[S]) noexcept { + return hash; + } + }; + } + + template SR_NODISCARD static constexpr uint64_t ComputeHashConstexpr(const char (&text)[S]) noexcept { + return static_cast(Hash::Detail::Encoder::EncodeChar(Hash::Detail::InitialHash(), text)); + } + + SR_NODISCARD static constexpr uint64_t ComputeHash(const char* text) noexcept { + uint64_t hash = Hash::Detail::InitialHash(); + for (size_t i = 0; text[i] != '\0'; ++i) { + hash = (hash ^ static_cast(static_cast(text[i]))) * Hash::Detail::MagicPrime(); + } + return hash; } - SR_INLINE_STATIC constexpr size_t SR_FNV_OFFSET_BASIS = 14695981039346656037ULL; - SR_INLINE_STATIC constexpr size_t SR_FNV_PRIME = 1099511628211ULL; + SR_NODISCARD static constexpr uint64_t ComputeHash(const std::string_view text) noexcept { + uint64_t hash = Hash::Detail::InitialHash(); + for (const char i : text) { + hash = (hash ^ static_cast(static_cast(i))) * Hash::Detail::MagicPrime(); + } + return hash; + } - SR_NODISCARD SR_INLINE_STATIC size_t FNV1AAppendBytes(size_t value, const unsigned char* const first, const size_t count) noexcept { - for (size_t i = 0; i < count; ++i) { - value ^= static_cast(first[i]); + SR_INLINE_STATIC constexpr uint64_t SR_FNV_OFFSET_BASIS = 14695981039346656037ULL; + SR_INLINE_STATIC constexpr uint64_t SR_FNV_PRIME = 1099511628211ULL; + + SR_NODISCARD constexpr SR_INLINE_STATIC uint64_t FNV1AAppendBytes(uint64_t value, const unsigned char* const first, const uint64_t count) noexcept { + for (uint64_t i = 0; i < count; ++i) { + value ^= static_cast(first[i]); value *= SR_FNV_PRIME; } return value; } - template SR_NODISCARD SR_INLINE_STATIC size_t FNV1AAppendValue(const size_t value, const T& keyValue) noexcept { + template SR_NODISCARD SR_INLINE_STATIC constexpr uint64_t FNV1AAppendValue(const uint64_t value, const T& keyValue) noexcept { return FNV1AAppendBytes(value, &reinterpret_cast(keyValue), sizeof(T)); } - template SR_NODISCARD size_t HashArrayRepresentation(const T* const first, const size_t count) noexcept { + template SR_NODISCARD constexpr uint64_t HashArrayRepresentation(const T* const first, const size_t count) noexcept { return FNV1AAppendBytes(SR_FNV_OFFSET_BASIS, reinterpret_cast(first), count * sizeof(T)); } - template SR_NODISCARD size_t HashRepresentation(const T& keyVal) noexcept { + template SR_NODISCARD constexpr uint64_t HashRepresentation(const T& keyVal) noexcept { return FNV1AAppendValue(SR_FNV_OFFSET_BASIS, keyVal); } - template class SRHash; + template struct SRHash; template struct SRConditionallyEnabledHash { - SR_NODISCARD size_t operator()(const T& keyVal) const + SR_NODISCARD constexpr size_t operator()(const T& keyVal) const noexcept(noexcept(SR_UTILS_NS::SRHash::DoHash(keyVal))) { return SR_UTILS_NS::SRHash::DoHash(keyVal); } }; template struct SRConditionallyEnabledHash { - SRConditionallyEnabledHash() = delete; - SRConditionallyEnabledHash(const SRConditionallyEnabledHash&) = delete; - SRConditionallyEnabledHash(SRConditionallyEnabledHash&&) = delete; - SRConditionallyEnabledHash& operator=(const SRConditionallyEnabledHash&) = delete; - SRConditionallyEnabledHash& operator=(SRConditionallyEnabledHash&&) = delete; + constexpr SRConditionallyEnabledHash() = delete; + constexpr SRConditionallyEnabledHash(const SRConditionallyEnabledHash&) = delete; + constexpr SRConditionallyEnabledHash(SRConditionallyEnabledHash&&) = delete; + constexpr SRConditionallyEnabledHash& operator=(const SRConditionallyEnabledHash&) = delete; + constexpr SRConditionallyEnabledHash& operator=(SRConditionallyEnabledHash&&) = delete; }; template struct SRHash : SRConditionallyEnabledHash && !std::is_volatile_v && (std::is_enum_v || std::is_integral_v || std::is_pointer_v)> { - static size_t DoHash(const T& value) noexcept { + constexpr static uint64_t DoHash(const T& value) noexcept { return FNV1AAppendValue(SR_FNV_OFFSET_BASIS, value); } }; - template uint64_t CalculateHash(const T& value) { - static SRHash h; + template constexpr uint64_t CalculateHash(const T& value) { + constexpr SRHash h; return h(value); } - template uint64_t HashCombine(const T& value, uint64_t hash = 0) { + template constexpr uint64_t HashCombine(const T& value, uint64_t hash = 0) { return hash ^ CalculateHash(value) + 0x9e3779b9 + (hash << 6) + (hash >> 2); } - SR_MAYBE_UNUSED static uint64_t CombineTwoHashes(uint64_t hash1, uint64_t hash2) { + SR_MAYBE_UNUSED constexpr static uint64_t CombineTwoHashes(uint64_t hash1, uint64_t hash2) { return hash2 ^ hash1 + 0x9e3779b9 + (hash2 << 6) + (hash2 >> 2); } @@ -178,42 +214,40 @@ namespace SR_UTILS_NS { T sha256(const std::string& msg) { return sha256(msg.data(), msg.size()); } - - using SRHashType = uint64_t; } template struct SR_UTILS_NS::SRHash, Alloc>> : SR_UTILS_NS::SRConditionallyEnabledHash, Alloc>, IsECharT> { - SR_NODISCARD static size_t DoHash(const std::basic_string, Alloc>& keyVal) noexcept { + SR_NODISCARD constexpr static size_t DoHash(const std::basic_string, Alloc>& keyVal) noexcept { return HashArrayRepresentation(keyVal.c_str(), keyVal.size()); } }; template struct SR_UTILS_NS::SRHash> : SR_UTILS_NS::SRConditionallyEnabledHash, IsECharT> { - SR_NODISCARD static size_t DoHash(const std::basic_string_view keyVal) noexcept { + SR_NODISCARD constexpr static size_t DoHash(const std::basic_string_view keyVal) noexcept { return HashArrayRepresentation(keyVal.data(), keyVal.size()); } }; template<> struct SR_UTILS_NS::SRHash { - SR_NODISCARD size_t operator()(const float keyVal) const noexcept { + SR_NODISCARD constexpr size_t operator()(const float keyVal) const noexcept { return HashRepresentation(keyVal == 0.0F ? 0.0F : keyVal); } }; template<> struct SR_UTILS_NS::SRHash { - SR_NODISCARD size_t operator()(const double keyVal) const noexcept { + SR_NODISCARD constexpr size_t operator()(const double keyVal) const noexcept { return HashRepresentation(keyVal == 0.0 ? 0.0 : keyVal); } }; template<> struct SR_UTILS_NS::SRHash { - SR_NODISCARD size_t operator()(const long double keyVal) const noexcept { + SR_NODISCARD constexpr size_t operator()(const long double keyVal) const noexcept { return HashRepresentation(keyVal == 0.0L ? 0.0L : keyVal); } }; template<> struct SR_UTILS_NS::SRHash { - SR_NODISCARD size_t operator()(nullptr_t) const noexcept { + SR_NODISCARD constexpr size_t operator()(nullptr_t) const noexcept { void* null = nullptr; return HashRepresentation(null); } diff --git a/inc/Utils/Common/StringAtomLiterals.h b/inc/Utils/Common/StringAtomLiterals.h index b4eb41df..6730a1d2 100644 --- a/inc/Utils/Common/StringAtomLiterals.h +++ b/inc/Utils/Common/StringAtomLiterals.h @@ -15,4 +15,14 @@ SR_INLINE uint64_t operator"" _atom_hash(const char* str, size_t) { return SR_HASH_STR_REGISTER(str); } +/// TODO: constexpr StringAtom support +/// SR_INLINE constexpr SR_UTILS_NS::StringAtom operator"" _atom_cexpr(const char* str, size_t) { +/// return SR_UTILS_NS::StringAtom(str); +/// } + +/*constexpr uint64_t operator"" _atom_hash_cexpr(const char* str, size_t size) { + const auto strView = std::string_view(str, size); + return SR_HASH_CONSTEXPR_STR_VIEW_REGISTER(strView); +}*/ + #endif //SR_COMMON_STRING_ATOM_LITERALS_H diff --git a/inc/Utils/ECS/Component.h b/inc/Utils/ECS/Component.h index ceb1516f..e8e75017 100644 --- a/inc/Utils/ECS/Component.h +++ b/inc/Utils/ECS/Component.h @@ -5,17 +5,23 @@ #ifndef SR_ENGINE_UTILS_COMPONENT_H #define SR_ENGINE_UTILS_COMPONENT_H +#include +#include +#include +#include +#include #include + #include + +#include + #include #include -#include -#include -#include #include #include -#include -#include +#include + #include /** @@ -42,13 +48,16 @@ namespace SR_UTILS_NS { class GameObject; class SR_DLL_EXPORT Component : public Entity { + SR_CLASS() friend class GameObject; friend class IComponentable; friend class ComponentManager; public: using Ptr = SR_HTYPES_NS::SharedPtr; + using OriginType = Component; using ScenePtr = SR_WORLD_NS::Scene*; using GameObjectPtr = SR_HTYPES_NS::SharedPtr; + using SceneObjectPtr = SR_HTYPES_NS::SharedPtr; public: ~Component() override; @@ -124,9 +133,10 @@ namespace SR_UTILS_NS { SR_NODISCARD ScenePtr GetScene() const; SR_NODISCARD bool HasScene() const { return TryGetScene(); } SR_NODISCARD GameObjectPtr GetGameObject() const; + SR_NODISCARD SceneObjectPtr GetSceneObject() const; SR_NODISCARD bool HasParent() const { return m_parent; } SR_NODISCARD ScenePtr TryGetScene() const; - SR_NODISCARD GameObjectPtr GetRoot() const; + SR_NODISCARD SceneObjectPtr GetRoot() const; SR_NODISCARD Transform* GetTransform() const noexcept; SR_NODISCARD SR_UTILS_NS::PropertyContainer& GetComponentProperties() noexcept { return m_properties; } SR_NODISCARD const SR_UTILS_NS::PropertyContainer& GetComponentProperties() const noexcept { return m_properties; } @@ -135,21 +145,23 @@ namespace SR_UTILS_NS { SR_NODISCARD std::string GetEntityInfo() const override; protected: - SR_NODISCARD SR_HTYPES_NS::Marshal::Ptr Save(SavableContext data) const override; + SR_NODISCARD SR_HTYPES_NS::Marshal::Ptr SaveLegacy(SavableContext data) const override; void SetParent(IComponentable* pParent); protected: bool m_isComponentLoaded = false; bool m_isAttached = false; - bool m_isEnabled = true; bool m_isActive = false; bool m_isAwake = false; bool m_isStarted = false; + /// @property + bool m_isEnabled = true; + int32_t m_indexInSceneUpdater = SR_ID_INVALID; - GameObjectPtr m_gameObject; + SceneObjectPtr m_sceneObject = nullptr; IComponentable* m_parent = nullptr; SR_WORLD_NS::Scene* m_scene = nullptr; diff --git a/inc/Utils/ECS/GameObject.h b/inc/Utils/ECS/GameObject.h index 3db021f5..68857899 100644 --- a/inc/Utils/ECS/GameObject.h +++ b/inc/Utils/ECS/GameObject.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/inc/Utils/TypeTraits/TypeTraits.h b/inc/Utils/TypeTraits/TypeTraits.h new file mode 100644 index 00000000..3ca3cdaa --- /dev/null +++ b/inc/Utils/TypeTraits/TypeTraits.h @@ -0,0 +1,278 @@ +// +// Created by Monika on 16.10.2024. +// + +#ifndef SR_COMMON_TYPE_TRAITS_H +#define SR_COMMON_TYPE_TRAITS_H + +#include + +namespace SR_UTILS_NS { + struct SerializationId { + SR_CONSTEXPR SerializationId() noexcept = default; + + SR_CONSTEXPR ~SerializationId() noexcept = default; + + template static constexpr SerializationId Create(const char (&text)[S]) noexcept { + SerializationId id; + for (uint64_t i = 0; i < S - 1; ++i) { + id.name[i] = text[i]; + } + id.name[S - 1] = '\0'; + id.hash = ComputeHashConstexpr(text); + return id; + } + + static SerializationId CreateFromCStr(const char* text) noexcept { + SerializationId id; + SR_STRNCPY(id.name, text, MaxNameLength - 1); + id.name[MaxNameLength - 1] = '\0'; + id.hash = ComputeHash(text); + return id; + } + + static SerializationId CreateFromString(const std::string_view text) noexcept { + SerializationId id; + SR_STRNCPY(id.name, text.data(), std::min(text.size(), MaxNameLength - 1)); + id.name[MaxNameLength - 1] = '\0'; + id.hash = ComputeHash(text); + return id; + } + + SR_NODISCARD const char* GetName() const noexcept { return name; } + SR_NODISCARD uint64_t GetHash() const noexcept { return hash; } + + private: + static constexpr uint64_t MaxNameLength = 256; + uint64_t hash = 0; + char name[MaxNameLength]{}; + }; + + template + struct IsCompleteType : std::false_type {}; + + template + struct IsCompleteType> : std::true_type {}; + + template + constexpr bool IsCompleteTypeV = IsCompleteType::value; + + template typename Tmpl1> + struct IsStdArrayTemplate : std::false_type + {}; + + template<> + struct IsStdArrayTemplate : std::true_type + {}; + + template typename Tmpl> + SR_INLINE constexpr bool IsStdArrayTemplateV = IsStdArrayTemplate::value; + + template + struct IsTypeFromStdArrayTemplate : std::false_type + {}; + + template + struct IsTypeFromStdArrayTemplate> : std::true_type + {}; + + template + SR_INLINE constexpr bool IsTypeFromStdArrayTemplateV = IsTypeFromStdArrayTemplate::value; + + namespace Details + { + template class Op, class... Args> + struct Detector { + using value_t = std::false_type; + using type = Default; + }; + + template class Op, class... Args> + struct Detector>, Op, Args...> { + using value_t = std::true_type; + using type = Op; + }; + + struct Empty {}; + + template + struct GetPromPack { + using type = typename GetPromPack::type; + }; + + template + struct GetPromPack<0, T, Types...> { + using type = T; + }; + + template + auto GetFromPackResolver() + { + if constexpr (Index < sizeof...(Types)) { + return GetPromPack(); + } + else { + return GetPromPack<0, Empty>(); + } + } + } + + template class Op, class... Args> + struct IsDetected : Details::Detector::value_t + {}; + + template class Op, class... Args> + inline constexpr bool IsDetectedV = IsDetected::value; + + template class Op, class... Args> + using DetectedT = typename Details::Detector::type; + + template class Op, class... Args> + struct DetectedOr : Details::Detector + {}; + + template class Op, class... Args> + using DetectedOrT = typename DetectedOr::type; + + template class Op, class... Args> + struct IsDetectedExact : std::is_same> + {}; + + template class Op, class... Args> + inline constexpr bool IsDetectedExactV = IsDetectedExact::value; + + template class Op, class... Args> + struct IsDetectedConvertible : std::is_convertible, To> + {}; + + template class Op, class... Args> + inline constexpr bool IsDetectedConvertibleV = IsDetectedConvertible::value; + + template + struct IsTemplateClass : std::false_type + {}; + + template typename Tmpl, typename... Args> + struct IsTemplateClass> : std::true_type + {}; + + template + inline constexpr bool IsTemplateClassV = IsTemplateClass::value; + + template typename Tmpl1, template typename Tmpl2> + struct IsSameClassTemplate : std::false_type + {}; + + template typename Tmpl> + struct IsSameClassTemplate : std::true_type + {}; + + template typename Tmpl1, template typename Tmpl2> + inline constexpr bool IsSameClassTemplateV = IsSameClassTemplate::value; + + template typename> + struct IsTypeFromClassTemplate : std::false_type + {}; + + template typename Tmpl, typename... Args> + struct IsTypeFromClassTemplate, Tmpl> : std::true_type + {}; + + template typename Tmpl> + inline constexpr bool IsTypeFromClassTemplateV = IsTypeFromClassTemplate::value; + + template struct IsSREnum { + static constexpr bool IsEnum() { + if constexpr (std::is_enum::value) { + return SR_UTILS_NS::EnumTraits::IsEnum; + } + else { + return false; + } + } + + static constexpr bool value = IsSREnum::IsEnum(); + }; + + template + inline constexpr bool IsSREnumV = IsSREnum::value; + + template + using GetPromPackT = typename decltype(Details::GetFromPackResolver())::type; + + template + inline constexpr bool HasTypeInPackV = std::disjunction_v...>; + + template + inline constexpr bool PackOfSameTypeV = std::conjunction_v...>; + + template + inline constexpr bool NoTypeInPackV = std::conjunction_v>...>; + + template + struct TypeValuePair + { + using type = T; + static SR_INLINE constexpr auto value = val; + }; + + template + inline constexpr auto TypeValuePairV = TypeValuePair::value; + + template + using TypeValuePairT = typename TypeValuePair::type; + + // Предназначено в основном для использования в static_assert, чтобы сделать его зависимым от T + template + inline constexpr bool AlwaysFalseV = std::is_same_v, std::add_cv_t>>; + + template + struct GetFirstOfTypeFromSequenceAssert + { + static_assert(AlwaysFalseV, "There's no same type for T in sequence!"); + static SR_INLINE constexpr auto value = 0; + }; + + template + struct GetFirstOfTypeFromSequence + { + static SR_INLINE constexpr auto value = std::conditional_t, Pair, GetFirstOfTypeFromSequence>::value; + }; + + template + struct GetFirstOfTypeFromSequence + { + static SR_INLINE constexpr auto value = std::conditional_t, Pair, GetFirstOfTypeFromSequenceAssert>::value; + }; + + template + inline constexpr auto GetFirstOfTypeFromSequenceV = GetFirstOfTypeFromSequence::value; + + template + struct RemoveCVRef + { + using type = std::remove_cv_t>; + }; + + template + using RemoveCVRefT = typename RemoveCVRef::type; + + template + using CheckerEqualityComparable = decltype(std::declval() == std::declval()); + + template + using CheckerOperatorMinus = decltype(std::declval() - std::declval()); + + template class Op, class X, class Y> + struct CheckOperatorUsable : IsDetected + {}; + + template + struct CheckOperatorUsable, std::optional> : std::false_type + {}; + + template class Op, class X, class Y> + constexpr bool CheckOperatorUsableV = CheckOperatorUsable::value; +} + +#endif //SR_COMMON_TYPE_TRAITS_H diff --git a/inc/Utils/Types/SharedPtr.h b/inc/Utils/Types/SharedPtr.h index 7825d0d5..bc574f9a 100644 --- a/inc/Utils/Types/SharedPtr.h +++ b/inc/Utils/Types/SharedPtr.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace SR_UTILS_NS { enum class SharedPtrPolicy : uint8_t { @@ -222,7 +223,10 @@ namespace SR_HTYPES_NS { return; } - if constexpr (SR_UTILS_NS::IsDerivedFrom::value) { + if constexpr (!SR_UTILS_NS::IsCompleteTypeV) { + SR_SAFE_PTR_ASSERT(ptr == nullptr, "Ptr is not nullptr!"); + } + else if constexpr (SR_UTILS_NS::IsDerivedFrom::value) { if ((m_data = ptr->GetPtrData())) { m_data->IncrementStrong(); m_ptr = ptr; diff --git a/inc/Utils/Types/StringAtom.h b/inc/Utils/Types/StringAtom.h index 7f9681e8..5a7bb8b5 100644 --- a/inc/Utils/Types/StringAtom.h +++ b/inc/Utils/Types/StringAtom.h @@ -15,17 +15,17 @@ namespace SR_UTILS_NS { SR_INLINE_STATIC std::string DEFAULT = std::string(); static StringHashInfo* DEFAULT_STRING_INFO; public: - StringAtom(); + constexpr StringAtom(); - StringAtom(const StringAtom& str) = default; + constexpr StringAtom(const StringAtom& str) = default; - StringAtom(StringHashInfo* pInfo); /// NOLINT - StringAtom(const char* str); /// NOLINT - StringAtom(const std::string& str); /// NOLINT - StringAtom(const std::string_view& str); /// NOLINT + constexpr StringAtom(StringHashInfo* pInfo); /// NOLINT + constexpr StringAtom(const char* str); /// NOLINT + constexpr StringAtom(const std::string& str); /// NOLINT + StringAtom(std::string_view str); /// NOLINT public: - operator std::string() const noexcept; /// NOLINT + operator const std::string&() const noexcept; /// NOLINT operator std::string_view() const noexcept; /// NOLINT bool operator==(const StringAtom& rhs) const noexcept; bool operator==(const std::string& rhs) const noexcept; diff --git a/inc/Utils/Web/HTML/HTML.h b/inc/Utils/Web/HTML/HTML.h index a98da635..8e2fbcbd 100644 --- a/inc/Utils/Web/HTML/HTML.h +++ b/inc/Utils/Web/HTML/HTML.h @@ -11,198 +11,111 @@ #include #include +#ifdef SR_COMMON_LITEHTML + #include +#endif + namespace SR_UTILS_NS::Web { - class HTMLPage; - class HTMLNode; + class HTMLPage; - class HTMLAttribute : public SR_UTILS_NS::NonCopyable { +#ifdef SR_COMMON_LITEHTML + class HTMLContainerInterface : public SR_HTYPES_NS::SharedPtr, public litehtml::document_container { + using Super = SR_HTYPES_NS::SharedPtr; public: - HTMLAttribute(HTMLPage* pPage, Passkey) - : m_pPage(pPage) - { } + using Ptr = SR_HTYPES_NS::SharedPtr; - HTMLAttribute(HTMLAttribute&& other) noexcept - : m_pPage(SR_EXCHANGE(other.m_pPage, nullptr)) - , m_pNode(SR_EXCHANGE(other.m_pNode, nullptr)) - , m_name(SR_EXCHANGE(other.m_name, { })) - , m_value(SR_EXCHANGE(other.m_value, { })) - , m_id(SR_EXCHANGE(other.m_id, SR_ID_INVALID)) + HTMLContainerInterface() + : Super(this, SR_UTILS_NS::SharedPtrPolicy::Automatic) { } - ~HTMLAttribute() override; - - HTMLAttribute& operator=(HTMLAttribute&& other) noexcept { - m_pPage = SR_EXCHANGE(other.m_pPage, nullptr); - m_pNode = SR_EXCHANGE(other.m_pNode, nullptr); - m_name = SR_EXCHANGE(other.m_name, { }); - m_value = SR_EXCHANGE(other.m_value, { }); - m_id = SR_EXCHANGE(other.m_id, SR_ID_INVALID); - return *this; - } + ~HTMLContainerInterface() override = default; public: - void SetName(std::string&& name) { m_name = std::move(name); } - void SetValue(std::string&& value) { m_value = std::move(value); } - - void SetNode(HTMLNode* pNode, Passkey) { m_pNode = pNode; } - void SetId(const uint64_t id, Passkey) { m_id = id; } - - SR_NODISCARD const std::string& GetName() const { return m_name; } - SR_NODISCARD const std::string& GetValue() const { return m_value; } - - SR_NODISCARD HTMLNode* GetNode() const { return m_pNode; } - SR_NODISCARD uint64_t GetId() const { return m_id; } - - private: - std::string m_name; - std::string m_value; - - HTMLPage* m_pPage = nullptr; - HTMLNode* m_pNode = nullptr; - - uint64_t m_id = SR_ID_INVALID; - - }; - - class HTMLNode : public SR_UTILS_NS::NonCopyable { - using Super = SR_UTILS_NS::NonCopyable; - public: - HTMLNode(HTMLPage* pPage, Passkey) - : Super() - , m_pPage(pPage) - { } - - HTMLNode(HTMLNode&& other) noexcept - : m_pPage(SR_EXCHANGE(other.m_pPage, { })) - , m_parentId(SR_EXCHANGE(other.m_parentId, { })) - , m_tag(SR_EXCHANGE(other.m_tag, HTMLTag::Undefined)) - , m_style(SR_EXCHANGE(other.m_style, { })) - , m_nodeName(SR_EXCHANGE(other.m_nodeName, { })) - , m_text(SR_EXCHANGE(other.m_text, { })) - , m_children(SR_EXCHANGE(other.m_children, { })) - , m_attributes(SR_EXCHANGE(other.m_attributes, { })) - , m_id(SR_EXCHANGE(other.m_id, SR_ID_INVALID)) - { } - - HTMLNode& operator=(HTMLNode&& other) noexcept { - m_pPage = SR_EXCHANGE(other.m_pPage, { }); - m_parentId = SR_EXCHANGE(other.m_parentId, { }); - m_tag = SR_EXCHANGE(other.m_tag, HTMLTag::Undefined); - m_style = SR_EXCHANGE(other.m_style, { }); - m_nodeName = SR_EXCHANGE(other.m_nodeName, { }); - m_text = SR_EXCHANGE(other.m_text, { }); - m_children = SR_EXCHANGE(other.m_children, { }); - m_attributes = SR_EXCHANGE(other.m_attributes, { }); - m_id = SR_EXCHANGE(other.m_id, SR_ID_INVALID); - return *this; - } - - ~HTMLNode() override; + litehtml::uint_ptr create_font(const char* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm) override { return 0; } + void delete_font(litehtml::uint_ptr hFont) override { } + int text_width(const char* text, litehtml::uint_ptr hFont) override { return 0; } + void draw_text(litehtml::uint_ptr hdc, const char* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos) override { } + int pt_to_px(int pt) const override; + int get_default_font_size() const override; + const char* get_default_font_name() const override; + void draw_list_marker(litehtml::uint_ptr hdc, const litehtml::list_marker& marker) override { } + void load_image(const char* src, const char* baseurl, bool redraw_on_ready) override { } + void get_image_size(const char* src, const char* baseurl, litehtml::size& sz) override { } + void draw_image(litehtml::uint_ptr hdc, const litehtml::background_layer& layer, const std::string& url, const std::string& base_url) override { } + void draw_solid_fill(litehtml::uint_ptr hdc, const litehtml::background_layer& layer, const litehtml::web_color& color) override { } + void draw_linear_gradient(litehtml::uint_ptr hdc, const litehtml::background_layer& layer, const litehtml::background_layer::linear_gradient& gradient) override { } + void draw_radial_gradient(litehtml::uint_ptr hdc, const litehtml::background_layer& layer, const litehtml::background_layer::radial_gradient& gradient) override { } + void draw_conic_gradient(litehtml::uint_ptr hdc, const litehtml::background_layer& layer, const litehtml::background_layer::conic_gradient& gradient) override { } + void draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root) override { } + + void set_caption(const char* caption) override { } + void set_base_url(const char* base_url) override { } + void link(const std::shared_ptr& doc, const litehtml::element::ptr& el) override { } + void on_anchor_click(const char* url, const litehtml::element::ptr& el) override { } + void on_mouse_event(const litehtml::element::ptr& el, litehtml::mouse_event event) override { } + void set_cursor(const char* cursor) override { } + void transform_text(litehtml::string& text, litehtml::text_transform tt) override { } + void import_css(litehtml::string& text, const litehtml::string& url, litehtml::string& baseurl) override; + void set_clip(const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius) override { } + void del_clip() override { } + void get_client_rect(litehtml::position& client) const override { } + litehtml::element::ptr create_element( const char* tag_name, + const litehtml::string_map& attributes, + const std::shared_ptr& doc) override { return nullptr; } + + void get_media_features(litehtml::media_features& media) const override { } + void get_language(litehtml::string& language, litehtml::string& culture) const override { } public: - void SetParent(const HTMLNode* pParent) { m_parentId = pParent->GetId(); } - void SetParent(const uint64_t parentId) { m_parentId = parentId; } - void SetTag(const HTMLTag tag) { m_tag = tag; } - void SetNodeName(std::string&& nodeName) { m_nodeName = std::move(nodeName); } - void SetText(std::string&& text) { m_text = std::move(text); } - - void AddChild(const HTMLNode* pChild) { m_children.emplace_back(pChild->GetId()); } - void AddAttribute(const HTMLAttribute* pAttribute) { m_attributes.emplace_back(pAttribute->GetId()); } - - void SetStyle(const CSSStyle& style) { m_style = style; } - - SR_NODISCARD HTMLNode* GetParent() const; - SR_NODISCARD HTMLTag GetTag() const { return m_tag; } - SR_NODISCARD const std::string& GetNodeName() const; - SR_NODISCARD const std::string& GetText() const { return m_text; } + void AddPath(const SR_UTILS_NS::Path& path); + void SetPage(HTMLPage* page) { m_page = page; } - SR_NODISCARD CSSStyle& GetStyle() { return m_style; } - SR_NODISCARD const CSSStyle& GetStyle() const { return m_style; } - - SR_NODISCARD const std::vector& GetChildren() const { return m_children; } - SR_NODISCARD const std::vector& GetAttributes() const { return m_attributes; } - - SR_NODISCARD HTMLAttribute* GetAttributeByName(const std::string& name) const; - - SR_NODISCARD HTMLPage* GetPage() const { return m_pPage; } - - SR_NODISCARD uint64_t GetId() const { return m_id; } - void SetId(const uint64_t id, Passkey) { m_id = id; } - - void SetUserData(void* pUserData) { m_pUserData = pUserData; } - SR_NODISCARD void* GetUserData() const { return m_pUserData; } - - void RemoveUserDataRecursively(); + SR_NODISCARD const std::vector& GetPaths() const { return m_paths; } + SR_NODISCARD const SR_UTILS_NS::Path& GetPath() const; + SR_NODISCARD HTMLPage* GetPage() const { return m_page; } private: - HTMLPage* m_pPage = nullptr; - uint64_t m_parentId = SR_ID_INVALID; - HTMLTag m_tag = HTMLTag::Undefined; - CSSStyle m_style; - std::string m_nodeName; - std::string m_text; - std::vector m_children; - std::vector m_attributes; + HTMLPage* m_page = nullptr; + std::vector m_paths; - uint64_t m_id = SR_ID_INVALID; + }; - void* m_pUserData = nullptr; +#else + class HTMLContainerInterface : public SR_HTYPES_NS::SharedPtr { - }; + }; +#endif class HTMLPage final : public SR_HTYPES_NS::SharedPtr { using Super = SR_HTYPES_NS::SharedPtr; - public: - using Ptr = SR_HTYPES_NS::SharedPtr; - - public: + private: HTMLPage(); - ~HTMLPage(); - - SR_NODISCARD HTMLNode* AllocateNode(); - void FreeNode(HTMLNode* pNode); - void FreeNode(const uint64_t id) { FreeNode(GetNodeById(id)); } - - SR_NODISCARD HTMLAttribute* AllocateAttribute(); - void FreeAttribute(HTMLAttribute* pAttribute); - void FreeAttribute(const uint64_t id) { FreeAttribute(GetAttributeById(id)); } public: - SR_NODISCARD HTMLNode* GetHead() { return m_headId != SR_ID_INVALID ? &m_nodePool.AtUnchecked(m_headId) : nullptr; } - SR_NODISCARD HTMLNode* GetBody() { return m_bodyId != SR_ID_INVALID ? &m_nodePool.AtUnchecked(m_bodyId) : nullptr; } - SR_NODISCARD const HTMLNode* GetHead() const { return m_headId != SR_ID_INVALID ? &m_nodePool.AtUnchecked(m_headId) : nullptr; } - SR_NODISCARD const HTMLNode* GetBody() const { return m_bodyId != SR_ID_INVALID ? &m_nodePool.AtUnchecked(m_bodyId) : nullptr; } - - SR_NODISCARD SR_MATH_NS::UVector2 GetSize() const; - - SR_NODISCARD HTMLNode* GetNodeById(uint64_t id); - SR_NODISCARD HTMLAttribute* GetAttributeById(uint64_t id); + using Ptr = SR_HTYPES_NS::SharedPtr; - void AddStyle(const CSS::Ptr& pStyle) { m_styles.emplace_back(pStyle); } + ~HTMLPage(); - SR_NODISCARD std::optional GetStyle(const std::string& selector) const { - for (const auto& pStyle : m_styles) { - if (const auto pStyleValue = pStyle->GetStyle(selector)) { - return *pStyleValue; - } - } - return std::nullopt; - } + public: + static Ptr Load(const SR_UTILS_NS::Path& path, const HTMLContainerInterface::Ptr& pContainer = nullptr); - void SetSize(const SR_MATH_NS::UVector2& size); - void SetHead(const HTMLNode* pHead) { m_headId = pHead->GetId(); } - void SetBody(const HTMLNode* pBody) { m_bodyId = pBody->GetId(); } + SR_NODISCARD const std::vector& GetPaths() const; + SR_NODISCARD HTMLContainerInterface::Ptr GetContainer() const { return m_container; } - void RemoveUserDataRecursively(); + #ifdef SR_COMMON_LITEHTML + SR_NODISCARD litehtml::document::ptr GetDocument() const { return m_document; } + #else + SR_NODISCARD void* GetDocument() const { return nullptr; } + #endif private: - uint64_t m_headId = SR_ID_INVALID; - uint64_t m_bodyId = SR_ID_INVALID; - - SR_HTYPES_NS::ObjectPool m_nodePool; - SR_HTYPES_NS::ObjectPool m_attributePool; + HTMLContainerInterface::Ptr m_container; - std::vector m_styles; + #ifdef SR_COMMON_LITEHTML + litehtml::document::ptr m_document; + #else + void* m_document; + #endif }; } diff --git a/inc/Utils/macros.h b/inc/Utils/macros.h index ad87a7fb..d6485ca6 100644 --- a/inc/Utils/macros.h +++ b/inc/Utils/macros.h @@ -277,8 +277,10 @@ #if defined(SR_MSVC) #define SR_STRCMPI _strcmpi + #define SR_STRNCPY strncpy_s #else #define SR_STRCMPI strcasecmp + #define SR_STRNCPY strncpy #endif #ifdef SR_MSVC diff --git a/py/ResourceEmbedder.py b/py/ResourceEmbedder.py index 39b81d5a..6abc9762 100644 --- a/py/ResourceEmbedder.py +++ b/py/ResourceEmbedder.py @@ -1,5 +1,7 @@ from Common import * +print("ResourceEmbedder.py: running...") + def needs_update(path, export_path): if not os.path.exists(path): print(f"Path does not exist: {path}") diff --git a/src/Utils/Common/HashManager.cpp b/src/Utils/Common/HashManager.cpp index b5920d7a..1f335d9c 100644 --- a/src/Utils/Common/HashManager.cpp +++ b/src/Utils/Common/HashManager.cpp @@ -6,8 +6,17 @@ namespace SR_UTILS_NS { HashManager& HashManager::Instance() { - static HashManager instance; - return instance; + static std::atomic pInstance = nullptr; + HashManager* pTmp = pInstance.load(std::memory_order_acquire); + if (pTmp == nullptr) { + auto&& pNewInstance = new HashManager(); + if (!pInstance.compare_exchange_strong(pTmp, pNewInstance, std::memory_order_release, std::memory_order_relaxed)) { + delete pNewInstance; + } else { + pTmp = pNewInstance; + } + } + return *pTmp; } HashManager::Hash HashManager::AddHash(const char* str) { @@ -22,13 +31,18 @@ namespace SR_UTILS_NS { return GetOrAddInfo(str)->hash; } - const std::string& HashManager::HashToString(HashManager::Hash hash) const { + const std::string_view& HashManager::HashToString(HashManager::Hash hash) const { SR_LOCK_GUARD; - static std::string gDefault; + static std::string_view gDefault; if (auto&& pIt = m_strings.find(hash); pIt != m_strings.end()) { - return pIt->second->data; + return pIt->second->view; } + + /*if (const auto str = g_StringRegistry.FindConstexprStringByHash(hash)) { + return str.value(); + }*/ + return gDefault; } @@ -53,6 +67,7 @@ namespace SR_UTILS_NS { pInfo->size = str.size(); pInfo->data = std::move(str); pInfo->hash = hash; + pInfo->view = pInfo->data; m_strings.insert(std::make_pair(hash, pInfo)); diff --git a/src/Utils/Types/StringAtom.cpp b/src/Utils/Types/StringAtom.cpp index d37b9fb7..17b35fc8 100644 --- a/src/Utils/Types/StringAtom.cpp +++ b/src/Utils/Types/StringAtom.cpp @@ -8,23 +8,23 @@ namespace SR_UTILS_NS { StringHashInfo* StringAtom::DEFAULT_STRING_INFO = SR_UTILS_NS::HashManager::Instance().GetOrAddInfo(""); - StringAtom::StringAtom() { + constexpr StringAtom::StringAtom() { m_info = DEFAULT_STRING_INFO; } - StringAtom::StringAtom(const char* str) + constexpr StringAtom::StringAtom(const char* str) : StringAtom(SR_UTILS_NS::HashManager::Instance().GetOrAddInfo(str)) { } - StringAtom::StringAtom(const std::string& str) + constexpr StringAtom::StringAtom(const std::string& str) : StringAtom(SR_UTILS_NS::HashManager::Instance().GetOrAddInfo(str)) { } - StringAtom::StringAtom(const std::string_view& str) + StringAtom::StringAtom(std::string_view str) : StringAtom(SR_UTILS_NS::HashManager::Instance().GetOrAddInfo(str)) { } - StringAtom::StringAtom(StringHashInfo* pInfo) + constexpr StringAtom::StringAtom(StringHashInfo* pInfo) : m_info(pInfo) { SRAssert(m_info); @@ -38,7 +38,7 @@ namespace SR_UTILS_NS { m_info = DEFAULT_STRING_INFO; } - StringAtom::operator std::string() const noexcept { /// NOLINT + StringAtom::operator const std::string&() const noexcept { /// NOLINT return m_info ? m_info->data : DEFAULT; } diff --git a/src/Utils/Web/CSS/CSS.cpp b/src/Utils/Web/CSS/CSS.cpp index 0ee8459b..a49b7676 100644 --- a/src/Utils/Web/CSS/CSS.cpp +++ b/src/Utils/Web/CSS/CSS.cpp @@ -36,13 +36,97 @@ namespace SR_UTILS_NS::Web { void CSSStyle::ParseProperty(std::string_view name, std::string_view data) { const SRHashType nameHash = SR_HASH_STR_VIEW(name); - if (nameHash == "display"_atom_hash) { + if (nameHash == "position"_atom_hash_cexpr) { + position = StringToCSSPosition(data); + } + else if (nameHash == "box-sizing"_atom_hash_cexpr) { + boxSizing = StringToCSSBoxSizing(data); + } + else if (nameHash == "margin"_atom_hash_cexpr) { + const auto& values = SR_UTILS_NS::StringUtils::SplitView(data, " "); + if (values.size() == 1) { + const auto result = CSSSizeValue::Parse(values[0]); + if (result) { + marginTop = marginRight = marginBottom = marginLeft = result.value(); + } + } + else if (values.size() == 2) { + const auto result1 = CSSSizeValue::Parse(values[0]); + const auto result2 = CSSSizeValue::Parse(values[1]); + if (result1 && result2) { + marginTop = marginBottom = result1.value(); + marginRight = marginLeft = result2.value(); + } + } + else if (values.size() == 3) { + const auto result1 = CSSSizeValue::Parse(values[0]); + const auto result2 = CSSSizeValue::Parse(values[1]); + const auto result3 = CSSSizeValue::Parse(values[2]); + if (result1 && result2 && result3) { + marginTop = result1.value(); + marginRight = marginLeft = result2.value(); + marginBottom = result3.value(); + } + } + else if (values.size() == 4) { + const auto result1 = CSSSizeValue::Parse(values[0]); + const auto result2 = CSSSizeValue::Parse(values[1]); + const auto result3 = CSSSizeValue::Parse(values[2]); + const auto result4 = CSSSizeValue::Parse(values[3]); + if (result1 && result2 && result3 && result4) { + marginTop = result1.value(); + marginRight = result2.value(); + marginBottom = result3.value(); + marginLeft = result4.value(); + } + } + } + else if (nameHash == "padding"_atom_hash_cexpr) { + const auto& values = SR_UTILS_NS::StringUtils::SplitView(data, " "); + if (values.size() == 1) { + const auto result = CSSSizeValue::Parse(values[0]); + if (result) { + paddingTop = paddingRight = paddingBottom = paddingLeft = result.value(); + } + } + else if (values.size() == 2) { + const auto result1 = CSSSizeValue::Parse(values[0]); + const auto result2 = CSSSizeValue::Parse(values[1]); + if (result1 && result2) { + paddingTop = paddingBottom = result1.value(); + paddingRight = paddingLeft = result2.value(); + } + } + else if (values.size() == 3) { + const auto result1 = CSSSizeValue::Parse(values[0]); + const auto result2 = CSSSizeValue::Parse(values[1]); + const auto result3 = CSSSizeValue::Parse(values[2]); + if (result1 && result2 && result3) { + paddingTop = result1.value(); + paddingRight = paddingLeft = result2.value(); + paddingBottom = result3.value(); + } + } + else if (values.size() == 4) { + const auto result1 = CSSSizeValue::Parse(values[0]); + const auto result2 = CSSSizeValue::Parse(values[1]); + const auto result3 = CSSSizeValue::Parse(values[2]); + const auto result4 = CSSSizeValue::Parse(values[3]); + if (result1 && result2 && result3 && result4) { + paddingTop = result1.value(); + paddingRight = result2.value(); + paddingBottom = result3.value(); + paddingLeft = result4.value(); + } + } + } + else if (nameHash == "display"_atom_hash_cexpr) { display = StringToCSSDisplay(data); } - else if (nameHash == "color"_atom_hash) { + else if (nameHash == "color"_atom_hash_cexpr) { color = CSSColor::Parse(data); } - else if (nameHash == "background-color"_atom_hash || nameHash == "background"_atom_hash) { + else if (nameHash == "background-color"_atom_hash_cexpr || nameHash == "background"_atom_hash_cexpr) { backgroundColor = CSSColor::Parse(data); } else if (const auto& it = CSS_CLASS_SIZE_PROPERTIES.find(nameHash); it != CSS_CLASS_SIZE_PROPERTIES.end()) { @@ -66,11 +150,17 @@ namespace SR_UTILS_NS::Web { if (depth > 0) { result += std::string(depth, '\t'); } - result += SR_FORMAT("{}: {};\n", SR_HASH_TO_STR(hash).c_str(), value.ToString()); + result += SR_FORMAT("{}: {};\n", SR_HASH_TO_STR(hash), value.ToString()); } if (depth > 0) { result += std::string(depth, '\t'); } - result += SR_FORMAT("display: {};\n", SR_HASH_TO_STR(CSSDisplayToString(display)).c_str()); + result += SR_FORMAT("display: {};\n", SR_HASH_TO_STR(CSSDisplayToString(display))); + + if (depth > 0) { result += std::string(depth, '\t'); } + result += SR_FORMAT("box-sizing: {};\n", SR_HASH_TO_STR(CSSBoxSizingToString(boxSizing))); + + if (depth > 0) { result += std::string(depth, '\t'); } + result += SR_FORMAT("position: {};\n", SR_HASH_TO_STR(CSSPositionToString(position))); if (const auto str = color.ToString(); !str.empty()) { if (depth > 0) { result += std::string(depth, '\t'); } @@ -85,6 +175,69 @@ namespace SR_UTILS_NS::Web { return result; } + CSSStyle CSSStyle::Merge(const CSSStyle& main, const CSSStyle& other) { + CSSStyle result = main; + if (!other.width.IsDefault()) { + result.width = other.width; + } + if (!other.height.IsDefault()) { + result.height = other.height; + } + if (!other.marginTop.IsDefault()) { + result.marginTop = other.marginTop; + } + if (!other.marginRight.IsDefault()) { + result.marginRight = other.marginRight; + } + if (!other.marginBottom.IsDefault()) { + result.marginBottom = other.marginBottom; + } + if (!other.marginLeft.IsDefault()) { + result.marginLeft = other.marginLeft; + } + if (!other.paddingTop.IsDefault()) { + result.paddingTop = other.paddingTop; + } + if (!other.paddingRight.IsDefault()) { + result.paddingRight = other.paddingRight; + } + if (!other.paddingBottom.IsDefault()) { + result.paddingBottom = other.paddingBottom; + } + if (!other.paddingLeft.IsDefault()) { + result.paddingLeft = other.paddingLeft; + } + if (!other.borderTop.IsDefault()) { + result.borderTop = other.borderTop; + } + if (other.borderRight.IsDefault()) { + result.borderRight = other.borderRight; + } + if (!other.borderBottom.IsDefault()) { + result.borderBottom = other.borderBottom; + } + if (!other.borderLeft.IsDefault()) { + result.borderLeft = other.borderLeft; + } + if (!other.opacity.IsDefault()) { + result.opacity = other.opacity; + } + if (!other.zIndex.IsDefault()) { + result.zIndex = other.zIndex; + } + if (other.display.IsDefault()) { + result.display = other.display; + } + + /// TODO: need merge instead of replace + result.color = other.color; + result.backgroundColor = other.backgroundColor; + result.boxSizing = other.boxSizing; + result.position = other.position; + + return result; + } + /// ---------------------------------------------------------------------------------------------------------------- CSS::CSS() @@ -96,9 +249,17 @@ namespace SR_UTILS_NS::Web { if (depth > 0) { result += std::string(depth, '\t'); } - for (const auto& [token, style] : m_tokens) { + + result = "* {\n" + m_globalStyle.ToString(depth + 1) + "}\n"; + + for (const auto& [token, style] : m_styles) { std::string body = "{\n" + style.ToString(depth + 1) + "}"; - result += SR_FORMAT("{} {}\n", token.c_str(), body); + if (token.second) { + result += SR_FORMAT(".{} {}\n", token.first.c_str(), body); + } + else { + result += SR_FORMAT("{} {}\n", token.first.c_str(), body); + } } return result; }