8#ifndef HPP_ALIB_STRINGS_ASTRING
9#define HPP_ALIB_STRINGS_ASTRING 1
11#ifndef HPP_ALIB_STRINGS_CSTRING
15#if !defined(HPP_ALIB_LANG_PLATFORM_INCLUDES)
22 #pragma warning( push )
23 #pragma warning( disable : 4127 )
26namespace alib {
namespace strings {
31template<
typename TChar>
class TAString;
36template<
typename T,
typename TChar,
typename If=
void>
struct T_Append_not_specialized_for_type
39template<
typename T,
typename TChar >
struct T_Append_not_specialized_for_type
40<T,TChar,typename std::enable_if<
41 std::is_same<decltype(std::declval<TAString<TChar>>().append(std::declval<const T&>()) ),
92template<
typename TAppendable,
94 typename TEnableIf =
void >
124template<
typename T,
typename TChar,
typename TEnableIf=
void>
struct TT_IsAppendable :
public std::false_type {};
126#if !defined(ALIB_DOX)
128ATMP_VOID_IF(
ATMP_EQ(void, decltype( std::declval<T_Append<T, TChar>>()( std::declval<TAString<TChar> &>(),
129 std::declval<T const &>() ) ) ) )
130> :
public std::true_type {};
135#define ALIB_STRINGS_APPENDABLE_TYPE(TYPE) \
136namespace alib::strings { \
137 template<> struct T_Append<TYPE, alib::character> \
139 ALIB_API void operator()( TAString<alib::character>& target, const TYPE src ); \
142#define ALIB_STRINGS_APPENDABLE_TYPE_N(TYPE) \
143namespace alib::strings { \
144 template<> struct T_Append<TYPE, alib::nchar> \
146 ALIB_API void operator()( TAString<alib::nchar>& target, const TYPE src ); \
149#define ALIB_STRINGS_APPENDABLE_TYPE_W(TYPE) \
150namespace alib::strings { \
151 template<> struct T_Append<TYPE, alib::wchar> \
153 ALIB_API void operator()( TAString<alib::wchar>& target, const TYPE src ); \
156#define ALIB_STRINGS_APPENDABLE_TYPE_DEF(TYPE, IMPL) \
157void alib::strings::T_Append<TYPE,alib::character> \
158 ::operator()( TAString<alib::character>& target, const TYPE src) { IMPL } \
160#define ALIB_STRINGS_APPENDABLE_TYPE_DEF_N(TYPE, IMPL) \
161void alib::strings::T_Append<TYPE,alib::nchar> \
162 ::operator()( TAString<alib::nchar>& target, const TYPE src) { IMPL } \
164#define ALIB_STRINGS_APPENDABLE_TYPE_DEF_W(TYPE, IMPL) \
165void alib::strings::T_Append<TYPE,alib::wchar> \
166 ::operator()( TAString<alib::wchar>& target, const TYPE src) { IMPL } \
169#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE(TYPE, IMPL) \
170namespace alib::strings { \
171 template<> struct T_Append<TYPE,alib::character> \
173 void operator()( TAString<alib::character>& target, const TYPE& src ){ IMPL} \
176#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE_N(TYPE, IMPL) \
177namespace alib::strings { \
178 template<> struct T_Append<TYPE,alib::nchar> \
180 void operator()( TAString<alib::nchar>& target, const TYPE& src ){ IMPL} \
183#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE_W(TYPE, IMPL) \
184namespace alib::strings { \
185 template<> struct T_Append<TYPE,alib::wchar> \
187 void operator()( TAString<alib::wchar>& target, const TYPE& src ){ IMPL} \
285template<
typename TChar>
286class TAString :
public TString<TChar>
304 #if ALIB_DEBUG_STRINGS
377 :
TString<TChar>( extBuffer, 0 )
420 if ( !move.HasInternalBuffer() )
442 #if ALIB_DEBUG_STRINGS
444 move.buffer=
nullptr;
458 template <
class TAppendable>
483 #if defined(ALIB_DOX)
500 template<
typename TCharArray>
inline operator TCharArray ()
const;
518 template<
typename TCharArray>
inline explicit operator TCharArray ()
const;
554 explicit operator T ()
const
584 return Reset().
Append( copy.Buffer(), copy.Length() );
682 #if ALIB_DEBUG_STRINGS
684 "STRINGS",
"Previous allocation request was too short" )
690 #if ALIB_DEBUG_STRINGS
802 template<
bool TCheck =true>
807 "STRINGS",
"Can't write character '\0'" )
808 if constexpr (TCheck)
817 "STRINGS",
"Non-checking invocation: ",
"Index out of range" )
838 "STRINGS",
"Index out of bounds" )
844 using TString<TChar>::operator[];
864 "STRINGS",
"Negative AString length requested" )
866 "STRINGS",
"Requested AString length exceeds capacity" )
884 "STRINGS",
"Detected AString length exceeds capacity" )
911 "STRINGS",
"Negative AString length requested" )
913 "STRINGS",
"Increase of AString length requested" )
937 template <
bool TCheck= true,
typename TCharSrc >
941 typename std::enable_if< characters::TT_IsChar<TCharSrc>::value
942 && !std::is_same<TCharSrc,TChar>::value,
TAString&>::type
959 template <
bool TCheck= true>
965 if constexpr ( TCheck )
971 if ( srcLength <= 0 )
984 "Nullptr passed with non-checking method version." )
1011 template <
bool TCheck= true>
1014 if constexpr (TCheck)
1018 if ( src.TString<TChar>::AdjustRegion( regionStart, regionLength ) )
1033 && regionStart + regionLength <= src.
Length(),
"STRINGS",
1034 "Non-checking invocation: ",
"Invalid region given" )
1039 return Append<false>( src.
Buffer() + regionStart, regionLength );
1055 template <
bool TCheck= true>
1058 return Append( src, regionStart, regionLength );
1079 #if !defined(ALIB_DOX)
1083 template<
typename TC,
typename TV,
typename If>
1084 friend struct T_Append_not_specialized_for_type;
1098 append(
const T& src )
1100 T_Append<ATMP_RCVR(T), TChar>()( *
this, src );
1110 append(
const T& src )
1112 T_Append<ATMP_RCVP(T)* , TChar>()( *
this, src );
1123 append(
const T& src )
1125 using TSrc=
typename characters::TT_CharArrayType<
ATMP_RCVR(T)>::TChar;
1126 using TCA=
typename characters::T_CharArray<
ATMP_RCVR(T),TSrc>;
1127 const TSrc* buf= TCA::Buffer( src );
1128 if ( TCheck && !buf )
1131 Append<false>( buf, TCA::Length( src ) );
1141 append(
const T& src )
1143 using TSrc=
typename characters::TT_ZTCharArrayType<
ATMP_RCVR(T)>::TChar;
1144 using TCA=
typename characters::T_ZTCharArray<
ATMP_RCVR(T),TSrc>;
1145 const TSrc* buf= TCA::Buffer( src );
1146 if ( TCheck && !buf )
1149 Append<false>( buf, TCA::Length( src ) );
1158 template<
bool TCheck= true>
1159 bool append(TChar src )
1161 if ( TCheck && src == 0 )
1171 characters::TT_IsChar<
ATMP_RCVR(T)>::value )
1174 if ( TCheck && src == 0 )
1180 if constexpr (
ATMP_EQ( TChar, TOtherChar) )
1194 mbLength= WideCharToMultiByte( CP_UTF8, 0, &wc, 1,
1196 MB_LEN_MAX * 2, NULL, NULL );
1197 if ( mbLength <= 0 )
1199 ALIB_DBG( DWORD error= GetLastError(); )
1200 ALIB_WARNING(
"STRINGS",
"Cannot convert wide character string to UTF-8. Error: ",
1201 ( error == ERROR_INSUFFICIENT_BUFFER ?
"ERROR_INSUFFICIENT_BUFFER"
1202 : error == ERROR_INVALID_FLAGS ?
"ERROR_INVALID_FLAGS."
1203 : error == ERROR_INVALID_PARAMETER ?
"ERROR_INVALID_PARAMETER"
1204 : error == ERROR_NO_UNICODE_TRANSLATION ?
"ERROR_NO_UNICODE_TRANSLATION"
1205 : static_cast<const char*>(
NAString( error ) ) ) )
1209 mbLength= wctomb(
reinterpret_cast<nchar*
>(TString<TChar>::vbuffer)
1213 if ( mbLength <= 0 )
1261 template <
bool TCheck= true,
typename TAppendable>
1264 static_assert( T_Append_not_specialized_for_type<TAppendable,TChar>::value,
1265 "See Programmer's manual of ALib Module Strings for information about "
1266 "how to specialize T_Append for custom types to mitigate this error. "
1267 "More compiler errors might follow." );
1268 append<TCheck>( src );
1284 template <
bool TCheck= true,
class TAppendable >
1287 return Append<TCheck>( src );
1297 template <
class TAppendable>
1300 return Append<true>(src);
1329 template <
bool TCheck= true,
typename TAppendable>
1334 Append<TCheck>( src );
1365 template <
bool TCheck= true>
1370 if constexpr ( TCheck )
1378 "STRINGS",
"Non-checking invocation: ",
"Illegal parameters" )
1404 template <
bool TCheck= true>
1407 if constexpr ( TCheck )
1414 "Non-checking invocation: ",
"Negative quantity given" )
1437 template <
bool TCheck= true>
1440 if constexpr ( TCheck )
1448 "Non-checking invocation: ",
"Negative quantity given" )
1450 "Non-checking invocation: ",
"Illegal position given" )
1489 template <
bool TCheck= true >
1496 if constexpr ( TCheck )
1512 && regionLength >= 0,
"STRINGS",
1513 "Non-checking invocation: ",
"Illegal arguments" )
1546 template <
bool TCheck= true >
1551 if constexpr ( TCheck )
1553 if ( regionLength <= 0 )
1564 "STRINGS",
"Non-checking invocation: ",
1565 "Region length out of range." )
1588 template <
bool TCheck= true >
1593 if constexpr (TCheck)
1595 if ( regionLength > 0 )
1606 "STRINGS",
"Non-checking invocation: ",
1607 "Region length out of range" )
1663 Delete<false>( 0, idx );
1707 template <
bool TCheck= true>
1711 if constexpr ( TCheck )
1718 "Non-checking invocation: ",
"Source string is nulled" )
1724 "Non-checking invocation: ",
"Invalid region given" )
1762 template <
bool TCheck= true>
1765 if constexpr ( TCheck )
1777 "Non-checking invocation: ",
"Invalid region given" )
1831 template <
bool TCheck= true>
1834 if constexpr ( TCheck )
1846 "Non-checking invocation: ",
"Invalid region given" )
1865 template <
bool TCheck= true>
1868 if constexpr ( TCheck )
1880 "Non-checking invocation: ",
"Invalid region given" )
1898 template <
bool TCheck= true>
1901 if constexpr ( TCheck )
1913 "Non-checking invocation: ",
"Invalid region given" )
1967#if (ALIB_CPP_STANDARD >= 20 && !defined(_MSC_VER)) && !defined(ALIB_DOX)
2000#if ALIB_DEBUG_STRINGS
2020template<>
template<>
ALIB_API TAString<nchar>& TAString<nchar>::Append<true ,wchar>(
const wchar*,
integer);
2021template<>
template<>
ALIB_API TAString<nchar>& TAString<nchar>::Append<false,wchar>(
const wchar*,
integer);
2022template<>
template<>
ALIB_API TAString<nchar>& TAString<nchar>::Append<true ,xchar>(
const xchar*,
integer);
2023template<>
template<>
ALIB_API TAString<nchar>& TAString<nchar>::Append<false,xchar>(
const xchar*,
integer);
2040template<>
template<>
ALIB_API TAString<wchar>& TAString<wchar>::Append<true ,nchar>(
const nchar*,
integer );
2041template<>
template<>
ALIB_API TAString<wchar>& TAString<wchar>::Append<false,nchar>(
const nchar*,
integer );
2042template<>
template<>
ALIB_API TAString<wchar>& TAString<wchar>::Append<true ,xchar>(
const xchar*,
integer );
2043template<>
template<>
ALIB_API TAString<wchar>& TAString<wchar>::Append<false,xchar>(
const xchar*,
integer );
2059template<>
template<>
ALIB_API TAString<xchar>& TAString<xchar>::Append<true ,nchar>(
const nchar*,
integer );
2060template<>
template<>
ALIB_API TAString<xchar>& TAString<xchar>::Append<false,nchar>(
const nchar*,
integer );
2061template<>
template<>
ALIB_API TAString<xchar>& TAString<xchar>::Append<true ,wchar>(
const wchar*,
integer );
2062template<>
template<>
ALIB_API TAString<xchar>& TAString<xchar>::Append<false,wchar>(
const wchar*,
integer );
2077template<
typename TChar>
2078class TStringLengthResetter
2087 void*
operator new (size_t);
2090 void*
operator new (size_t,
void*);
2093 void*
operator new[](size_t);
2096 void*
operator new[](size_t,
void*);
2105 , originalLength(pAString.Length())
2110 { aString.ShortenTo(originalLength); }
2117 { aString.ShortenTo(originalLength); }
2122 {
return originalLength; }
2126#define ALIB_STRING_RESETTER(astring) \
2127alib::strings::TStringLengthResetter< \
2128 std::remove_reference<decltype(astring)>::type::CharType> \
2129 ALIB_IDENTIFIER(astring)(astring)
2134#if defined(_MSC_VER)
2135 #pragma warning( pop )
TAString & ShortenTo(integer newLength)
ALIB_API integer TrimAt(integer idx, const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
TAString & _(const TAppendable &src)
bool dbgWarnWhenExternalBufferIsReplaced
void GrowBufferAtLeastBy(integer minimumGrowth)
ALIB_API TAString & Trim(const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
std::reverse_iterator< Iterator > ReverseIterator
TAString & ToLower(integer regionStart=0, integer regionLength=MAX_LEN)
constexpr TAString(TChar *extBuffer, integer extBufferSize)
TAString & Delete(integer regionStart, integer regionLength=MAX_LEN)
bool HasInternalBuffer() const
ALIB_WARNINGS_RESTORE ReverseIterator rbegin()
TAString(const TAString ©)
TAString & DeleteEnd(integer regionLength)
TAString & Append(const TCharSrc *src, integer srcLength)
TAString & operator<<(const TAppendable &src)
TAString & ToUpper(integer regionStart=0, integer regionLength=MAX_LEN)
typename TString< TChar >::template TRandomAccessIterator< TChar > Iterator
TAString(const TAppendable &src)
TAString & Append(const TChar *src, integer srcLength)
TAString & operator=(const TAString ©)
TAString & InsertChars(TChar c, integer qty, integer pos)
TAString & TrimStart(const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
void SetCharAt(integer idx, TChar c)
TAString & ReplaceSubstring(const TString< TChar > &src, integer regionStart, integer regionLength)
integer debugLastAllocRequest
ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE Iterator begin()
TAString & Append(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
TAString & InsertChars(TChar c, integer qty)
TAString & TrimEnd(const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
TAString & DeleteStart(integer regionLength)
TChar & operator[](integer idx)
TAString(TAString &&move) noexcept
void DbgDisableBufferReplacementWarning()
void EnsureRemainingCapacity(integer spaceNeeded)
ALIB_API void SetBuffer(integer newCapacity)
TAString & Append(const TAppendable &src)
void SetLength(integer newLength)
TAString & Reverse(integer regionStart=0, integer regionLength=MAX_LEN)
ALIB_API integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0)
TAString & InsertAt(const TString< TChar > &src, integer pos)
TAString & ReplaceRegion(TChar c, integer regionStart, integer regionLength)
const TChar * Terminate() const
TAString & Reset(const TAppendable &src)
integer originalLength
The The original length of the string.
TStringLengthResetter(TAString< TChar > &pAString)
TAString< TChar > & aString
The AString to reset.
constexpr bool IsNull() const
constexpr bool IsEmpty() const
constexpr bool IsNotEmpty() const
constexpr integer Length() const
constexpr bool IsNotNull() const
integer CopyTo(TChar *dest) const
bool AdjustRegion(integer ®ionStart, integer ®ionLength) const
constexpr TString() noexcept=default
constexpr const TChar * Buffer() const
#define ALIB_WARNING(...)
#define ATMP_RETURN_IF_2TP(TReturn, TParam1, TParam2,...)
#define ATMP_VOID_IF(Cond)
#define ALIB_WARNINGS_RESTORE
#define ATMP_EQ( T, TEqual)
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ALIB_STRING_DBG_CHK(instance)
#define ATMP_SELECT_IF_1TP(TParam, ...)
#define ALIB_DEBUG_STRINGS
PLATFORM_SPECIFIC character
@ KeepWithSender
Keeps responsibility, e.g. when passing an object.
bool operator==(const String &lhs, const String &rhs)
static constexpr integer MAX_LEN
bool operator<=>(const String &lhs, const String &rhs)
strings::TAString< xchar > XAString
Type alias in namespace alib.
strings::TAString< nchar > NAString
Type alias in namespace alib.
characters::wchar wchar
Type alias in namespace alib.
characters::xchar xchar
Type alias in namespace alib.
strings::TCString< nchar > NCString
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.
strings::TAString< wchar > WAString
Type alias in namespace alib.
strings::TCString< xchar > XCString
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
strings::TCString< wchar > WCString
Type alias in namespace alib.
static TChar ToLower(TChar c)
static TChar ToUpper(TChar c)
static integer Length(const TChar *cstring)
static ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE void Reverse(TChar *src, integer length)
static void Fill(TChar *dest, integer length, TChar value)
static void Copy(const TChar *src, integer length, TChar *dest)
static void Move(const TChar *src, integer length, TChar *dest)
static constexpr ConstructionType Construction
static TString Construct(const TChar *array, integer length)
static TString Construct(const TChar *array, integer length)
void operator()(TAString< TChar > &target, const TAppendable &src)