8#ifndef HPP_ALIB_STRINGS_TASTRING
9#define HPP_ALIB_STRINGS_TASTRING 1
11#if !defined(HPP_ALIB_STRINGS_TASTRING_INLINING)
12# error "ALib sources with ending '.inl' must not be included from outside."
20 #pragma warning( push )
21 #pragma warning( disable : 4127 )
25namespace alib {
namespace strings {
30template<
typename TChar,
typename TAllocator>
36template<
typename T,
typename TChar,
typename TAllocator,
typename If=
void>
struct T_Append_not_specialized_for_type
39template<
typename T,
typename TChar,
typename TAllocator>
struct T_Append_not_specialized_for_type
40<T,TChar,TAllocator,typename std::enable_if<
41 std::is_same<decltype(std::declval<TAString<TChar,TAllocator>>().append(std::declval<const T&>()) ),
92template<
typename TAppendable,
95 typename TEnableIf =
void >
127template<
typename T,
typename TChar,
typename TAllocator,
typename TEnableIf=
void>
132template<
typename T,
typename TChar,
typename TAllocator>
134ATMP_VOID_IF(
ATMP_EQ(void, decltype( std::declval<T_Append<T, TChar,TAllocator>>()( std::declval<TAString<TChar,TAllocator> &>(),
135 std::declval<T const &>() ) ) ) )
136> :
public std::true_type {};
140#define ALIB_STRINGS_APPENDABLE_TYPE(TYPE) \
141namespace alib::strings { \
142 template<> struct T_Append<TYPE, alib::character, alib::lang::HeapAllocator> \
144 ALIB_API void operator()( TAString<alib::character, alib::lang::HeapAllocator>& target, const TYPE src ); \
147#define ALIB_STRINGS_APPENDABLE_TYPE_N(TYPE) \
148namespace alib::strings { \
149 template<> struct T_Append<TYPE, alib::nchar, alib::lang::HeapAllocator> \
151 ALIB_API void operator()( TAString<alib::nchar, alib::lang::HeapAllocator>& target, const TYPE src ); \
154#define ALIB_STRINGS_APPENDABLE_TYPE_W(TYPE) \
155namespace alib::strings { \
156 template<> struct T_Append<TYPE, alib::wchar, alib::lang::HeapAllocator> \
158 ALIB_API void operator()( TAString<alib::wchar, alib::lang::HeapAllocator>& target, const TYPE src ); \
161#define ALIB_STRINGS_APPENDABLE_TYPE_DEF(TYPE, IMPL) \
162void alib::strings::T_Append<TYPE,alib::character, alib::lang::HeapAllocator> \
163 ::operator()( TAString<alib::character, alib::lang::HeapAllocator>& target, const TYPE src) { IMPL }
165#define ALIB_STRINGS_APPENDABLE_TYPE_DEF_N(TYPE, IMPL) \
166void alib::strings::T_Append<TYPE,alib::nchar, alib::lang::HeapAllocator> \
167 ::operator()( TAString<alib::nchar, alib::lang::HeapAllocator>& target, const TYPE src) { IMPL }
169#define ALIB_STRINGS_APPENDABLE_TYPE_DEF_W(TYPE, IMPL) \
170void alib::strings::T_Append<TYPE,alib::wchar, alib::lang::HeapAllocator> \
171 ::operator()( TAString<alib::wchar, alib::lang::HeapAllocator>& target, const TYPE src) { IMPL }
174#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE(TYPE, IMPL) \
175namespace alib::strings { \
176 template<> struct T_Append<TYPE,alib::character, alib::lang::HeapAllocator> \
178 void operator()( TAString<alib::character, alib::lang::HeapAllocator>& target, const TYPE& src ){ IMPL} \
181#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE_N(TYPE, IMPL) \
182namespace alib::strings { \
183 template<> struct T_Append<TYPE,alib::nchar, alib::lang::HeapAllocator> \
185 void operator()( TAString<alib::nchar, alib::lang::HeapAllocator>& target, const TYPE& src ){ IMPL} \
188#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE_W(TYPE, IMPL) \
189namespace alib::strings { \
190 template<> struct T_Append<TYPE,alib::wchar, alib::lang::HeapAllocator> \
192 void operator()( TAString<alib::wchar, alib::lang::HeapAllocator>& target, const TYPE& src ){ IMPL} \
289template<
typename TChar,
typename TAllocator>
290class TAString :
public TString<TChar>
291 ,
public lang::AllocatorMember<TAllocator>
312 #if ALIB_DEBUG_STRINGS
392 :
base ( extBuffer, 0 )
418 :
base( extBuffer, 0 )
477 if ( !move.HasInternalBuffer() )
499 #if ALIB_DEBUG_STRINGS
501 move.buffer=
nullptr;
515 template <
class TAppendable>
536 ,
size_t(
capacity + 1) *
sizeof(TChar)
561 template<
typename TCharArray>
inline operator TCharArray ()
const;
579 template<
typename TCharArray>
inline explicit operator TCharArray ()
const;
615 explicit operator T ()
const
645 return Reset().
Append( copy.Buffer(), copy.Length() );
744 #if ALIB_DEBUG_STRINGS
746 "STRINGS",
"Previous allocation request was too short" )
752 #if ALIB_DEBUG_STRINGS
845 return base::vbuffer;
865 template<
typename TCheck =CHK>
870 "STRINGS",
"Can't write character '\0'" )
871 if constexpr ( TCheck::value )
875 *(base::vbuffer + idx )= c;
880 "STRINGS",
"Non-checking invocation: ",
"Index out of range" )
881 *(base::vbuffer + idx )= c;
901 "STRINGS",
"Index out of bounds" )
903 return base::vbuffer[idx];
907 using base::operator[];
927 "STRINGS",
"Negative AString length requested" )
929 "STRINGS",
"Requested AString length exceeds capacity" )
947 "STRINGS",
"Detected AString length exceeds capacity" )
974 "STRINGS",
"Negative AString length requested" )
976 "STRINGS",
"Increase of AString length requested" )
977 #if ALIB_DEBUG_STRINGS
1005 template <
typename TCheck= CHK,
typename TCharSrc >
1008 template <
typename TCheck= CHK,
typename TCharSrc >
1027 template <
typename TCheck= CHK>
1033 if constexpr ( TCheck::value )
1039 if ( srcLength <= 0 )
1052 "Nullptr passed with non-checking method version." )
1080 template <
typename TCheck= CHK>
1083 if constexpr ( TCheck::value )
1087 if ( src.base::AdjustRegion( regionStart, regionLength ) )
1102 && regionStart + regionLength <= src.
Length(),
"STRINGS",
1103 "Non-checking invocation: ",
"Invalid region given" )
1125 template <
typename TCheck= CHK>
1128 return Append( src, regionStart, regionLength );
1150 template<
typename TC,
typename TV,
typename TAlloc2,
typename If>
1151 friend struct T_Append_not_specialized_for_type;
1165 append(
const T& src )
1167 T_Append<ATMP_RCVR(T), TChar,TAllocator>()( *
this, src );
1177 append(
const T& src )
1179 T_Append<ATMP_RCVP(T)* , TChar,TAllocator>()( *
this, src );
1190 append(
const T& src )
1192 using TSrc=
typename characters::TT_CharArrayType<
ATMP_RCVR(T)>::TChar;
1193 using TCA=
typename characters::T_CharArray<
ATMP_RCVR(T),TSrc>;
1194 const TSrc* buf= TCA::Buffer( src );
1195 if ( TCheck::value && !buf )
1208 append(
const T& src )
1210 using TSrc=
typename characters::TT_ZTCharArrayType<
ATMP_RCVR(T)>::TChar;
1211 using TCA=
typename characters::T_ZTCharArray<
ATMP_RCVR(T),TSrc>;
1212 const TSrc* buf= TCA::Buffer( src );
1213 if ( TCheck::value && !buf )
1225 template<
typename TCheck= CHK>
1226 bool append(TChar src )
1228 if ( TCheck::value && src == 0 )
1238 characters::TT_IsChar<
ATMP_RCVR(T)>::value )
1241 if ( TCheck::value && src == 0 )
1247 if constexpr (
ATMP_EQ( TChar, TOtherChar) )
1250 base::vbuffer[
base::length++ ]=
static_cast<TChar
>( src );
1261 mbLength= WideCharToMultiByte( CP_UTF8, 0, &wc, 1,
1263 MB_LEN_MAX * 2, NULL, NULL );
1264 if ( mbLength <= 0 )
1266 ALIB_DBG( DWORD error= GetLastError(); )
1267 ALIB_WARNING(
"STRINGS",
"Cannot convert wide character string to UTF-8. Error: ",
1268 ( error == ERROR_INSUFFICIENT_BUFFER ?
"ERROR_INSUFFICIENT_BUFFER"
1269 : error == ERROR_INVALID_FLAGS ?
"ERROR_INVALID_FLAGS."
1270 : error == ERROR_INVALID_PARAMETER ?
"ERROR_INVALID_PARAMETER"
1271 : error == ERROR_NO_UNICODE_TRANSLATION ?
"ERROR_NO_UNICODE_TRANSLATION"
1272 :
static_cast<const char*
>(
NAString( error ) ) ) )
1276 mbLength= wctomb(
reinterpret_cast<nchar*
>(base::vbuffer)
1280 if ( mbLength <= 0 )
1328 template <
typename TCheck= CHK,
typename TAppendable>
1331 static_assert( T_Append_not_specialized_for_type<TAppendable,TChar,TAllocator>::value,
1332 "See Programmer's manual of ALib Module Strings for information about "
1333 "how to specialize T_Append for custom types to mitigate this error. "
1334 "More compiler errors might follow." );
1335 append<TCheck>( src );
1351 template <
typename TCheck= CHK,
class TAppendable >
1364 template <
class TAppendable>
1396 template <
typename TCheck= CHK,
typename TAppendable>
1433 template <
typename TCheck= CHK>
1438 if constexpr ( TCheck::value )
1446 "STRINGS",
"Non-checking invocation: ",
"Illegal parameters" )
1456 base::vbuffer + pos + srcLength );
1472 template <
typename TCheck= CHK>
1475 if constexpr ( TCheck::value )
1482 "Non-checking invocation: ",
"Negative quantity given" )
1505 template <
typename TCheck= CHK>
1508 if constexpr ( TCheck::value )
1516 "Non-checking invocation: ",
"Negative quantity given" )
1518 "Non-checking invocation: ",
"Illegal position given" )
1528 base::vbuffer + pos + qty );
1557 template <
typename TCheck= CHK >
1564 if constexpr ( TCheck::value )
1570 if ( (regionEnd= regionStart + regionLength) >=
base::length )
1580 && regionLength >= 0,
"STRINGS",
1581 "Non-checking invocation: ",
"Illegal arguments" )
1584 if ( (regionEnd= regionStart + regionLength) >=
base::length )
1595 base::vbuffer + regionStart );
1614 template <
typename TCheck= CHK >
1619 if constexpr ( TCheck::value )
1621 if ( regionLength <= 0 )
1632 "STRINGS",
"Non-checking invocation: ",
1633 "Region length out of range." )
1672 template <
typename TCheck= CHK >
1677 if constexpr ( TCheck::value )
1679 if ( regionLength > 0 )
1690 "STRINGS",
"Non-checking invocation: ",
1691 "Region length out of range" )
1808 template <
typename TCheck= CHK>
1812 if constexpr ( TCheck::value )
1819 "Non-checking invocation: ",
"Source string is nulled" )
1825 "Non-checking invocation: ",
"Invalid region given" )
1840 base::vbuffer + regionStart + src.
Length() );
1843 src.
CopyTo( base::vbuffer + regionStart );
1864 template <
typename TCheck= CHK>
1867 if constexpr ( TCheck::value )
1879 "Non-checking invocation: ",
"Invalid region given" )
1942 template <
typename TCheck= CHK>
1945 if constexpr ( TCheck::value )
1957 "Non-checking invocation: ",
"Invalid region given" )
1976 template <
typename TCheck= CHK>
1979 if constexpr ( TCheck::value )
1991 "Non-checking invocation: ",
"Invalid region given" )
2009 template <
typename TCheck= CHK>
2012 if constexpr ( TCheck::value )
2024 "Non-checking invocation: ",
"Invalid region given" )
2086template<
typename TChar,
typename TAllocator>
2087class TStringLengthResetter
2096 void*
operator new (size_t);
2099 void*
operator new (size_t,
void*);
2102 void*
operator new[](size_t);
2105 void*
operator new[](size_t,
void*);
2114 , originalLength(pAString.Length())
2119 { aString.ShortenTo(originalLength); }
2126 { aString.ShortenTo(originalLength); }
2131 {
return originalLength; }
2135#define ALIB_STRING_RESETTER(astring) \
2136alib::strings::TStringLengthResetter< \
2137 std::remove_reference<decltype(astring)>::type::CharType, \
2138 std::remove_reference<decltype(astring)>::type::AllocatorType > \
2139 ALIB_IDENTIFIER(astring)(astring)
2144#if defined(_MSC_VER)
2145 #pragma warning( pop )
TAString & ShortenTo(integer newLength)
constexpr TAString()
Constructs an empty, nulled AString (does not allocate a buffer).
constexpr const TChar * Terminate() const
ALIB_API integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
TAString & _(const TAppendable &src)
typename base::template TRandomAccessIterator< TChar > Iterator
bool dbgWarnWhenExternalBufferIsReplaced
ALIB_API void GrowBufferAtLeastBy(integer minimumGrowth)
std::reverse_iterator< Iterator > ReverseIterator
Same as Iterator, but working from the end to the start of the string.
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)
lang::AllocatorMember< TAllocator > allocBase
The allocator type that TAllocator specifies.
TAString & Append(const TCharSrc *src, integer srcLength)
TAString & DeleteStart(const TString< TChar > &deleteIfMatch)
TAString & operator<<(const TAppendable &src)
ALIB_API integer TrimAt(integer idx, const TCString< TChar > &trimChars=TT_CStringConstants< TChar >::DefaultWhitespaces())
constexpr TAString(TAllocator &pAllocator, TChar *extBuffer, integer extBufferSize)
TAString & ToUpper(integer regionStart=0, integer regionLength=MAX_LEN)
TAString & DeleteEnd(const TString< TChar > &deleteIfMatch)
void SetNull()
Invokes SetBuffer(0).
TAString(const TAppendable &src)
TAString & Append(const TChar *src, integer srcLength)
TAString & operator=(const TAString ©)
TAllocator AllocatorType
Exposes the allocator type specified by template parameter TAllocator.
TAString & InsertChars(TChar c, integer qty, integer pos)
TAString & TrimEnd(const TCString< TChar > &trimChars=TT_CStringConstants< TChar >::DefaultWhitespaces())
void SetCharAt(integer idx, TChar c)
TAString & ReplaceSubstring(const TString< TChar > &src, integer regionStart, integer regionLength)
integer debugLastAllocRequest
TAString & TrimStart(const TCString< TChar > &trimChars=TT_CStringConstants< TChar >::DefaultWhitespaces())
TAString & Append(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
TAString & InsertChars(TChar c, integer qty)
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
TAString & DeleteStart(integer regionLength)
ALIB_API TAString & Trim(const TCString< TChar > &trimChars=TT_CStringConstants< TChar >::DefaultWhitespaces())
TChar & operator[](integer idx)
TAString(TAString &&move) noexcept
void DbgDisableBufferReplacementWarning()
void EnsureRemainingCapacity(integer spaceNeeded)
constexpr TAString(TAllocator &pAllocator)
ALIB_API void SetBuffer(integer newCapacity)
~TAString() noexcept
Destructs an AString object. An internally allocated buffer will be deleted.
TAString & Append(const TAppendable &src)
void SetLength(integer newLength)
TString< TChar > base
The base string-type.
TAString & Reverse(integer regionStart=0, integer regionLength=MAX_LEN)
TAString & InsertAt(const TString< TChar > &src, integer pos)
TAString & ReplaceRegion(TChar c, integer regionStart, integer regionLength)
TAString & Reset(const TAppendable &src)
~TStringLengthResetter()
Destructor. Restores the string's original length.
integer originalLength
The The original length of the string.
TAString< TChar, TAllocator > & aString
The AString to reset.
TStringLengthResetter(TAString< TChar, TAllocator > &pAString)
constexpr bool IsNull() const
ALIB_WARNINGS_RESTORE ConstReverseIterator rbegin() const
constexpr bool IsNotEmpty() const
ConstReverseIterator rend() const
constexpr integer Length() const
constexpr bool IsNotNull() const
integer IndexOfAny(const TString &needles, integer startIdx=0) const
integer CopyTo(TChar *dest) const
bool AdjustRegion(integer ®ionStart, integer ®ionLength) const
ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE ConstIterator end() const
ConstIterator begin() const
bool EndsWith(const TString &needle) const
bool StartsWith(const TString &needle) const
constexpr const TChar * Buffer() const
integer LastIndexOfAny(const TString &needles, integer startIdx=MAX_LEN) 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 ATMP_T_IF(T, Cond)
#define ALIB_DEBUG_STRINGS
void Reverse(TChar *src, integer length)
integer Length(const TChar *cstring)
@ ExplicitOnly
Allows explicit construction of objects from character array data.
@ Implicit
Allows implicit (and explicit) construction of objects from character array data.
void Move(const TChar *src, integer length, TChar *dest)
void Copy(const TChar *src, integer length, TChar *dest)
void Fill(TChar *dest, integer length, TChar value)
Case
Denotes upper and lower case character treatment.
@ KeepWithSender
Keeps responsibility, e.g., when passing an object.
static constexpr integer MAX_LEN
The maximum length of an ALib string.
characters::wchar wchar
Type alias in namespace alib.
strings::TAString< nchar, lang::HeapAllocator > NAString
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
static constexpr ConstructionType Construction
static TString Construct(const TChar *array, integer length)
static TString Construct(const TChar *array, integer length)
TAllocator & GetAllocator() const noexcept
void operator()(TAString< TChar > &target, const TAppendable &src)