diff --git a/Redcraft.Utility/Source/Public/String/String.h b/Redcraft.Utility/Source/Public/String/String.h index ac61174..be96c2b 100644 --- a/Redcraft.Utility/Source/Public/String/String.h +++ b/Redcraft.Utility/Source/Public/String/String.h @@ -21,44 +21,6 @@ NAMESPACE_PRIVATE_BEGIN template struct TIsTString : FFalse { }; template struct TIsTString> : FTrue { }; -template -class TCStringFromTString final : FNoncopyable -{ -public: - - FORCEINLINE TCStringFromTString(const T* InPtr, bool bInDelete) - : Ptr(InPtr), bDelete(bInDelete) - { } - - FORCEINLINE TCStringFromTString(TCStringFromTString&& InValue) - : Ptr(InValue.Ptr), bDelete(Exchange(InValue.bDelete, false)) - { } - - FORCEINLINE ~TCStringFromTString() - { - if (bDelete) delete[] Ptr; - } - - FORCEINLINE TCStringFromTString& operator=(TCStringFromTString&& InValue) - { - if (bDelete) delete[] Ptr; - - Ptr = InValue.Ptr; - - bDelete = Exchange(InValue.bDelete, false); - - return *this; - } - - NODISCARD FORCEINLINE operator const T*() const { return Ptr; } - -private: - - const T* Ptr; - bool bDelete; - -}; - NAMESPACE_PRIVATE_END template concept CTString = NAMESPACE_PRIVATE::TIsTString>::Value; @@ -1068,21 +1030,10 @@ public: { const_cast(this->GetData())[this->Num()] = LITERAL(ElementType, '\0'); - return NAMESPACE_PRIVATE::TCStringFromTString(this->GetData(), false); + return *TStringView(this->GetData(), this->Num() + 1); } - if (this->Back() == LITERAL(ElementType, '\0')) - { - return NAMESPACE_PRIVATE::TCStringFromTString(this->GetData(), false); - } - - ElementType* Buffer = new ElementType[this->Num() + 1]; - - Copy(Buffer); - - Buffer[this->Num()] = LITERAL(ElementType, '\0'); - - return NAMESPACE_PRIVATE::TCStringFromTString(Buffer, true); + return *TStringView(*this); } /** @return The non-modifiable standard C character string version of the string. */ diff --git a/Redcraft.Utility/Source/Public/String/StringView.h b/Redcraft.Utility/Source/Public/String/StringView.h index 3627a6e..76e7f34 100644 --- a/Redcraft.Utility/Source/Public/String/StringView.h +++ b/Redcraft.Utility/Source/Public/String/StringView.h @@ -31,6 +31,44 @@ NAMESPACE_PRIVATE_BEGIN template struct TIsTStringView : FFalse { }; template struct TIsTStringView> : FTrue { }; +template +class TCStringFromTStringView final : FNoncopyable +{ +public: + + FORCEINLINE TCStringFromTStringView(const T* InPtr, bool bInDelete) + : Ptr(InPtr), bDelete(bInDelete) + { } + + FORCEINLINE TCStringFromTStringView(TCStringFromTStringView&& InValue) + : Ptr(InValue.Ptr), bDelete(Exchange(InValue.bDelete, false)) + { } + + FORCEINLINE ~TCStringFromTStringView() + { + if (bDelete) delete[] Ptr; + } + + FORCEINLINE TCStringFromTStringView& operator=(TCStringFromTStringView&& InValue) + { + if (bDelete) delete[] Ptr; + + Ptr = InValue.Ptr; + + bDelete = Exchange(InValue.bDelete, false); + + return *this; + } + + NODISCARD FORCEINLINE operator const T*() const { return Ptr; } + +private: + + const T* Ptr; + bool bDelete; + +}; + NAMESPACE_PRIVATE_END template concept CTStringView = NAMESPACE_PRIVATE::TIsTStringView>::Value; @@ -447,6 +485,25 @@ public: return RFind([Char](ElementType C) { return C != Char; }, Index); } +public: + + /** @return The non-modifiable standard C character string version of the string view. */ + NODISCARD FORCEINLINE auto operator*() const + { + if (this->Back() == LITERAL(ElementType, '\0') || Contains(LITERAL(ElementType, '\0'))) + { + return NAMESPACE_PRIVATE::TCStringFromTStringView(this->GetData(), false); + } + + ElementType* Buffer = new ElementType[this->Num() + 1]; + + Copy(Buffer); + + Buffer[this->Num()] = LITERAL(ElementType, '\0'); + + return NAMESPACE_PRIVATE::TCStringFromTStringView(Buffer, true); + } + public: /** @return true if the string only contains valid characters, false otherwise. */