Compare commits
4 Commits
155044cc52
...
700c901c7b
Author | SHA1 | Date | |
---|---|---|---|
700c901c7b | |||
38806ca2b6 | |||
615fb2429d | |||
e73cf69cb9 |
@ -280,7 +280,7 @@ void TestBitset()
|
||||
|
||||
FBitset BitsetXORA = BitsetA; BitsetXORA &= BitsetB;
|
||||
FBitset BitsetXORB = BitsetB; BitsetXORB &= BitsetA;
|
||||
|
||||
|
||||
uint64 IntANDA = IntA; IntANDA &= IntB;
|
||||
uint32 IntANDB = IntB; IntANDB &= IntA;
|
||||
|
||||
@ -297,7 +297,7 @@ void TestBitset()
|
||||
always_check((BitsetXORA.ToIntegral() == IntXORA));
|
||||
always_check((BitsetXORB.ToIntegral() == IntXORB));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
FBitset BitsetA(64, 0x0139'0239'0339'0439ull);
|
||||
uint64 IntA = 0x0139'0239'0339'0439ull;
|
||||
@ -420,7 +420,7 @@ void TestStaticBitset()
|
||||
|
||||
TStaticBitset<32> BitsetXORA = BitsetA; BitsetXORA &= BitsetB;
|
||||
TStaticBitset<32> BitsetXORB = BitsetB; BitsetXORB &= BitsetA;
|
||||
|
||||
|
||||
uint32 IntANDA = IntA; IntANDA &= IntB;
|
||||
uint32 IntANDB = IntB; IntANDB &= IntA;
|
||||
|
||||
@ -437,7 +437,7 @@ void TestStaticBitset()
|
||||
always_check((BitsetXORA.ToIntegral() == IntXORA));
|
||||
always_check((BitsetXORB.ToIntegral() == IntXORB));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TStaticBitset<32> BitsetA(0x0139'0239ull);
|
||||
uint32 IntA = 0x0139'0239ull;
|
||||
@ -589,7 +589,7 @@ void TestList()
|
||||
|
||||
List.PopBack();
|
||||
always_check((List == TList<int32>({ 1, 2, 3, 4, 5 })));
|
||||
|
||||
|
||||
List.EmplaceFront(1) = 0;
|
||||
always_check((List == TList<int32>({ 0, 1, 2, 3, 4, 5 })));
|
||||
|
||||
|
@ -533,6 +533,15 @@ void TestTemplateString()
|
||||
always_check(Str.FindLastNotOf(LITERAL(T, "Hello! Goodbye!")) == 25);
|
||||
always_check(Str.FindLastNotOf(LITERAL(T, '!')) == 27);
|
||||
}
|
||||
|
||||
{
|
||||
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToString() == TEXT("\u4E38\u8FA3"));
|
||||
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToWString() == WTEXT("\u4E38\u8FA3"));
|
||||
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToU8String() == U8TEXT("\u4E38\u8FA3"));
|
||||
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToU16String() == U16TEXT("\u4E38\u8FA3"));
|
||||
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToU32String() == U32TEXT("\u4E38\u8FA3"));
|
||||
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToUnicodeString() == UNICODETEXT("\u4E38\u8FA3"));
|
||||
}
|
||||
};
|
||||
|
||||
Test(InPlaceType<char>);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Memory/MemoryOperator.h"
|
||||
#include "Memory/ObserverPointer.h"
|
||||
#include "Miscellaneous/AssertionMacros.h"
|
||||
#include "Miscellaneous/ConstantIterator.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
@ -57,16 +58,8 @@ public:
|
||||
|
||||
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
|
||||
TArray(size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
|
||||
{
|
||||
Impl.ArrayNum = Count;
|
||||
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
|
||||
Impl.Pointer = Impl->Allocate(Max());
|
||||
|
||||
for (size_t Index = 0; Index < Num(); ++Index)
|
||||
{
|
||||
new (Impl.Pointer + Index) ElementType(InValue);
|
||||
}
|
||||
}
|
||||
: TArray(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
|
||||
{ }
|
||||
|
||||
/** Constructs the container with the contents of the range ['First', 'Last'). */
|
||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>> && CMovable<ElementType>)
|
||||
@ -412,98 +405,7 @@ public:
|
||||
{
|
||||
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||
|
||||
const size_t InsertIndex = Iter - Begin();
|
||||
|
||||
if (Count == 0) return Iterator(this, Impl.Pointer + InsertIndex);
|
||||
|
||||
const size_t NumToAllocate = Num() + Count > Max() ? Impl->CalculateSlackGrow(Num() + Count, Max()) : Max();
|
||||
|
||||
check(NumToAllocate >= Num() + Count);
|
||||
|
||||
if (NumToAllocate != Max())
|
||||
{
|
||||
ElementType* OldAllocation = Impl.Pointer;
|
||||
const size_t NumToDestruct = Num();
|
||||
|
||||
Impl.ArrayNum = Num() + Count;
|
||||
Impl.ArrayMax = NumToAllocate;
|
||||
Impl.Pointer = Impl->Allocate(Max());
|
||||
|
||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
||||
|
||||
for (size_t Index = InsertIndex; Index != InsertIndex + Count; ++Index)
|
||||
{
|
||||
new (Impl.Pointer + Index) ElementType(InValue);
|
||||
}
|
||||
|
||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + Count, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
||||
|
||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||
Impl->Deallocate(OldAllocation);
|
||||
|
||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
||||
}
|
||||
|
||||
/*
|
||||
* NO(XA) - No Operation
|
||||
* IA(AB) - Insert Assignment
|
||||
* IC(BC) - Insert Construction
|
||||
* MA(CD) - Move Assignment
|
||||
* MC(DO) - Move Construction
|
||||
*
|
||||
* IR(AC) - Insert Range
|
||||
* UI(UO) - Uninitialized
|
||||
*
|
||||
* |X|-------------------| |-UI-|O|
|
||||
* |X|----|A|-IR-| C|-----------|O|
|
||||
* |X|-NO-|A|-IA-|BC|-MA-|D|-MC-|O|
|
||||
*
|
||||
* |X|-----------------| |-UI-|O|
|
||||
* |X|----------|A|-IR-| CD|----|O|
|
||||
* |X|----NO----|A|-IA-|BCD|-MC-|O|
|
||||
*
|
||||
* |X|-----------| |-----UI-----|O|
|
||||
* |X|----|A|----IR-----|C |----|O|
|
||||
* |X|-NO-|A|-IA-|B|-IC-|CD|-MC-|O|
|
||||
*
|
||||
* |X|----------------| |-UI-| O|
|
||||
* |X|----------------|A |-IR-|C O|
|
||||
* |X|-------NO-------|AB|-IC-|CDO|
|
||||
*
|
||||
* |X|-----------| |----UI----| O|
|
||||
* |X|----------------|A |-IR-|C O|
|
||||
* |X|-------NO-------|AB|-IC-|CDO|
|
||||
*/
|
||||
|
||||
const size_t IndexA = InsertIndex;
|
||||
const size_t IndexC = InsertIndex + Count;
|
||||
const size_t IndexB = Num() > IndexA ? (Num() < IndexC ? Num() : IndexC) : IndexA;
|
||||
const size_t IndexD = Num() > IndexC ? Num() : IndexC;
|
||||
const size_t IndexO = Num() + Count;
|
||||
|
||||
for (size_t TargetIndex = IndexO - 1; TargetIndex != IndexD - 1; --TargetIndex)
|
||||
{
|
||||
new (Impl.Pointer + TargetIndex) ElementType(MoveTemp(Impl.Pointer[TargetIndex - Count]));
|
||||
}
|
||||
|
||||
for (size_t TargetIndex = IndexD - 1; TargetIndex != IndexC - 1; --TargetIndex)
|
||||
{
|
||||
Impl.Pointer[TargetIndex] = MoveTemp(Impl.Pointer[TargetIndex - Count]);
|
||||
}
|
||||
|
||||
for (size_t TargetIndex = IndexA; TargetIndex != IndexB; ++TargetIndex)
|
||||
{
|
||||
Impl.Pointer[TargetIndex] = InValue;
|
||||
}
|
||||
|
||||
for (size_t TargetIndex = IndexB; TargetIndex != IndexC; ++TargetIndex)
|
||||
{
|
||||
new (Impl.Pointer + TargetIndex) ElementType(InValue);
|
||||
}
|
||||
|
||||
Impl.ArrayNum = Num() + Count;
|
||||
|
||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
||||
return Insert(Iter, MakeCountedConstantIterator(InValue, Count), DefaultSentinel);
|
||||
}
|
||||
|
||||
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
|
||||
@ -550,14 +452,43 @@ public:
|
||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
||||
}
|
||||
|
||||
/*
|
||||
* NO(XA) - No Operation
|
||||
* IA(AB) - Insert Assignment
|
||||
* IC(BC) - Insert Construction
|
||||
* MA(CD) - Move Assignment
|
||||
* MC(DO) - Move Construction
|
||||
*
|
||||
* IR(AC) - Insert Range
|
||||
* UI(UO) - Uninitialized
|
||||
*
|
||||
* |X|-------------------| |-UI-|O|
|
||||
* |X|----|A|-IR-| C|-----------|O|
|
||||
* |X|-NO-|A|-IA-|BC|-MA-|D|-MC-|O|
|
||||
*
|
||||
* |X|-----------------| |-UI-|O|
|
||||
* |X|----------|A|-IR-| CD|----|O|
|
||||
* |X|----NO----|A|-IA-|BCD|-MC-|O|
|
||||
*
|
||||
* |X|-----------| |-----UI-----|O|
|
||||
* |X|----|A|----IR-----|C |----|O|
|
||||
* |X|-NO-|A|-IA-|B|-IC-|CD|-MC-|O|
|
||||
*
|
||||
* |X|----------------| |-UI-| O|
|
||||
* |X|----------------|A |-IR-|C O|
|
||||
* |X|-------NO-------|AB|-IC-|CDO|
|
||||
*
|
||||
* |X|-----------| |----UI----| O|
|
||||
* |X|----------------|A |-IR-|C O|
|
||||
* |X|-------NO-------|AB|-IC-|CDO|
|
||||
*/
|
||||
|
||||
const size_t IndexA = InsertIndex;
|
||||
const size_t IndexC = InsertIndex + Count;
|
||||
const size_t IndexB = Num() > IndexA ? (Num() < IndexC ? Num() : IndexC) : IndexA;
|
||||
const size_t IndexD = Num() > IndexC ? Num() : IndexC;
|
||||
const size_t IndexO = Num() + Count;
|
||||
|
||||
size_t TargetIndex = Num() + Count - 1;
|
||||
|
||||
for (size_t TargetIndex = IndexO - 1; TargetIndex != IndexD - 1; --TargetIndex)
|
||||
{
|
||||
new (Impl.Pointer + TargetIndex) ElementType(MoveTemp(Impl.Pointer[TargetIndex - Count]));
|
||||
|
@ -424,8 +424,8 @@ public:
|
||||
template <CCommonType<IteratorType> J>
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Length - RHS.Length; }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { CheckThis(); return -LHS.Num(); }
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { CheckThis(); return RHS.Num(); }
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr explicit operator TObserverPtr<ElementType[]>() const requires (CContiguousIterator<IteratorType>) { CheckThis(); return TObserverPtr<ElementType[]>(Current); }
|
||||
|
||||
@ -646,7 +646,7 @@ FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N)
|
||||
template <CInputIterator I, CSentinelFor<I> S>
|
||||
FORCEINLINE constexpr ptrdiff Distance(I First, S Last)
|
||||
{
|
||||
if constexpr (CSizedSentinelFor<I, S>)
|
||||
if constexpr (CSizedSentinelFor<S, I>)
|
||||
{
|
||||
return Last - First;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Memory/MemoryOperator.h"
|
||||
#include "Memory/ObserverPointer.h"
|
||||
#include "Miscellaneous/AssertionMacros.h"
|
||||
#include "Miscellaneous/ConstantIterator.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
@ -75,25 +76,9 @@ public:
|
||||
}
|
||||
|
||||
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
|
||||
TList(size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>) : TList()
|
||||
{
|
||||
FNode* EndNode = Impl.HeadNode->PrevNode;
|
||||
|
||||
while (Count > Impl.ListNum)
|
||||
{
|
||||
FNode* Node = new (Impl->Allocate(1)) FNode(InPlace, InValue);
|
||||
|
||||
EndNode->NextNode = Node;
|
||||
Node->PrevNode = EndNode;
|
||||
|
||||
++Impl.ListNum;
|
||||
|
||||
EndNode = Node;
|
||||
}
|
||||
|
||||
EndNode->NextNode = Impl.HeadNode;
|
||||
Impl.HeadNode->PrevNode = EndNode;
|
||||
}
|
||||
TList(size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>)
|
||||
: TList(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
|
||||
{ }
|
||||
|
||||
/** Constructs the container with the contents of the range ['First', 'Last'). */
|
||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
||||
@ -260,35 +245,7 @@ public:
|
||||
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
|
||||
Iterator Insert(ConstIterator Iter, size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
|
||||
{
|
||||
if (Count == 0) return Iterator(Iter.Pointer);
|
||||
|
||||
FNode* InsertNode = Iter.Pointer->PrevNode;
|
||||
|
||||
const auto InsertOnce = [&]() -> FNode*
|
||||
{
|
||||
FNode* Node = new (Impl->Allocate(1)) FNode(InPlace, InValue);
|
||||
|
||||
InsertNode->NextNode = Node;
|
||||
Node->PrevNode = InsertNode;
|
||||
|
||||
++Impl.ListNum;
|
||||
|
||||
InsertNode = Node;
|
||||
|
||||
return Node;
|
||||
};
|
||||
|
||||
FNode* FirstNode = InsertOnce();
|
||||
|
||||
for (size_t Index = 0; Index != Count - 1; ++Index)
|
||||
{
|
||||
InsertOnce();
|
||||
}
|
||||
|
||||
InsertNode->NextNode = Iter.Pointer;
|
||||
Iter.Pointer->PrevNode = InsertNode;
|
||||
|
||||
return Iterator(FirstNode);
|
||||
return Insert(Iter, MakeCountedConstantIterator(InValue, Count), DefaultSentinel);
|
||||
}
|
||||
|
||||
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
|
||||
@ -334,7 +291,7 @@ public:
|
||||
Iterator Emplace(ConstIterator Iter, Ts&&... Args)
|
||||
{
|
||||
FNode* Node = new (Impl->Allocate(1)) FNode(InPlace, Forward<Ts>(Args)...);
|
||||
|
||||
|
||||
++Impl.ListNum;
|
||||
|
||||
Node->PrevNode = Iter.Pointer->PrevNode;
|
||||
@ -430,7 +387,7 @@ public:
|
||||
Erase(First, End());
|
||||
|
||||
Impl.ListNum = Count;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -176,8 +176,8 @@ public:
|
||||
template <CCommonType<IteratorType> J>
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Length - RHS.Length; }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { CheckThis(); return -LHS.Num(); }
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { CheckThis(); return RHS.Num(); }
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; }
|
||||
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return Current; }
|
||||
@ -204,6 +204,7 @@ private:
|
||||
};
|
||||
|
||||
static_assert(CRandomAccessIterator<TCountedIterator<TConstantIterator<int>>>);
|
||||
static_assert(CSizedSentinelFor<FDefaultSentinel, TCountedIterator<TConstantIterator<int>>>);
|
||||
|
||||
template <typename T> requires (CDestructible<T> || CLValueReference<T>)
|
||||
NODISCARD FORCEINLINE constexpr auto MakeConstantIterator(T&& Value)
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "String/StringView.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "Templates/TypeHash.h"
|
||||
#include "Templates/Optional.h"
|
||||
#include "Templates/Container.h"
|
||||
#include "Containers/Iterator.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
@ -328,44 +329,44 @@ public:
|
||||
NODISCARD friend FORCEINLINE TString operator+(const TString<ElementType>& LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
||||
|
||||
/** @return true if the string view starts with the given prefix, false otherwise. */
|
||||
NODISCARD FORCEINLINE constexpr bool StartsWith(TStringView<ElementType> Prefix) const
|
||||
NODISCARD FORCEINLINE bool StartsWith(TStringView<ElementType> Prefix) const
|
||||
{
|
||||
return TStringView<ElementType>(*this).StartsWith(Prefix);
|
||||
}
|
||||
|
||||
/** @return true if the string view starts with the given prefix, false otherwise. */
|
||||
NODISCARD FORCEINLINE constexpr bool StartsWith(ElementType Prefix) const
|
||||
NODISCARD FORCEINLINE bool StartsWith(ElementType Prefix) const
|
||||
{
|
||||
return TStringView<ElementType>(*this).StartsWith(Prefix);
|
||||
}
|
||||
|
||||
/** @return true if the string view ends with the given suffix, false otherwise. */
|
||||
NODISCARD FORCEINLINE constexpr bool EndsWith(TStringView<ElementType> Suffix) const
|
||||
NODISCARD FORCEINLINE bool EndsWith(TStringView<ElementType> Suffix) const
|
||||
{
|
||||
return TStringView<ElementType>(*this).EndsWith(Suffix);
|
||||
}
|
||||
|
||||
/** @return true if the string view ends with the given suffix, false otherwise. */
|
||||
NODISCARD FORCEINLINE constexpr bool EndsWith(ElementType Suffix) const
|
||||
NODISCARD FORCEINLINE bool EndsWith(ElementType Suffix) const
|
||||
{
|
||||
return TStringView<ElementType>(*this).EndsWith(Suffix);
|
||||
}
|
||||
|
||||
/** @return true if the string view contains the given substring, false otherwise. */
|
||||
NODISCARD FORCEINLINE constexpr bool Contains(TStringView<ElementType> View) const
|
||||
NODISCARD FORCEINLINE bool Contains(TStringView<ElementType> View) const
|
||||
{
|
||||
return TStringView<ElementType>(*this).Contains(View);
|
||||
}
|
||||
|
||||
/** @return true if the string view contains the given character, false otherwise. */
|
||||
NODISCARD FORCEINLINE constexpr bool Contains(ElementType Char) const
|
||||
NODISCARD FORCEINLINE bool Contains(ElementType Char) const
|
||||
{
|
||||
return TStringView<ElementType>(*this).Contains(Char);
|
||||
}
|
||||
|
||||
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */
|
||||
template <CPredicate<ElementType> F>
|
||||
NODISCARD FORCEINLINE constexpr bool Contains(F&& InPredicate) const
|
||||
NODISCARD FORCEINLINE bool Contains(F&& InPredicate) const
|
||||
{
|
||||
return TStringView<ElementType>(*this).Contains(Forward<F>(InPredicate));
|
||||
}
|
||||
@ -493,7 +494,7 @@ public:
|
||||
}
|
||||
|
||||
/** Copies the characters of this string to the destination buffer without null-termination. */
|
||||
FORCEINLINE constexpr size_t Copy(ElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
|
||||
FORCEINLINE size_t Copy(ElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
|
||||
{
|
||||
checkf(Dest != nullptr, TEXT("Illegal destination buffer. Please check the pointer."));
|
||||
|
||||
@ -502,10 +503,10 @@ public:
|
||||
return TStringView<ElementType>(*this).Copy(Dest, Count, Offset);
|
||||
}
|
||||
|
||||
FORCEINLINE constexpr size_t Copy(nullptr_t, size_t Count = DynamicExtent, size_t Offset = 0) const = delete;
|
||||
FORCEINLINE size_t Copy(nullptr_t, size_t = DynamicExtent, size_t = 0) const = delete;
|
||||
|
||||
/** @return The index of the first occurrence of the given substring, or INDEX_NONE if not found. */
|
||||
NODISCARD constexpr size_t Find(TStringView<ElementType> View, size_t Index = 0) const
|
||||
NODISCARD size_t Find(TStringView<ElementType> View, size_t Index = 0) const
|
||||
{
|
||||
checkf(Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -513,7 +514,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
||||
NODISCARD constexpr size_t Find(ElementType Char, size_t Index = 0) const
|
||||
NODISCARD size_t Find(ElementType Char, size_t Index = 0) const
|
||||
{
|
||||
checkf(Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -522,7 +523,7 @@ public:
|
||||
|
||||
/** @return The index of the first occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
||||
template <CPredicate<ElementType> F>
|
||||
NODISCARD constexpr size_t Find(F&& InPredicate, size_t Index = 0) const
|
||||
NODISCARD size_t Find(F&& InPredicate, size_t Index = 0) const
|
||||
{
|
||||
checkf(Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -530,7 +531,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the last occurrence of the given substring, or INDEX_NONE if not found. */
|
||||
NODISCARD constexpr size_t RFind(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
||||
NODISCARD size_t RFind(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
||||
{
|
||||
checkf(Index == INDEX_NONE || Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -538,7 +539,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
||||
NODISCARD constexpr size_t RFind(ElementType Char, size_t Index = INDEX_NONE) const
|
||||
NODISCARD size_t RFind(ElementType Char, size_t Index = INDEX_NONE) const
|
||||
{
|
||||
checkf(Index == INDEX_NONE || Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -547,7 +548,7 @@ public:
|
||||
|
||||
/** @return The index of the last occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
||||
template <CPredicate<ElementType> F>
|
||||
NODISCARD constexpr size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
|
||||
NODISCARD size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
|
||||
{
|
||||
checkf(Index == INDEX_NONE || Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -555,7 +556,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the first occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(TStringView<ElementType> View, size_t Index = 0) const
|
||||
NODISCARD FORCEINLINE size_t FindFirstOf(TStringView<ElementType> View, size_t Index = 0) const
|
||||
{
|
||||
checkf(Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -563,7 +564,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(ElementType Char, size_t Index = 0) const
|
||||
NODISCARD FORCEINLINE size_t FindFirstOf(ElementType Char, size_t Index = 0) const
|
||||
{
|
||||
checkf(Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -571,7 +572,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the last occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindLastOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
||||
NODISCARD FORCEINLINE size_t FindLastOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
||||
{
|
||||
checkf(Index == INDEX_NONE || Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -579,7 +580,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindLastOf(ElementType Char, size_t Index = INDEX_NONE) const
|
||||
NODISCARD FORCEINLINE size_t FindLastOf(ElementType Char, size_t Index = INDEX_NONE) const
|
||||
{
|
||||
checkf(Index == INDEX_NONE || Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -587,7 +588,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the first absence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(TStringView<ElementType> View, size_t Index = 0) const
|
||||
NODISCARD FORCEINLINE size_t FindFirstNotOf(TStringView<ElementType> View, size_t Index = 0) const
|
||||
{
|
||||
checkf(Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -595,7 +596,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the first absence of the given character, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(ElementType Char, size_t Index = 0) const
|
||||
NODISCARD FORCEINLINE size_t FindFirstNotOf(ElementType Char, size_t Index = 0) const
|
||||
{
|
||||
checkf(Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -603,7 +604,7 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the last absence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
||||
NODISCARD FORCEINLINE size_t FindLastNotOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
||||
{
|
||||
checkf(Index == INDEX_NONE || Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
@ -611,13 +612,371 @@ public:
|
||||
}
|
||||
|
||||
/** @return The index of the last absence of the given character, or INDEX_NONE if not found. */
|
||||
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(ElementType Char, size_t Index = INDEX_NONE) const
|
||||
NODISCARD FORCEINLINE size_t FindLastNotOf(ElementType Char, size_t Index = INDEX_NONE) const
|
||||
{
|
||||
checkf(Index == INDEX_NONE || Index < Num(), TEXT("Illegal index. Please check Index."));
|
||||
|
||||
return TStringView<ElementType>(*this).FindLastNotOf(Char, Index);
|
||||
}
|
||||
|
||||
/** Try to decode the given character using the U-encoded to a string using the T-encoded. */
|
||||
template <CCharType U>
|
||||
bool DecodeFrom(U Char, bool bAllowShrinking = true)
|
||||
{
|
||||
return DecodeFrom(TStringView(&Char, 1), bAllowShrinking);
|
||||
}
|
||||
|
||||
/** Try to decode the given string using the U-encoded to a string using the T-encoded. */
|
||||
template <CCharType U, CAllocator<U> A>
|
||||
bool DecodeFrom(const TString<U, A>& String, bool bAllowShrinking = true)
|
||||
{
|
||||
return DecodeFrom(TStringView(String), bAllowShrinking);
|
||||
}
|
||||
|
||||
/** Try to decode the given string view using the U-encoded to a string using the T-encoded. */
|
||||
template <CCharType U>
|
||||
bool DecodeFrom(TStringView<U> View, bool bAllowShrinking = true)
|
||||
{
|
||||
NativeData.Reset(false);
|
||||
|
||||
auto AppendToResult = [this]<typename W>(auto& Self, TStringView<W> View) -> bool
|
||||
{
|
||||
// char -> char
|
||||
// wchar -> wchar
|
||||
if constexpr (CSameAs<W, char> && CSameAs<T, char> || CSameAs<W, wchar> && CSameAs<T, wchar>)
|
||||
{
|
||||
// Unable to determine whether the user-preferred locale encoded character is valid or not, it is assumed to be valid.
|
||||
NativeData.Insert(NativeData.End(), View.Begin(), View.End());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// char -> wchar
|
||||
// char -> wchar -> ...
|
||||
else if constexpr (CSameAs<W, char>)
|
||||
{
|
||||
NAMESPACE_STD::locale Loc = NAMESPACE_STD::locale("");
|
||||
|
||||
check((NAMESPACE_STD::has_facet<NAMESPACE_STD::codecvt<wchar_t, char, NAMESPACE_STD::mbstate_t>>(Loc)));
|
||||
|
||||
const auto& Facet = NAMESPACE_STD::use_facet<NAMESPACE_STD::codecvt<wchar, char, NAMESPACE_STD::mbstate_t>>(Loc);
|
||||
|
||||
NAMESPACE_STD::mbstate_t State = NAMESPACE_STD::mbstate_t();
|
||||
|
||||
const char* BeginFrom = View.GetData().Get();
|
||||
const char* EndFrom = BeginFrom + View.Num();
|
||||
|
||||
wchar Buffer[FWChar::MaxCodeUnitLength];
|
||||
|
||||
const char* NextFrom;
|
||||
wchar* NextTo;
|
||||
|
||||
do
|
||||
{
|
||||
const auto Result = Facet.in(State, BeginFrom, EndFrom, NextFrom, Iteration::Begin(Buffer), Iteration::End(Buffer), NextTo);
|
||||
|
||||
if (BeginFrom == NextFrom) return false;
|
||||
|
||||
if (Result == NAMESPACE_STD::codecvt_base::error) return false;
|
||||
if (Result == NAMESPACE_STD::codecvt_base::noconv) return false;
|
||||
|
||||
// char -> wchar
|
||||
if constexpr (CSameAs<T, wchar>)
|
||||
{
|
||||
for (wchar* Iter = Buffer; Iter != NextTo; ++Iter)
|
||||
{
|
||||
NativeData.PushBack(*Iter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Self(Self, TStringView(Buffer, NextTo))) return false;
|
||||
}
|
||||
|
||||
BeginFrom = NextFrom;
|
||||
}
|
||||
while (BeginFrom != EndFrom);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// wchar -> char
|
||||
else if constexpr (CSameAs<W, wchar> && CSameAs<T, char>)
|
||||
{
|
||||
NAMESPACE_STD::locale Loc = NAMESPACE_STD::locale("");
|
||||
|
||||
check((NAMESPACE_STD::has_facet<NAMESPACE_STD::codecvt<wchar_t, char, NAMESPACE_STD::mbstate_t>>(Loc)));
|
||||
|
||||
const auto& Facet = NAMESPACE_STD::use_facet<NAMESPACE_STD::codecvt<wchar, char, NAMESPACE_STD::mbstate_t>>(Loc);
|
||||
|
||||
NAMESPACE_STD::mbstate_t State = NAMESPACE_STD::mbstate_t();
|
||||
|
||||
const wchar* BeginFrom = View.GetData().Get();
|
||||
const wchar* EndFrom = BeginFrom + View.Num();
|
||||
|
||||
char Buffer[FChar::MaxCodeUnitLength];
|
||||
|
||||
const wchar* NextFrom;
|
||||
char* NextTo;
|
||||
|
||||
do
|
||||
{
|
||||
const auto Result = Facet.out(State, BeginFrom, EndFrom, NextFrom, Iteration::Begin(Buffer), Iteration::End(Buffer), NextTo);
|
||||
|
||||
if (BeginFrom == NextFrom) return false;
|
||||
|
||||
if (Result == NAMESPACE_STD::codecvt_base::error) return false;
|
||||
if (Result == NAMESPACE_STD::codecvt_base::noconv) return false;
|
||||
|
||||
for (char* Iter = Buffer; Iter != NextTo; ++Iter)
|
||||
{
|
||||
NativeData.PushBack(*Iter);
|
||||
}
|
||||
|
||||
BeginFrom = NextFrom;
|
||||
}
|
||||
while (BeginFrom != EndFrom);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// u8char -> unicodechar -> ...
|
||||
else if constexpr (CSameAs<W, u8char>)
|
||||
{
|
||||
auto Iter = View.Begin();
|
||||
|
||||
while (Iter != View.End())
|
||||
{
|
||||
unicodechar Temp = static_cast<unicodechar>(*Iter++);
|
||||
|
||||
unicodechar Unicode;
|
||||
|
||||
if ((Temp & 0b10000000) == 0b00000000) // 0XXXXXXX
|
||||
{
|
||||
Unicode = Temp;
|
||||
}
|
||||
|
||||
else if ((Temp & 0b11100000) == 0b11000000) // 110XXXXX 10XXXXXX
|
||||
{
|
||||
if (Iter + 1 > View.End()) return false;
|
||||
|
||||
Unicode = (Temp & 0b00011111) << 6;
|
||||
|
||||
Temp = static_cast<unicodechar>(*Iter++); if ((Temp & 0b11000000) != 0b10000000) return false; else Unicode |= Temp & 0b00111111;
|
||||
}
|
||||
|
||||
else if ((Temp & 0b11110000) == 0b11100000) // 1110XXXX 10XXXXXX 10XXXXXX
|
||||
{
|
||||
if (Iter + 2 > View.End()) return false;
|
||||
|
||||
Unicode = (Temp & 0b00001111) << 12;
|
||||
|
||||
Temp = static_cast<unicodechar>(*Iter++); if ((Temp & 0b11000000) != 0b10000000) return false; else Unicode |= (Temp & 0b00111111) << 6;
|
||||
Temp = static_cast<unicodechar>(*Iter++); if ((Temp & 0b11000000) != 0b10000000) return false; else Unicode |= Temp & 0b00111111;
|
||||
}
|
||||
|
||||
else if ((Temp & 0b11111000) == 0b11110000) // 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
|
||||
{
|
||||
if (Iter + 3 > View.End()) return false;
|
||||
|
||||
Unicode = (Temp & 0b00000111) << 18;
|
||||
|
||||
Temp = static_cast<unicodechar>(*Iter++); if ((Temp & 0b11000000) != 0b10000000) return false; else Unicode |= (Temp & 0b00111111) << 12;
|
||||
Temp = static_cast<unicodechar>(*Iter++); if ((Temp & 0b11000000) != 0b10000000) return false; else Unicode |= (Temp & 0b00111111) << 6;
|
||||
Temp = static_cast<unicodechar>(*Iter++); if ((Temp & 0b11000000) != 0b10000000) return false; else Unicode |= Temp & 0b00111111;
|
||||
}
|
||||
|
||||
else return false;
|
||||
|
||||
if (!Self(Self, TStringView(&Unicode, 1))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// u16char -> unicodechar -> ...
|
||||
// wchar -> unicodechar -> ... for Windows
|
||||
else if constexpr (CSameAs<W, u16char> || PLATFORM_WINDOWS && CSameAs<W, wchar>)
|
||||
{
|
||||
auto Iter = View.Begin();
|
||||
|
||||
while (Iter != View.End())
|
||||
{
|
||||
unicodechar Temp = static_cast<unicodechar>(*Iter++);
|
||||
|
||||
unicodechar Unicode;
|
||||
|
||||
// High Surrogate <UD800>..<UDBFF>;
|
||||
// Low Surrogate <UDC00>..<UDFFF>;
|
||||
|
||||
if (Temp >= 0xD800 && Temp <= 0xDBFF)
|
||||
{
|
||||
if (Iter == View.End()) return false;
|
||||
|
||||
Unicode = (Temp & 0b00000011'11111111) << 10;
|
||||
|
||||
Temp = static_cast<unicodechar>(*Iter++);
|
||||
|
||||
if (Temp >= 0xDC00 && Temp <= 0xDFFF)
|
||||
{
|
||||
Unicode |= Temp & 0b00000011'11111111;
|
||||
|
||||
Unicode += 0x10000;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
else Unicode = Temp;
|
||||
|
||||
if (!Self(Self, TStringView(&Unicode, 1))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// wchar -> unicodechar -> ... for Linux
|
||||
else if constexpr (PLATFORM_LINUX && CSameAs<W, wchar>)
|
||||
{
|
||||
return Self(Self, TStringView(reinterpret_cast<const u32char*>(View.GetData().Get()), View.Num()));
|
||||
}
|
||||
|
||||
// unicodechar u32char -> u8char
|
||||
else if constexpr (CSameAs<W, unicodechar> && CSameAs<T, u8char>)
|
||||
{
|
||||
for (unicodechar Char : View)
|
||||
{
|
||||
if (!FUnicodeChar::IsValid(Char)) return false;
|
||||
|
||||
if (!(Char & ~0b0000000'00000000'00000000'01111111)) // 0XXXXXXX
|
||||
{
|
||||
NativeData.PushBack(static_cast<u8char>(Char));
|
||||
}
|
||||
else if (!(Char & ~0b0000000'00000000'00000111'11111111)) // 110XXXXX 10XXXXXX
|
||||
{
|
||||
NativeData.PushBack(static_cast<u8char>(0b11000000 | (Char >> 6 & 0b00011111)));
|
||||
NativeData.PushBack(static_cast<u8char>(0b10000000 | (Char & 0b00111111)));
|
||||
}
|
||||
else if (!(Char & ~0b0000000'00000000'11111111'11111111)) // 1110XXXX 10XXXXXX 10XXXXXX
|
||||
{
|
||||
NativeData.PushBack(static_cast<u8char>(0b11100000 | (Char >> 12 & 0b00001111)));
|
||||
NativeData.PushBack(static_cast<u8char>(0b10000000 | (Char >> 6 & 0b00111111)));
|
||||
NativeData.PushBack(static_cast<u8char>(0b10000000 | (Char & 0b00111111)));
|
||||
}
|
||||
else if (!(Char & ~0b0000000'11111111'11111111'11111111)) // 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
|
||||
{
|
||||
NativeData.PushBack(static_cast<u8char>(0b11110000 | (Char >> 18 & 0b00000111)));
|
||||
NativeData.PushBack(static_cast<u8char>(0b10000000 | (Char >> 12 & 0b00111111)));
|
||||
NativeData.PushBack(static_cast<u8char>(0b10000000 | (Char >> 6 & 0b00111111)));
|
||||
NativeData.PushBack(static_cast<u8char>(0b10000000 | (Char & 0b00111111)));
|
||||
}
|
||||
else check_no_entry();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// unicodechar u32char -> u16char
|
||||
// unicodechar u32char -> wchar for Windows
|
||||
// unicodechar u32char -> wchar -> char for Windows
|
||||
else if constexpr (CSameAs<W, unicodechar> && (CSameAs<T, u16char> || PLATFORM_WINDOWS && (CSameAs<T, char> || CSameAs<T, wchar>)))
|
||||
{
|
||||
for (unicodechar Char : View)
|
||||
{
|
||||
if (!FUnicodeChar::IsValid(Char)) return false;
|
||||
|
||||
if (!(Char & ~0b0000000'00000000'11111111'11111111)) // XXXXXXXX'XXXXXXXX
|
||||
{
|
||||
if constexpr (PLATFORM_WINDOWS && (CSameAs<T, char> || CSameAs<T, wchar>))
|
||||
{
|
||||
wchar WChar = static_cast<wchar>(Char);
|
||||
|
||||
if (!Self(Self, TStringView(&WChar, 1))) return false;
|
||||
}
|
||||
else NativeData.PushBack(static_cast<u16char>(Char));
|
||||
}
|
||||
else if (!(Char & ~0b0000000'00011111'11111111'11111111)) // 110110XX'XXXXXXXX 110111XX'XXXXXXXX
|
||||
{
|
||||
Char -= 0x10000;
|
||||
|
||||
u16char Buffer[] = {
|
||||
static_cast<u16char>(0b11011000'00000000 | (Char >> 10 & 0b00000011'11111111)),
|
||||
static_cast<u16char>(0b11011100'00000000 | (Char & 0b00000011'11111111))
|
||||
};
|
||||
|
||||
if constexpr (PLATFORM_WINDOWS && (CSameAs<T, char> || CSameAs<T, wchar>))
|
||||
{
|
||||
if (!Self(Self, TStringView(reinterpret_cast<const wchar*>(Buffer), 2))) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
NativeData.PushBack(Buffer[0]);
|
||||
NativeData.PushBack(Buffer[1]);
|
||||
}
|
||||
}
|
||||
else check_no_entry();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// unicodechar u32char -> unicodechar u32char
|
||||
// unicodechar u32char -> wchar for Linux
|
||||
// unicodechar u32char -> wchar -> char for Linux
|
||||
else if constexpr (CSameAs<W, unicodechar> && (CSameAs<T, unicodechar> || PLATFORM_LINUX && (CSameAs<T, char> || CSameAs<T, wchar>)))
|
||||
{
|
||||
for (unicodechar Char : View)
|
||||
{
|
||||
if (!FUnicodeChar::IsValid(Char)) return false;
|
||||
}
|
||||
|
||||
if constexpr (PLATFORM_LINUX && (CSameAs<T, char> || CSameAs<T, wchar>))
|
||||
{
|
||||
return Self(Self, TStringView(reinterpret_cast<const wchar*>(View.GetData().Get()), View.Num()));
|
||||
}
|
||||
else NativeData.Insert(NativeData.End(), View.Begin(), View.End());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else static_assert(sizeof(W) == -1, "Unsupported character type");
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
bool bIsValid = AppendToResult(AppendToResult, View);
|
||||
|
||||
if (!bIsValid) NativeData.Reset(false);
|
||||
|
||||
NativeData.PushBack(LITERAL(T, '\0'));
|
||||
|
||||
if (bAllowShrinking) NativeData.Shrink();
|
||||
|
||||
return bIsValid;
|
||||
}
|
||||
|
||||
/** Try to encode a T-encoded string to a U-encoded string. */
|
||||
template <CCharType U, CAllocator<U> A = TDefaultStringAllocator<T>>
|
||||
NODISCARD TOptional<TString<U, A>> EncodeTo() const
|
||||
{
|
||||
TString<U, A> Result;
|
||||
|
||||
bool bIsValid = Result.DecodeFrom(*this);
|
||||
|
||||
if (!bIsValid) return Invalid;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/** @return The non-modifiable standard C character string version of the string. */
|
||||
NODISCARD FORCEINLINE const ElementType* ToCString() const { return NativeData.GetData().Get(); }
|
||||
|
||||
/** @return The target-encoded string from the T-encoded string. */
|
||||
NODISCARD FORCEINLINE auto ToString() const { return EncodeTo<char>(); }
|
||||
NODISCARD FORCEINLINE auto ToWString() const { return EncodeTo<wchar>(); }
|
||||
NODISCARD FORCEINLINE auto ToU8String() const { return EncodeTo<u8char>(); }
|
||||
NODISCARD FORCEINLINE auto ToU16String() const { return EncodeTo<u16char>(); }
|
||||
NODISCARD FORCEINLINE auto ToU32String() const { return EncodeTo<u32char>(); }
|
||||
NODISCARD FORCEINLINE auto ToUnicodeString() const { return EncodeTo<unicodechar>(); }
|
||||
|
||||
/** Resizes the string to contain 'Count' characters. Additional null characters are appended. */
|
||||
FORCEINLINE void SetNum(size_t Count, bool bAllowShrinking = true) { SetNum(Count, LITERAL(ElementType, '\0'), bAllowShrinking); }
|
||||
|
||||
@ -634,9 +993,6 @@ public:
|
||||
NODISCARD FORCEINLINE TObserverPtr< ElementType[]> GetData() { return NativeData.GetData(); }
|
||||
NODISCARD FORCEINLINE TObserverPtr<const ElementType[]> GetData() const { return NativeData.GetData(); }
|
||||
|
||||
/** @return The non-modifiable standard C character string version of the string. */
|
||||
NODISCARD FORCEINLINE const ElementType* ToCString() const { return NativeData.GetData().Get(); }
|
||||
|
||||
/** @return The iterator to the first or end character. */
|
||||
NODISCARD FORCEINLINE Iterator Begin() { return NativeData.Begin(); }
|
||||
NODISCARD FORCEINLINE ConstIterator Begin() const { return NativeData.Begin(); }
|
||||
|
Loading…
Reference in New Issue
Block a user