UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
NetBitArray.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Containers/Array.h"
6#include "HAL/Platform.h"
7#include "HAL/PlatformMath.h"
10#include <type_traits>
11
12namespace UE::Net
13{
14 class FNetBitArray;
15 class FNetBitArrayView;
16
17 namespace Private
18 {
19 class FNetBitArrayRangedForConstIterator;
20 }
21}
22
23
24/* NetBitArray validation support. */
25#ifndef UE_NETBITARRAY_VALIDATE
26#if (UE_BUILD_SHIPPING || UE_BUILD_TEST)
27# define UE_NETBITARRAY_VALIDATE 0
28#else
29# define UE_NETBITARRAY_VALIDATE 1
30#endif
31#endif
32
33#if UE_NETBITARRAY_VALIDATE
34# define UE_NETBITARRAY_CHECK(x) check(x)
35#else
36# define UE_NETBITARRAY_CHECK(...)
37#endif
38
39#define UE_NETBITARRAY_VALIDATE_BOTH_COMPATIBLE(lhs,rhs) UE_NETBITARRAY_CHECK((lhs).GetData() != (rhs).GetData() && (lhs).GetNumBits() == (rhs).GetNumBits())
40
41namespace UE::Net
42{
43
45{
46public:
49
51 static constexpr uint32 WordBitCount = sizeof(StorageWordType)*8U;
52
54 static constexpr uint32 InvalidIndex = ~0U;
55
56 // Some WordOps that can be passed to Combine() and ForAllSetBits()
57 static constexpr StorageWordType AndOp(StorageWordType A, StorageWordType B) { return A & B; }
58 static constexpr StorageWordType AndNotOp(StorageWordType A, StorageWordType B) { return A & ~B; }
59 static constexpr StorageWordType OrOp(StorageWordType A, StorageWordType B) { return A | B; }
60 static constexpr StorageWordType XorOp(StorageWordType A, StorageWordType B) { return A ^ B; }
61
62 // Round up to a value that uses all available bits in a single NetBitArray Word
64 {
65 return Value > 0 ? ((Value + WordBitCount - 1) & ~(WordBitCount - 1)) : WordBitCount;
66 }
67};
68
74{
75public:
78
80 explicit FNetBitArray(uint32 BitCount);
81
84
86 bool operator==(const FNetBitArray& Other) const;
87
92 void Init(uint32 BitCount);
93
97 void InitAndCopy(const FNetBitArray& Source);
98 void InitAndCopy(const FNetBitArrayView& Source);
102 void Empty();
103
110 void SetNumBits(uint32 BitCount);
111
118 void AddBits(uint32 BitCount);
119
121 uint32 GetNumBits() const;
122
124 uint32 GetNumWords() const;
125
131 {
132 checkf((int32)MaxWordIterationCount <= Storage.Num(), TEXT("MaxWordIterationCount (%u) is higher than this NetBitArray word count (%d). Out of Bounds memory access will occur."), MaxWordIterationCount, Storage.Num());
133 return Storage.GetData();
134 }
135
141 {
142 checkf((int32)MaxWordIterationCount <= Storage.Num(), TEXT("MaxWordIterationCount (%u) is higher than this NetBitArray word count (%d). Out of Bounds memory access will occur."), MaxWordIterationCount, Storage.Num());
143 return Storage.GetData();
144 }
145
147 inline const StorageWordType* GetData() const UE_LIFETIMEBOUND { return Storage.GetData(); }
148
150 inline StorageWordType* GetData() UE_LIFETIMEBOUND { return Storage.GetData(); }
151
154 {
155 checkf(WordIndex < (uint32)Storage.Num(), TEXT("NetBitArray index out of bounds: %u / max %u"), WordIndex, Storage.Num());
156 return Storage.GetData()[WordIndex];
157 }
158
161 {
162 checkf(WordIndex < (uint32)Storage.Num(), TEXT("NetBitArray index out of bounds: %u / max %u"), WordIndex, Storage.Num());
163 return Storage.GetData()[WordIndex];
164 }
165
167 UE_DEPRECATED(5.5, "Use ClearAllBits instead.")
169
171 void ClearAllBits();
172
174 void SetAllBits();
175
177 bool IsBitSet(uint32 Index) const { return GetBit(Index); }
178
180 bool IsAnyBitSet() const;
181
183 bool IsAnyBitSet(uint32 StartIndex, uint32 Count) const;
184
186 bool IsNoBitSet() const;
187
189 void SetBit(uint32 Index);
190
192 void SetBitValue(uint32 Index, bool bValue);
193
195 void SetBits(uint32 StartIndex, uint32 Count);
196
198 void ClearBits(uint32 StartIndex, uint32 Count);
199
201 void ClearBit(uint32 Index);
202
204 inline void OrBitValue(uint32 Index, bool bValue);
205
207 inline void AndBitValue(uint32 Index, bool bValue);
208
210 bool GetBit(uint32 Index) const;
211
213 uint32 FindFirstZero() const;
214
216 uint32 FindFirstOne() const;
217
219 uint32 FindFirstZero(uint32 StartIndex) const;
220
222 uint32 FindFirstOne(uint32 StartIndex) const;
223
225 uint32 FindLastZero() const;
226
228 uint32 FindLastOne() const;
229
231 NETCORE_API FString ToString() const;
232
245
247 uint32 CountSetBits(uint32 StartIndex = 0, uint32 Count = ~0U) const;
248
250 void Copy(const FNetBitArray& Other);
251 void Copy(const FNetBitArrayView& Other);
252
261 template<typename WordOpFunctor> void Set(const FNetBitArray& First, WordOpFunctor&& WordOp, const FNetBitArray& Second);
262
270 template<typename WordOpFunctor> void Combine(const FNetBitArray& Other, WordOpFunctor&& WordOp);
271
282 template<typename WordOpFunctor1, typename WordOpFunctor2> void CombineMultiple(WordOpFunctor1&& Op, const FNetBitArray& ArrayA, WordOpFunctor2&& Op2, const FNetBitArray& ArrayB);
283
285 template<typename T>
286 void ForAllSetBits(T&& Functor) const;
287
289 template<typename T>
290 void ForAllSetBitsInRange(const uint32 StartBit, const uint32 EndBit, T&& Functor) const;
291
293 template<typename T>
294 void ForAllUnsetBits(T&& Functor) const;
295
297 template<typename T, typename V>
298 static void ForAllSetBits(const FNetBitArray& A, const FNetBitArray& B, T&& WordOpFunctor, V&& Functor);
299
301 template <typename WordOpFunctor1, typename WordOpFunctor2, typename UserFunctor>
302 static void ForAllSetBitsMultiple(const FNetBitArray& A, WordOpFunctor1&& Op1, const FNetBitArray& B, WordOpFunctor2&& Op2, const FNetBitArray& C, UserFunctor&& Functor);
303
305 template<typename T, typename V>
306 static void ForAllExclusiveBits(const FNetBitArray& A, const FNetBitArray& B, T&& FunctorA, V&& FunctorB);
307
309 template<typename T, typename V, typename Predicate>
310 static void ForAllExclusiveBitsByPredicate(const FNetBitArray& A, const FNetBitArray& B, T&& FunctorA, V&& FunctorB, Predicate&& Pred);
311
316 Private::FNetBitArrayRangedForConstIterator begin() const;
317 Private::FNetBitArrayRangedForConstIterator end() const;
318
319private:
320 StorageWordType GetLastWordMask() const { return (~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1))); }
321 void ClearPaddingBits();
322
324 void Reserve(uint32 BitCount);
325
327 uint32 BitCount;
328};
329
337{
338public:
339
341 inline FNetBitArrayView();
342
349
351 bool operator==(const FNetBitArrayView& Other) const;
352
354 inline bool IsBitSet(uint32 Index) const { return GetBit(Index); }
355
357 inline bool IsAnyBitSet() const;
358
360 inline bool IsAnyBitSet(uint32 StartIndex, uint32 Count) const;
361
363 inline bool IsNoBitSet() const;
364
366 UE_DEPRECATED(5.5, "Use ClearAllBits instead.")
368
370 inline void ClearAllBits();
371
373 inline void ClearPaddingBits();
374
376 inline void SetAllBits();
377
379 inline void SetBit(uint32 Index);
380
382 inline void SetBitValue(uint32 Index, bool bValue);
383
385 inline void SetBits(uint32 StartIndex, uint32 Count);
386
388 inline void ClearBits(uint32 StartIndex, uint32 Count);
389
391 inline void ClearBit(uint32 Index) const;
392
394 inline bool GetBit(uint32 Index) const;
395
397 inline void OrBitValue(uint32 Index, bool bValue);
398
400 inline void AndBitValue(uint32 Index, bool bValue);
401
403 inline uint32 FindFirstZero() const;
404
406 inline uint32 FindFirstOne() const;
407
409 inline uint32 FindFirstZero(uint32 StartIndex) const;
410
412 inline uint32 FindFirstOne(uint32 StartIndex) const;
413
415 uint32 FindLastZero() const;
416
418 uint32 FindLastOne() const;
419
421 inline uint32 GetNumBits() const;
422
424 inline uint32 GetNumWords() const;
425
431 {
432 checkf(MaxWordIterationCount <= WordCount, TEXT("MaxWordIterationCount (%u) is higher than this NetBitArrayView word count (%u). Out of Bounds memory access will occur."), MaxWordIterationCount, WordCount);
433 return Storage;
434 }
435
441 {
442 checkf(MaxWordIterationCount <= WordCount, TEXT("MaxWordIterationCount (%u) is higher than this NetBitArrayView word count (%u). Out of Bounds memory access will occur."), MaxWordIterationCount, WordCount);
443 return Storage;
444 }
445
447 inline const StorageWordType* GetData() const UE_LIFETIMEBOUND { return Storage; }
448
450 inline StorageWordType* GetData() UE_LIFETIMEBOUND { return Storage; }
451
454 {
455 checkf(WordIndex < WordCount, TEXT("NetBitArrayView index out of bounds: %u / max %u"), WordIndex, WordCount);
456 return Storage[WordIndex];
457 }
458
461 {
462 checkf(WordIndex < WordCount, TEXT("NetBitArrayView index out of bounds: %u / max %u"), WordIndex, WordCount);
463 return Storage[WordIndex];
464 }
465
467 NETCORE_API FString ToString() const;
468
481
483 uint32 CountSetBits(uint32 StartIndex = 0, uint32 Count = ~0U) const;
484
486 inline void Copy(const FNetBitArrayView& Other);
487 inline void Copy(const FNetBitArray& Other);
488
497 template<typename WordOpFunctor> void Set(const FNetBitArrayView& First, WordOpFunctor&& WordOp, const FNetBitArrayView& Second);
498
506 template<typename WordOpFunctor> void Combine(const FNetBitArrayView& Other, WordOpFunctor&& WordOp);
507
518 template<typename WordOpFunctor1, typename WordOpFunctor2> void CombineMultiple(WordOpFunctor1&& Op, const FNetBitArrayView& ArrayA, WordOpFunctor2&& Op2, const FNetBitArrayView& ArrayB);
519
521 template <typename T>
522 void ForAllSetBits(T&& Functor) const;
523
525 template <typename T>
526 void ForAllSetBitsInRange(const uint32 StartBit, const uint32 EndBit, T&& Functor) const;
527
529 template<typename T>
530 void ForAllUnsetBits(T&& Functor) const;
531
533 template <typename T, typename V>
534 static void ForAllSetBits(const FNetBitArrayView& A, const FNetBitArrayView& B, T&& WordOpFunctor, V&& Functor);
535
537 template <typename WordOpFunctor1, typename WordOpFunctor2, typename UserFunctor>
539
541 template <typename T, typename V>
542 static void ForAllExclusiveBits(const FNetBitArrayView& A, const FNetBitArrayView& B, T&& FunctorA, V&& FunctorB);
543
545 template<typename T, typename V, typename Predicate>
546 static void ForAllExclusiveBitsByPredicate(const FNetBitArrayView& A, const FNetBitArrayView& B, T&& FunctorA, V&& FunctorB, Predicate&& Pred);
547
548 static constexpr inline uint32 CalculateRequiredWordCount(uint32 BitCount);
549
554 Private::FNetBitArrayRangedForConstIterator begin() const;
555 Private::FNetBitArrayRangedForConstIterator end() const;
556
557private:
558 inline StorageWordType GetLastWordMask() const { return (~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1))); }
559
560 StorageWordType* Storage;
561 uint32 WordCount;
562 uint32 BitCount;
563};
564
565//*************************************************************************************************
566// FNetBitArrayHelper
567// Implementation helper
568//*************************************************************************************************
569
571{
572private:
573 friend FNetBitArray;
574 friend FNetBitArrayView;
575
576 typedef FNetBitArray::StorageWordType StorageWordType;
577 static constexpr uint32 WordBitCount = sizeof(StorageWordType) * 8u;
578
579 static StorageWordType GetLastWordMask(uint32 BitCount)
580 {
581 return (~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1)));
582 }
583
584 static bool IsAnyBitSet(const StorageWordType* Storage, const uint32 WordCount)
585 {
586 for (uint32 WordIt = 0; WordIt < WordCount; ++WordIt)
587 {
588 if (Storage[WordIt])
589 {
590 return true;
591 }
592 }
593
594 return false;
595 }
596
597 static bool IsAnyBitSet(const StorageWordType* Storage, const uint32 BitCount, const uint32 StartIndex, const uint32 Count)
598 {
599 // Range validation
600 if ((Count == 0) | (StartIndex >= BitCount))
601 {
602 return false;
603 }
604
605 const uint32 EndIndex = static_cast<uint32>(FPlatformMath::Min(uint64(StartIndex) + Count - 1U, uint64(BitCount) - 1U));
606 const uint32 WordStartIt = StartIndex / WordBitCount;
607 StorageWordType StartWordMask = (~StorageWordType(0) << (StartIndex & (WordBitCount - 1)));
608 const uint32 WordEndIt = EndIndex / WordBitCount;
609 const StorageWordType EndWordMask = (~StorageWordType(0) >> (~EndIndex & (WordBitCount - 1)));
610
612 {
613 // Compute mask based on start and end word status.
614 const bool bIsEndWord = (WordIt == WordEndIt);
615 const StorageWordType WordMask = StartWordMask & (bIsEndWord ? EndWordMask : ~StorageWordType(0));
616 // Only the first word is the start word so we can set all bits now.
618
619 if (Storage[WordIt] & WordMask)
620 {
621 return true;
622 }
623 }
624
625 return false;
626 }
627
628 static void SetBits(StorageWordType* Storage, const uint32 BitCount, const uint32 StartIndex, const uint32 Count)
629 {
630 UE_NETBITARRAY_CHECK((Count > 0) & (StartIndex < BitCount));
631
632 const uint32 EndIndex = static_cast<uint32>(FPlatformMath::Min(uint64(StartIndex) + Count - 1U, uint64(BitCount) - 1U));
633 const uint32 WordStartIt = StartIndex / WordBitCount;
634 StorageWordType StartWordMask = (~StorageWordType(0) << (StartIndex & (WordBitCount - 1)));
635 const uint32 WordEndIt = EndIndex / WordBitCount;
636 const StorageWordType EndWordMask = (~StorageWordType(0) >> (~EndIndex & (WordBitCount - 1)));
637
639 {
640 // Compute mask based on start and end word status.
641 const bool bIsEndWord = (WordIt == WordEndIt);
642 const StorageWordType WordMask = StartWordMask & (bIsEndWord ? EndWordMask : ~StorageWordType(0));
643 // Only the first word is the start word so we can set all bits now.
645
646 Storage[WordIt] |= ~StorageWordType(0) & WordMask;
647 }
648 }
649
650 static void ClearBits(StorageWordType* Storage, const uint32 BitCount, const uint32 StartIndex, const uint32 Count)
651 {
652 UE_NETBITARRAY_CHECK((Count > 0) & (StartIndex < BitCount));
653
654 const uint32 EndIndex = static_cast<uint32>(FPlatformMath::Min(uint64(StartIndex) + Count - 1U, uint64(BitCount) - 1U));
655 const uint32 WordStartIt = StartIndex / WordBitCount;
656 StorageWordType StartWordMask = (~StorageWordType(0) << (StartIndex & (WordBitCount - 1)));
657 const uint32 WordEndIt = EndIndex / WordBitCount;
658 const StorageWordType EndWordMask = (~StorageWordType(0) >> (~EndIndex & (WordBitCount - 1)));
659
661 {
662 // Compute mask based on start and end word status.
663 const bool bIsEndWord = (WordIt == WordEndIt);
664 const StorageWordType WordMask = StartWordMask & (bIsEndWord ? EndWordMask : ~StorageWordType(0));
665 // Only the first word is the start word so we can set all bits now.
667
668 Storage[WordIt] = Storage[WordIt] & ~WordMask;
669 }
670 }
671
672 static void SetBit(StorageWordType* Storage, const uint32 BitCount, const uint32 Index)
673 {
674 UE_NETBITARRAY_CHECK(Index < BitCount);
675
676 const SIZE_T WordIndex = Index/WordBitCount;
677 const StorageWordType WordMask = (StorageWordType(1) << (Index & (WordBitCount - 1)));
678
679 Storage[WordIndex] |= WordMask;
680 }
681
682 static void SetBitValue(StorageWordType* Storage, const uint32 BitCount, const uint32 Index, const bool bValue)
683 {
684 UE_NETBITARRAY_CHECK(Index < BitCount);
685
686 const SIZE_T WordIndex = Index/WordBitCount;
687 const StorageWordType WordMask = (StorageWordType(1) << (Index & (WordBitCount - 1)));
688 const StorageWordType ValueMask = bValue ? WordMask : StorageWordType(0);
689
690 Storage[WordIndex] = (Storage[WordIndex] & ~WordMask) | ValueMask;
691 }
692
693 static void ClearBit(StorageWordType* Storage, const uint32 BitCount, const uint32 Index)
694 {
695 UE_NETBITARRAY_CHECK(Index < BitCount);
696
697 const SIZE_T WordIndex = Index/WordBitCount;
698 const StorageWordType WordMask = (StorageWordType(1) << (Index & (WordBitCount - 1)));
699
700 Storage[WordIndex] &= ~WordMask;
701 }
702
703 static bool GetBit(const StorageWordType* Storage, const uint32 BitCount, const uint32 Index)
704 {
705 UE_NETBITARRAY_CHECK(Index < BitCount);
706
707 const SIZE_T WordIndex = Index/WordBitCount;
708 const StorageWordType WordMask = (StorageWordType(1) << (Index & (WordBitCount - 1)));
709
710 return (Storage[WordIndex] & WordMask) != 0u;
711 }
712
713 static void OrBitValue(StorageWordType* Storage, const uint32 BitCount, const uint32 Index, const bool bValue)
714 {
715 UE_NETBITARRAY_CHECK(Index < BitCount);
716
717 const SIZE_T WordIndex = Index / WordBitCount;
718 const StorageWordType WordMask = (StorageWordType(1) << (Index & (WordBitCount - 1)));
719 const StorageWordType ValueMask = bValue ? WordMask : StorageWordType(0);
720
721 Storage[WordIndex] = Storage[WordIndex] | ValueMask;
722 }
723
724 static void AndBitValue(StorageWordType* Storage, const uint32 BitCount, const uint32 Index, const bool bValue)
725 {
726 UE_NETBITARRAY_CHECK(Index < BitCount);
727
728 const SIZE_T WordIndex = Index / WordBitCount;
729 const StorageWordType WordMask = (StorageWordType(1) << (Index & (WordBitCount - 1)));
730 const StorageWordType ValueMask = bValue ? ~StorageWordType(0) : ~WordMask;
731
732 Storage[WordIndex] = Storage[WordIndex] & ValueMask;
733 }
734
735 static uint32 FindFirstZero(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount)
736 {
737 for (uint32 WordIt = 0, CurrentBitIndex = 0; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
738 {
739 const StorageWordType Word = Storage[WordIt];
740 if (Word != StorageWordType(~StorageWordType(0)))
741 {
742 const uint32 Index = CurrentBitIndex + FPlatformMath::CountTrailingZeros(~Word);
743 // Need to make sure the index is not out of bounds
744 return (Index < BitCount ? Index : FNetBitArrayBase::InvalidIndex);
745 }
746 }
747
749 }
750
751 static uint32 FindFirstOne(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount)
752 {
753 for (uint32 WordIt = 0, CurrentBitIndex = 0; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
754 {
755 const StorageWordType Word = Storage[WordIt];
756 if (Word != 0)
757 {
758 const uint32 Index = CurrentBitIndex + FPlatformMath::CountTrailingZeros(Word);
759 // Need to make sure the index is not out of bounds
760 return (Index < BitCount ? Index : FNetBitArrayBase::InvalidIndex);
761 }
762 }
763
765 }
766
767 static uint32 FindFirstZero(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount, const uint32 StartIndex)
768 {
769 // WordMask is used to hide zero bits in the first word we check to prevent returning an index before StartIndex.
770 uint32 CurrentBitIndex = StartIndex & ~(WordBitCount - 1U);
771 uint32 WordMask = ~(~0U << (StartIndex & (WordBitCount - 1U)));
772 for (uint32 WordIt = StartIndex/WordBitCount; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
773 {
774 const StorageWordType Word = Storage[WordIt] | WordMask;
775 WordMask = 0U;
776 if (Word != StorageWordType(~StorageWordType(0)))
777 {
778 const uint32 Index = CurrentBitIndex + FPlatformMath::CountTrailingZeros(~Word);
779 // Need to make sure the index is not out of bounds
780 return (Index < BitCount ? Index : FNetBitArrayBase::InvalidIndex);
781 }
782 }
783
785 }
786
787 static uint32 FindFirstOne(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount, const uint32 StartIndex)
788 {
789 uint32 CurrentBitIndex = StartIndex & ~(WordBitCount - 1U);
790 // WordMask is needed only in the first word we check to prevent returning an index before StartIndex.
791 uint32 WordMask = ~0U << (StartIndex & (WordBitCount - 1U));
792 for (uint32 WordIt = StartIndex/WordBitCount; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
793 {
794 const StorageWordType Word = Storage[WordIt] & WordMask;
795 // From here on we accept all words as they are.
796 WordMask = ~0U;
797 if (Word != 0)
798 {
799 const uint32 Index = CurrentBitIndex + FPlatformMath::CountTrailingZeros(Word);
800 // Need to make sure the index is not out of bounds
801 return (Index < BitCount ? Index : FNetBitArrayBase::InvalidIndex);
802 }
803 }
804
806 }
807
808 static uint32 FindLastZero(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount)
809 {
810 StorageWordType WordMask = GetLastWordMask(BitCount);
811
812 for (uint32 WordIt = WordCount; WordIt > 0; )
813 {
814 --WordIt;
815 const StorageWordType Word = Storage[WordIt];
816 if (Word != WordMask)
817 {
818 const uint32 BitOffset = WordIt*WordBitCount;
819 const uint32 Index = BitOffset + WordBitCount - 1U - FPlatformMath::CountLeadingZeros(~Word & WordMask);
820 // Need to make sure the index is not out of bounds
821 return (Index < BitCount ? Index : FNetBitArrayBase::InvalidIndex);
822 }
823
824 WordMask = StorageWordType(~StorageWordType(0));
825 }
826
828 }
829
830 static uint32 FindLastOne(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount)
831 {
832 for (uint32 WordIt = WordCount; WordIt > 0; )
833 {
834 --WordIt;
835 const StorageWordType Word = Storage[WordIt];
836 if (Word != 0U)
837 {
838 const uint32 BitOffset = WordIt*WordBitCount;
839 const uint32 Index = BitOffset + WordBitCount - 1U - FPlatformMath::CountLeadingZeros(Word);
840 return Index;
841 }
842 }
843
845 }
846
847 NETCORE_API static uint32 GetSetBitIndices(const StorageWordType* Storage, const uint32 BitCount, const uint32 StartIndex, const uint32 Count, uint32* const OutIndices, const uint32 OutIndicesCapacity);
848
849 NETCORE_API static uint32 CountSetBits(const StorageWordType* Storage, const uint32 BitCount, const uint32 StartIndex, const uint32 Count);
850
851 template<typename WordOpFunctor> static void Set(StorageWordType* Storage, const StorageWordType* FirstSource, const StorageWordType* SecondSource, const uint32 WordCount, WordOpFunctor&& WordOp)
852 {
853 for (uint32 WordIt = 0; WordIt < WordCount; ++WordIt)
854 {
856 }
857 }
858
859 template<typename Functor> static void Combine(StorageWordType* Storage, const StorageWordType* OtherStorage, const uint32 WordCount, Functor&& WordOp)
860 {
861 for (uint32 WordIt = 0; WordIt < WordCount; ++WordIt)
862 {
863 Storage[WordIt] = WordOp(Storage[WordIt], OtherStorage[WordIt]);
864 }
865 }
866
867 template<typename WordOpFunctor1, typename WordOpFunctor2> static void CombineMultiple(StorageWordType* WriteStorage, const StorageWordType* const ReadStorageA, const StorageWordType* const ReadStorageB, const uint32 WordCount, WordOpFunctor1&& WordOpWrite, WordOpFunctor2&& WordOpRead)
868 {
869 for (uint32 WordIt = 0; WordIt < WordCount; ++WordIt)
870 {
872 }
873 }
874
875 static bool IsEqual(const StorageWordType* Storage, const StorageWordType* OtherStorage, const uint32 WordCount)
876 {
877 StorageWordType Result = 0U;
878 for (uint32 WordIt = 0; WordIt < WordCount; ++WordIt)
879 {
880 Result |= Storage[WordIt] ^ OtherStorage[WordIt];
881 }
882 return Result == 0U;
883 }
884
885 template<typename T> static void ForAllSetBits(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount, T&& Functor)
886 {
887 const StorageWordType LastWordMask = ~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1));
888 const uint32 LastWordIt = WordCount - 1;
889
890 for (uint32 WordIt = 0, CurrentBitIndex = 0; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
891 {
892 StorageWordType CurrentWord = Storage[WordIt] & ((WordIt == LastWordIt) ? LastWordMask : ~0U);
893
894 // Test All bits in the CurrentWord and invoke functor if they are set
895 uint32 LocalBitIndex = CurrentBitIndex;
896 while (CurrentWord)
897 {
898 if (CurrentWord & 0x1)
899 {
900 Functor(LocalBitIndex);
901 }
902 CurrentWord >>= 1;
904 }
905 }
906 }
907
908 //Calls Functor for every set bit from StartBit to EndBit (inclusive)
909 template<typename T> static void ForAllSetBitsInRange(const StorageWordType* Storage, const uint32 TotalWordCount, const uint32 TotalBitCount, const uint32 StartBit, const uint32 EndBit, T&& Functor)
910 {
913 const uint32 StartWord = StartBit / WordBitCount;
914 const uint32 EndWord = EndBit / WordBitCount;
915 const uint32 StartWordBitIndex = StartWord * WordBitCount;//Beginning bit of the StartWord (may be lower than StartBit)
916 const uint32 EndWordBitIndex = EndWord * WordBitCount;//Beginning bit of the EndWord (may be lower than EndBit)
917 const StorageWordType StartWordMask = ~StorageWordType(0) << (StartBit - StartWordBitIndex);
919 const StorageWordType EndWordMask = ~StorageWordType(0) >> (WordBitCount - EndWordBitCount);
920
921 for (uint32 WordIt = StartWord, CurrentBitIndex = StartWordBitIndex; WordIt <= EndWord; ++WordIt, CurrentBitIndex += WordBitCount)
922 {
923 StorageWordType WordMask = (~StorageWordType(0) & ((WordIt == StartWord) ? StartWordMask : ~0U)) & ((WordIt == EndWord) ? EndWordMask : ~0U);
924 StorageWordType CurrentWord = Storage[WordIt] & WordMask;
925
926 // Test All bits in the CurrentWord and invoke functor if they are set
927 uint32 LocalBitIndex = CurrentBitIndex;
928 while (CurrentWord)
929 {
930 if (CurrentWord & 0x1)
931 {
932 Functor(LocalBitIndex);
933 }
934 CurrentWord >>= 1;
936 }
937 }
938 }
939
940 template<typename T> static void ForAllUnsetBits(const StorageWordType* Storage, const uint32 WordCount, const uint32 BitCount, T&& Functor)
941 {
942 const StorageWordType LastWordMask = ~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1));
943 const uint32 LastWordIt = WordCount - 1;
944
945 for (uint32 WordIt = 0, CurrentBitIndex = 0; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
946 {
947 const StorageWordType WordMask = ((WordIt == LastWordIt) ? LastWordMask : ~0U);
948
949 // Flip bits to test the zero values
950 StorageWordType CurrentWord = ~Storage[WordIt] & WordMask;
951
952 // Test All bits in the CurrentWord and invoke functor if they are set
953 uint32 LocalBitIndex = CurrentBitIndex;
954 while (CurrentWord)
955 {
956 if (CurrentWord & 0x1)
957 {
958 Functor(LocalBitIndex);
959 }
960 CurrentWord >>= 1;
962 }
963 }
964 }
965
966 template<typename T, typename V> static void ForAllSetBits(const StorageWordType* StorageA, const StorageWordType* StorageB, const uint32 WordCount, const uint32 BitCount, T&& WordOpFunctor, V&& Functor)
967 {
968 const StorageWordType LastWordMask = ~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1));
969 const uint32 LastWordIt = WordCount - 1;
970
971 for (uint32 WordIt = 0, CurrentBitIndex = 0; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
972 {
973 const StorageWordType CurrentWordA = StorageA[WordIt];
974 const StorageWordType CurrentWordB = StorageB[WordIt];
975
976 StorageWordType CurrentWord = WordOpFunctor(CurrentWordA, CurrentWordB) & ((WordIt == LastWordIt) ? LastWordMask : ~0U);
977
978 // Test All bits in the CurrentWord and invoke functor if they are set
979 uint32 LocalBitIndex = CurrentBitIndex;
980 while (CurrentWord)
981 {
982 if (CurrentWord & 0x1)
983 {
984 Functor(LocalBitIndex);
985 }
986 CurrentWord >>= 1;
988 }
989 }
990 }
991
992 template <typename WordOpFunctor1, typename WordOpFunctor2, typename UserFunctor> static void ForAllSetBitsMultiple(const StorageWordType* StorageA, const StorageWordType* StorageB, const StorageWordType* StorageC, const uint32 WordCount, const uint32 BitCount, WordOpFunctor1&& WordOp1, WordOpFunctor2&& WordOp2, UserFunctor&& Functor)
993 {
994 const StorageWordType LastWordMask = ~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1));
995 const uint32 LastWordIt = WordCount - 1;
996
997 for (uint32 WordIt = 0, CurrentBitIndex = 0; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
998 {
999 const StorageWordType CurrentWordA = StorageA[WordIt];
1000 const StorageWordType CurrentWordB = StorageB[WordIt];
1001 const StorageWordType CurrentWordC = StorageC[WordIt];
1002
1003 StorageWordType CurrentWord = WordOp1(CurrentWordA, WordOp2(CurrentWordB, CurrentWordC) ) & ((WordIt == LastWordIt) ? LastWordMask : ~0U);
1004
1005 // Test All bits in the CurrentWord and invoke functor if they are set
1006 uint32 LocalBitIndex = CurrentBitIndex;
1007 while (CurrentWord)
1008 {
1009 if (CurrentWord & 0x1)
1010 {
1011 Functor(LocalBitIndex);
1012 }
1013 CurrentWord >>= 1;
1014 ++LocalBitIndex;
1015 }
1016 }
1017 }
1018
1019 template<typename T, typename V, typename Predicate> static void ForAllExclusiveBitsByPredicate(const StorageWordType* StorageA, const StorageWordType* StorageB, const uint32 WordCount, const uint32 BitCount, T&& FunctorA, V&& FunctorB, Predicate&& Pred)
1020 {
1021 const StorageWordType LastWordMask = ~StorageWordType(0) >> (uint32(-int32(BitCount)) & (WordBitCount - 1));
1022 const uint32 LastWordIt = WordCount - 1;
1023
1024 for (uint32 WordIt = 0, CurrentBitIndex = 0; WordIt < WordCount; ++WordIt, CurrentBitIndex += WordBitCount)
1025 {
1026 StorageWordType CurrentWordA = StorageA[WordIt];
1027 const StorageWordType CurrentWordB = StorageB[WordIt];
1028 StorageWordType CurrentWordXOR = (CurrentWordA ^ CurrentWordB) & ((WordIt == LastWordIt) ? LastWordMask : ~0U);
1029
1030 // if CurrentWord contains any set bits invoke the correct functor
1031 uint32 LocalBitIndex = CurrentBitIndex;
1032 while (CurrentWordXOR)
1033 {
1034 if (CurrentWordXOR & 0x1)
1035 {
1036 if (Pred(LocalBitIndex))
1037 {
1038 if (CurrentWordA & 0x1)
1039 {
1041 }
1042 else
1043 {
1045 }
1046 }
1047 }
1048
1049 CurrentWordXOR >>= 1;
1050 CurrentWordA >>= 1;
1051
1052 ++LocalBitIndex;
1053 }
1054 }
1055 }
1056
1057 template<typename T, typename V> static void ForAllExclusiveBits(const StorageWordType* StorageA, const StorageWordType* StorageB, const uint32 WordCount, const uint32 BitCount, T&& FunctorA, V&& FunctorB)
1058 {
1059 constexpr auto AlwaysProcessPredicate = [](uint32 Index)
1060 {
1061 return true;
1062 };
1063
1064 return ForAllExclusiveBitsByPredicate(StorageA, StorageB, WordCount, BitCount, FunctorA, FunctorB, AlwaysProcessPredicate);
1065 }
1066
1067};
1068
1069namespace Private
1070{
1071
1072//*************************************************************************************************
1073// FNetBitArrayRangedForConstIterator
1074//*************************************************************************************************
1075class FNetBitArrayRangedForConstIterator
1076{
1077public:
1078 FNetBitArrayRangedForConstIterator();
1079
1080 FNetBitArrayRangedForConstIterator& operator++();
1081
1082 bool operator!=(const FNetBitArrayRangedForConstIterator& It) const;
1083
1085 uint32 operator*() const;
1086
1087private:
1088 friend FNetBitArray;
1089 friend FNetBitArrayView;
1090
1091 enum class ERangeStart : unsigned
1092 {
1093 Begin,
1094 End
1095 };
1096
1097 FNetBitArrayRangedForConstIterator(const FNetBitArrayBase::StorageWordType* InData UE_LIFETIMEBOUND, uint32 BitCount, ERangeStart RangeStart);
1098
1099 void AdvanceToNextSetBit();
1100
1101 const FNetBitArrayBase::StorageWordType* Data = nullptr;
1102 uint32 BitCount = 0;
1103 uint32 WordCount = 0;
1104 uint32 CurrentBitIndex = 0;
1105 uint32 CurrentWord = 0;
1106};
1107
1108} // end namespace Private
1109
1110//*************************************************************************************************
1111// FNetBitArray Implementation
1112//*************************************************************************************************
1114: BitCount(0)
1115{
1116}
1117
1119{
1120 if (BitCount != Other.BitCount)
1121 {
1122 return false;
1123 }
1124
1125 return FNetBitArrayHelper::IsEqual(this->GetData(), Other.GetData(), GetNumWords());
1126}
1127
1129: BitCount(InBitCount)
1130{
1132}
1133
1135: BitCount(InBitCount)
1136{
1137 Reserve(BitCount);
1138}
1139
1141{
1142 BitCount = InBitCount;
1143
1144 const uint32 WordCount = (InBitCount + WordBitCount - 1U)/WordBitCount;
1145 Storage.Reset(WordCount);
1146 Storage.AddZeroed(WordCount);
1147}
1148
1149inline void FNetBitArray::Reserve(uint32 InBitCount)
1150{
1151 BitCount = InBitCount;
1152
1153 const uint32 WordCount = (InBitCount + WordBitCount - 1U) / WordBitCount;
1154 Storage.Reset(WordCount);
1155 Storage.AddUninitialized(WordCount);
1156}
1157
1158inline void FNetBitArray::InitAndCopy(const FNetBitArray& Source)
1159{
1160 Reserve(Source.GetNumBits());
1161
1162 Copy(Source);
1163}
1164
1166{
1167 Reserve(Source.GetNumBits());
1168
1169 Copy(Source);
1170}
1171
1173{
1174 BitCount = 0U;
1175 Storage.Empty();
1176}
1177
1179{
1180 BitCount = InBitCount;
1181
1182 const uint32 WordCount = (InBitCount + WordBitCount - 1U)/WordBitCount;
1183 Storage.SetNumZeroed(WordCount, EAllowShrinking::No);
1184 ClearPaddingBits();
1185}
1186
1191
1193{
1194 return BitCount;
1195}
1196
1198{
1199 return static_cast<uint32>(Storage.Num());
1200}
1201
1203{
1204 FPlatformMemory::Memset(Storage.GetData(), 0, Storage.Num()*sizeof(StorageWordType));
1205}
1206
1208{
1209 FPlatformMemory::Memset(Storage.GetData(), 0xff, Storage.Num()*sizeof(StorageWordType));
1210 ClearPaddingBits();
1211}
1212
1213inline bool FNetBitArray::IsAnyBitSet() const
1214{
1215 return FNetBitArrayHelper::IsAnyBitSet(Storage.GetData(), Storage.Num());
1216}
1217
1218inline bool FNetBitArray::IsAnyBitSet(uint32 StartIndex, uint32 Count) const
1219{
1220 return ((Count == 1U) ? GetBit(StartIndex) : FNetBitArrayHelper::IsAnyBitSet(Storage.GetData(), BitCount, StartIndex, Count));
1221}
1222
1223inline bool FNetBitArray::IsNoBitSet() const
1224{
1225 return !IsAnyBitSet();
1226}
1227
1229{
1230 FNetBitArrayHelper::SetBit(Storage.GetData(), BitCount, Index);
1231}
1232
1233inline void FNetBitArray::SetBitValue(uint32 Index, bool bValue)
1234{
1235 FNetBitArrayHelper::SetBitValue(Storage.GetData(), BitCount, Index, bValue);
1236}
1237
1239{
1240 FNetBitArrayHelper::SetBits(Storage.GetData(), BitCount, StartIndex, Count);
1241}
1242
1244{
1245 FNetBitArrayHelper::ClearBits(Storage.GetData(), BitCount, StartIndex, Count);
1246}
1247
1249{
1250 FNetBitArrayHelper::ClearBit(Storage.GetData(), BitCount, Index);
1251}
1252
1254{
1255 return FNetBitArrayHelper::GetBit(Storage.GetData(), BitCount, Index);
1256}
1257
1258inline void FNetBitArray::OrBitValue(uint32 Index, bool bValue)
1259{
1260 FNetBitArrayHelper::OrBitValue(Storage.GetData(), BitCount, Index, bValue);
1261}
1262
1263inline void FNetBitArray::AndBitValue(uint32 Index, bool bValue)
1264{
1265 FNetBitArrayHelper::AndBitValue(Storage.GetData(), BitCount, Index, bValue);
1266}
1267
1269{
1270 return FNetBitArrayHelper::FindFirstZero(Storage.GetData(), Storage.Num(), BitCount);
1271}
1272
1274{
1275 return FNetBitArrayHelper::FindFirstOne(Storage.GetData(), Storage.Num(), BitCount);
1276}
1277
1279{
1280 return FNetBitArrayHelper::FindFirstZero(Storage.GetData(), Storage.Num(), BitCount, StartIndex);
1281}
1282
1284{
1285 return FNetBitArrayHelper::FindFirstOne(Storage.GetData(), Storage.Num(), BitCount, StartIndex);
1286}
1287
1289{
1290 return FNetBitArrayHelper::FindLastZero(Storage.GetData(), Storage.Num(), BitCount);
1291}
1292
1294{
1295 return FNetBitArrayHelper::FindLastOne(Storage.GetData(), Storage.Num(), BitCount);
1296}
1297
1299{
1300 return FNetBitArrayHelper::GetSetBitIndices(Storage.GetData(), BitCount, StartIndex, Count, OutIndices, OutIndicesCapacity);
1301}
1302
1304{
1305 return FNetBitArrayHelper::CountSetBits(Storage.GetData(), BitCount, StartIndex, Count);
1306}
1307
1309{
1311 if (GetNumWords() > 0 && Other.GetNumWords() > 0)
1312 {
1313 // Intentionally doing a memory copy instead of using assignment operator as we know the bit counts are the same and don't need extra checks.
1315 }
1316}
1317
1319{
1321 if (GetNumWords() > 0 && Other.GetNumWords() > 0)
1322 {
1323 // Intentionally doing a memory copy instead of using assignment operator as we know the bit counts are the same and don't need extra checks.
1325 }
1326}
1327
1328template<typename WordOpFunctor> inline void FNetBitArray::Set(const FNetBitArray& First, WordOpFunctor&& WordOp, const FNetBitArray& Second)
1329{
1332 FNetBitArrayHelper::Set(GetData(), First.GetData(), Second.GetData(), GetNumWords(), WordOp);
1333}
1334
1335template<typename WordOpFunctor> inline void FNetBitArray::Combine(const FNetBitArray& Other, WordOpFunctor&& WordOp)
1336{
1338 FNetBitArrayHelper::Combine(Storage.GetData(), Other.Storage.GetData(), Storage.Num(), WordOp);
1339}
1340
1341template<typename WordOpFunctor1, typename WordOpFunctor2> inline void FNetBitArray::CombineMultiple(WordOpFunctor1&& Op, const FNetBitArray& ArrayA, WordOpFunctor2&& Op2, const FNetBitArray& ArrayB)
1342{
1345 FNetBitArrayHelper::CombineMultiple(Storage.GetData(), ArrayA.Storage.GetData(), ArrayB.Storage.GetData(), Storage.Num(), Op, Op2);
1346}
1347
1348template<typename T> inline void FNetBitArray::ForAllSetBits(T&& Functor) const
1349{
1350 FNetBitArrayHelper::ForAllSetBits(Storage.GetData(), Storage.Num(), BitCount, Functor);
1351}
1352
1353template<typename T> inline void FNetBitArray::ForAllSetBitsInRange(const uint32 StartBit, const uint32 EndBit, T&& Functor) const
1354{
1355 FNetBitArrayHelper::ForAllSetBitsInRange(Storage.GetData(), Storage.Num(), BitCount, StartBit, EndBit, Functor);
1356}
1357
1358template<typename T> inline void FNetBitArray::ForAllUnsetBits(T&& Functor) const
1359{
1360 FNetBitArrayHelper::ForAllUnsetBits(Storage.GetData(), Storage.Num(), BitCount, Functor);
1361}
1362
1363template <typename T, typename V> inline void FNetBitArray::ForAllSetBits(const FNetBitArray& A, const FNetBitArray& B, T&& WordOpFunctor, V&& Functor)
1364{
1365 UE_NETBITARRAY_CHECK(A.GetNumBits() == B.GetNumBits());
1366 FNetBitArrayHelper::ForAllSetBits(A.Storage.GetData(), B.Storage.GetData(), A.Storage.Num(), A.BitCount, WordOpFunctor, Functor);
1367}
1368
1369template<typename WordOpFunctor1, typename WordOpFunctor2, typename UserFunctor> inline void FNetBitArray::ForAllSetBitsMultiple(const FNetBitArray& A, WordOpFunctor1&& Op1, const FNetBitArray& B, WordOpFunctor2&& Op2, const FNetBitArray& C, UserFunctor&& Functor)
1370{
1373 FNetBitArrayHelper::ForAllSetBitsMultiple(A.Storage.GetData(), B.Storage.GetData(), C.Storage.GetData(), A.Storage.Num(), A.BitCount, Op1, Op2, Functor);
1374}
1375
1376template <typename T, typename V> inline void FNetBitArray::ForAllExclusiveBits(const FNetBitArray& A, const FNetBitArray& B, T&& FunctorA, V&& FunctorB)
1377{
1378 UE_NETBITARRAY_CHECK(A.GetNumBits() == B.GetNumBits());
1379 FNetBitArrayHelper::ForAllExclusiveBits(A.Storage.GetData(), B.Storage.GetData(), A.Storage.Num(), A.BitCount, FunctorA, FunctorB);
1380}
1381
1382template <typename T, typename V, typename Predicate> inline void FNetBitArray::ForAllExclusiveBitsByPredicate(const FNetBitArray& A, const FNetBitArray& B, T&& FunctorA, V&& FunctorB, Predicate&& Pred)
1383{
1384 UE_NETBITARRAY_CHECK(A.GetNumBits() == B.GetNumBits());
1385 FNetBitArrayHelper::ForAllExclusiveBitsByPredicate(A.Storage.GetData(), B.Storage.GetData(), A.Storage.Num(), A.BitCount, FunctorA, FunctorB, Pred);
1386}
1387
1388inline void FNetBitArray::ClearPaddingBits()
1389{
1390 if (BitCount > 0)
1391 {
1392 StorageWordType& LastWord = Storage.GetData()[Storage.Num() - 1];
1393 LastWord &= GetLastWordMask();
1394 }
1395}
1396
1397//*************************************************************************************************
1398// FNetBitArrayRangedForConstIterator implementation
1399//*************************************************************************************************
1400inline Private::FNetBitArrayRangedForConstIterator FNetBitArray::begin() const
1401{
1402 return Private::FNetBitArrayRangedForConstIterator(Storage.GetData(), BitCount, Private::FNetBitArrayRangedForConstIterator::ERangeStart::Begin);
1403}
1404
1405inline Private::FNetBitArrayRangedForConstIterator FNetBitArray::end() const
1406{
1407 return Private::FNetBitArrayRangedForConstIterator(Storage.GetData(), BitCount, Private::FNetBitArrayRangedForConstIterator::ERangeStart::End);
1408}
1409
1410
1411//*************************************************************************************************
1412// NetBitArrayView implementation
1413//*************************************************************************************************
1415{
1416 return (BitCount + WordBitCount - 1) / WordBitCount;
1417}
1418
1420: Storage(&BitCount)
1421, WordCount(0)
1422, BitCount(0)
1423{
1424}
1425
1427: Storage(StorageIn)
1428, WordCount(CalculateRequiredWordCount(BitCountIn))
1429, BitCount(BitCountIn)
1430{
1431 if (BitCountIn == 0)
1432 {
1433 Storage = const_cast<uint32*>(&BitCount);
1434 }
1435}
1436
1442
1444: FNetBitArrayView(StorageIn, BitCountIn, NoResetNoValidate)
1445{
1446 UE_NETBITARRAY_CHECK(Storage != nullptr);
1447 UE_NETBITARRAY_CHECK((BitCount == 0) || ((Storage[WordCount - 1] & ~GetLastWordMask()) == 0u));
1448}
1449
1451{
1452 if (BitCount != Other.BitCount)
1453 {
1454 return false;
1455 }
1456
1457 return FNetBitArrayHelper::IsEqual(this->GetData(), Other.GetData(), GetNumWords());
1458}
1459
1461{
1462 return FNetBitArrayHelper::IsAnyBitSet(Storage, WordCount);
1463}
1464
1466{
1467 return ((Count == 1U) ? GetBit(StartIndex) : FNetBitArrayHelper::IsAnyBitSet(GetData(), BitCount, StartIndex, Count));
1468}
1469
1471{
1472 return !IsAnyBitSet();
1473}
1474
1476{
1477 FPlatformMemory::Memset(&Storage[0], 0, WordCount * sizeof(StorageWordType));
1478}
1479
1481{
1482 if (BitCount > 0)
1483 {
1484 Storage[WordCount - 1] = Storage[WordCount - 1] & GetLastWordMask();
1485 }
1486}
1487
1489{
1490 FPlatformMemory::Memset(&Storage[0], 0xff, WordCount * sizeof(StorageWordType));
1492}
1493
1495{
1497 if (GetNumWords() > 0 && Other.GetNumWords() > 0 )
1498 {
1499 FPlatformMemory::Memcpy(&Storage[0], &Other.Storage[0], WordCount * sizeof(StorageWordType));
1500 }
1501}
1502
1504{
1506 if (GetNumWords() > 0 && Other.GetNumWords() > 0)
1507 {
1508 FPlatformMemory::Memcpy(&Storage[0], Other.GetData(), WordCount * sizeof(StorageWordType));
1509 }
1510}
1511
1513{
1514 FNetBitArrayHelper::SetBit(Storage, BitCount, Index);
1515}
1516
1518{
1519 FNetBitArrayHelper::SetBitValue(Storage, BitCount, Index, bValue);
1520}
1521
1523{
1524 FNetBitArrayHelper::SetBits(Storage, BitCount, StartIndex, Count);
1525}
1526
1528{
1529 FNetBitArrayHelper::ClearBits(Storage, BitCount, StartIndex, Count);
1530}
1531
1533{
1534 FNetBitArrayHelper::ClearBit(Storage, BitCount, Index);
1535}
1536
1538{
1539 return FNetBitArrayHelper::GetBit(Storage, BitCount, Index);
1540}
1541
1543{
1544 FNetBitArrayHelper::OrBitValue(Storage, BitCount, Index, bValue);
1545}
1546
1548{
1549 FNetBitArrayHelper::AndBitValue(Storage, BitCount, Index, bValue);
1550}
1551
1553{
1554 return FNetBitArrayHelper::FindFirstZero(Storage, WordCount, BitCount);
1555}
1556
1558{
1559 return FNetBitArrayHelper::FindFirstOne(Storage, WordCount, BitCount);
1560}
1561
1563{
1564 return FNetBitArrayHelper::FindFirstZero(Storage, WordCount, BitCount, StartIndex);
1565}
1566
1568{
1569 return FNetBitArrayHelper::FindFirstOne(Storage, WordCount, BitCount, StartIndex);
1570}
1571
1573{
1574 return FNetBitArrayHelper::FindLastZero(Storage, WordCount, BitCount);
1575}
1576
1578{
1579 return FNetBitArrayHelper::FindLastOne(Storage, WordCount, BitCount);
1580}
1581
1583{
1584 return WordCount;
1585}
1586
1588{
1589 return BitCount;
1590}
1591
1593{
1594 return FNetBitArrayHelper::GetSetBitIndices(Storage, BitCount, StartIndex, Count, OutIndices, OutIndicesCapacity);
1595}
1596
1598{
1599 return FNetBitArrayHelper::CountSetBits(Storage, BitCount, StartIndex, Count);
1600}
1601
1602template<typename WordOpFunctor> inline void FNetBitArrayView::Set(const FNetBitArrayView& First, WordOpFunctor&& WordOp, const FNetBitArrayView& Second)
1603{
1606 FNetBitArrayHelper::Set(GetData(), First.GetData(), Second.GetData(), GetNumWords(), WordOp);
1607}
1608
1609template<typename WordOpFunctor> inline void FNetBitArrayView::Combine(const FNetBitArrayView& Other, WordOpFunctor&& WordOp)
1610{
1612 FNetBitArrayHelper::Combine(Storage, Other.Storage, WordCount, WordOp);
1613}
1614
1615template<typename WordOpFunctor1, typename WordOpFunctor2> inline void FNetBitArrayView::CombineMultiple(WordOpFunctor1&& Op, const FNetBitArrayView& ArrayA, WordOpFunctor2&& Op2, const FNetBitArrayView& ArrayB)
1616{
1619 FNetBitArrayHelper::CombineMultiple(Storage, ArrayA.Storage, ArrayB.Storage, WordCount, Op, Op2);
1620}
1621
1622template<typename T> inline void FNetBitArrayView::ForAllSetBits(T&& Functor) const
1623{
1624 FNetBitArrayHelper::ForAllSetBits(Storage, WordCount, BitCount, Functor);
1625}
1626
1627template<typename T> inline void FNetBitArrayView::ForAllSetBitsInRange(const uint32 StartBit, const uint32 EndBit, T&& Functor) const
1628{
1629 FNetBitArrayHelper::ForAllSetBitsInRange(Storage, WordCount, BitCount, StartBit, EndBit, Functor);
1630}
1631
1632template<typename T> inline void FNetBitArrayView::ForAllUnsetBits(T&& Functor) const
1633{
1634 FNetBitArrayHelper::ForAllUnsetBits(Storage, WordCount, BitCount, Functor);
1635}
1636
1637template <typename T, typename V>
1639{
1640 UE_NETBITARRAY_CHECK(A.GetNumBits() == B.GetNumBits());
1641 FNetBitArrayHelper::ForAllSetBits(A.Storage, B.Storage, A.WordCount, A.BitCount, WordOpFunctor, Functor);
1642}
1643
1644template <typename WordOpFunctor1, typename WordOpFunctor2, typename UserFunctor>
1646{
1649 FNetBitArrayHelper::ForAllSetBitsMultiple(A.Storage, B.Storage, C.Storage, A.WordCount, A.BitCount, Op1, Op2, Functor);
1650}
1651
1652template <typename T, typename V>
1654{
1655 UE_NETBITARRAY_CHECK(A.GetNumBits() == B.GetNumBits());
1656 FNetBitArrayHelper::ForAllExclusiveBits(A.Storage, B.Storage, A.WordCount, A.BitCount, FunctorA, FunctorB);
1657}
1658
1659template <typename T, typename V, typename Predicate>
1661{
1662 UE_NETBITARRAY_CHECK(A.GetNumBits() == B.GetNumBits());
1663 FNetBitArrayHelper::ForAllExclusiveBitsByPredicate(A.Storage, B.Storage, A.WordCount, A.BitCount, FunctorA, FunctorB, Pred);
1664}
1665
1666inline Private::FNetBitArrayRangedForConstIterator FNetBitArrayView::begin() const
1667{
1668 return Private::FNetBitArrayRangedForConstIterator(Storage, BitCount, Private::FNetBitArrayRangedForConstIterator::ERangeStart::Begin);
1669}
1670
1671inline Private::FNetBitArrayRangedForConstIterator FNetBitArrayView::end() const
1672{
1673 return Private::FNetBitArrayRangedForConstIterator(Storage, BitCount, Private::FNetBitArrayRangedForConstIterator::ERangeStart::End);
1674}
1675
1678{
1679 return FNetBitArrayView(const_cast<FNetBitArrayView::StorageWordType*>(Storage), BitCount);
1680}
1681
1686
1689{
1690 return FNetBitArrayView(const_cast<FNetBitArrayView::StorageWordType*>(BitArray.GetData()), BitArray.GetNumBits());
1691}
1692
1698
1699
1700} // end namespace UE::Net
1701
1702namespace UE::Net::Private
1703{
1704
1705
1706//*************************************************************************************************
1707// FNetBitArrayRangedForConstIterator
1708// Implementation
1709//*************************************************************************************************
1710
1711inline FNetBitArrayRangedForConstIterator::FNetBitArrayRangedForConstIterator()
1712{
1713}
1714
1715inline FNetBitArrayRangedForConstIterator::FNetBitArrayRangedForConstIterator(const FNetBitArrayBase::StorageWordType* InData UE_LIFETIMEBOUND, uint32 InBitCount, FNetBitArrayRangedForConstIterator::ERangeStart RangeStart)
1716: Data(InData)
1717, BitCount(InBitCount)
1718, WordCount(FNetBitArrayView::CalculateRequiredWordCount(BitCount))
1719, CurrentBitIndex(RangeStart == ERangeStart::Begin ? 0 : BitCount)
1720{
1721 UE_NETBITARRAY_CHECK(InData != nullptr || InBitCount == 0);
1722 CurrentWord = (CurrentBitIndex < BitCount ? Data[0] : FNetBitArrayBase::StorageWordType(0));
1723 AdvanceToNextSetBit();
1724}
1725
1726inline FNetBitArrayRangedForConstIterator& FNetBitArrayRangedForConstIterator::operator++()
1727{
1728 AdvanceToNextSetBit();
1729 return *this;
1730}
1731
1732inline uint32 FNetBitArrayRangedForConstIterator::operator*() const
1733{
1734 return CurrentBitIndex;
1735}
1736
1737inline bool FNetBitArrayRangedForConstIterator::operator!=(const FNetBitArrayRangedForConstIterator& It) const
1738{
1739 UE_NETBITARRAY_CHECK(this->Data == It.Data);
1740 return this->CurrentBitIndex != It.CurrentBitIndex;
1741}
1742
1743inline void FNetBitArrayRangedForConstIterator::AdvanceToNextSetBit()
1744{
1745 using SignedWordType = typename std::make_signed<FNetBitArrayBase::StorageWordType>::type;
1746
1747 uint32 WordIt = CurrentBitIndex/FNetBitArrayBase::WordBitCount;
1748 while (CurrentWord == 0U)
1749 {
1750 ++WordIt;
1751 if (WordIt >= WordCount)
1752 {
1753 CurrentBitIndex = BitCount;
1754 return;
1755 }
1756
1757 CurrentWord = Data[WordIt];
1758 // It's ok to not adjust the bit index to start on a word boundary. It's handled outside the loop.
1759 CurrentBitIndex += FNetBitArrayBase::WordBitCount;
1760 }
1761
1762 const uint32 NewBitIndex = (CurrentBitIndex & ~(FNetBitArrayBase::WordBitCount - 1U)) + FPlatformMath::CountTrailingZeros(CurrentWord);
1763 CurrentBitIndex = FPlatformMath::Min(NewBitIndex, BitCount);
1764
1765 // Clear least significant bit from CurrentWord. It doesn't matter if we're at the end if the bit array as the CurrentWord will be ignored in that case.
1766 const FNetBitArrayBase::StorageWordType LeastSignificantBit = CurrentWord & FNetBitArrayBase::StorageWordType(-SignedWordType(CurrentWord));
1767 CurrentWord ^= LeastSignificantBit;
1768}
1769
1770} // end namespace UE::Net::Private
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
#define UE_LIFETIMEBOUND
Definition Platform.h:812
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
void Init()
Definition LockFreeList.h:4
#define UE_NETBITARRAY_VALIDATE_BOTH_COMPATIBLE(lhs, rhs)
Definition NetBitArray.h:39
#define UE_NETBITARRAY_CHECK(x)
Definition NetBitArray.h:34
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Array.h:670
UE_FORCEINLINE_HINT SizeType AddUninitialized()
Definition Array.h:1664
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void SetNumZeroed(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2340
void Reset(SizeType NewSize=0)
Definition Array.h:2246
UE_NODEBUG UE_FORCEINLINE_HINT ElementType * GetData() UE_LIFETIMEBOUND
Definition Array.h:1027
SizeType AddZeroed()
Definition Array.h:2755
void Empty(SizeType Slack=0)
Definition Array.h:2273
Definition NetBitArray.h:45
static constexpr StorageWordType AndNotOp(StorageWordType A, StorageWordType B)
Definition NetBitArray.h:58
static constexpr StorageWordType OrOp(StorageWordType A, StorageWordType B)
Definition NetBitArray.h:59
uint32 StorageWordType
Definition NetBitArray.h:50
EResetOnInitType
Definition NetBitArray.h:48
@ ResetOnInit
Definition NetBitArray.h:48
static uint32 RoundUpToMaxWordBitCount(uint32 Value)
Definition NetBitArray.h:63
static constexpr uint32 InvalidIndex
Definition NetBitArray.h:54
static constexpr StorageWordType XorOp(StorageWordType A, StorageWordType B)
Definition NetBitArray.h:60
static constexpr uint32 WordBitCount
Definition NetBitArray.h:51
ENoResetNoValidateType
Definition NetBitArray.h:47
@ NoResetNoValidate
Definition NetBitArray.h:47
static constexpr StorageWordType AndOp(StorageWordType A, StorageWordType B)
Definition NetBitArray.h:57
Definition NetBitArray.h:571
Definition NetBitArray.h:337
FNetBitArrayView()
Definition NetBitArray.h:1419
uint32 FindFirstOne() const
Definition NetBitArray.h:1557
void ForAllSetBits(T &&Functor) const
Definition NetBitArray.h:1622
StorageWordType * GetData() UE_LIFETIMEBOUND
Definition NetBitArray.h:450
static void ForAllSetBitsMultiple(const FNetBitArrayView &A, WordOpFunctor1 &&Op1, const FNetBitArrayView &B, WordOpFunctor2 &&Op2, const FNetBitArrayView &C, UserFunctor &&Functor)
Definition NetBitArray.h:1645
void ForAllUnsetBits(T &&Functor) const
Definition NetBitArray.h:1632
bool IsAnyBitSet() const
Definition NetBitArray.h:1460
void ClearBits(uint32 StartIndex, uint32 Count)
Definition NetBitArray.h:1527
uint32 GetNumBits() const
Definition NetBitArray.h:1587
bool IsBitSet(uint32 Index) const
Definition NetBitArray.h:354
StorageWordType GetWord(uint32 WordIndex) const UE_LIFETIMEBOUND
Definition NetBitArray.h:453
void ClearBit(uint32 Index) const
Definition NetBitArray.h:1532
void Reset()
Definition NetBitArray.h:367
uint32 CountSetBits(uint32 StartIndex=0, uint32 Count=~0U) const
Definition NetBitArray.h:1597
static void ForAllExclusiveBitsByPredicate(const FNetBitArrayView &A, const FNetBitArrayView &B, T &&FunctorA, V &&FunctorB, Predicate &&Pred)
Definition NetBitArray.h:1660
const StorageWordType * GetDataChecked(uint32 MaxWordIterationCount) const UE_LIFETIMEBOUND
Definition NetBitArray.h:430
uint32 GetSetBitIndices(uint32 StartIndex, uint32 Count, uint32 *OutIndices, uint32 OutIndicesCapacity) const
Definition NetBitArray.h:1592
void AndBitValue(uint32 Index, bool bValue)
Definition NetBitArray.h:1547
void Copy(const FNetBitArrayView &Other)
Definition NetBitArray.h:1494
static void ForAllExclusiveBits(const FNetBitArrayView &A, const FNetBitArrayView &B, T &&FunctorA, V &&FunctorB)
Definition NetBitArray.h:1653
Private::FNetBitArrayRangedForConstIterator begin() const
Definition NetBitArray.h:1666
Private::FNetBitArrayRangedForConstIterator end() const
Definition NetBitArray.h:1671
void SetBit(uint32 Index)
Definition NetBitArray.h:1512
void CombineMultiple(WordOpFunctor1 &&Op, const FNetBitArrayView &ArrayA, WordOpFunctor2 &&Op2, const FNetBitArrayView &ArrayB)
Definition NetBitArray.h:1615
void Set(const FNetBitArrayView &First, WordOpFunctor &&WordOp, const FNetBitArrayView &Second)
Definition NetBitArray.h:1602
void ClearPaddingBits()
Definition NetBitArray.h:1480
bool operator==(const FNetBitArrayView &Other) const
Definition NetBitArray.h:1450
uint32 FindFirstZero() const
Definition NetBitArray.h:1552
void SetBits(uint32 StartIndex, uint32 Count)
Definition NetBitArray.h:1522
uint32 FindLastOne() const
Definition NetBitArray.h:1577
void SetAllBits()
Definition NetBitArray.h:1488
StorageWordType * GetDataChecked(uint32 MaxWordIterationCount) UE_LIFETIMEBOUND
Definition NetBitArray.h:440
const StorageWordType * GetData() const UE_LIFETIMEBOUND
Definition NetBitArray.h:447
void SetBitValue(uint32 Index, bool bValue)
Definition NetBitArray.h:1517
void ForAllSetBitsInRange(const uint32 StartBit, const uint32 EndBit, T &&Functor) const
Definition NetBitArray.h:1627
bool IsNoBitSet() const
Definition NetBitArray.h:1470
uint32 FindLastZero() const
Definition NetBitArray.h:1572
StorageWordType & GetWord(uint32 WordIndex) UE_LIFETIMEBOUND
Definition NetBitArray.h:460
NETCORE_API FString ToString() const
Definition NetBitArray.cpp:23
bool GetBit(uint32 Index) const
Definition NetBitArray.h:1537
uint32 GetNumWords() const
Definition NetBitArray.h:1582
void OrBitValue(uint32 Index, bool bValue)
Definition NetBitArray.h:1542
void ClearAllBits()
Definition NetBitArray.h:1475
static constexpr uint32 CalculateRequiredWordCount(uint32 BitCount)
Definition NetBitArray.h:1414
void Combine(const FNetBitArrayView &Other, WordOpFunctor &&WordOp)
Definition NetBitArray.h:1609
Definition NetBitArray.h:74
const StorageWordType * GetData() const UE_LIFETIMEBOUND
Definition NetBitArray.h:147
void Reset()
Definition NetBitArray.h:168
void AndBitValue(uint32 Index, bool bValue)
Definition NetBitArray.h:1263
FNetBitArray()
Definition NetBitArray.h:1113
Private::FNetBitArrayRangedForConstIterator begin() const
Definition NetBitArray.h:1400
StorageWordType * GetData() UE_LIFETIMEBOUND
Definition NetBitArray.h:150
void AddBits(uint32 BitCount)
Definition NetBitArray.h:1187
void ForAllSetBitsInRange(const uint32 StartBit, const uint32 EndBit, T &&Functor) const
Definition NetBitArray.h:1353
void ForAllUnsetBits(T &&Functor) const
Definition NetBitArray.h:1358
const StorageWordType * GetDataChecked(uint32 MaxWordIterationCount) const UE_LIFETIMEBOUND
Definition NetBitArray.h:130
NETCORE_API FString ToString() const
Definition NetBitArray.cpp:15
void Set(const FNetBitArray &First, WordOpFunctor &&WordOp, const FNetBitArray &Second)
Definition NetBitArray.h:1328
bool GetBit(uint32 Index) const
Definition NetBitArray.h:1253
void SetBitValue(uint32 Index, bool bValue)
Definition NetBitArray.h:1233
void ClearBits(uint32 StartIndex, uint32 Count)
Definition NetBitArray.h:1243
StorageWordType GetWord(uint32 WordIndex) const UE_LIFETIMEBOUND
Definition NetBitArray.h:153
void InitAndCopy(const FNetBitArray &Source)
Definition NetBitArray.h:1158
uint32 FindFirstOne() const
Definition NetBitArray.h:1273
uint32 CountSetBits(uint32 StartIndex=0, uint32 Count=~0U) const
Definition NetBitArray.h:1303
void Copy(const FNetBitArray &Other)
Definition NetBitArray.h:1308
void OrBitValue(uint32 Index, bool bValue)
Definition NetBitArray.h:1258
bool IsNoBitSet() const
Definition NetBitArray.h:1223
void SetBits(uint32 StartIndex, uint32 Count)
Definition NetBitArray.h:1238
void ForAllSetBits(T &&Functor) const
Definition NetBitArray.h:1348
void SetNumBits(uint32 BitCount)
Definition NetBitArray.h:1178
uint32 FindFirstZero() const
Definition NetBitArray.h:1268
void Combine(const FNetBitArray &Other, WordOpFunctor &&WordOp)
Definition NetBitArray.h:1335
bool IsAnyBitSet() const
Definition NetBitArray.h:1213
void SetBit(uint32 Index)
Definition NetBitArray.h:1228
void SetAllBits()
Definition NetBitArray.h:1207
void ClearBit(uint32 Index)
Definition NetBitArray.h:1248
static void ForAllSetBitsMultiple(const FNetBitArray &A, WordOpFunctor1 &&Op1, const FNetBitArray &B, WordOpFunctor2 &&Op2, const FNetBitArray &C, UserFunctor &&Functor)
Definition NetBitArray.h:1369
void ClearAllBits()
Definition NetBitArray.h:1202
void Init(uint32 BitCount)
Definition NetBitArray.h:1140
StorageWordType * GetDataChecked(uint32 MaxWordIterationCount) UE_LIFETIMEBOUND
Definition NetBitArray.h:140
bool operator==(const FNetBitArray &Other) const
Definition NetBitArray.h:1118
void CombineMultiple(WordOpFunctor1 &&Op, const FNetBitArray &ArrayA, WordOpFunctor2 &&Op2, const FNetBitArray &ArrayB)
Definition NetBitArray.h:1341
static void ForAllExclusiveBits(const FNetBitArray &A, const FNetBitArray &B, T &&FunctorA, V &&FunctorB)
Definition NetBitArray.h:1376
uint32 FindLastOne() const
Definition NetBitArray.h:1293
static void ForAllExclusiveBitsByPredicate(const FNetBitArray &A, const FNetBitArray &B, T &&FunctorA, V &&FunctorB, Predicate &&Pred)
Definition NetBitArray.h:1382
bool IsBitSet(uint32 Index) const
Definition NetBitArray.h:177
uint32 GetNumWords() const
Definition NetBitArray.h:1197
StorageWordType & GetWord(uint32 WordIndex) UE_LIFETIMEBOUND
Definition NetBitArray.h:160
uint32 GetSetBitIndices(uint32 StartIndex, uint32 Count, uint32 *OutIndices, uint32 OutIndicesCapacity) const
Definition NetBitArray.h:1298
void Empty()
Definition NetBitArray.h:1172
Private::FNetBitArrayRangedForConstIterator end() const
Definition NetBitArray.h:1405
uint32 GetNumBits() const
Definition NetBitArray.h:1192
uint32 FindLastZero() const
Definition NetBitArray.h:1288
GeometryCollection::Facades::FMuscleActivationData Data
Definition MuscleActivationConstraints.h:15
Definition OverriddenPropertySet.cpp:45
Definition NetworkVersion.cpp:28
Definition NetworkVersion.cpp:28
FNetBitArrayView MakeNetBitArrayView(const FNetBitArrayView::StorageWordType *Storage, uint32 BitCount)
Definition NetBitArray.h:1677
U16 Index
Definition radfft.cpp:71
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition GenericPlatformMemory.h:591
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition GenericPlatformMemory.h:581