UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
StringConv.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3// This file contains the classes used when converting strings between
4// standards (ANSI, UNICODE, etc.)
5
6#pragma once
7
8#include "CoreTypes.h"
11#include "Containers/Array.h"
12#include "Misc/CString.h"
13#include "Templates/IsArray.h"
16#include "Traits/ElementType.h"
19#include <type_traits>
20
21#define DEFAULT_STRING_CONVERSION_SIZE 128u
22
23template <typename From, typename To>
25{
26public:
27 typedef From FromType;
28 typedef To ToType;
29
30 template <
31 typename CharType
33 >
34 inline static void Convert(To* Dest, int32 DestLen, const CharType* Source, int32 SourceLen)
35 {
36 To* Result = FPlatformString::Convert(Dest, DestLen, (const FromType*)Source, SourceLen);
37 check(Result);
38 }
39
40 template <
41 typename CharType
43 >
44 [[nodiscard]] static int32 ConvertedLength(const CharType* Source, int32 SourceLen)
45 {
46 return FPlatformString::ConvertedLength<To>((const FromType*)Source, SourceLen);
47 }
48};
49
50namespace StringConv
51{
53 [[nodiscard]] inline bool IsValidCodepoint(const uint32 Codepoint)
54 {
55 if ((Codepoint > 0x10FFFF) || // No Unicode codepoints above 10FFFFh, (for now!)
56 (Codepoint == 0xFFFE) || (Codepoint == 0xFFFF)) // illegal values.
57 {
58 return false;
59 }
60 return true;
61 }
62
65 {
66 return Codepoint >= HIGH_SURROGATE_START_CODEPOINT && Codepoint <= HIGH_SURROGATE_END_CODEPOINT;
67 }
68
71 {
72 return Codepoint >= LOW_SURROGATE_START_CODEPOINT && Codepoint <= LOW_SURROGATE_END_CODEPOINT;
73 }
74
79
86
89 {
91 }
92
94 template<typename CharType>
96 {
97 static_assert(sizeof(CharType) == 4, "CharType must be 4-bytes!");
98
99 for (int32 Index = 0; Index < StrLen; ++Index)
100 {
101 CharType Codepoint = StrBuffer[Index];
102
103 // Check if this character is a high-surrogate
104 if (StringConv::IsHighSurrogate(Codepoint))
105 {
106 // Ensure our string has enough characters to read from
107 if ((Index + 1) >= StrLen)
108 {
109 // Unpaired surrogate - replace with bogus char
111 break;
112 }
113
114 const uint32 HighCodepoint = Codepoint;
115 Codepoint = StrBuffer[Index + 1];
116
117 // If our High Surrogate is set, check if this character is the matching low-surrogate
118 if (StringConv::IsLowSurrogate(Codepoint))
119 {
120 const uint32 LowCodepoint = Codepoint;
121
122 // Combine our high and low surrogates together to a single Unicode codepoint
123 Codepoint = StringConv::EncodeSurrogate(static_cast<uint16>(HighCodepoint), static_cast<uint16>(LowCodepoint));
124
125 StrBuffer[Index] = Codepoint;
126 {
127 const int32 ArrayNum = StrLen + 1;
128 const int32 IndexToRemove = Index + 1;
129 const int32 NumToMove = ArrayNum - IndexToRemove - 1;
130 if (NumToMove > 0)
131 {
133 }
134 }
135 --StrLen;
136 continue;
137 }
138
139 // Unpaired surrogate - replace with bogus char
141 }
142 else if (StringConv::IsLowSurrogate(Codepoint))
143 {
144 // Unpaired surrogate - replace with bogus char
146 }
147 }
148
149 return StrLen;
150 }
151
153 template<typename AllocatorType>
155 {
156#if PLATFORM_TCHAR_IS_4_BYTES
159#endif // PLATFORM_TCHAR_IS_4_BYTES
160 }
161
162 struct FUnused;
163
164 // Helper functions for getting the conversion type from a converter
165 template <typename ConverterType>
166 typename ConverterType::LegacyFromType GetLegacyFromType(typename ConverterType::LegacyFromType*);
167
168 template <typename ConverterType>
170}
171
172namespace UE::Core::Private
173{
178 {
180 : Counter(0)
181 {
182 }
183
185 {
186 return *this;
187 }
188
190 {
191 ++Counter;
192 return *this;
193 }
195 {
196 ++Counter;
197 return *this;
198 }
200 {
201 Counter += Amount;
202 return *this;
203 }
204
205 template <typename T>
206 T operator=(T Val) const
207 {
208 return Val;
209 }
210
212 {
213 return Lhs.Counter - Rhs.Counter;
214 }
215
217 {
218 return Counter;
219 }
220
221 private:
222 int32 Counter;
223 };
224
225 // This should be replaced with Platform stuff when FPlatformString starts to know about UTF-8.
227 {
228 // Leave this until we convert all the call sites and can change FromType to this.
229 using IntendedToType = UTF8CHAR;
230
231 public:
234
243 template <typename BufferType>
245 {
246 // Ensure we have at least one character in size to write
248 {
249 return 0;
250 }
251
253
254 if (!StringConv::IsValidCodepoint(Codepoint))
255 {
257 }
258 else if (StringConv::IsHighSurrogate(Codepoint) || StringConv::IsLowSurrogate(Codepoint)) // UTF-8 Characters are not allowed to encode codepoints in the surrogate pair range
259 {
261 }
262
263 // Do the encoding...
264 if (Codepoint < 0x80)
265 {
266 *(OutputIterator++) = (ToType)Codepoint;
267 }
268 else if (Codepoint < 0x800)
269 {
271 {
272 *(OutputIterator++) = (ToType)((Codepoint >> 6) | 128 | 64);
273 *(OutputIterator++) = (ToType)((Codepoint & 0x3F) | 128);
274 }
275 }
276 else if (Codepoint < 0x10000)
277 {
279 {
280 *(OutputIterator++) = (ToType) ((Codepoint >> 12) | 128 | 64 | 32);
281 *(OutputIterator++) = (ToType)(((Codepoint >> 6) & 0x3F) | 128);
282 *(OutputIterator++) = (ToType) ((Codepoint & 0x3F) | 128);
283 }
284 }
285 else
286 {
288 {
289 *(OutputIterator++) = (ToType) ((Codepoint >> 18) | 128 | 64 | 32 | 16);
290 *(OutputIterator++) = (ToType)(((Codepoint >> 12) & 0x3F) | 128);
291 *(OutputIterator++) = (ToType)(((Codepoint >> 6 ) & 0x3F) | 128);
292 *(OutputIterator++) = (ToType) ((Codepoint & 0x3F) | 128);
293 }
294 }
295
297 }
298
309 template <
310 typename SrcBufferType
312 >
313 static inline int32 Convert(IntendedToType* Dest, int32 DestLen, const SrcBufferType* Source, int32 SourceLen)
314 {
315 IntendedToType* Result = FPlatformString::Convert(Dest, DestLen, (const FromType*)Source, SourceLen);
316 if (!Result)
317 {
318 return -1;
319 }
320
321 return (int32)(Result - Dest);
322 }
323 template <
324 typename SrcBufferType
326 >
327 static UE_FORCEINLINE_HINT int32 Convert(ToType* Dest, int32 DestLen, const SrcBufferType* Source, int32 SourceLen)
328 {
329 // This helper function is only for backwards compatibility and won't be necessary once IntendedToType becomes the ToType
330 return FTCHARToUTF8_Convert::Convert((IntendedToType*)Dest, DestLen, Source, SourceLen);
331 }
332
338 template <
339 typename SrcBufferType
341 >
343 {
344 return FPlatformString::ConvertedLength<IntendedToType>((const FromType*)Source, SourceLen);
345 }
346 };
347
349 {
350 No = 0,
351 Yes = 1
352 };
353
354 // This tag type is only intended to be used by StrCast to construct existing classes in direct ways.
355 // It is defined is in this Private namespace to indicate that the constructors that use it are not to be used by end-users.
357 {
358 explicit FFromStrCast() = default;
359 };
360}
361
362using FTCHARToUTF8_Convert /*UE_DEPRECATED(5.1, "FTCHARToUTF8_Convert has been deprecated in favor of FPlatformString::Convert and StringCast")*/ = UE::Core::Private::FTCHARToUTF8_Convert;
363
365{
366public:
369 typedef TCHAR ToType;
370
379 template <
380 typename SrcBufferType
382 >
383 static UE_FORCEINLINE_HINT void Convert(ToType* Dest, const int32 DestLen, const SrcBufferType* Source, const int32 SourceLen)
384 {
385 FPlatformString::Convert(Dest, DestLen, (const FromType*)Source, SourceLen);
386 }
387 static UE_FORCEINLINE_HINT void Convert(ToType* Dest, const int32 DestLen, const LegacyFromType* Source, const int32 SourceLen)
388 {
389 FPlatformString::Convert(Dest, DestLen, (const FromType*)Source, SourceLen);
390 }
391
399 template <
400 typename SrcBufferType
402 >
403 [[nodiscard]] static int32 ConvertedLength(const SrcBufferType* Source, const int32 SourceLen)
404 {
405 return FPlatformString::ConvertedLength<ToType>((const FromType*)Source, SourceLen);
406 }
407 [[nodiscard]] static int32 ConvertedLength(const LegacyFromType* Source, const int32 SourceLen)
408 {
409 return FPlatformString::ConvertedLength<ToType>((const FromType*)Source, SourceLen);
410 }
411};
412
413template<typename InFromType, typename InToType>
415{
416 static_assert(sizeof(InFromType) == 4, "FromType must be 4 bytes!");
417 static_assert(sizeof(InToType) == 2, "ToType must be 2 bytes!");
418
419public:
422
431 template <typename BufferType>
433 {
434 // Ensure we have at least one character in size to write
436 {
437 return 0;
438 }
439
441
442 if (!StringConv::IsValidCodepoint(Codepoint))
443 {
445 }
446 else if (StringConv::IsHighSurrogate(Codepoint) || StringConv::IsLowSurrogate(Codepoint)) // Surrogate pairs range should not be present in UTF-32
447 {
449 }
450
451 // We want to write out two chars
452 if (StringConv::IsEncodedSurrogate(Codepoint))
453 {
454 // We need two characters to write the surrogate pair
456 {
460
463 }
464 }
465 else if (Codepoint > ENCODED_SURROGATE_END_CODEPOINT)
466 {
467 // Ignore values higher than the supplementary plane range
469 }
470 else
471 {
472 // Normal codepoint
473 *(OutputIterator++) = (ToType)Codepoint;
474 }
475
477 }
478
487 template <
488 typename SrcBufferType
490 >
491 static UE_FORCEINLINE_HINT void Convert(ToType* Dest, int32 DestLen, const SrcBufferType* Source, int32 SourceLen)
492 {
493 Convert_Impl(Dest, DestLen, (const FromType*)Source, SourceLen);
494 }
495
501 template <
502 typename SrcBufferType
504 >
505 [[nodiscard]] static inline int32 ConvertedLength(const SrcBufferType* Source, int32 SourceLen)
506 {
508 const int32 DestLen = SourceLen * 2;
509 Convert_Impl(Dest, DestLen, (const FromType*)Source, SourceLen);
510
511 return Dest.GetCount();
512 }
513
514private:
515 template <typename DestBufferType>
516 static void Convert_Impl(DestBufferType& Dest, int32 DestLen, const FromType* Source, const int32 SourceLen)
517 {
518 for (int32 i = 0; i < SourceLen; ++i)
519 {
520 uint32 Codepoint = static_cast<uint32>(Source[i]);
521
522 if (!WriteCodepointToBuffer(Codepoint, Dest, DestLen))
523 {
524 // Could not write data, bail out
525 return;
526 }
527 }
528 }
529
530 template <typename DestBufferType>
531 static bool WriteCodepointToBuffer(const uint32 Codepoint, DestBufferType& Dest, int32& DestLen)
532 {
533 int32 WrittenChars = Utf16FromCodepoint(Codepoint, Dest, DestLen);
534 if (WrittenChars < 1)
535 {
536 return false;
537 }
538
539 Dest += WrittenChars;
540 DestLen -= WrittenChars;
541 return true;
542 }
543};
544
545template<typename InFromType, typename InToType>
547{
548 static_assert(sizeof(InFromType) == 2, "FromType must be 2 bytes!");
549 static_assert(sizeof(InToType) == 4, "ToType must be 4 bytes!");
550
551public:
554
563 template <
564 typename SrcBufferType
566 >
567 static UE_FORCEINLINE_HINT void Convert(ToType* Dest, const int32 DestLen, const SrcBufferType* Source, const int32 SourceLen)
568 {
569 Convert_Impl(Dest, DestLen, (const FromType*)Source, SourceLen);
570 }
571
579 template <
580 typename SrcBufferType
582 >
583 [[nodiscard]] static int32 ConvertedLength(const SrcBufferType* Source, const int32 SourceLen)
584 {
586 Convert_Impl(Dest, MAX_int32, (const FromType*)Source, SourceLen);
587
588 return Dest.GetCount();
589 }
590
591private:
592 [[nodiscard]] static uint32 CodepointFromUtf16(const FromType*& SourceString, const uint32 SourceLengthRemaining)
593 {
595
596 const FromType* CodeUnitPtr = SourceString;
597
598 uint32 Codepoint = *CodeUnitPtr;
599
600 // Check if this character is a high-surrogate
601 if (StringConv::IsHighSurrogate(Codepoint))
602 {
603 // Ensure our string has enough characters to read from
604 if (SourceLengthRemaining < 2)
605 {
606 // Skip to end and write out a single char (we always have room for at least 1 char)
607 SourceString += SourceLengthRemaining;
609 }
610
611 const uint16 HighSurrogate = (uint16)Codepoint;
612 Codepoint = *(++CodeUnitPtr);
613
614 // If our High Surrogate is set, check if this character is the matching low-surrogate
615 if (StringConv::IsLowSurrogate(Codepoint))
616 {
617 const uint16 LowSurrogate = (uint16)Codepoint;
618
619 // Combine our high and low surrogates together to a single Unicode codepoint
621
622 SourceString += 2; // skip to next possible start of codepoint.
623 return Codepoint;
624 }
625 else
626 {
627 ++SourceString; // Did not find matching low-surrogate, write out a bogus character and continue
629 }
630 }
631 else if (StringConv::IsLowSurrogate(Codepoint))
632 {
633 // Unpaired low surrogate
634 ++SourceString;
636 }
637 else
638 {
639 // Single codepoint
640 ++SourceString;
641 return Codepoint;
642 }
643 }
644
648 template <typename DestBufferType>
649 static void Convert_Impl(DestBufferType& ConvertedBuffer, int32 DestLen, const FromType* Source, const int32 SourceLen)
650 {
651 const FromType* SourceEnd = Source + SourceLen;
653 {
654 // Read our codepoint, advancing the source pointer
655 uint32 Codepoint = CodepointFromUtf16(Source, SourceEnd - Source);
656
657 *(ConvertedBuffer++) = Codepoint;
658 --DestLen;
659 }
660 }
661};
662
669template<typename Converter, int32 DefaultConversionSize = DEFAULT_STRING_CONVERSION_SIZE>
670class TStringConversion : private Converter, private TInlineAllocator<DefaultConversionSize>::template ForElementType<typename Converter::ToType>
671{
673
674 typedef typename Converter::FromType FromType;
675 typedef typename Converter::ToType ToType;
676
677 using LegacyFromType = decltype(StringConv::GetLegacyFromType<Converter>(nullptr));
678
682 void Init(const FromType* Source, int32 SourceLen, UE::Core::Private::ENullTerminatedString NullTerminated)
683 {
685
686 StringLength = Converter::ConvertedLength(Source, SourceLen);
687
688 int32 BufferSize = StringLength + NullOffset;
689
690 AllocatorType::ResizeAllocation(0, BufferSize, sizeof(ToType));
691
692 Ptr = (ToType*)AllocatorType::GetAllocation();
693 Converter::Convert(Ptr, BufferSize, Source, SourceLen + NullOffset);
694 }
695
696public:
697 // Non-copyable, non-movable
702
703 template <
704 typename SrcBufferType
706 >
707 [[nodiscard]] explicit TStringConversion(const SrcBufferType* Source)
708 {
709 if (Source)
710 {
711 Init((const FromType*)Source, TCString<FromType>::Strlen((const FromType*)Source), UE::Core::Private::ENullTerminatedString::Yes);
712 }
713 else
714 {
715 Ptr = nullptr;
716 StringLength = 0;
717 }
718 }
719 [[nodiscard]] explicit TStringConversion(const LegacyFromType* Source)
720 : TStringConversion((const FromType*)Source)
721 {
722 }
723
724 template <
725 typename SrcBufferType
727 >
728 [[nodiscard]] TStringConversion(const SrcBufferType* Source, int32 SourceLen)
729 {
730 if (Source)
731 {
733 if (SourceLen > 0 && ((const FromType*)Source)[SourceLen-1] == 0)
734 {
735 // Given buffer is null-terminated
737 SourceLen -= 1;
738 }
739
740 Init((const FromType*)Source, SourceLen, NullTerminated);
741 }
742 else
743 {
744 Ptr = nullptr;
745 StringLength = 0;
746 }
747 }
748 [[nodiscard]] TStringConversion(const LegacyFromType* Source, int32 SourceLen)
749 : TStringConversion((const FromType*)Source, SourceLen)
750 {
751 }
752
753 [[nodiscard]] explicit TStringConversion(UE::Core::Private::FFromStrCast, const FromType* Source, int32 SourceLen)
754 {
756 }
757
761 template <
762 typename FromRangeType,
763 typename FromRangeCharType = std::remove_cv_t<std::remove_pointer_t<decltype(GetData(std::declval<FromRangeType>()))>>
766 !TIsArray<std::remove_reference_t<FromRangeType>>::Value &&
768 )
769 >
771 : TStringConversion((const FromType*)GetData(Source), GetNum(Source))
772 {
773 }
774
782 {
783 return Ptr;
784 }
785
792 {
793 return StringLength;
794 }
795
796private:
797 ToType* Ptr;
798 int32 StringLength;
799};
800
801template <typename Converter, int32 DefaultConversionSize>
802[[nodiscard]] inline auto GetData(const TStringConversion<Converter, DefaultConversionSize>& Conversion) -> decltype(Conversion.Get())
803{
804 return Conversion.Get();
805}
806
807template <typename Converter, int32 DefaultConversionSize>
808[[nodiscard]] inline auto GetNum(const TStringConversion<Converter, DefaultConversionSize>& Conversion) -> decltype(Conversion.Length())
809{
810 return Conversion.Length();
811}
812
813template <typename Converter, int32 DefaultConversionSize>
815{
816 static constexpr bool Value = true;
817};
818
819template <typename Converter, int32 DefaultConversionSize>
821{
822 using Type = typename Converter::ToType;
823};
824
825
830template<typename InFromType, typename InToType = InFromType>
832{
833 static_assert(sizeof(InFromType) == sizeof(InToType), "FromType must be the same size as ToType!");
834
835public:
838
839public:
840 template <
841 typename SrcBufferType
843 >
844 [[nodiscard]] explicit TStringPointer(const SrcBufferType* Source)
845 {
846 if (Source)
847 {
848 Ptr = (const ToType*)Source;
849 StringLength = -1; // Length calculated on-demand
850 }
851 else
852 {
853 Ptr = nullptr;
854 StringLength = 0;
855 }
856 }
857
858 template <
859 typename SrcBufferType
861 >
862 [[nodiscard]] explicit TStringPointer(const SrcBufferType* Source, int32 SourceLen)
863 {
864 if (Source)
865 {
866 if (SourceLen > 0 && ((const FromType*)Source)[SourceLen-1] == 0)
867 {
868 // Given buffer is null-terminated
869 SourceLen -= 1;
870 }
871
872 Ptr = (const ToType*)Source;
873 StringLength = SourceLen;
874 }
875 else
876 {
877 Ptr = nullptr;
878 StringLength = 0;
879 }
880 }
881
882 // This constructor is only intended to be used by StrCast, not end users
884 : Ptr((const ToType*)Source)
885 , StringLength(SourceLen)
886 {
887 }
888
892 template <
893 typename FromRangeType,
894 typename FromRangeCharType = std::remove_cv_t<std::remove_pointer_t<decltype(GetData(std::declval<FromRangeType>()))>>
897 !TIsArray<std::remove_reference_t<FromRangeType>>::Value &&
899 )
900 >
902 : TStringPointer((const FromType*)GetData(Source), GetNum(Source))
903 {
904 }
905
910
919 {
920 return Ptr;
921 }
922
929 {
930 return StringLength == -1 ? TCString<ToType>::Strlen(Ptr) : StringLength;
931 }
932
933private:
934 // Non-copyable
935 TStringPointer(const TStringPointer&) = delete;
936 TStringPointer& operator=(const TStringPointer&) = delete;
937
938 const ToType* Ptr;
939 int32 StringLength;
940};
941
942template <typename FromType, typename ToType>
943[[nodiscard]] inline auto GetData(const TStringPointer<FromType, ToType>& Pointer) -> decltype(Pointer.Get())
944{
945 return Pointer.Get();
946}
947
948template <typename FromType, typename ToType>
949[[nodiscard]] inline auto GetNum(const TStringPointer<FromType, ToType>& Pointer) -> decltype(Pointer.Length())
950{
951 return Pointer.Length();
952}
953
954template <typename FromType, typename ToType>
955struct TIsContiguousContainer<TStringPointer<FromType, ToType>>
956{
957 static constexpr bool Value = true;
958};
959
960template <typename FromType, typename ToType>
961struct TElementType<TStringPointer<FromType, ToType>>
962{
963 using Type = ToType;
964};
965
966
984/*********************************************************************
985 * NOTE:
986 * The following converting types and macros should be considered
987 * deprecated and StringCast should be used instead.
988 *
989 * The reasons for deprecation include:
990 *
991 * - char is the wrong type for representing a UTF-8 encoding. UTF8CHAR should be used now, which will become char8_t from C++20 onwards.
992 * - The macros hide a reinterpret_cast of the argument, which is both misleading and dangerous.
993 * - The const return value is silently cast away, which is also misleading and dangerous.
994 * - The macros are frequently used to initialize a local variable, which ends up pointing at deleted memory.
995 * - The names are hardcoded with the types they cast from and to, making them unusable in generic contexts.
996 *
997 * Examples of migration:
998 * ANSICHAR* AnsiCharPtr = ...;
999 * UTF8CHAR* Utf8CharPtr = ...;
1000 * TCHAR* TCharPtr = ...;
1001 *
1002 * Before:
1003 * FUTF8ToTCHAR Conv1(AnsiCharPtr); // Use Conv1.Get() and Conv1.Length()
1004 * FUTF8ToTCHAR Conv2(Utf8CharPtr); // Use Conv2.Get() and Conv2.Length()
1005 * FunctionTakingTCHARPtr(ANSI_TO_TCHAR(AnsiCharPtr));
1006 * Printf(TEXT("Narrow string: %s"), ANSI_TO_TCHAR(AnsiCharPtr));
1007 * Printf(TEXT("UTF-8 string: %s"), UTF8_TO_TCHAR(Utf8CharPtr));
1008 *
1009 * After:
1010 * auto Conv1 = StringCast<TCHAR>((const UTF8CHAR*)AnsiCharPtr); // Use Conv1.Get() and Conv1.Length()
1011 * auto Conv2 = StringCast<TCHAR>(UTF8CharPtr); // Use Conv2.Get() and Conv2.Length()
1012 * FunctionTakingTCHARPtr(StringCast<TCHAR>(AnsiCharPtr).Get());
1013 * Printf(TEXT("Narrow string: %hs"), AnsiCharPtr);
1014 * Printf(TEXT("Narrow string: %hs"), Utf8CharPtr);
1015 *********************************************************************/
1016using FTCHARToUTF8 /*UE_DEPRECATED(5.xx, "FTCHARToUTF8(PtrToTChar) is deprecated, please use StringCast<UTF8CHAR>(PtrToTChar) instead.")*/ = TStringConversion<UE::Core::Private::FTCHARToUTF8_Convert>;
1017using FUTF8ToTCHAR /*UE_DEPRECATED(5.xx, "FUTF8ToTCHAR(PtrToUTF8) is deprecated, please use StringCast<TCHAR>(PtrToUTF8Char) instead.")*/ = TStringConversion<FUTF8ToTCHAR_Convert>;
1018
1019#define TCHAR_TO_ANSI(str) /*UE_DEPRECATED_MACRO(5.xx, "TCHAR_TO_ANSI(Ptr) is deprecated, please use StringCast<ANSICHAR>(PtrToTChar) instead.")*/ (ANSICHAR*)StringCast<ANSICHAR>(static_cast<const TCHAR*>(str)).Get()
1020#define ANSI_TO_TCHAR(str) /*UE_DEPRECATED_MACRO(5.xx, "ANSI_TO_TCHAR(Ptr) is deprecated, please use StringCast<TCHAR>(PtrToAnsiChar) instead.")*/ (TCHAR*)StringCast<TCHAR>(static_cast<const ANSICHAR*>(str)).Get()
1021#define TCHAR_TO_UTF8(str) /*UE_DEPRECATED_MACRO(5.xx, "TCHAR_TO_UTF8(Ptr) is deprecated, please use StringCast<UTF8CHAR>(PtrToTChar) instead.")*/ (ANSICHAR*)FTCHARToUTF8((const TCHAR*)str).Get()
1022#define UTF8_TO_TCHAR(str) /*UE_DEPRECATED_MACRO(5.xx, "UTF8_TO_TCHAR(Ptr) is deprecated, please use StringCast<TCHAR>(PtrToUTF8Char) instead.")*/ (TCHAR*)FUTF8ToTCHAR((const ANSICHAR*)str).Get()
1023
1024
1026// NOTE: //
1027// The following converting types and macros cannot be deprecated //
1028// until FPlatformString has proper handling of UTF16CHAR and //
1029// UTF32CHAR. //
1031
1032// special handling for platforms still using a 32-bit TCHAR
1033#if PLATFORM_TCHAR_IS_4_BYTES
1034
1037#define TCHAR_TO_UTF16(str) (UTF16CHAR*)FTCHARToUTF16((const TCHAR*)str).Get()
1038#define UTF16_TO_TCHAR(str) (TCHAR*)FUTF16ToTCHAR((const UTF16CHAR*)str).Get()
1039
1040static_assert(sizeof(TCHAR) == sizeof(UTF32CHAR), "TCHAR and UTF32CHAR are expected to be the same size for inline conversion! PLATFORM_TCHAR_IS_4_BYTES is not configured correctly for this platform.");
1043#define TCHAR_TO_UTF32(str) (UTF32CHAR*)(str)
1044#define UTF32_TO_TCHAR(str) (TCHAR*)(str)
1045
1046#elif PLATFORM_TCHAR_IS_UTF8CHAR
1047
1050#define TCHAR_TO_UTF16(str) (UTF16CHAR*)FTCHARToUTF16((const TCHAR*)str).Get()
1051#define UTF16_TO_TCHAR(str) (TCHAR*)FUTF16ToTCHAR((const UTF16CHAR*)str).Get()
1052
1055#define TCHAR_TO_UTF32(str) (UTF32CHAR*)FTCHARToUTF32((const TCHAR*)str).Get()
1056#define UTF32_TO_TCHAR(str) (TCHAR*)FUTF32ToTCHAR((const UTF32CHAR*)str).Get()
1057
1058#else
1059
1060static_assert(sizeof(TCHAR) == sizeof(UTF16CHAR), "TCHAR and UTF16CHAR are expected to be the same size for inline conversion! PLATFORM_TCHAR_IS_4_BYTES is not configured correctly for this platform.");
1063#define TCHAR_TO_UTF16(str) (UTF16CHAR*)(str)
1064#define UTF16_TO_TCHAR(str) (TCHAR*)(str)
1065
1068#define TCHAR_TO_UTF32(str) (UTF32CHAR*)FTCHARToUTF32((const TCHAR*)str).Get()
1069#define UTF32_TO_TCHAR(str) (TCHAR*)FUTF32ToTCHAR((const UTF32CHAR*)str).Get()
1070
1071#endif
1072
1073// special handling for going from char16_t to wchar_t for third party libraries that need wchar_t
1074#if PLATFORM_TCHAR_IS_CHAR16 && PLATFORM_WCHAR_IS_4_BYTES
1077#define TCHAR_TO_WCHAR(str) (wchar_t*)FTCHARToWChar((const TCHAR*)str).Get()
1078#define WCHAR_TO_TCHAR(str) (TCHAR*)FWCharToTCHAR((const wchar_t*)str).Get()
1079
1080#elif PLATFORM_TCHAR_IS_UTF8CHAR
1081
1084#define TCHAR_TO_WCHAR(str) (wchar_t*)FTCHARToUTF32((const TCHAR*)str).Get()
1085#define WCHAR_TO_TCHAR(str) (TCHAR*)FWCharToTCHAR((const wchar_t*)str).Get()
1086
1087#else
1088
1089static_assert(sizeof(TCHAR) == sizeof(wchar_t), "TCHAR and wchar_t are expected to be the same size for inline conversion! PLATFORM_WCHAR_IS_4_BYTES is not configured correctly for this platform.");
1092#define TCHAR_TO_WCHAR(str) (wchar_t*)(str)
1093#define WCHAR_TO_TCHAR(str) (TCHAR*)(str)
1094
1095#endif
1096
1135template <typename To, int32 DefaultConversionSize = DEFAULT_STRING_CONVERSION_SIZE, typename From>
1136[[nodiscard]] inline auto StringCast(const From* Str)
1137{
1139 {
1140 return TStringPointer<To>((const To*)Str);
1141 }
1142 else
1143 {
1145 }
1146}
1147
1169template <typename To, int32 DefaultConversionSize = DEFAULT_STRING_CONVERSION_SIZE, typename From>
1170[[nodiscard]] inline auto StringCast(const From* Str, int32 Len)
1171{
1173 {
1174 return TStringPointer<To>((const To*)Str, Len);
1175 }
1176 else
1177 {
1179 }
1180}
1181
1206template <typename To, int32 DefaultConversionSize = DEFAULT_STRING_CONVERSION_SIZE, typename From>
1207[[nodiscard]] inline auto StrCast(const From* Str, int32 Len)
1208{
1210 {
1211 return TStringPointer<To>(UE::Core::Private::FFromStrCast{}, (const To*)Str, Len);
1212 }
1213 else
1214 {
1216 }
1217}
1218
1219
1226template <typename To, typename From>
1227[[nodiscard]] inline To CharCast(From Ch)
1228{
1229 To Result;
1230 FPlatformString::Convert(&Result, 1, &Ch, 1);
1231 return Result;
1232}
1233
1237template <typename ToType, typename FromType, int32 DefaultConversionSize = DEFAULT_STRING_CONVERSION_SIZE>
1238class TStringPassthru : private TInlineAllocator<DefaultConversionSize>::template ForElementType<FromType>
1239{
1241
1242public:
1244 : Dest (InDest)
1245 , DestLen(InDestLen)
1246 , SrcLen (InSrcLen)
1247 {
1248 AllocatorType::ResizeAllocation(0, SrcLen, sizeof(FromType));
1249 }
1250
1252 {
1253 AllocatorType::MoveToEmpty(Other);
1254 }
1255
1256 inline void Apply() const
1257 {
1258 const FromType* Source = (const FromType*)AllocatorType::GetAllocation();
1259 check(FPlatformString::ConvertedLength<ToType>(Source, SrcLen) <= DestLen);
1260 FPlatformString::Convert(Dest, DestLen, Source, SrcLen);
1261 }
1262
1264 {
1265 return (FromType*)AllocatorType::GetAllocation();
1266 }
1267
1268private:
1269 // Non-copyable
1271 TStringPassthru& operator=(const TStringPassthru&);
1272
1273 ToType* Dest;
1274 int32 DestLen;
1275 int32 SrcLen;
1276};
1277
1278// This seemingly-pointless class is intended to be API-compatible with TStringPassthru
1279// and is returned by StringPassthru when no string conversion is necessary.
1280template <typename T>
1282{
1283public:
1285 : Ptr(InPtr)
1286 {
1287 }
1288
1289 // @note Setting to UE_LIFETIMEBOUND even though TPassthruPointer doesn't own the pointer, because we want StringMemoryPassthru to give consistent warnings no matter what implementation choice it makes
1291 {
1292 return Ptr;
1293 }
1294
1296 {
1297 }
1298
1299private:
1300 T* Ptr;
1301};
1302
1335template <typename From, typename To, int32 DefaultConversionSize = DEFAULT_STRING_CONVERSION_SIZE>
1336[[nodiscard]] inline auto StringMemoryPassthru(To* Buffer, int32 BufferSize, int32 SourceLength)
1337{
1339 {
1340 check(SourceLength <= BufferSize);
1341 return TPassthruPointer<From>((From*)Buffer);
1342 }
1343 else
1344 {
1345 return TStringPassthru<To, From, DefaultConversionSize>(Buffer, BufferSize, SourceLength);
1346 }
1347}
1348
1349template <typename ToType, typename FromType>
1350[[nodiscard]] inline TArray<ToType> StringToArray(const FromType* Src, int32 SrcLen)
1351{
1352 int32 DestLen = FPlatformString::ConvertedLength<ToType>(Src, SrcLen);
1353
1354 TArray<ToType> Result;
1355 Result.AddUninitialized(DestLen);
1356 FPlatformString::Convert(Result.GetData(), DestLen, Src, SrcLen);
1357
1358 return Result;
1359}
1360
1361template <typename ToType, typename FromType>
1366
1367#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_4
1368#include "Templates/AndOrNot.h"
1369#include "Templates/EnableIf.h"
1371#endif
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define UE_PTRDIFF_TO_INT32(argument)
Definition CoreMiscDefines.h:442
#define UE_LIFETIMEBOUND
Definition Platform.h:812
FPlatformTypes::UTF32CHAR UTF32CHAR
A 32-bit character containing a UTF32 (Unicode, 32-bit, fixed-width) code unit.
Definition Platform.h:1143
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::UTF8CHAR UTF8CHAR
An 8-bit character containing a UTF8 (Unicode, 8-bit, variable-width) code unit.
Definition Platform.h:1137
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
FPlatformTypes::CHAR16 UTF16CHAR
A 16-bit character containing a UTF16 (Unicode, 16-bit, variable-width) code unit.
Definition Platform.h:1141
FPlatformTypes::ANSICHAR ANSICHAR
An ANSI character. Normally a signed type.
Definition Platform.h:1131
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define HIGH_SURROGATE_END_CODEPOINT
Definition GenericPlatformString.h:48
#define LOW_SURROGATE_END_CODEPOINT
Definition GenericPlatformString.h:50
#define HIGH_SURROGATE_START_CODEPOINT
Definition GenericPlatformString.h:47
#define LOW_SURROGATE_START_CODEPOINT
Definition GenericPlatformString.h:49
#define ENCODED_SURROGATE_START_CODEPOINT
Definition GenericPlatformString.h:51
#define UNICODE_BOGUS_CHAR_CODEPOINT
Definition GenericPlatformString.h:54
#define ENCODED_SURROGATE_END_CODEPOINT
Definition GenericPlatformString.h:52
void Init()
Definition LockFreeList.h:4
#define MAX_int32
Definition NumericLimits.h:25
#define UE_REQUIRES(...)
Definition Requires.h:86
auto StringCast(const From *Str)
Definition StringConv.h:1136
TStringConversion< TUTF16ToUTF32_Convert< TCHAR, UTF32CHAR > > FTCHARToUTF32
Definition StringConv.h:1066
TStringPointer< wchar_t, TCHAR > FWCharToTCHAR
Definition StringConv.h:1091
auto GetNum(const TStringConversion< Converter, DefaultConversionSize > &Conversion) -> decltype(Conversion.Length())
Definition StringConv.h:808
auto GetData(const TStringConversion< Converter, DefaultConversionSize > &Conversion) -> decltype(Conversion.Get())
Definition StringConv.h:802
TStringConversion< TUTF32ToUTF16_Convert< UTF32CHAR, TCHAR > > FUTF32ToTCHAR
Definition StringConv.h:1067
TStringPointer< UTF16CHAR, TCHAR > FUTF16ToTCHAR
Definition StringConv.h:1062
TStringPointer< TCHAR, wchar_t > FTCHARToWChar
Definition StringConv.h:1090
TArray< ToType > StringToArray(const FromType *Src, int32 SrcLen)
Definition StringConv.h:1350
auto StringMemoryPassthru(To *Buffer, int32 BufferSize, int32 SourceLength)
Definition StringConv.h:1336
TStringPointer< TCHAR, UTF16CHAR > FTCHARToUTF16
Definition StringConv.h:1061
auto StrCast(const From *Str, int32 Len)
Definition StringConv.h:1207
To CharCast(From Ch)
Definition StringConv.h:1227
float Val(const FString &Value)
Definition UnrealMath.cpp:3163
uint16_t uint16
Definition binka_ue_file_header.h:7
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition StringConv.h:365
UTF8CHAR FromType
Definition StringConv.h:368
static UE_FORCEINLINE_HINT void Convert(ToType *Dest, const int32 DestLen, const SrcBufferType *Source, const int32 SourceLen)
Definition StringConv.h:383
ANSICHAR LegacyFromType
Definition StringConv.h:367
TCHAR ToType
Definition StringConv.h:369
static int32 ConvertedLength(const SrcBufferType *Source, const int32 SourceLen)
Definition StringConv.h:403
static UE_FORCEINLINE_HINT void Convert(ToType *Dest, const int32 DestLen, const LegacyFromType *Source, const int32 SourceLen)
Definition StringConv.h:387
static int32 ConvertedLength(const LegacyFromType *Source, const int32 SourceLen)
Definition StringConv.h:407
Definition Array.h:670
Definition StringConv.h:1282
UE_FORCEINLINE_HINT T * Get() const UE_LIFETIMEBOUND
Definition StringConv.h:1290
UE_FORCEINLINE_HINT void Apply() const
Definition StringConv.h:1295
UE_FORCEINLINE_HINT TPassthruPointer(T *InPtr)
Definition StringConv.h:1284
Definition ContainerAllocationPolicies.h:894
Definition StringConv.h:671
TStringConversion & operator=(TStringConversion &&)=delete
UE_FORCEINLINE_HINT const ToType * Get() const UE_LIFETIMEBOUND
Definition StringConv.h:781
TStringConversion(FromRangeType &&Source)
Definition StringConv.h:770
UE_FORCEINLINE_HINT int32 Length() const
Definition StringConv.h:791
TStringConversion(const TStringConversion &)=delete
TStringConversion(TStringConversion &&)=delete
TStringConversion(const LegacyFromType *Source, int32 SourceLen)
Definition StringConv.h:748
TStringConversion(const SrcBufferType *Source, int32 SourceLen)
Definition StringConv.h:728
TStringConversion(const LegacyFromType *Source)
Definition StringConv.h:719
TStringConversion(const SrcBufferType *Source)
Definition StringConv.h:707
TStringConversion(UE::Core::Private::FFromStrCast, const FromType *Source, int32 SourceLen)
Definition StringConv.h:753
TStringConversion & operator=(const TStringConversion &)=delete
Definition StringConv.h:25
static void Convert(To *Dest, int32 DestLen, const CharType *Source, int32 SourceLen)
Definition StringConv.h:34
To ToType
Definition StringConv.h:28
From FromType
Definition StringConv.h:27
static int32 ConvertedLength(const CharType *Source, int32 SourceLen)
Definition StringConv.h:44
Definition StringConv.h:1239
void Apply() const
Definition StringConv.h:1256
TStringPassthru(ToType *InDest, int32 InDestLen, int32 InSrcLen)
Definition StringConv.h:1243
UE_FORCEINLINE_HINT FromType * Get() UE_LIFETIMEBOUND
Definition StringConv.h:1263
UE_FORCEINLINE_HINT TStringPassthru(TStringPassthru &&Other)
Definition StringConv.h:1251
Definition StringConv.h:832
UE_FORCEINLINE_HINT int32 Length() const
Definition StringConv.h:928
TStringPointer(const SrcBufferType *Source)
Definition StringConv.h:844
TStringPointer(TStringPointer &&Other)=default
TStringPointer(UE::Core::Private::FFromStrCast, const FromType *Source, int32 SourceLen)
Definition StringConv.h:883
TStringPointer(const SrcBufferType *Source, int32 SourceLen)
Definition StringConv.h:862
TStringPointer(FromRangeType &&Source)
Definition StringConv.h:901
UE_FORCEINLINE_HINT const ToType * Get() const UE_LIFETIMEBOUND
Definition StringConv.h:918
InToType ToType
Definition StringConv.h:837
InFromType FromType
Definition StringConv.h:836
Definition StringConv.h:547
InFromType FromType
Definition StringConv.h:552
InToType ToType
Definition StringConv.h:553
static int32 ConvertedLength(const SrcBufferType *Source, const int32 SourceLen)
Definition StringConv.h:583
static UE_FORCEINLINE_HINT void Convert(ToType *Dest, const int32 DestLen, const SrcBufferType *Source, const int32 SourceLen)
Definition StringConv.h:567
Definition StringConv.h:415
static int32 ConvertedLength(const SrcBufferType *Source, int32 SourceLen)
Definition StringConv.h:505
static int32 Utf16FromCodepoint(uint32 Codepoint, BufferType OutputIterator, uint32 OutputIteratorNumRemaining)
Definition StringConv.h:432
static UE_FORCEINLINE_HINT void Convert(ToType *Dest, int32 DestLen, const SrcBufferType *Source, int32 SourceLen)
Definition StringConv.h:491
InToType ToType
Definition StringConv.h:421
InFromType FromType
Definition StringConv.h:420
Definition StringConv.h:227
static UE_FORCEINLINE_HINT int32 ConvertedLength(const SrcBufferType *Source, int32 SourceLen)
Definition StringConv.h:342
static UE_FORCEINLINE_HINT int32 Convert(ToType *Dest, int32 DestLen, const SrcBufferType *Source, int32 SourceLen)
Definition StringConv.h:327
TCHAR FromType
Definition StringConv.h:232
ANSICHAR ToType
Definition StringConv.h:233
static int32 Utf8FromCodepoint(uint32 Codepoint, BufferType OutputIterator, uint32 OutputIteratorByteSizeRemaining)
Definition StringConv.h:244
static int32 Convert(IntendedToType *Dest, int32 DestLen, const SrcBufferType *Source, int32 SourceLen)
Definition StringConv.h:313
Definition StringConv.h:51
UE_FORCEINLINE_HINT bool IsHighSurrogate(const uint32 Codepoint)
Definition StringConv.h:64
UE_FORCEINLINE_HINT bool IsEncodedSurrogate(const uint32 Codepoint)
Definition StringConv.h:88
bool IsValidCodepoint(const uint32 Codepoint)
Definition StringConv.h:53
int32 InlineCombineSurrogates_Buffer(CharType *StrBuffer, int32 StrLen)
Definition StringConv.h:95
ConverterType::LegacyFromType GetLegacyFromType(typename ConverterType::LegacyFromType *)
UE_FORCEINLINE_HINT bool IsLowSurrogate(const uint32 Codepoint)
Definition StringConv.h:70
UE_FORCEINLINE_HINT uint32 EncodeSurrogate(const uint16 HighSurrogate, const uint16 LowSurrogate)
Definition StringConv.h:75
void DecodeSurrogate(const uint32 Codepoint, uint16 &OutHighSurrogate, uint16 &OutLowSurrogate)
Definition StringConv.h:80
void InlineCombineSurrogates_Array(TArray< TCHAR, AllocatorType > &StrBuffer)
Definition StringConv.h:154
implementation
Definition PlayInEditorLoadingScope.h:8
ENullTerminatedString
Definition StringConv.h:349
U16 Index
Definition radfft.cpp:71
static UE_FORCEINLINE_HINT void * Memmove(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:109
Definition CString.h:60
static int32 Strlen(const CharType *String)
Definition CString.h:1047
typename Converter::ToType Type
Definition StringConv.h:822
ToType Type
Definition StringConv.h:963
Definition ElementType.h:30
Definition IsArray.h:10
Definition IsCharEncodingCompatibleWith.h:65
Definition IsContiguousContainer.h:16
static constexpr bool Value
Definition IsContiguousContainer.h:20
FCountingOutputIterator()
Definition StringConv.h:179
const FCountingOutputIterator & operator++()
Definition StringConv.h:189
T operator=(T Val) const
Definition StringConv.h:206
friend int32 operator-(FCountingOutputIterator Lhs, FCountingOutputIterator Rhs)
Definition StringConv.h:211
const FCountingOutputIterator & operator+=(const int32 Amount)
Definition StringConv.h:199
const FCountingOutputIterator & operator*() const
Definition StringConv.h:184
const FCountingOutputIterator & operator++(int)
Definition StringConv.h:194
int32 GetCount() const
Definition StringConv.h:216
Definition StringConv.h:357