Files
UnrealEngineUWP/Engine/Source/Developer/TraceAnalysis/Private/Analysis/StreamReader.cpp
Johan Berg 190178593b Consider if a buffer is in demand (someone asked for more data than it can provide) as a condition of processing more trace data.
While there may be data remaining in the buffer, there might not be enough to decode another transport packet. Thus it is not correct to only consider the remaining number of bytes in the buffer as a condition of continuing to process data. Fortunately there is a demain hint that is set when someone asks for more data than a stream reader can provide. This can be used to differentiate between data remaining in the buffer, and not being able to do anything more with it.

#rb martin.ridgers, johan.berg
#rm 5.0
#ushell-cherrypick of 18267675 by Martin.Ridgers
#jira UE-134430, UE-135475
#preflight 619cf19cf70a9e92db3b69f7

[CL 18269671 by Johan Berg in ue5-main branch]
2021-11-23 09:34:58 -05:00

132 lines
2.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "StreamReader.h"
#include "HAL/UnrealMemory.h"
#include "Math/UnrealMath.h"
namespace UE {
namespace Trace {
////////////////////////////////////////////////////////////////////////////////
FStreamReader::~FStreamReader()
{
FMemory::Free(Buffer);
}
////////////////////////////////////////////////////////////////////////////////
const uint8* FStreamReader::GetPointer(uint32 Size)
{
if (Cursor + Size > End)
{
DemandHint = FMath::Max(DemandHint, Size);
return nullptr;
}
return Buffer + Cursor;
}
////////////////////////////////////////////////////////////////////////////////
void FStreamReader::Advance(uint32 Size)
{
Cursor += Size;
}
////////////////////////////////////////////////////////////////////////////////
int32 FStreamReader::GetRemaining() const
{
return int32(PTRINT(End - Cursor));
}
////////////////////////////////////////////////////////////////////////////////
bool FStreamReader::CanMeetDemand() const
{
return (GetRemaining() >= int32(DemandHint));
}
////////////////////////////////////////////////////////////////////////////////
bool FStreamReader::IsEmpty() const
{
return Cursor >= End;
}
////////////////////////////////////////////////////////////////////////////////
bool FStreamReader::Backtrack(const uint8* To)
{
uint32 BacktrackedCursor = uint32(UPTRINT(To - Buffer));
if (BacktrackedCursor > End)
{
return false;
}
Cursor = BacktrackedCursor;
return true;
}
////////////////////////////////////////////////////////////////////////////////
struct FMark* FStreamReader::SaveMark() const
{
return (FMark*)(UPTRINT(Cursor));
}
////////////////////////////////////////////////////////////////////////////////
void FStreamReader::RestoreMark(struct FMark* Mark)
{
Cursor = uint32(UPTRINT(Mark));
if (Cursor > End)
{
Cursor = End;
}
}
////////////////////////////////////////////////////////////////////////////////
void FStreamBuffer::Append(const uint8* Data, uint32 Size)
{
uint8* Out = Append(Size);
FMemory::Memcpy(Out, Data, Size);
}
////////////////////////////////////////////////////////////////////////////////
uint8* FStreamBuffer::Append(uint32 Size)
{
DemandHint = FMath::Max(Size, DemandHint);
Consolidate();
uint8* Out = Buffer + End;
End += Size;
check(End <= BufferSize);
return Out;
}
////////////////////////////////////////////////////////////////////////////////
void FStreamBuffer::Consolidate()
{
int32 Remaining = End - Cursor;
DemandHint += Remaining;
if (DemandHint >= BufferSize)
{
const uint32 GrowthSizeMask = (64 << 10) - 1;
BufferSize = (DemandHint + GrowthSizeMask + 1) & ~GrowthSizeMask;
Buffer = (uint8*)FMemory::Realloc(Buffer, BufferSize);
}
if (!Remaining)
{
Cursor = 0;
End = 0;
}
else if (Cursor)
{
memmove(Buffer, Buffer + Cursor, Remaining);
Cursor = 0;
End = Remaining;
check(End <= BufferSize);
}
DemandHint = 0;
}
} // namespace Trace
} // namespace UE