From 28a903973d766675cbc5e0345900dcdba5a92610 Mon Sep 17 00:00:00 2001
From: pv
Date: Fri, 17 Nov 2023 11:43:31 +0300
Subject: [PATCH 1/2] Implement NodeRef
---
include/RED4ext/NativeTypes.hpp | 7 +-
include/RED4ext/NodeRef.hpp | 125 ++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+), 6 deletions(-)
create mode 100644 include/RED4ext/NodeRef.hpp
diff --git a/include/RED4ext/NativeTypes.hpp b/include/RED4ext/NativeTypes.hpp
index b40a980b5..828ad0e2a 100644
--- a/include/RED4ext/NativeTypes.hpp
+++ b/include/RED4ext/NativeTypes.hpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
#include
@@ -220,12 +221,6 @@ struct MessageResourcePath
};
RED4EXT_ASSERT_SIZE(MessageResourcePath, 0x8);
-struct NodeRef
-{
- uint64_t hash; // 00
-};
-RED4EXT_ASSERT_SIZE(NodeRef, 0x8);
-
struct RuntimeEntityRef
{
int64_t unk00; // 00
diff --git a/include/RED4ext/NodeRef.hpp b/include/RED4ext/NodeRef.hpp
new file mode 100644
index 000000000..ea84192fa
--- /dev/null
+++ b/include/RED4ext/NodeRef.hpp
@@ -0,0 +1,125 @@
+#pragma once
+
+#include
+
+#include
+#include
+
+namespace RED4ext
+{
+struct NodeRef
+{
+ static constexpr auto GlobalRoot = FNV1a64("$"); // NodeRef("$")
+ static constexpr auto RelativeRoot = FNV1a64("~"); // NodeRef("~")
+
+ constexpr NodeRef(uint64_t aHash = 0) noexcept
+ : hash(aHash)
+ {
+ }
+
+ constexpr NodeRef(const char* aNodeRefStr) noexcept
+ : hash(Hash(aNodeRefStr))
+ {
+ }
+
+ constexpr operator uint64_t() const noexcept
+ {
+ return hash;
+ }
+
+ constexpr size_t operator()(const NodeRef& aNodeRef) const
+ {
+ return aNodeRef.hash;
+ }
+
+ constexpr NodeRef& operator=(const uint64_t aRhs) noexcept
+ {
+ hash = aRhs;
+ return *this;
+ }
+
+ constexpr NodeRef& operator=(const char* aRhs) noexcept
+ {
+ *this = NodeRef(aRhs);
+ return *this;
+ }
+
+ constexpr NodeRef& operator=(const NodeRef& aRhs) noexcept
+ {
+ hash = aRhs.hash;
+ return *this;
+ }
+
+ constexpr bool operator==(const NodeRef& aRhs) const noexcept
+ {
+ return hash == aRhs.hash;
+ }
+
+ constexpr bool operator!=(const NodeRef& aRhs) const noexcept
+ {
+ return !(*this == aRhs);
+ }
+
+ constexpr bool operator==(const uint64_t aRhs) const noexcept
+ {
+ return hash == aRhs;
+ }
+
+ constexpr bool operator!=(const uint64_t aRhs) const noexcept
+ {
+ return hash != aRhs;
+ }
+
+ [[nodiscard]] constexpr bool IsEmpty() const noexcept
+ {
+ return hash == 0;
+ }
+
+ static constexpr uint64_t Hash(const char* aNodeRefStr)
+ {
+ constexpr uint64_t prime = 0x100000001b3;
+ constexpr uint64_t seed = 0xCBF29CE484222325;
+
+ uint64_t hash = seed;
+
+ while (aNodeRefStr && *aNodeRefStr)
+ {
+ if (*aNodeRefStr == '#')
+ {
+ ++aNodeRefStr;
+ continue;
+ }
+
+ if (*aNodeRefStr == ';')
+ {
+ ++aNodeRefStr;
+
+ while (*aNodeRefStr && *aNodeRefStr != '/')
+ ++aNodeRefStr;
+
+ if (!*aNodeRefStr)
+ break;
+ }
+
+ hash ^= *aNodeRefStr;
+ hash *= prime;
+
+ ++aNodeRefStr;
+ }
+
+ return hash == seed ? 0 : hash;
+ }
+
+ uint64_t hash;
+};
+RED4EXT_ASSERT_SIZE(NodeRef, 0x8);
+
+template
+struct HashMapHash>>
+{
+ uint32_t operator()(const T& aKey) const noexcept
+ {
+ return static_cast(aKey) ^ ((aKey >> 32) & 0xFFFFFFFF);
+ }
+};
+} // namespace RED4ext
From 86fa042361d3c87e14c93f4b90679b3b67c49af8 Mon Sep 17 00:00:00 2001
From: pv
Date: Fri, 17 Nov 2023 11:44:07 +0300
Subject: [PATCH 2/2] Add convenience methods for DynArray
---
include/RED4ext/DynArray.hpp | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/include/RED4ext/DynArray.hpp b/include/RED4ext/DynArray.hpp
index 629fd7d95..7a0f0433f 100644
--- a/include/RED4ext/DynArray.hpp
+++ b/include/RED4ext/DynArray.hpp
@@ -27,6 +27,17 @@ struct DynArray
{
}
+ DynArray(std::initializer_list aItems, Memory::IAllocator* aAllocator = nullptr)
+ : DynArray(aAllocator)
+ {
+ Reserve(aItems.size());
+
+ for (const auto& item : aItems)
+ {
+ EmplaceBack(item);
+ }
+ }
+
DynArray(const DynArray& aOther)
: DynArray(aOther.GetAllocator())
{
@@ -239,6 +250,26 @@ struct DynArray
}
#pragma endregion
+ T& Front()
+ {
+ return *entries;
+ }
+
+ const T& Front() const
+ {
+ return *entries;
+ }
+
+ T& Back()
+ {
+ return *(entries + size - 1);
+ }
+
+ const T& Back() const
+ {
+ return *(entries + size - 1);
+ }
+
T* entries; // 00
uint32_t capacity; // 08
uint32_t size; // 0C