UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
FormatArgsTrace.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include <CoreTypes.h>
8#include "Misc/CString.h"
12#include "Traits/IsCharType.h"
13
15{
25
26 // Convenient alias to use when allowing overflow for very large messages
27 template <int InlineSize>
29
30 // Encode arguments in any type of resizable array
31 template <typename BufferType, typename... Types>
32 static int32 EncodeArgumentsWithArray(BufferType& Array, Types... FormatArgs)
33 {
34 constexpr int32 FormatArgsCount = sizeof...(FormatArgs);
35 static_assert(FormatArgsCount < 256, "Maximum number of arguments is 256");
36 const int32 FormatArgsSize = 1 + FormatArgsCount + int32(GetArgumentsEncodedSize(FormatArgs...));
37 Array.SetNumUninitialized(FormatArgsSize);
38 uint8* Buffer = Array.GetData();
42 EncodeArgumentsInternal(TypeCodesBufferPtr, PayloadBufferPtr, FormatArgs...);
44 return FormatArgsSize;
45 }
46
47 // Encode arguments in a fixed size buffer
48 template <int BufferSize, typename... Types>
49 static uint16 EncodeArguments(uint8(&Buffer)[BufferSize], Types... FormatArgs)
50 {
51 static_assert(BufferSize < 65536, "Maximum buffer size of 16 bits exceeded");
52 uint64 FormatArgsCount = sizeof...(FormatArgs);
53 if (FormatArgsCount >= 256)
54 {
55 // Nope
56 return 0;
57 }
58 uint64 FormatArgsSize = 1 + FormatArgsCount + GetArgumentsEncodedSize(FormatArgs...);
59 if (FormatArgsSize > BufferSize)
60 {
61 // Nope
62 return 0;
63 }
67 EncodeArgumentsInternal(TypeCodesBufferPtr, PayloadBufferPtr, FormatArgs...);
69 return (uint16)FormatArgsSize;
70 }
71
72private:
73 template <typename T>
74 struct TIsStringArgument
75 {
77 };
78
80 constexpr static uint64 GetArgumentEncodedSize(T Argument)
81 {
82 if constexpr (TIsStringArgument<T>::Value)
83 {
84 if (Argument != nullptr)
85 {
86 return FMath::Min<int32>((int32)UINT16_MAX, (TCString<CharType>::Strlen(Argument) + 1) * sizeof(CharType));
87 }
88 else
89 {
90 return sizeof(CharType);
91 }
92 }
93 else
94 {
95 return sizeof(T);
96 }
97 }
98
99 constexpr static uint64 GetArgumentsEncodedSize()
100 {
101 return 0;
102 }
103
104 template <typename T, typename... Types>
105 static uint64 GetArgumentsEncodedSize(T Head, Types... Tail)
106 {
107 return GetArgumentEncodedSize(Head) + GetArgumentsEncodedSize(Tail...);
108 }
109
110 template <typename T>
111 static void EncodeArgumentInternal(uint8*& TypeCodesPtr, uint8*& PayloadPtr, T Argument)
112 {
113 if constexpr (TIsStringArgument<T>::Value)
114 {
115 using CharType = std::remove_cv_t<typename TRemovePointer<T>::Type>;
116
117 *TypeCodesPtr++ = FormatArgTypeCode_CategoryString | sizeof(CharType);
118 if (Argument != nullptr)
119 {
120 uint16 SizeBytes = (uint16)FMath::Min<int32>((int32)UINT16_MAX, (TCString<CharType>::Strlen(Argument) + 1) * sizeof(CharType));
121 memcpy(PayloadPtr, Argument, SizeBytes);
122 if (UNLIKELY(SizeBytes == UINT16_MAX))
123 {
124 const CharType Ellipsis[4] = {L'.', L'.', L'.', L'\0'};
125 // Patch ellipsis to the end of the string. Make sure write is aligned
126 void* PatchPoint = PayloadPtr + SizeBytes - sizeof(Ellipsis) - (SizeBytes % sizeof(CharType));
128 }
129 PayloadPtr += SizeBytes;
130 }
131 else
132 {
133 CharType Terminator { 0 };
134 memcpy(PayloadPtr, &Terminator, sizeof(CharType));
135 PayloadPtr += sizeof(CharType);
136 }
137 }
138 else
139 {
140 if constexpr (std::is_floating_point_v<T>)
141 {
143 }
144 else
145 {
147 }
148
149#if PLATFORM_SUPPORTS_UNALIGNED_LOADS
150 *reinterpret_cast<T*>(PayloadPtr) = Argument;
151#else
152 // For ARM targets, it's possible that using __packed here would be preferable
153 // but I have not checked the codegen -- it's possible that the compiler generates
154 // the same code for this fixed size memcpy
155 memcpy(PayloadPtr, &Argument, sizeof Argument);
156#endif
157
158 PayloadPtr += sizeof(T);
159 }
160 }
161
162 constexpr static void EncodeArgumentsInternal(uint8*& TypeCodesPtr, uint8*& PayloadPtr)
163 {
164 }
165
166 template <typename T, typename... Types>
167 static void EncodeArgumentsInternal(uint8*& ArgDescriptorsPtr, uint8*& ArgPayloadPtr, T Head, Types... Tail)
168 {
169 EncodeArgumentInternal(ArgDescriptorsPtr, ArgPayloadPtr, Head);
170 EncodeArgumentsInternal(ArgDescriptorsPtr, ArgPayloadPtr, Tail...);
171 }
172};
#define check(expr)
Definition AssertionMacros.h:314
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UNLIKELY(x)
Definition Platform.h:857
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
memcpy(InputBufferBase, BinkBlocksData, BinkBlocksSize)
uint8_t uint8
Definition binka_ue_file_header.h:8
uint16_t uint16
Definition binka_ue_file_header.h:7
Definition Array.h:670
Definition FormatArgsTrace.h:15
static uint16 EncodeArguments(uint8(&Buffer)[BufferSize], Types... FormatArgs)
Definition FormatArgsTrace.h:49
EFormatArgTypeCode
Definition FormatArgsTrace.h:17
@ FormatArgTypeCode_CategoryBitShift
Definition FormatArgsTrace.h:18
@ FormatArgTypeCode_SizeBitMask
Definition FormatArgsTrace.h:19
@ FormatArgTypeCode_CategoryFloatingPoint
Definition FormatArgsTrace.h:22
@ FormatArgTypeCode_CategoryBitMask
Definition FormatArgsTrace.h:20
@ FormatArgTypeCode_CategoryString
Definition FormatArgsTrace.h:23
@ FormatArgTypeCode_CategoryInteger
Definition FormatArgsTrace.h:21
static int32 EncodeArgumentsWithArray(BufferType &Array, Types... FormatArgs)
Definition FormatArgsTrace.h:32
Definition AndOrNot.h:11
Definition CString.h:60
static int32 Strlen(const CharType *String)
Definition CString.h:1047
Definition IsCharType.h:10