UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
VVMUniqueStringInline.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#if WITH_VERSE_VM || defined(__INTELLISENSE__)
6
10
11namespace Verse
12{
13template <typename T>
14inline FUtf8StringView FUniqueStringSetKeyFuncsBase<T>::GetSetKey(VUniqueString& Element)
15{
16 return Element.AsStringView();
17}
18
19template <typename T>
20inline FUtf8StringView FUniqueStringSetKeyFuncsBase<T>::GetSetKey(const T& Element)
21{
22 if (const VUniqueString* String = Element.Get())
23 {
24 return String->AsStringView();
25 }
26 else
27 {
28 return FUtf8StringView();
29 }
30}
31
32template <typename T>
33inline bool FUniqueStringSetKeyFuncsBase<T>::Matches(FUtf8StringView A, FUtf8StringView B)
34{
35 return A.Equals(B, ESearchCase::CaseSensitive);
36}
37
38template <typename T>
39inline uint32 FUniqueStringSetKeyFuncsBase<T>::GetKeyHash(FUtf8StringView Key)
40{
41 return GetTypeHash(Key);
42}
43
46
47inline VUniqueStringSet::FConstIterator::FConstIterator(SetType::TRangedForConstIterator InCurrentIteration)
48 : CurrentIteration(InCurrentIteration) {}
49
50inline const TWriteBarrier<VUniqueString>* VUniqueStringSet::FConstIterator::operator->() const
51{
52 return &*CurrentIteration;
53}
54
55inline const TWriteBarrier<VUniqueString>& VUniqueStringSet::FConstIterator::operator*() const
56{
57 return *CurrentIteration;
58}
59
60inline bool VUniqueStringSet::FConstIterator::operator==(const FConstIterator& Rhs) const
61{
62 return CurrentIteration == Rhs.CurrentIteration;
63}
64
65inline bool VUniqueStringSet::FConstIterator::operator!=(const FConstIterator& Rhs) const
66{
67 return CurrentIteration != Rhs.CurrentIteration;
68}
69
70inline VUniqueStringSet::FConstIterator& VUniqueStringSet::FConstIterator::operator++()
71{
72 ++CurrentIteration;
73 return *this;
74}
75
76inline VUniqueStringSet::FConstIterator VUniqueStringSet::begin() const
77{
78 return Strings.begin();
79}
80
81inline VUniqueStringSet::FConstIterator VUniqueStringSet::end() const
82{
83 return Strings.end();
84}
85
86inline VUniqueStringSet& VUniqueStringSet::New(FAllocationContext Context, TSet<VUniqueString*> InStrings)
87{
88 return Pool->Intern(Context, InStrings);
89}
90
91inline VUniqueStringSet& VUniqueStringSet::New(FAllocationContext Context, const std::initializer_list<FUtf8StringView>& InStrings)
92{
94 StringSet.Reserve(InStrings.size());
95 for (const FUtf8StringView& String : InStrings)
96 {
97 VUniqueString& UniqueString = VUniqueString::New(Context, String);
99 }
100 return Pool->Intern(Context, StringSet);
101}
102
103inline VUniqueStringSet& VUniqueStringSet::Make(FAllocationContext Context, const TSet<VUniqueString*>& InSet)
104{
105 // All of the string sets' memory is being managed externally via `TSet` so this is OK.
106 const size_t NumBytes = sizeof(VUniqueStringSet);
107 return *new (Context.Allocate(FHeap::DestructorSpace, NumBytes)) VUniqueStringSet(Context, InSet);
108}
109
110inline bool VUniqueStringSet::operator==(const VUniqueStringSet& Other) const
111{
112 // We can compare by pointer address, because two unique string sets that are the same should have been vended the same way.
113 return this == &Other;
114}
115
116inline uint32 VUniqueStringSet::Num() const
117{
118 return Strings.Num();
119}
120
121inline FSetElementId VUniqueStringSet::FindId(const FUtf8StringView& String) const
122{
123 return Strings.FindId(String);
124}
125
126inline bool VUniqueStringSet::IsValidId(const FSetElementId& Id) const
127{
128 return Strings.IsValidId(Id);
129}
130
131inline VUniqueStringSet::SetType VUniqueStringSet::FormSet(FAllocationContext Context, const TSet<VUniqueString*>& InSet)
132{
133 VUniqueStringSet::SetType Strings;
134 Strings.Reserve(InSet.Num());
136 {
138 Strings.Add({Context, *InString});
139 }
140 return Strings;
141}
142
143inline VUniqueStringSet::VUniqueStringSet(FAllocationContext Context, const TSet<VUniqueString*>& InSet)
145 , Strings(FormSet(Context, InSet))
146{
147}
148
149inline bool VUniqueStringSet::Equals(const TSet<VUniqueString*>& A, const TSet<VUniqueString*>& B)
150{
151 if (A.Num() != B.Num())
152 {
153 return false;
154 }
156}
157
159{
160 // Each of the strings in the set should already be pointing at a globally-unique string; thus we should be
161 // able to reliably hash just the pointers of each string, rather than having to hash the contents of each
162 // specific string.
163 // TODO: (yiliang.siew) Is there potentially a better commutative hash function than just `XOR`?
164 uint32 Result = 0;
165 for (const VUniqueString* const Element : Set)
166 {
167 Result ^= PointerHash(Element);
168 }
169 return Result;
170}
171
173{
174 // Each of the strings in the set should already be pointing at a globally-unique string; thus we should be
175 // able to reliably hash just the pointers of each string, rather than having to hash the contents of each
176 // specific string.
177 uint32 Result = 0;
178 for (const TWriteBarrier<VUniqueString>& Element : Set)
179 {
180 Result ^= PointerHash(Element.Get());
181 }
182 return Result;
183}
184
185inline FHashableUniqueStringSetKey::FHashableUniqueStringSetKey()
186 : Type(EType::Invalid) {}
187
188inline FHashableUniqueStringSetKey::FHashableUniqueStringSetKey(const TSet<VUniqueString*>& InSet)
189 : Set(&InSet)
190 , Type(EType::Set) {}
191
192inline FHashableUniqueStringSetKey::FHashableUniqueStringSetKey(const VUniqueStringSet& InCell)
193 : Cell(&InCell)
194 , Type(EType::Cell) {}
195
196inline bool FHashableUniqueStringSetKey::operator==(const FHashableUniqueStringSetKey& Other) const
197{
199 if (InCell.Num() != static_cast<uint32>(InSet.Num()))
200 {
201 return false;
202 }
204 {
205 if (!InSet.Contains(UniqueString.Get()))
206 {
207 return false;
208 }
209 }
210 return true;
211 };
212
214 // We are just doing a basic pointer comparison here because this path should only ever get hit
215 // when both cells are not the same. If you hit this, check how you're adding to the unique string set pool.
217 checkSlow(!InCell.Equals(InOther));
218 return false;
219 };
220
221 if (Type == EType::Invalid || Other.Type == EType::Invalid)
222 {
223 V_DIE_IF(Type == Other.Type); // We shouldn't have a case of a null-to-null lookup.
224 return false;
225 }
226
227 switch (Type)
228 {
229 case EType::Cell:
230 switch (Other.Type)
231 {
232 case EType::Cell:
233 return CompareCells(*Cell, *Other.Cell);
234 case EType::Set:
235 return CompareCellAndSet(*Cell, *Other.Set);
236 case EType::Invalid:
237 VERSE_UNREACHABLE(); // Should have been hit above.
238 default:
239 return false;
240 }
241 break;
242 case EType::Set:
243 switch (Other.Type)
244 {
245 case EType::Cell:
246 return CompareCellAndSet(*Other.Cell, *Set);
247 case EType::Invalid: // Should have been hit above.
248 case EType::Set:
249 // There shouldn't be a case where a key lookup causes a set-to-set comparison,
250 // because the map entries should only be cells.
252 break;
253 default:
254 return false;
255 }
256 break;
257
258 case EType::Invalid: // Should have been hit above.
259 default:
261 break;
262 }
263
264 return true;
265};
266
267inline FHashableUniqueStringSetKeyFuncs::KeyInitType FHashableUniqueStringSetKeyFuncs::GetSetKey(FHashableUniqueStringSetKeyFuncs::ElementInitType& Element)
268{
269 return {Element};
270}
271
272inline FHashableUniqueStringSetKeyFuncs::KeyInitType FHashableUniqueStringSetKeyFuncs::GetSetKey(const TWeakBarrier<VUniqueStringSet>& Element)
273{
274 const VUniqueStringSet* ElementSet = Element.Get();
275 if (!ElementSet)
276 {
277 // We can hit this after `FHeap::Terminate`, but before `ConductCensus` is called, so
278 // the memory still "lives", but the cell is not marked and is impending being swept.
279 // In such a case, we treat it as if it doesn't exist in the set at all.
280 return {};
281 }
282 return {*ElementSet};
283}
284
285inline bool FHashableUniqueStringSetKeyFuncs::Matches(FHashableUniqueStringSetKeyFuncs::KeyInitType A, FHashableUniqueStringSetKeyFuncs::KeyInitType B)
286{
287 return A == B;
288}
289
290inline uint32 FHashableUniqueStringSetKeyFuncs::GetKeyHash(KeyInitType Key)
291{
292 switch (Key.Type)
293 {
294 case FHashableUniqueStringSetKey::EType::Cell:
295 V_DIE_UNLESS(Key.Cell);
296 return GetTypeHash(*Key.Cell);
297 case FHashableUniqueStringSetKey::EType::Set:
298 V_DIE_UNLESS(Key.Set);
299 return GetSetVUniqueStringTypeHash(*Key.Set);
300 case FHashableUniqueStringSetKey::EType::Invalid:
301 default:
302 break;
303 }
305}
306
307} // namespace Verse
308#endif // WITH_VERSE_VM
#define checkSlow(expr)
Definition AssertionMacros.h:332
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
TStringView< UTF8CHAR > FUtf8StringView
Definition StringFwd.h:48
uint32 PointerHash(const void *Key)
Definition TypeHash.h:91
#define VERSE_UNREACHABLE()
Definition VVMUnreachable.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition SetUtilities.h:95
UE_FORCEINLINE_HINT bool IsValidId() const
Definition SetUtilities.h:101
UE_FORCEINLINE_HINT DataType::RangedForIteratorType begin()
Definition UnrealString.h.inl:301
Type
Definition PawnAction_Move.h:11
@ CaseSensitive
Definition CString.h:23
uint32 GetTypeHash(const FKey &Key)
Definition BlackboardKey.h:35
FORCEINLINE T * Get(const FObjectPtr &ObjectPtr)
Definition ObjectPtr.h:426
Definition TestUtils.cpp:8
EType
Definition AccessDetection.h:11
@ Element
Definition Visu.h:18
FORCEINLINE UE_STRING_CLASS RhsType && Rhs
Definition String.cpp.inl:718
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
Definition Archive.h:36
uint32 GetTypeHash(TPtrVariant< Ts... > Ptr)
Definition VVMPtrVariant.h:83