Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
BitReader.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 "CoreTypes.h"
7#include "HAL/UnrealMemory.h"
8#include "Misc/AssertionMacros.h"
9#include "Serialization/BitArchive.h"
10
11class FArchive;
12
13void appBitsCpy( uint8* Dest, int32 DestBit, uint8* Src, int32 SrcBit, int32 BitCount );
14
15/*-----------------------------------------------------------------------------
16 FBitReader.
17-----------------------------------------------------------------------------*/
18
19//@TODO: FLOATPRECISION: Public API assumes it can have > 2 GB of bits, but internally uses int32 based TArray for bytes and also has uint32 clamping on bit counts in various places
20
21//
22// Reads bitstreams.
23//
24struct FBitReader : public FBitArchive
25{
26 friend struct FBitReaderMark;
27
28public:
29 FBitReader( uint8* Src = nullptr, int64 CountBits = 0 );
30
31 FBitReader(const FBitReader&) = default;
32 FBitReader& operator=(const FBitReader&) = default;
33 FBitReader(FBitReader&&) = default;
35
36 void SetData( FBitReader& Src, int64 CountBits );
37 void SetData( uint8* Src, int64 CountBits );
38 void SetData( TArray<uint8>&& Src, int64 CountBits );
39
40 /** Equivalent to SetData (reset position, copy from Src into internal buffer), but uses Reset not Empty to avoid a realloc if possible. */
41 void ResetData(FBitReader& Src, int64 CountBits);
42
43#if defined(_MSC_VER) && PLATFORM_DESKTOP
44#pragma warning( push )
45#pragma warning( disable : 4789 ) // Windows PGO (LTCG) is causing nonsensical errors in certain build environments
46#endif
47 FORCEINLINE_DEBUGGABLE void SerializeBits( void* Dest, int64 LengthBits )
48 {
49 //@TODO: FLOATPRECISION: This function/class pretends it is 64-bit aware, e.g., in the type of LengthBits and the Pos member, but it is not as appBitsCpy is only 32 bits, the inner Buffer is a 32 bit TArray, etc...
50 if ( IsError() || Pos+LengthBits > Num)
51 {
52 if (!IsError())
53 {
54 SetOverflowed(LengthBits);
55 //UE_LOG( LogNetSerialization, Error, TEXT( "FBitReader::SerializeBits: Pos + LengthBits > Num" ) );
56 }
57 FMemory::Memzero( Dest, (LengthBits+7)>>3 );
58 return;
59 }
60 //for( int32 i=0; i<LengthBits; i++,Pos++ )
61 // if( Buffer(Pos>>3) & GShift[Pos&7] )
62 // ((uint8*)Dest)[i>>3] |= GShift[i&7];
63 if( LengthBits == 1 )
64 {
65 ((uint8*)Dest)[0] = 0;
66 if( Buffer[(int32)(Pos>>3)] & Shift(Pos&7) )
67 ((uint8*)Dest)[0] |= 0x01;
68 Pos++;
69 }
70 else if (LengthBits != 0)
71 {
72 ((uint8*)Dest)[((LengthBits+7)>>3) - 1] = 0;
73 appBitsCpy((uint8*)Dest, 0, Buffer.GetData(), (int32)Pos, (int32)LengthBits);
74 Pos += LengthBits;
75 }
76 }
77#if defined(_MSC_VER) && PLATFORM_DESKTOP
78#pragma warning( pop )
79#endif
80
81 virtual void SerializeBitsWithOffset( void* Dest, int32 DestBit, int64 LengthBits ) override;
82
83 // OutValue < ValueMax
84 FORCEINLINE_DEBUGGABLE void SerializeInt(uint32& OutValue, uint32 ValueMax)
85 {
86 if (!IsError())
87 {
88 // Use local variable to avoid Load-Hit-Store
89 uint32 Value = 0;
90 int64 LocalPos = Pos;
91 const int64 LocalNum = Num;
92
93 for (uint32 Mask=1; (Value + Mask) < ValueMax && Mask; Mask *= 2, LocalPos++)
94 {
95 if (LocalPos >= LocalNum)
96 {
97 SetOverflowed(LocalPos - Pos);
98 break;
99 }
100
101 if (Buffer[(int32)(LocalPos >> 3)] & Shift(LocalPos & 7))
102 {
103 Value |= Mask;
104 }
105 }
106
107 // Now write back
108 Pos = LocalPos;
109 OutValue = Value;
110 }
111 }
112
113 virtual void SerializeIntPacked(uint32& Value) override;
114
116 {
117 uint32 Value = 0;
118
119 SerializeInt(Value, Max);
120
121 return Value;
122 }
123
125 {
126 uint8 Bit=0;
127 //SerializeBits( &Bit, 1 );
128 if ( !IsError() )
129 {
130 int64 LocalPos = Pos;
131 const int64 LocalNum = Num;
132 if (LocalPos >= LocalNum)
133 {
135 //UE_LOG( LogNetSerialization, Error, TEXT( "FBitReader::SerializeInt: LocalPos >= LocalNum" ) );
136 }
137 else
138 {
139 Bit = !!(Buffer[(int32)(LocalPos>>3)] & Shift(LocalPos&7));
140 Pos++;
141 }
142 }
143 return Bit;
144 }
145
146 FORCEINLINE_DEBUGGABLE void Serialize( void* Dest, int64 LengthBytes )
147 {
148 SerializeBits( Dest, LengthBytes*8 );
149 }
150
152 {
153 return Buffer.GetData();
154 }
155
156 FORCEINLINE_DEBUGGABLE const uint8* GetData() const
157 {
158 return Buffer.GetData();
159 }
160
162 {
163 return Buffer;
164 }
165
167 {
168 check(Pos % 8 == 0);
169 return &Buffer[(int32)(Pos >> 3)];
170 }
171
173 {
174 return ((Num - Pos) + 7) >> 3;
175 }
177 {
178 return (Num - Pos);
179 }
181 {
182 return IsError() || Pos>=Num;
183 }
185 {
186 return (Num+7)>>3;
187 }
189 {
190 return Num;
191 }
193 {
194 return Pos;
195 }
197 {
198 int64 PrePos = Pos;
199
200 // Skip over remaining bits in current byte
201 Pos = (Pos+7) & (~0x07);
202
203 if ( Pos > Num )
204 {
205 //UE_LOG( LogNetSerialization, Error, TEXT( "FBitReader::EatByteAlign: Pos > Num" ) );
206 SetOverflowed(Pos - PrePos);
207 }
208 }
209
210 /**
211 * Marks this bit reader as overflowed.
212 *
213 * @param LengthBits The number of bits being read at the time of overflow
214 */
215 void SetOverflowed(int64 LengthBits);
216
217 /** Set the stream at the end */
218 void SetAtEnd() { Pos = Num; }
219
221 void AppendDataFromChecked( uint8* Src, uint32 NumBits );
222 void AppendTo( TArray<uint8> &Buffer );
223
224 /** Counts the in-memory bytes used by this object */
225 virtual void CountMemory(FArchive& Ar) const;
226
227protected:
228
230 int64 Num;
231 int64 Pos;
232
233 /** Copies version information used for network compatibility from Source to this archive */
235
236private:
237
238 FORCEINLINE uint8 Shift(uint8 Cnt)
239 {
240 return (uint8)(1<<Cnt);
241 }
242
243};
244
245
246//
247// For pushing and popping FBitWriter positions.
248//
250{
251public:
252
254 : Pos(0)
255 { }
256
258 : Pos(Reader.Pos)
259 { }
260
262 {
263 return Pos;
264 }
265
267 {
268 Reader.Pos = Pos;
269 }
270
271 void Copy( FBitReader& Reader, TArray<uint8> &Buffer );
272
273private:
274
275 int64 Pos;
276};
#define check(expr)
void appBitsCpy(uint8 *Dest, int32 DestBit, uint8 *Src, int32 SrcBit, int32 BitCount)
#define FORCEINLINE_DEBUGGABLE
#define PLATFORM_DESKTOP
Definition Platform.h:6
#define FORCEINLINE
Definition Platform.h:644
FORCEINLINE bool IsError() const
Definition Archive.h:337
FORCEINLINE_DEBUGGABLE int64 GetPosBits() const
Definition BitReader.h:192
FORCEINLINE uint8 Shift(uint8 Cnt)
Definition BitReader.h:238
FORCEINLINE_DEBUGGABLE uint8 * GetDataPosChecked()
Definition BitReader.h:166
virtual void CountMemory(FArchive &Ar) const
void SetData(TArray< uint8 > &&Src, int64 CountBits)
void SetData(uint8 *Src, int64 CountBits)
FORCEINLINE_DEBUGGABLE int64 GetNumBytes() const
Definition BitReader.h:184
FORCEINLINE_DEBUGGABLE uint32 ReadInt(uint32 Max)
Definition BitReader.h:115
void ResetData(FBitReader &Src, int64 CountBits)
int64 Pos
Definition BitReader.h:231
FORCEINLINE_DEBUGGABLE uint8 ReadBit()
Definition BitReader.h:124
void AppendDataFromChecked(uint8 *Src, uint32 NumBits)
FBitReader & operator=(FBitReader &&)=default
FORCEINLINE_DEBUGGABLE void SerializeInt(uint32 &OutValue, uint32 ValueMax)
Definition BitReader.h:84
void SetData(FBitReader &Src, int64 CountBits)
void SetAtEnd()
Definition BitReader.h:218
FORCEINLINE_DEBUGGABLE int64 GetBitsLeft() const
Definition BitReader.h:176
FORCEINLINE_DEBUGGABLE void EatByteAlign()
Definition BitReader.h:196
void SetNetVersionsFromArchive(FArchive &Source)
void AppendTo(TArray< uint8 > &Buffer)
int64 Num
Definition BitReader.h:230
FBitReader(uint8 *Src=nullptr, int64 CountBits=0)
FORCEINLINE_DEBUGGABLE const TArray< uint8 > & GetBuffer() const
Definition BitReader.h:161
virtual void SerializeIntPacked(uint32 &Value) override
FORCEINLINE_DEBUGGABLE int64 GetBytesLeft() const
Definition BitReader.h:172
FORCEINLINE_DEBUGGABLE void SerializeBits(void *Dest, int64 LengthBits)
Definition BitReader.h:47
FORCEINLINE_DEBUGGABLE uint8 * GetData()
Definition BitReader.h:151
FBitReader & operator=(const FBitReader &)=default
FORCEINLINE_DEBUGGABLE void Serialize(void *Dest, int64 LengthBytes)
Definition BitReader.h:146
FBitReader(FBitReader &&)=default
TArray< uint8 > Buffer
Definition BitReader.h:229
void SetOverflowed(int64 LengthBits)
FBitReader(const FBitReader &)=default
FORCEINLINE_DEBUGGABLE bool AtEnd()
Definition BitReader.h:180
virtual void SerializeBitsWithOffset(void *Dest, int32 DestBit, int64 LengthBits) override
FORCEINLINE_DEBUGGABLE const uint8 * GetData() const
Definition BitReader.h:156
FORCEINLINE_DEBUGGABLE int64 GetNumBits() const
Definition BitReader.h:188
void AppendDataFromChecked(FBitReader &Src)
void Copy(FBitReader &Reader, TArray< uint8 > &Buffer)
FORCEINLINE_DEBUGGABLE int64 GetPos() const
Definition BitReader.h:261
FORCEINLINE_DEBUGGABLE void Pop(FBitReader &Reader)
Definition BitReader.h:266
FBitReaderMark(FBitReader &Reader)
Definition BitReader.h:257
static FORCEINLINE void * Memzero(void *Dest, SIZE_T Count)