Files
2025-05-18 13:04:45 +08:00

125 lines
3.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CborWriter.h"
#include "Serialization/MemoryWriter.h"
#include "Templates/UniquePtr.h"
#include "Trace/Analyzer.h"
namespace UE {
namespace Trace {
////////////////////////////////////////////////////////////////////////////////
template<typename DestType>
static void WriteArray(FCborWriter& CborWriter, const IAnalyzer::TArrayReader<DestType>& Reader)
{
if (const uint32 Num = Reader.Num())
{
CborWriter.WriteContainerStart(ECborCode::Array, Reader.Num());
for (uint32 j = 0; j < Num; ++j)
{
DestType Value = Reader[j];
CborWriter.WriteValue(Value);
}
}
else
{
CborWriter.WriteNull();
}
}
////////////////////////////////////////////////////////////////////////////////
void SerializeToCborImpl(
TArray<uint8>& Out,
const IAnalyzer::FEventData& EventData,
uint32 EventSize)
{
/* All this look up of fields is a bit slow. It'd be better to use the internals
* of the analysis engine instead */
const IAnalyzer::FEventTypeInfo& TypeInfo = EventData.GetTypeInfo();
const uint32 FieldCount = TypeInfo.GetFieldCount();
if (FieldCount == 0)
{
return;
}
uint32 SizeHint = ((EventSize * 11) / 10); // + 10%
SizeHint += FieldCount * 16;
SizeHint += Out.Num();
Out.Reserve(SizeHint);
FMemoryWriter MemoryWriter(Out, false, true);
FCborWriter CborWriter(&MemoryWriter, ECborEndianness::StandardCompliant);
CborWriter.WriteContainerStart(ECborCode::Map, FieldCount);
for (uint32 FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex)
{
const IAnalyzer::FEventFieldInfo& FieldInfo = *(TypeInfo.GetFieldInfo(FieldIndex));
const ANSICHAR* FieldName = FieldInfo.GetName();
CborWriter.WriteValue(FieldName, FCStringAnsi::Strlen(FieldName));
if (FieldInfo.GetType() == IAnalyzer::FEventFieldInfo::EType::AnsiString)
{
FAnsiStringView View;
EventData.GetString(FieldName, View);
CborWriter.WriteValue((const char*)(View.GetData()), View.Len());
continue;
}
if (FieldInfo.GetType() == IAnalyzer::FEventFieldInfo::EType::WideString)
{
FString String;
EventData.GetString(FieldName, String);
CborWriter.WriteValue(String);
continue;
}
if (FieldInfo.IsArray())
{
switch (FieldInfo.GetType())
{
case IAnalyzer::FEventFieldInfo::EType::Integer:
WriteArray(CborWriter, EventData.GetArray<uint64>(FieldName));
break;
case IAnalyzer::FEventFieldInfo::EType::Float:
WriteArray(CborWriter, EventData.GetArray<double>(FieldName));
break;
default:
//not supported
CborWriter.WriteNull();
break;
}
continue;
}
if (FieldInfo.GetType() == IAnalyzer::FEventFieldInfo::EType::Integer)
{
if (FieldInfo.IsSigned())
{
int64 Value = EventData.GetValue<int64>(FieldName);
CborWriter.WriteValue(Value);
}
else
{
uint64 Value = EventData.GetValue<uint64>(FieldName);
CborWriter.WriteValue(Value);
}
continue;
}
if (FieldInfo.GetType() == IAnalyzer::FEventFieldInfo::EType::Float)
{
double Value = EventData.GetValue<double>(FieldName);
CborWriter.WriteValue(Value);
continue;
}
// No suitable value type was added if we get here.
CborWriter.WriteNull();
}
}
} // namespace Trace
} // namespace UE