ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
astring.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of module \alib_strings of the \aliblong.
4 *
5 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6 * Published under \ref mainpage_license "Boost Software License".
7 **************************************************************************************************/
8#ifndef HPP_ALIB_STRINGS_ASTRING
9#define HPP_ALIB_STRINGS_ASTRING 1
10
11#ifndef HPP_ALIB_STRINGS_CSTRING
13#endif
14
15#if !defined(HPP_ALIB_LANG_PLATFORM_INCLUDES)
17#endif
18
19// With MS compiler, switch off "conditional expression is constant" for using a constant template
20// parameter to select checking vs. non-checking method versions
21#if defined(_MSC_VER)
22 #pragma warning( push )
23 #pragma warning( disable : 4127 )
24#endif
25
26namespace alib { namespace strings {
27
28// #################################################################################################
29// forward declarations
30// #################################################################################################
31template<typename TChar> class TAString;
32
33
34#if !defined(ALIB_DOX)
35// Used to create an error message if a type can not be appended to an AString
36template<typename T, typename TChar, typename If= void> struct T_Append_not_specialized_for_type
37: std::false_type {};
38
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&>()) ),
42 bool>::value>::type>
43: std::true_type {};
44#endif
45
46// #################################################################################################
47// template struct T_Append
48// #################################################################################################
49
50/** ************************************************************************************************
51 * This is a type-traits functor that allows to make custom types "appendable" to objects of
52 * type \b AString.
53 *
54 * Specializations of this struct have to implement
55 * \alib{strings;T_Append::operator()(TAString<TChar>&,const TAppendable&);operator()}, which is
56 * invoked by method \alib{strings;TAString::Append;AString::Append}, when an instance of the type
57 * in question is passed.
58 *
59 * For user defined string types that get adopted to \alib string system using a specialization of
60 * struct \alib{characters;T_CharArray}, no specialization of this functor is needed, because method
61 * \b AString::Append will accept such types likewise.
62 *
63 * The third template parameter of this struct, \p{TEnableIf}, may be used to perform templated
64 * specializations based on a condition evaluated with \c std::enable_if (or similar TMP mechanics).
65 *
66 * \note
67 * This struct is called a "functor" because its single member is
68 * \alib{strings;T_Append::operator()(TAString<TChar>&,const TAppendable&);operator()}.
69 * This is different to other type-traits structs defined by \alib, which demand to implement
70 * one or more static methods with specializations. As
71 * \alib{strings;T_Append::operator()(TAString<TChar>&,const TAppendable&);operator()} must not be
72 * static, the internal call to this operator is done by creating a temporary object of this
73 * "functor struct" and calling the operator on that.<br>
74 * The result in respect to the generated code is with both approaches the same. Using a functor
75 * here, is just a design decision.
76 *
77 * \see
78 * For details consult chapter \ref alib_strings_assembly_ttostring of the Programmer's Manual
79 * of module \alib_strings.
80 *
81 * \see
82 * The documentation of built-in specializations for \alib types are collected in
83 * sub-namespace \ref alib::strings::APPENDABLES.
84 *
85 * # Reference Documentation #
86 * @tparam TAppendable The type that should be made compatible with method
87 * \alib{strings::TAString;Append(const TAppendable&);TAString<TChar>::Append}.
88 * @tparam TChar The character type of the target \b AString.
89 * Defaults to \alib{characters;character}.
90 * @tparam TEnableIf Optional TMP parameter to allow templated specializations.
91 **************************************************************************************************/
92template< typename TAppendable,
93 typename TChar = alib::characters::character,
94 typename TEnableIf = void >
96{
97 #if defined(ALIB_DOX)
98 /** ********************************************************************************************
99 * This operator is invoked on a temporary object of this type by
100 * \alib{strings;TAString::Append(const TAppendable&);AString::Append}, when an object of type
101 * \p{TAppendable} is passed.
102 *
103 * Usually, specializations of this operator append a string representation of \p{src} to
104 * \p{target}. Special "appendable types" might modify \p{target} in other, arbitrary ways.
105 *
106 * @param target The target string.
107 * @param src The source object.
108 **********************************************************************************************/
109 void operator()( TAString<TChar>& target, const TAppendable& src );
110
111 #endif // doxygen
112};
113
114
115/** ************************************************************************************************
116 * Helper struct that inherits \c std::true_type if functor \alib{strings;T_Append} is specialized
117 * for type \p{T}, otherwise \c std::false_type.
118 *
119 * @tparam T The type to check.
120 * @tparam TChar The character type of the \alib{strings;TAString;AString} that \p{T} is
121 * asked to be appendable to.
122 * @tparam TEnableIf Used for conditional specializations of this struct.
123 * ************************************************************************************************/
124template<typename T, typename TChar, typename TEnableIf= void> struct TT_IsAppendable : public std::false_type {};
125
126#if !defined(ALIB_DOX)
127template<typename T, typename TChar> struct TT_IsAppendable<T, TChar,
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 {};
131
132
133#endif
134
135#define ALIB_STRINGS_APPENDABLE_TYPE(TYPE) \
136namespace alib::strings { \
137 template<> struct T_Append<TYPE, alib::character> \
138 { \
139 ALIB_API void operator()( TAString<alib::character>& target, const TYPE src ); \
140 }; } \
141
142#define ALIB_STRINGS_APPENDABLE_TYPE_N(TYPE) \
143namespace alib::strings { \
144 template<> struct T_Append<TYPE, alib::nchar> \
145 { \
146 ALIB_API void operator()( TAString<alib::nchar>& target, const TYPE src ); \
147 }; } \
148
149#define ALIB_STRINGS_APPENDABLE_TYPE_W(TYPE) \
150namespace alib::strings { \
151 template<> struct T_Append<TYPE, alib::wchar> \
152 { \
153 ALIB_API void operator()( TAString<alib::wchar>& target, const TYPE src ); \
154 }; } \
155
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 } \
159
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 } \
163
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 } \
167
168
169#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE(TYPE, IMPL) \
170namespace alib::strings { \
171 template<> struct T_Append<TYPE,alib::character> \
172 { \
173 void operator()( TAString<alib::character>& target, const TYPE& src ){ IMPL} \
174 }; } \
175
176#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE_N(TYPE, IMPL) \
177namespace alib::strings { \
178 template<> struct T_Append<TYPE,alib::nchar> \
179 { \
180 void operator()( TAString<alib::nchar>& target, const TYPE& src ){ IMPL} \
181 }; } \
182
183#define ALIB_STRINGS_APPENDABLE_TYPE_INLINE_W(TYPE, IMPL) \
184namespace alib::strings { \
185 template<> struct T_Append<TYPE,alib::wchar> \
186 { \
187 void operator()( TAString<alib::wchar>& target, const TYPE& src ){ IMPL} \
188 }; } \
189
190
191/** ************************************************************************************************
192 * Specializes base class
193 * \alib{strings;TString;String} to implement mutable character strings using writable and
194 * extendable buffer memory.
195 *
196 * <b>Construction:</b><br>
197 * Construction is described in Programmer's Manual, section
198 * \ref alib_strings_cc_construction_astring.
199 *
200 *
201 *<b>Buffer Management:</b><br>
202 * There are two possible types of buffers:
203 * - <b>Internal buffers</b><br>
204 * This is the standard case and implements a buffer that is allocated from
205 * <em>free memory</em> (aka 'the heap') that eventually grows over time and never shrinks, unless
206 * explicitly demanded by the user of the class. Those buffers are deleted when objects
207 * of this type are deleted.
208 * - <b>External buffers</b><br>
209 * Set with overloaded method #SetBuffer(TChar*, integer, integer, lang::Responsibility).
210 * External buffers are not managed by this class. However, if their capacity is exceeded, they
211 * will automatically become replaced by an internal buffer.
212 * Such replacement by default produces a \ref ALIB_WARNING "ALib warning" with debug builds.
213 * In situations that buffer replacement is accepted, warnings can be disabled with method
214 * #DbgDisableBufferReplacementWarning.
215 *
216 * Method #SetBuffer provides a boolean parameter that also allows to let an object of this
217 * class take control on a buffer provided from outside. In this case, the buffer is considered an
218 * internal buffer, rather than an external one.
219 *
220 * The default constructor creates a \e nulled \b AString which does not dispose about an allocated
221 * buffer, yet.
222 * Destruction will free the currently allocated buffer - if internal.
223 *
224 *
225 * \anchor alib_ns_strings_astring_copymove
226 *<b>Copy/Move Constructor and Assignment</b><br>
227 * The class provides the minimum equipment to be usable as member type of standard containers like
228 * \c std::vector. This includes a copy and move constructor as well as a copy assignment operator.
229 * Nevertheless, this class is not guaranteed to perform well when used with container types
230 * and such use should be avoided if possible.<br>
231 * Outside of containers, the automatic C++ copy and move construction semantics should be avoided.
232 * For example, the move constructor, grabs the buffer of a given movable \b %AString, as long
233 * as this given object does not use an external buffer. If it does, the contents of the
234 * movable object is copied like in the copy constructor.
235 *
236 * Consequently, objects of this class should have a well defined scope and not be copied and moved like
237 * the lightweight string types. A move assignment operator is not given. The rationale for this
238 * design decision is that usually, a "more temporary" string would be assigned to a "less temporary"
239 * one. In this case, it would not be helpful to replace the already allocated storage of the
240 * assignee.
241 *
242 * On the same token, besides the copy assignment, no other assignment operators are given. Instead,
243 * method #Reset(const TAppendable&) is to be used to clear the existing buffer and insert new
244 * string content. This helps to distinguish \b AString variables from those of the lightweight
245 * string types as shown in the following snippet:
246 *
247 * string1= "Hello"; // Can't be an AString. Rather String, Substring or CString
248 * string2.Reset("World"); // Obviously an AString. The given string is copied!
249 *
250 * \anchor alib_ns_strings_astring_write_access
251 * <b>Writing directly into the Buffer:</b><br>
252 * Parent class \alib{strings;TString;String} holds its protected field
253 * \alib{strings;TString::buffer;buffer} in an anonymous C++ union of two pointers,
254 * one typed <em>const char*</em> and the other <em>char*</em>.
255 * This class exposes the non-constant buffer pointer of that union with method #VBuffer.
256 * This allows users of this class to <em>freely</em> operate on the buffer.
257 * Of-course, it is up to the programmer that the integrity of the instance is kept intact and
258 * that also the #Capacity of the buffer must not be exceeded.
259 * In the case that the string's length is changed, method #SetLength needs to be
260 * used to notify such change with the \b AString object. The latter of-course is invokable only
261 * on mutable objects, while method #VBuffer is declared \c const.
262 *
263 * In addition to this, a bunch of methods allow the modification of single characters.
264 * #operator[] is extended by a non-const version that returns a reference to a character instead
265 * of just the character value.
266 *
267 * \anchor alib_ns_strings_astring_appendto
268 * <b>Appending Objects to AStrings:</b><br>
269 * This class is used to provide a global concept of having a sort of <b>"ToString"</b> method
270 * with any C++ class. For this, the class provides method #Append, which uses template
271 * meta programming to accept types with a corresponding specialization of functor
272 * \alib{strings;T_Append}.
273 *
274 * The concept is described in detail with chapter \ref alib_strings_assembly_ttostring
275 * of this module's \ref alib_mod_strings "Programmer's Manual".
276 *
277 *
278 * @tparam TChar The character type.<br>
279 * Alias names for specializations of this class using character types
280 * \alib{characters;character}, \alib{characters;nchar}, \alib{characters;wchar},
281 * \alib{characters;xchar}, \alib{characters;complementChar} and \alib{characters;strangeChar}
282 * are provided in namespace #alib with type definitions \alib{AString}, \alib{NAString},
283 * \alib{WAString}, \alib{XAString}, \alib{ComplementAString} and \alib{StrangeAString}.
284 **************************************************************************************************/
285template<typename TChar>
286class TAString : public TString<TChar>
287{
288 // #############################################################################################
289 // Protected fields
290 // #############################################################################################
291 protected:
292 /**
293 * The current size of the buffer excluding the trailing <c>'\0'</c>.
294 * If no buffer is allocated, this field is \c 0.
295 * If an external Buffer not managed by this class is used, then the size of that buffer is
296 * stored as a negative value. Method #Capacity therefore returns the absolute value
297 * of this field.
298 */
300
301 /** ############################################################################################
302 * @name Debug Methods/Types
303 #############################################################################################*/
304 #if ALIB_DEBUG_STRINGS
305 protected:
306 /**
307 * Used to check if previous grow request was exactly what is now the length.<br>
308 * This field is available only if code selection symbol \ref ALIB_DEBUG_STRINGS
309 * is set.
310 */
312
313 /**
314 * Checks this object's state. This method is internally invoked with almost
315 * every other method of this class, but only if compiler symbol
316 * \ref ALIB_DEBUG_STRINGS is \c true.<br>
317 * Invocations to this method should be performed using macro
318 * \ref ALIB_STRING_DBG_CHK.<br>
319 *
320 * \see
321 * For (a little) more information see
322 * \ref alib_strings_details_debugging of this module's
323 * \ref alib_mod_strings "Programmer's Manual"
324 */
325 public:
326 void dbgCheck() const;
327
328 #endif
329
330 protected:
331 /**
332 * If \c true, a \ref ALIB_WARNING "warning" is issued when an external buffer, whose
333 * life-cycle is not controlled by this instance gets replaced.
334 * This field exists only with debug-compilations of this class.
335 *
336 * \see
337 * See method #DbgDisableBufferReplacementWarning for more information.
338 */
339 #if ALIB_DEBUG
341 #endif
342
343 public:
344 /**
345 * Used to disable warnings that are by default raised in debug-compilations of
346 * method #SetBuffer.
347 *
348 * \note
349 * In release-compilations this inline method is empty and will be optimized out.
350 *
351 * \see See method #SetBuffer for more information.
352 */
357
358 protected:
359 /** ****************************************************************************************
360 * Constructs an \b %AString with the given external buffer.
361 * The given buffer's life-cycle is considered to be managed externally.<br>
362 * This constructor is protected and provided for derived classes that dispose about
363 * their own buffer.
364 *
365 * \note
366 * Protected access was given to this method also to avoid misunderstandings that this
367 * constructor is not for providing copyable string data. If the functionality of this
368 * constructor is needed, it can simply be imitated by
369 * - default construction and
370 * - immediate invocation of #SetBuffer(TChar*, integer, integer, lang::Responsibility).
371 *
372 * @param extBuffer The external buffer to use.
373 * @param extBufferSize The capacity of the given buffer.
374 ******************************************************************************************/
375 constexpr
376 explicit TAString( TChar* extBuffer, integer extBufferSize )
377 : TString<TChar>( extBuffer, 0 )
378 , capacity (- (extBufferSize - 1))
380 ,debugLastAllocRequest(extBufferSize-1)
381 #endif
382 {}
383
384 /** ############################################################################################
385 * @name Constructors, Destructor and Assignment
386 #############################################################################################*/
387 public:
388 /** ****************************************************************************************
389 * Constructs an empty, \e nulled \b %AString (does not allocate a buffer).
390 ******************************************************************************************/
391 explicit
392 constexpr
394 : TString<TChar>(nullptr, 0)
395 , capacity (0)
396 {}
397
398 /** ****************************************************************************************
399 * Copy constructor that allocates memory and copies the contents of the given object.
400 * @param copy The object to copy.
401 ******************************************************************************************/
402 explicit
403 TAString(const TAString& copy)
404 : TString<TChar>(nullptr, 0)
405 , capacity (0)
406 {
407 ALIB_DBG( dbgWarnWhenExternalBufferIsReplaced= copy.dbgWarnWhenExternalBufferIsReplaced; )
408 Append( copy );
409 }
410
411 /** ****************************************************************************************
412 * Move constructor.
413 * See \ref alib_ns_strings_astring_copymove "Copy/Move Constructor and Assignment"
414 * for details.
415 * @param move The object to move.
416 ******************************************************************************************/
417 TAString(TAString&& move) noexcept
418 {
419 // given move object has external buffer: we have to copy
420 if ( !move.HasInternalBuffer() )
421 {
422 TString<TChar>::buffer= nullptr;
424 capacity= 0;
425 ALIB_DBG( dbgWarnWhenExternalBufferIsReplaced= move.dbgWarnWhenExternalBufferIsReplaced; )
426 Append( move );
427 return;
428 }
429
430 // copy values
433 capacity= move.capacity;
434
435 // clean moved object (buffer does not need to be nulled)
436 move.length=
437 move.capacity= 0;
438
439 // in debug mode, more copying and more destructor prevention is needed
440 #if ALIB_DEBUG
441 dbgWarnWhenExternalBufferIsReplaced= move.dbgWarnWhenExternalBufferIsReplaced;
442 #if ALIB_DEBUG_STRINGS
443 debugLastAllocRequest= move.debugLastAllocRequest;
444 move.buffer= nullptr;
445 #endif
446 #endif
447 }
448
449
450 /** ****************************************************************************************
451 * Constructs the object and uses #Append to create a string representation of the given
452 * object.
453 *
454 * @tparam TAppendable The type of parameter \p{source} that has a specialization of
455 * functor \alib{strings;T_Append}.
456 * @param src The source object to append to this string.
457 ******************************************************************************************/
458 template <class TAppendable>
459 explicit
460 TAString (const TAppendable& src )
461 : TString<TChar>(nullptr, 0)
462 , capacity (0)
463 {
464 Append( src );
465 }
466
467 /** ****************************************************************************************
468 * Destructs an \b %AString object. An internally allocated buffer will be deleted.
469 ******************************************************************************************/
470 ~TAString() noexcept
471 {
474 if ( HasInternalBuffer() )
475 std::free( const_cast<void*>(reinterpret_cast<const void*>( TString<TChar>::buffer
477 - 16
478 #endif
479 )) );
481 }
482
483 #if defined(ALIB_DOX)
484 /** ****************************************************************************************
485 * \b Implicit cast operator to objects of type \p{TCharArray}.<br>
486 * This operator is available for all custom types that have an accordingly specialized
487 * version of TMP struct \alib{characters;T_CharArray} and/or
488 * \alib{characters;T_ZTCharArray} defined.
489 * In the latter case, method #Terminate is invoked prior to the conversion.
490 *
491 * The cast is applicable only if no specialization of TMP struct
492 * \alib{strings;T_SuppressAutoCast} auto casts exists, that suppresses implicit casts.
493 *
494 * More information about casting \alib string types to other types is provided with chapter
495 * \ref alib_strings_cc_cast this module's \ref alib_mod_strings "Programmer's Manual".
496 *
497 * @tparam TCharArray The custom type to implicitly convert this object to.
498 * @return A value of custom string type.
499 ******************************************************************************************/
500 template<typename TCharArray> inline operator TCharArray () const;
501
502 /** ****************************************************************************************
503 * \b Explicit cast operator to objects of type \p{TCharArray}.<br>
504 * This operator is available for all custom types that have an accordingly specialized
505 * version of TMP struct \alib{characters;T_CharArray} and/or
506 * \alib{characters;T_ZTCharArray} defined.
507 * In the latter case, method #Terminate is invoked prior to the conversion.
508 *
509 * The cast is applicable only if no specialization of TMP struct
510 * \alib{strings;T_SuppressAutoCast} auto casts exists, that suppresses explicit casts.
511 *
512 * More information about casting \alib string types to other types is provided with chapter
513 * \ref alib_strings_cc_cast this module's \ref alib_mod_strings "Programmer's Manual".
514 *
515 * @tparam TCharArray The custom type to explicitly convert this object to.
516 * @return A value of custom string type.
517 ******************************************************************************************/
518 template<typename TCharArray> inline explicit operator TCharArray () const;
519 #else
520
521 // ############################## casting back ######################################
522 ATMP_SELECT_IF_1TP(typename T,
525 operator T () const
526 {
528 }
529
530 ATMP_SELECT_IF_1TP(typename T,
534 explicit
535 operator T () const
536 {
538 }
539
540 ATMP_SELECT_IF_1TP(typename T,
543 && !T_SuppressAutoCast<TAString<TChar>,characters::ConstructionType::Implicit,ATMP_RCV(T)>::value )
544 operator T () const
545 {
546 Terminate();
548 }
549
550 ATMP_SELECT_IF_1TP(typename T,
552 && characters::T_ZTCharArray<T,TChar>::Construction == characters::ConstructionType::ExplicitOnly
553 && !T_SuppressAutoCast<TAString<TChar>,characters::ConstructionType::ExplicitOnly,ATMP_RCV(T)>::value )
554 explicit operator T () const
555 {
556 Terminate();
558 }
559
560 #endif // defined(ALIB_DOX)
561
562
563 /** ****************************************************************************************
564 * Copy assign operator.
565 * If the given other \b AString is \e nulled, this object becomes \e nulled. Otherwise,
566 * this string is cleared and the given other string is appended.
567 *
568 * \see
569 * For details why no other assignment operators exists for this class, note paragraph
570 * \ref alib_ns_strings_astring_copymove "Copy/Move Constructor and Assignment"
571 * of this class's reference documentation.
572 *
573 * @param copy The object to copy the contents from.
574 * @return \c *this to allow concatenated calls.
575 ******************************************************************************************/
577 {
578 if ( copy.IsNull() )
579 {
580 SetNull();
581 return *this;
582 }
583
584 return Reset().Append( copy.Buffer(), copy.Length() );
585 }
586
587 /** ############################################################################################
588 * @name Memory allocation and buffer access
589 #############################################################################################*/
590
591 /** ****************************************************************************************
592 * Resizes the buffer to meet exactly the given size.
593 *
594 * The following rules apply:
595 * - The string represented by this instance is copied to the new buffer.
596 * If this is larger than the new buffer size, the string is cut at the end to fit.
597 * - If the desired new size is \c 0, then the currently allocated buffer will be disposed
598 * and the object's state is \e nulled.
599 * - If the current buffer's life-cycle is managed externally (e.g. was set using
600 * #SetBuffer(TChar*,integer,integer,lang::Responsibility)
601 * with parameter \p{responsibility} being \c Responsibility::KeepWithSender), this method
602 * will replace the buffer by a new one, even if the new requested size is the same as
603 * the external buffer's size. In other words, the only case when this method does not
604 * replace the current buffer is when the current buffer's life-cycle is (already)
605 * internally managed and it has the same size than what is requested.
606 * - In this C++ version of \alib, the true allocation size is one character larger than
607 * what is given with parameter \p{newCapacity}.
608 * This allows method #Terminate to add a termination character without checking
609 * (and eventually reallocating and copying) an internally managed buffer.
610 *
611 * Any method of this class that extends the length of the string will directly or
612 * indirectly invoke this method, when the current buffer size is not sufficient.
613 * If a future string length, which is the result of more than one concatenation of data
614 * to an \b %AString is predictable, then it is advisable to reserve the allocated size
615 * prior to performing the planned concatenations, by invoking this method.
616 * This is to avoid unnecessary allocations and data copy operations.
617 *
618 * If an \ref SetBuffer(TChar*,integer,integer,lang::Responsibility) "external buffer" is set,
619 * in debug-compilations a \ref ALIB_WARNING "warning" is issued, because usually it
620 * is not wanted that an external buffer becomes replaced during the growth of a string.<br>
621 * Such warnings can be switched off using method #DbgDisableBufferReplacementWarning.
622 * For example, in some situation it might be taken into account that instances of derived
623 * type \alib{strings;TLocalString;LocalString} sometimes may grow more than average and
624 * in such case a heap-allocated buffer replaces a local one. By placing a call
625 * to method #DbgDisableBufferReplacementWarning, the code explicitly hints to that
626 * possibility and is well readable. In release-compilations no warnings are issued
627 * and method \b %DbgDisableBufferReplacementWarning is optimized out.
628 *
629 * @param newCapacity The new capacity of the internal buffer.
630 ******************************************************************************************/
631 ALIB_API void SetBuffer( integer newCapacity );
632
633 /** ****************************************************************************************
634 * This methods replaces the current buffer with the one provided.
635 *
636 * The following rules apply:
637 * - If a \c nullptr is provided still, the current buffer is released.
638 * - If provided buffer is not nullptr, its size provided with parameter \p{extBufferSize}
639 * has to be at least \c 1 for providing the space for a termination character.
640 * - After the operation, #Capacity will report \p{extBufferSize} <c>- 1</c>.
641 * - Optional parameter \p{responsibility} can be used to pass the responsibility for the
642 * deletion of the buffer to this object.
643 * - The length of the content provided with parameter \p{extLength} must not exceed
644 * the value of parameter \p{extBufferSize} \c -1.
645 * - In no event any data of an existing buffer is copied into the new one. The rationale
646 * here is that in most use cases, this is not needed. Should this be desired,
647 * then the contents has to be copied "manually" prior to invoking this method.
648 *
649 * The internal buffer allocation is performed with methods \c std::malloc, \c std::realloc
650 * and \c std::free. The latter two are also used on external buffers that are provided
651 * with this method if parameter \p{responsibility} is given as \b Responsibility::Transfer,
652 * because in this case such externally created buffer is considered an internal one.
653 * Consequently, it has to be assured that the given chunk of memory is "compatible" with these
654 * methods.
655
656 *
657 * @param extBuffer The external buffer to use.
658 * @param extBufferSize The size of the given buffer.
659 * @param extLength The length of any content located in the given buffer that should
660 * be used.
661 * Has to be smaller or equal to extBufferSize -1 to preserve
662 * space for a trailing '\0'.
663 * @param responsibility If \c Responsibility::Transfer, the given buffer will be deleted
664 * by this object when a new buffer is set or it is deleted itself.
665 * Defaults to \c Responsibility::KeepWithSender which denotes that
666 * the life-cycle of the given external buffer is managed elsewhere.
667 ******************************************************************************************/
669 void SetBuffer( TChar* extBuffer,
670 integer extBufferSize,
671 integer extLength = 0,
673
674 /** ****************************************************************************************
675 * Ensures that the capacity of the internal buffer meets or exceeds the actual length
676 * plus the given growth value.
677 *
678 * @param spaceNeeded The desired growth of the length of the string represented by this.
679 ******************************************************************************************/
681 {
682 #if ALIB_DEBUG_STRINGS
684 "STRINGS", "Previous allocation request was too short" )
685 #endif
686
687 if ( Capacity() < TString<TChar>::length + spaceNeeded )
688 GrowBufferAtLeastBy( spaceNeeded );
689
690 #if ALIB_DEBUG_STRINGS
692 #endif
693 }
694
695 /** ****************************************************************************************
696 * Increases the allocation size by either 50% of the current capacity or by the value
697 * provided, whichever is higher.
698 *
699 * @param minimumGrowth The desired minimum growth of length.
700 ******************************************************************************************/
701 void GrowBufferAtLeastBy( integer minimumGrowth );
702
703 /** ****************************************************************************************
704 * The size of the internal buffer (this is excluding the trailing \c '\0'character)
705 * which is reserved to terminate the string if needed.
706 * In other words, the internal memory available is the size returned here plus one.
707 *
708 * @return The size of the allocated buffer.
709 ******************************************************************************************/
711 {
712 return capacity >= 0 ? capacity
713 : -capacity;
714 }
715
716 /** ****************************************************************************************
717 * Returns \c true, if the buffer was allocated by this class itself. If the buffer was
718 * set using #SetBuffer(TChar*,integer,integer,lang::Responsibility) with parameter
719 * \p{responsibility} given as \c Responsibility::KeepWithSender (and not automatically
720 * replaced, yet, because it became too small) then \c false is returned.
721 * \note Derived class
722 * \alib{strings;TLocalString;LocalString} will report \c false here.
723 * This sounds wrong on the first sight, as the buffer is allocated by an 'internal'
724 * member. But from an AString's perspective, class <em>LocalString</em> works on
725 * an 'external' buffer.
726 *
727 * @return \c true if the buffer is internally allocated and will be deleted with the
728 * deletion of this object. False otherwise.
729 ******************************************************************************************/
730 bool HasInternalBuffer() const
731 {
732 return capacity > 0;
733 }
734
735 /** ****************************************************************************************
736 * Invokes \ref SetBuffer "SetBuffer(0)".
737 ******************************************************************************************/
738 void SetNull()
739 {
740 SetBuffer( 0 );
741 }
742
743 /** ****************************************************************************************
744 * Writes a zero-termination character <c>'\0'</c> to the end of the used part of the
745 * internal string buffer and returns the pointer to the start.
746 * In other words, this function returns the represented string as a \e "cstring".
747 *
748 * One implementation detail of this class is that it always ensures that the internal
749 * buffer's capacity is sufficient for a termination character. This way, using this
750 * method will not reallocate the string and the method can be invoked on constant objects.
751 *
752 * The explicit invocation of this method can often be omitted, due to the availability
753 * of the definition of an implicit cast operator to <c>const TChar</c>, which inlines
754 * a call to this method.
755 *
756 * @return The pointer to the zero-terminated character buffer.
757 ******************************************************************************************/
767
768 /** ############################################################################################
769 * @name Writable Buffer Access
770 #############################################################################################*/
771
772 /** ****************************************************************************************
773 * The internal buffer character array provided as non constant character pointer.
774 * \see Chapter
775 * \ref alib_ns_strings_astring_write_access "Write Access to the Buffer"
776 * of the reference documentation of this class.
777 *
778 * @return The internal buffer array.
779 ******************************************************************************************/
780 TChar* VBuffer() const
781 {
783 }
784
785 /** ****************************************************************************************
786 * Sets the character at the given index. A range check is performed. If this fails,
787 * nothing is done.
788 *
789 * \note
790 * The C++ language would allow to declare this method \c const, as it does not
791 * manipulate the data of the class itself but a character in the buffer pointer.<br>
792 * In exclamation cases, to manipulate the contents of <em>const %AString</em>, use
793 * method VBuffer() like in the following sample:
794 * \snippet "DOX_ALIB_STRINGS.cpp" DOX_ALIB_ASTRING_MODIFY_CONST_BUFFER
795 * <p>
796 *
797 * @tparam TCheck Performs a range check on the given index and a check for illegal setting
798 * of termination character '\0' anywhere else but at idx==length.
799 * @param idx The index of the character to write.
800 * @param c The character to write.
801 ******************************************************************************************/
802 template<bool TCheck =true>
803 void SetCharAt( integer idx, TChar c )
804 {
806 ALIB_ASSERT_ERROR( c != '\0' || idx==TString<TChar>::length,
807 "STRINGS", "Can't write character '\0'" )
808 if constexpr (TCheck)
809 {
810 if( (idx >= 0 && idx < TString<TChar>::length )
811 || ( c =='\0' && idx == TString<TChar>::length ) )
812 *(TString<TChar>::vbuffer + idx )= c;
813 }
814 else
815 {
816 ALIB_ASSERT_ERROR( idx >= 0 && idx < TString<TChar>::length,
817 "STRINGS", "Non-checking invocation: ", "Index out of range" )
818 *(TString<TChar>::vbuffer + idx )= c;
819 }
821 }
822
823 /** ****************************************************************************************
824 * Provides read/write access to single characters.
825 * Overrides \alib{strings;TString::operator[];String::operator[]} returning a reference to
826 * a \p{TChar} value, which allows to change the character stored.
827 *
828 * \attention
829 * No parameter check is performed (other than an assertions in debug-compilation of
830 * \alib). See \alib{strings;TString::operator[];String::operator[]} for details.
831 *
832 * @param idx The index of the character within this object's buffer.
833 * @returns If the character contained (or, if lvalue the one to set).
834 ******************************************************************************************/
836 {
837 ALIB_ASSERT_ERROR( idx >= 0 && idx < TString<TChar>::length ,
838 "STRINGS", "Index out of bounds" )
840 return TString<TChar>::vbuffer[idx];
842 }
843
844 using TString<TChar>::operator[];
845
846 /** ****************************************************************************************
847 * Sets a new length for this string.
848 *
849 * In debug-compilations, given \p{newLength} is checked to be positive and smaller or
850 * equal to the buffer's capacity.
851 *
852 * In the (frequent) situation that the given length is shorter (or equal) to the current
853 * length, for better readability, the use of method #ShortenTo instead of this method is
854 * recommended. Extending the length of the string should be done only in rare cases,
855 * when the string buffer was modified "externally" after retrieving it using
856 * #VBuffer.
857 *
858 * @param newLength The new length of the \b %AString. Must be between 0 and
859 * #Capacity.
860 ******************************************************************************************/
861 void SetLength( integer newLength )
862 {
863 ALIB_ASSERT_ERROR( newLength >= 0 ,
864 "STRINGS", "Negative AString length requested" )
865 ALIB_ASSERT_ERROR( newLength <= Capacity(),
866 "STRINGS", "Requested AString length exceeds capacity" )
867 TString<TChar>::length= newLength;
869 }
870
871 /** ****************************************************************************************
872 * Searches termination character <c>'\0'</c> and sets the corresponding length of the
873 * string.
874 * In debug-compilations, the detected length is smaller or equal to the buffer's capacity.
875 *
876 * This method may be used in the (seldom) situation, where the strings's buffer is
877 * exposed to other libraries (for example many operating system calls), which internally
878 * fill a given character buffer, but do not return it's length.
879 ******************************************************************************************/
881 {
884 "STRINGS", "Detected AString length exceeds capacity" )
886 }
887
888 /** ****************************************************************************************
889 * Sets the length of the string to a shorter (or equal) value.
890 *
891 * In release-compilations, this method has the same simple inline implementation as
892 * #SetLength, it just sets the internal field \b length to the given value.
893 * The reason for the method's existence is primarily readability of the code: The name
894 * expresses that the given \p{newLength} is shorter than the current length.
895 *
896 * In debug-compilations, an assertion is raised if the length provided is longer than
897 * the current length. An equal value is accepted.
898 *
899 * In situations when it is sure that a new length is equal or shorter to the existing
900 * one, the use of this method is recommended over the use of #SetLength.
901 * This is especially true for the frequent use case where a "base string" should be
902 * restored after one or more concatenations had been performed.
903 *
904 * @param newLength The new length of this \b %AString. Must be between 0 and the current
905 * length.
906 * @return \c *this to allow concatenated calls.
907 ******************************************************************************************/
909 {
910 ALIB_ASSERT_ERROR( newLength >= 0,
911 "STRINGS", "Negative AString length requested" )
913 "STRINGS", "Increase of AString length requested" )
914 TString<TChar>::length= newLength;
916 return *this;
917 }
918
919
920 /** ############################################################################################
921 * @name Appending Strings
922 #############################################################################################*/
923
924 /** ****************************************************************************************
925 * Appends an incompatible character array.
926 *
927 * @tparam TCharSrc The character type of the given array.
928 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
929 * If \c <false>, no nullptr check is done on parameter \p{src}.
930 * Also, this object would not loose a \e nulled state when the given
931 * cstring portion is empty.
932 * @param src A pointer to the start of the array to append.
933 * @param srcLength The length of the string.
934 *
935 * @return \c *this to allow concatenated calls.
936 ******************************************************************************************/
937 template <bool TCheck= true, typename TCharSrc >
938#if defined(ALIB_DOX)
939 TAString&
940#else
941 typename std::enable_if< characters::TT_IsChar<TCharSrc>::value
942 && !std::is_same<TCharSrc,TChar>::value, TAString&>::type
943#endif
944
945 Append( const TCharSrc* src, integer srcLength );
946
947 /** ****************************************************************************************
948 * Appends an array of the same character type.
949 *
950 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
951 * If \c <false>, no nullptr check is done on parameter \p{src}.
952 * Also, this object would not loose a \e nulled state when the given
953 * cstring portion is empty.
954 * @param src A pointer to the start of the array to append.
955 * @param srcLength The length of the string.
956 *
957 * @return \c *this to allow concatenated calls.
958 ******************************************************************************************/
959 template <bool TCheck= true>
960 TAString&
961 Append( const TChar* src, integer srcLength )
962 {
964
965 if constexpr ( TCheck )
966 {
967 if (!src)
968 return *this;
969
970 // check empty
971 if ( srcLength <= 0 )
972 {
973 // set "un-nulled"
975 SetBuffer( 15 );
976
977 return *this;
978 }
979 }
980 else
981 {
983 ALIB_ASSERT_ERROR( src || srcLength == 0, "STRINGS",
984 "Nullptr passed with non-checking method version." )
985 }
986
987 EnsureRemainingCapacity( srcLength );
991 TString<TChar>::length+= srcLength;
992
993 return *this;
994 }
995
996 /** ****************************************************************************************
997 * Appends a region of another \alib{strings;TString;String}.
998 * The checking version adjusts the given region to the bounds of the source string.
999 *
1000 * \note When using the non-checking version, parameter \p{regionLength} must be set
1001 * explicitly to the correct value (instead of using the default value).
1002 *
1003 * @tparam TCheck Chooses checking or non-checking implementation. Defaults to true.
1004 * @param src The \b %String to append.
1005 * @param regionStart The start of the region in \p{src} to append.
1006 * @param regionLength The maximum length of the region in \p{src} to append.
1007 * Defaults to \b %MAX_LEN
1008 *
1009 * @return \c *this to allow concatenated calls.
1010 ******************************************************************************************/
1011 template <bool TCheck= true>
1012 TAString& Append( const TString<TChar>& src, integer regionStart, integer regionLength =MAX_LEN )
1013 {
1014 if constexpr (TCheck)
1015 {
1016 if ( src.IsNull() )
1017 return *this;
1018 if ( src.TString<TChar>::AdjustRegion( regionStart, regionLength ) )
1019 {
1020 // special treatment if currently nothing is allocated and a blank string ("") is added:
1021 // we allocate, which means, we are not a nulled object anymore!
1022 // (...also, in this case we check the src parameter)
1023 if ( TString<TChar>::IsNull() )
1024 SetBuffer( 15 );
1025 return *this;
1026 }
1027 }
1028 else
1029 {
1030 //---- non-checking version ----
1031 ALIB_ASSERT_ERROR( regionStart >= 0 && regionLength >= 0
1032 && regionLength != MAX_LEN
1033 && regionStart + regionLength <= src.Length(), "STRINGS",
1034 "Non-checking invocation: ", "Invalid region given" )
1035 }
1036
1037 // both versions
1039 return Append<false>( src.Buffer() + regionStart, regionLength );
1041 }
1042
1043 /** ****************************************************************************************
1044 * Alias method of #Append(const TString<TChar>&, integer, integer).<br>
1045 * Provided for compatibility with C# and Java versions of \alib.
1046 *
1047 * @tparam TCheck Chooses checking or non-checking implementation. Defaults to true.
1048 * @param src The \b %String to append.
1049 * @param regionStart The start of the region in \p{src} to append.
1050 * @param regionLength The maximum length of the region in \p{src} to append.
1051 * Defaults to \b %MAX_LEN
1052 *
1053 * @return \c *this to allow concatenated calls.
1054 ******************************************************************************************/
1055 template <bool TCheck= true>
1056 TAString& _( const TString<TChar>& src, integer regionStart, integer regionLength =MAX_LEN )
1057 {
1058 return Append( src, regionStart, regionLength );
1059 }
1060
1061 /** ****************************************************************************************
1062 * Appends platform specific new line character(s) by appending literal string
1063 * \ref alib::NewLine "NewLine".
1064 * @return \c *this to allow concatenated calls.
1065 ******************************************************************************************/
1067 {
1068 return _<false>( TT_StringConstants<TChar>::NewLine() );
1069 }
1070
1071
1072 /** ############################################################################################
1073 * @name Appending Strings
1074 #############################################################################################*/
1075
1076 //##########################################################################################
1077 // Private overloaded "append" methods selected with std::enable_if
1078 //##########################################################################################
1079 #if !defined(ALIB_DOX)
1080
1081
1082 private:
1083 template<typename TC, typename TV, typename If>
1084 friend struct T_Append_not_specialized_for_type;
1085
1086
1087 // nullptr
1088 ATMP_RETURN_IF_2TP( bool, bool TCheck= true, typename T,
1089 ATMP_EQ(std::nullptr_t, T) )
1090 append(const T& )
1091 {
1092 return false;
1093 }
1094
1095 // T_Append types (appendable types)
1096 ATMP_RETURN_IF_2TP( bool, bool TCheck= true, typename T,
1097 !ATMP_IS_PTR(T) && TT_IsAppendable<ATMP_RCVR(T), TChar>::value )
1098 append(const T& src )
1099 {
1100 T_Append<ATMP_RCVR(T), TChar>()( *this, src );
1101
1102 if ( TCheck && TString<TChar>::IsNull() )
1103 SetBuffer( 15 );
1104 return true;
1105 }
1106
1107 // T_Append types (appendable pointer types)
1108 ATMP_RETURN_IF_2TP( bool, bool TCheck= true, typename T,
1109 ATMP_IS_PTR(T) && TT_IsAppendable<ATMP_RCVP(T)* , TChar>::value )
1110 append(const T& src )
1111 {
1112 T_Append<ATMP_RCVP(T)* , TChar>()( *this, src );
1113
1114 if ( TCheck && TString<TChar>::IsNull() )
1115 SetBuffer( 15 );
1116 return true;
1117 }
1118
1119
1120 // Strings defined with T_CharArray (any char width)
1121 ATMP_RETURN_IF_2TP( bool, bool TCheck= true, typename T,
1122 characters::T_CharArray<ATMP_RCVR(T), typename characters::TT_CharArrayType<ATMP_RCVR(T)>::TChar>::Access == characters::AccessType::Implicit )
1123 append(const T& src )
1124 {
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 )
1129 return false;
1130
1131 Append<false>( buf, TCA::Length( src ) );
1132 if ( TCheck && TString<TChar>::IsNull() )
1133 SetBuffer( 15 );
1134 return true;
1135 }
1136
1137 // Strings defined with T_ZTCharArray (any char width)
1138 ATMP_RETURN_IF_2TP( bool, bool TCheck= true, typename T,
1139 characters::T_CharArray <ATMP_RCVR(T), typename characters::TT_CharArrayType <ATMP_RCVR(T)>::TChar>::Access != characters::AccessType::Implicit
1140 && characters::T_ZTCharArray<ATMP_RCVR(T), typename characters::TT_ZTCharArrayType<ATMP_RCVR(T)>::TChar>::Access == characters::AccessType::Implicit )
1141 append(const T& src )
1142 {
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 )
1147 return false;
1148
1149 Append<false>( buf, TCA::Length( src ) );
1150 if ( TCheck && TString<TChar>::IsNull() )
1151 SetBuffer( 15 );
1152 return true;
1153 }
1154
1156
1157 // single character same type
1158 template<bool TCheck= true>
1159 bool append(TChar src )
1160 {
1161 if ( TCheck && src == 0 )
1162 return false;
1163
1165 TString<TChar>::vbuffer[ TString<TChar>::length++ ]= src;
1166 return true;
1167 }
1168
1169 // single character different type
1170 ATMP_RETURN_IF_2TP( bool, bool TCheck= true, typename T,
1171 characters::TT_IsChar<ATMP_RCVR(T)>::value )
1172 append( T src )
1173 {
1174 if ( TCheck && src == 0 )
1175 return false;
1176
1177 using TOtherChar= ATMP_RCVR(T);
1178
1179 // same type?
1180 if constexpr ( ATMP_EQ( TChar, TOtherChar) )
1181 {
1183 TString<TChar>::vbuffer[ TString<TChar>::length++ ]= static_cast<TChar>( src );
1184 return true;
1185 }
1186
1187 // AString<nchar>?
1188 else if constexpr ( ATMP_EQ( TChar, nchar) )
1189 {
1190 wchar wc= static_cast<wchar>( src );
1191 int mbLength;
1192 #if defined(_WIN32)
1193 EnsureRemainingCapacity( MB_LEN_MAX * 2);
1194 mbLength= WideCharToMultiByte( CP_UTF8, 0, &wc, 1,
1195 ((nchar*) TString<TChar>::vbuffer) + TString<TChar>::length,
1196 MB_LEN_MAX * 2, NULL, NULL );
1197 if ( mbLength <= 0 )
1198 {
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 ) ) ) )
1206 }
1207 #else
1208 EnsureRemainingCapacity( static_cast<integer>(MB_CUR_MAX) + 1);
1209 mbLength= wctomb( reinterpret_cast<nchar*>(TString<TChar>::vbuffer)
1210 + TString<TChar>::length, wc );
1211 #endif
1212
1213 if ( mbLength <= 0 )
1214 {
1215 ALIB_WARNING( "STRINGS", "Cannot convert WC to MBC." )
1216 return false;
1217 }
1218
1219 TString<TChar>::length+= mbLength;
1220 return mbLength;
1221 }
1222
1223 // AString<wchar>/<xchar>? (we are just casting)
1225 TString<TChar>::vbuffer[ TString<TChar>::length++ ]= static_cast<TChar>( src );
1226 return true;
1227 }
1229
1230 #endif // doxygen
1231
1232 public:
1233
1234 /** ****************************************************************************************
1235 * Templated method that accepts references and pointers to objects of "appendable types".
1236 * The latter are types that a specialization of functor \alib{strings;T_Append}
1237 * exists for and with that have a corresponding method to create a string representation
1238 * of a source object.<br>
1239 * In addition arbitrary string types, hence types that a specialization of TMP struct
1240 * \alib{characters;T_CharArray} or \alib{characters;T_ZTCharArray} exists for, are
1241 * accepted.<br>
1242 * Finally, single characters of different width are may be passed to this method.
1243 *
1244 * The method has aliases with #operator<<(const TAppendable&) and method
1245 * #_(const TAppendable&). The latter is provided for compatibility with C# and Java
1246 * versions of \alib.
1247 *
1248 * \see
1249 * See chapter \ref alib_strings_assembly_ttostring of this module's
1250 * \ref alib_mod_strings "Programmer's Manual" for more information.
1251 *
1252 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
1253 * If \c <false> is added to the method name, checks are omitted.
1254 * The type of checks omitted depend on the type of \p{TAppendable}.
1255 * In case of provision of pointers, no check for \c nullptr are made.
1256 * @tparam TAppendable The type of parameter \p{source}.
1257 * @param src The source of type \p{TAppendable} to append.
1258 *
1259 * @return \c *this to allow concatenated calls.
1260 ******************************************************************************************/
1261 template <bool TCheck= true, typename TAppendable>
1262 TAString& Append(const TAppendable& src )
1263 {
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 );
1269 return *this;
1270 }
1271
1272
1273 /** ****************************************************************************************
1274 * Alias to method #Append(const TAppendable&).<br>
1275 * Provided for compatibility with C# and Java versions of \alib.
1276 *
1277 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
1278 * If \c <false> is added to the method name, checks are omitted.
1279 * @tparam TAppendable The type of parameter \p{source}.
1280 * @param src The source object to append a string representation for.
1281 *
1282 * @return \c *this to allow concatenated calls.
1283 ******************************************************************************************/
1284 template <bool TCheck= true, class TAppendable >
1285 TAString& _(const TAppendable& src )
1286 {
1287 return Append<TCheck>( src );
1288 }
1289
1290 /** ****************************************************************************************
1291 * Alias operator invoking #Append<true>(const TAppendable&).
1292 *
1293 * @tparam TAppendable The type of parameter \p{source}.
1294 * @param src The object of type T to append.
1295 * @return \c *this to allow concatenated calls.
1296 ******************************************************************************************/
1297 template <class TAppendable>
1298 TAString& operator<< (const TAppendable& src )
1299 {
1300 return Append<true>(src);
1301 }
1302
1303
1304 /** ############################################################################################
1305 * @name Insert and Delete
1306 #############################################################################################*/
1307
1308 /** ****************************************************************************************
1309 * Sets the length of this string to zero. A \e nulled object remains \e nulled.
1310 * @return \c *this to allow concatenated calls.
1311 ******************************************************************************************/
1313 {
1316 return *this;
1317 }
1318
1319 /** ****************************************************************************************
1320 * Sets the length of the string to zero and then invokes #Append(const TAppendable&).
1321 *
1322 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
1323 * The value is used with the invocation of method \b Append.
1324 * @tparam TAppendable The type of parameter \p{source}.
1325 * @param src The source of type \p{TAppendable} to append.
1326 *
1327 * @return \c *this to allow concatenated calls.
1328 ******************************************************************************************/
1329 template <bool TCheck= true, typename TAppendable>
1330 TAString& Reset(const TAppendable& src )
1331 {
1334 Append<TCheck>( src );
1335 return *this;
1336 }
1337
1338
1339
1340 /** ****************************************************************************************
1341 * Sets the length of the string to zero. Same as method #Reset.
1342 * Provided for compatibility with C# and Java versions of \alib.
1343 * @return \c *this to allow concatenated calls.
1344 ******************************************************************************************/
1346 {
1349 return *this;
1350 }
1351
1352 /** ****************************************************************************************
1353 * Inserts the given string at given position. If the position is not between 0 and the
1354 * length of the target, nothing is inserted.
1355 *
1356 * \note
1357 * To insert a string with replacing a different one at the same time, use
1358 * \ref ReplaceSubstring(const TString<TChar>&,integer,integer) "ReplaceSubstring(src, pos, regionLength)".
1359 *
1360 * @tparam TCheck Chooses checking or non-checking implementation. Defaults to true.
1361 * @param src The \b %String to insert.
1362 * @param pos The position to insert \p{src}.
1363 * @return \c *this to allow concatenated calls.
1364 ******************************************************************************************/
1365 template <bool TCheck= true>
1367 {
1369 integer srcLength= src.Length();
1370 if constexpr ( TCheck )
1371 {
1372 if ( srcLength == 0 || pos < 0 || pos > TString<TChar>::length )
1373 return *this;
1374 }
1375 else
1376 {
1377 ALIB_ASSERT_ERROR( srcLength > 0 && pos >=0 && pos <= TString<TChar>::length,
1378 "STRINGS", "Non-checking invocation: ", "Illegal parameters" )
1379 }
1380
1381 EnsureRemainingCapacity( srcLength );
1382
1383 // move content and copy string new region
1385 if ( pos != TString<TChar>::length )
1388 TString<TChar>::vbuffer + pos + srcLength );
1391
1392 return *this;
1393 }
1394
1395 /** ****************************************************************************************
1396 * Appends the given character \p{c} \p{qty}-times.
1397 * The non-checking version does not check parameter \p{qty} to be greater than zero.
1398 *
1399 * @tparam TCheck Defaults to true, which chooses the checking version of the method.
1400 * @param c The character to insert \p{qty} times.
1401 * @param qty The quantity of characters to insert.
1402 * @return \c *this to allow concatenated calls.
1403 ******************************************************************************************/
1404 template <bool TCheck= true>
1406 {
1407 if constexpr ( TCheck )
1408 {
1409 if ( qty <= 0 )
1410 return *this;
1411 }
1412 else
1413 ALIB_ASSERT_ERROR( qty >= 0, "STRINGS",
1414 "Non-checking invocation: ", "Negative quantity given" )
1415
1421 return *this;
1422 }
1423
1424 /** ****************************************************************************************
1425 * Inserts the given character \p{c} \p{qty}-times at a given position.
1426 * If the given position is out of range, nothing is inserted.
1427 *
1428 * The non-checking version does not check the position to be in a valid range and
1429 * the \p{qty} to be greater than zero.
1430 *
1431 * @tparam TCheck Defaults to true, which chooses the checking version of the method.
1432 * @param c The character to insert \p{qty} times.
1433 * @param qty The quantity of characters to insert.
1434 * @param pos The index in this object where \p{c} is inserted \p{qty} times.
1435 * @return \c *this to allow concatenated calls.
1436 ******************************************************************************************/
1437 template <bool TCheck= true>
1438 TAString& InsertChars( TChar c, integer qty, integer pos )
1439 {
1440 if constexpr ( TCheck )
1441 {
1442 if ( qty <= 0 || pos < 0 || pos > TString<TChar>::length )
1443 return *this;
1444 }
1445 else
1446 {
1447 ALIB_ASSERT_ERROR( qty >= 0, "STRINGS",
1448 "Non-checking invocation: ", "Negative quantity given" )
1449 ALIB_ASSERT_ERROR( pos >= 0 && pos <= TString<TChar>::length, "STRINGS",
1450 "Non-checking invocation: ", "Illegal position given" )
1451 }
1452
1454
1455 // move content ?
1457 if ( pos != TString<TChar>::length )
1460 TString<TChar>::vbuffer + pos + qty );
1461
1462 // set
1466
1467 return *this;
1468 }
1469
1470 /** ****************************************************************************************
1471 * Removes a region from the string by moving the remaining string behind the region to
1472 * the region start and adjusting the string's length.
1473 *
1474 * A range check is performed and the region is cut to fit to the string.
1475 * The non-checking version (\p{TCheck} = \c false) omits the check, but still allows to
1476 * leave parameter \p{regionLength} as default (respectively allows the sum of parameters
1477 * \p{regionStart} and \p{regionLength} to be longer than the length of this \b %AString).
1478 * In this case, this string is cut starting from index \p{regionStart}.
1479 *
1480 * \note See also methods #Reset, #DeleteStart and #DeleteEnd.
1481 *
1482 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
1483 * If \c <false> is added to the method name, the start of the region
1484 * is not adjusted to the string's bounds.
1485 * @param regionStart The start of the region to delete.
1486 * @param regionLength The length of the region to delete. Defaults to \b %MAX_LEN.
1487 * @return \c *this to allow concatenated calls.
1488 ******************************************************************************************/
1489 template <bool TCheck= true >
1490 TAString& Delete( integer regionStart, integer regionLength =MAX_LEN )
1491 {
1493
1494 integer regionEnd;
1495
1496 if constexpr ( TCheck )
1497 {
1498 if ( TString<TChar>::AdjustRegion( regionStart, regionLength ) )
1499 return *this;
1500
1501 // delete over the end?
1502 if ( (regionEnd= regionStart + regionLength) >= TString<TChar>::length )
1503 {
1504 TString<TChar>::length= regionStart;
1505 return *this;
1506 }
1507 }
1508 else
1509 {
1510 ALIB_ASSERT_ERROR( regionStart >= 0
1511 && regionStart <= TString<TChar>::length
1512 && regionLength >= 0, "STRINGS",
1513 "Non-checking invocation: ", "Illegal arguments" )
1514
1515 // delete over the end?
1516 if ( (regionEnd= regionStart + regionLength) >= TString<TChar>::length )
1517 {
1518 TString<TChar>::length= regionStart;
1519 return *this;
1520 }
1521 }
1522
1523 // both versions
1526 TString<TChar>::length - regionEnd + 1,
1527 TString<TChar>::vbuffer + regionStart );
1528 TString<TChar>::length-= regionLength;
1530
1531 return *this;
1532 }
1533
1534 /** ****************************************************************************************
1535 * Deletes the given number of characters from the start of the string by moving the
1536 * rest of the string to the start and adjusting the string's length.
1537 *
1538 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
1539 * If \c <false> is added to the method name, no parameter checks are
1540 * performed.
1541 *
1542 * @param regionLength The length of the region at the start to delete.
1543 *
1544 * @return \c *this to allow concatenated calls.
1545 ******************************************************************************************/
1546 template <bool TCheck= true >
1548 {
1550
1551 if constexpr ( TCheck )
1552 {
1553 if ( regionLength <= 0 )
1554 {
1556 return *this;
1557 }
1558 if ( regionLength >= TString<TChar>::length )
1559 return Reset();
1560 }
1561 else
1562 {
1563 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength <= TString<TChar>::length,
1564 "STRINGS", "Non-checking invocation: ",
1565 "Region length out of range." )
1566 }
1567
1570 TString<TChar>::length - regionLength + 1,
1573 TString<TChar>::length-= regionLength;
1574 return *this;
1575 }
1576
1577 /** ****************************************************************************************
1578 * Reduces the length of the string by the given number of characters.
1579 *
1580 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
1581 * If \c <false> is added to the method name, no parameter checks are
1582 * performed and any given value is just subtracted from the
1583 * current length.
1584 * @param regionLength The length of the region at the end to delete.
1585 *
1586 * @return \c *this to allow concatenated calls.
1587 ******************************************************************************************/
1588 template <bool TCheck= true >
1589 TAString& DeleteEnd( integer regionLength )
1590 {
1592
1593 if constexpr (TCheck)
1594 {
1595 if ( regionLength > 0 )
1596 {
1597 if ( regionLength >= TString<TChar>::length )
1599 else
1600 TString<TChar>::length-= regionLength;
1601 }
1602 }
1603 else
1604 {
1605 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength <= TString<TChar>::length,
1606 "STRINGS", "Non-checking invocation: ",
1607 "Region length out of range" )
1608 TString<TChar>::length-= regionLength;
1609 }
1610
1611 return *this;
1612 }
1613
1614 /** ****************************************************************************************
1615 * All characters defined in given set are removed at the beginning and at the end of this
1616 * string.
1617 *
1618 * \see Method #TrimAt to remove whitespaces at arbitrary places in the string.
1619 *
1620 * @param trimChars Pointer to a zero terminated set of characters to be omitted.
1621 * Defaults to \ref DefaultWhitespaces.
1622 * @return \c *this to allow concatenated calls.
1623 ******************************************************************************************/
1624 ALIB_API
1625 TAString& Trim( const TCString<TChar>& trimChars
1627
1628 /** ****************************************************************************************
1629 * All characters defined in given set at, left of and right of the given index
1630 * are removed from the string.<br>
1631 * The method returns index of the first character of those characters that were behind the
1632 * trimmed region. With legal \p{idx} given, this value can only be smaller or equal to
1633 * \p{idx}. If \p{idx} is out of bounds, the length of the string is returned.
1634 *
1635 * @param idx The index to perform the trim operation at. Has to be between zero
1636 * and <em>Length() -1</em>.
1637 * @param trimChars Pointer to a zero terminated set of characters to be omitted.
1638 * Defaults to \ref DefaultWhitespaces.
1639 * @return The index of the first character of those characters that were behind the
1640 * trimmed region.
1641 ******************************************************************************************/
1642 ALIB_API
1643 integer TrimAt( integer idx, const TCString<TChar>& trimChars
1645
1646 /** ****************************************************************************************
1647 * All characters defined in given set are removed at the beginning of this string.
1648 *
1649 * \see Method #TrimAt to remove whitespaces at arbitrary places in the string.
1650 *
1651 * @param trimChars Pointer to a zero terminated set of characters to be omitted.
1652 * Defaults to \ref DefaultWhitespaces.
1653 * @return \c *this to allow concatenated calls.
1654 ******************************************************************************************/
1657 {
1658 if (TString<TChar>::length == 0 || trimChars.IsEmpty() )
1659 return *this;
1660
1661 integer idx= TString<TChar>::template IndexOfAny<lang::Inclusion::Exclude, false>( trimChars );
1662 if ( idx > 0 )
1663 Delete<false>( 0, idx );
1664 else if ( idx < 0 )
1666
1667 return *this;
1668 }
1669
1670 /** ****************************************************************************************
1671 * All characters defined in given set are removed at the end of this string.
1672 *
1673 * \see Method #TrimAt to remove whitespaces at arbitrary places in the string.
1674 *
1675 * @param trimChars Pointer to a zero terminated set of characters to be omitted.
1676 * Defaults to \ref DefaultWhitespaces.
1677 * @return \c *this to allow concatenated calls.
1678 ******************************************************************************************/
1681 {
1682 if( TString<TChar>::length > 0 && trimChars.IsNotEmpty() )
1684 TString<TChar>::template LastIndexOfAny<lang::Inclusion::Exclude, false>(
1685 trimChars, TString<TChar>::length - 1 ) + 1;
1686 return *this;
1687 }
1688
1689
1690 /** ############################################################################################
1691 * @name Replace
1692 #############################################################################################*/
1693
1694 /** ****************************************************************************************
1695 * Replaces a region in this object by a given string.
1696 * The given region is adjusted to this string's bounds.
1697 *
1698 * The non-checking version does not adjust the region and raises an assertion in
1699 * debug-compilations if the given region is out of bounds.
1700 *
1701 * @tparam TCheck Chooses checking or non-checking implementation. Defaults to true.
1702 * @param src The replacement string.
1703 * @param regionStart The start of the region.
1704 * @param regionLength The length of the region.
1705 * @return \c *this to allow concatenated calls.
1706 ******************************************************************************************/
1707 template <bool TCheck= true>
1708 TAString& ReplaceSubstring( const TString<TChar>& src, integer regionStart, integer regionLength )
1709 {
1711 if constexpr ( TCheck )
1712 {
1713 TString<TChar>::AdjustRegion( regionStart, regionLength );
1714 }
1715 else
1716 {
1717 ALIB_ASSERT_ERROR( src.IsNotNull(), "STRINGS",
1718 "Non-checking invocation: ", "Source string is nulled" )
1719 #if ALIB_DEBUG
1720 integer rs= regionStart;
1721 integer rl= regionLength;
1723 ALIB_ASSERT_ERROR( rs == regionStart && rl == regionLength, "STRINGS",
1724 "Non-checking invocation: ", "Invalid region given" )
1725 #endif
1726 }
1727
1728 integer lenDiff= src.Length() - regionLength;
1729
1730 // check buffer size
1731 if ( lenDiff > 0 )
1732 EnsureRemainingCapacity( lenDiff );
1733
1734 // move content
1736 if ( lenDiff != 0 )
1737 characters::CharArray<TChar>::Move( TString<TChar>::vbuffer + regionStart + regionLength,
1738 TString<TChar>::length - (regionStart + regionLength),
1739 TString<TChar>::vbuffer + regionStart + src.Length() );
1740
1741 // copy the source
1742 src.CopyTo( TString<TChar>::vbuffer + regionStart );
1743 TString<TChar>::length+= lenDiff;
1745
1746 return *this;
1747 }
1748
1749 /** ****************************************************************************************
1750 * Replaces a region in the string with the given character.
1751 * The given region is adjusted to this string's bounds. If the adjusted region is empty,
1752 * nothing is done.
1753 *
1754 * The non-checking version does not adjust the region.
1755 *
1756 * @tparam TCheck Chooses checking or non-checking implementation. Defaults to true.
1757 * @param regionStart The start of the region
1758 * @param regionLength The length of the region
1759 * @param c The character to set in the region.
1760 * @return \c *this to allow concatenated calls.
1761 ******************************************************************************************/
1762 template <bool TCheck= true>
1763 TAString& ReplaceRegion( TChar c, integer regionStart, integer regionLength )
1764 {
1765 if constexpr ( TCheck )
1766 {
1767 if ( TString<TChar>::AdjustRegion( regionStart, regionLength ) )
1768 return *this;
1769 }
1770 else
1771 {
1772 #if ALIB_DEBUG
1773 integer rs= regionStart;
1774 integer rl= regionLength;
1776 ALIB_ASSERT_ERROR( rs == regionStart && rl == regionLength, "STRINGS",
1777 "Non-checking invocation: ", "Invalid region given" )
1778 #endif
1779 }
1780
1782 characters::CharArray<TChar>::Fill( TString<TChar>::vbuffer + regionStart, regionLength, c );
1784 return *this;
1785 }
1786
1787 /** ****************************************************************************************
1788 * Replaces all occurrences of character \p{needle} found at or behind position \p{startIdx}
1789 * by character \p{replacement}.
1790 *
1791 * @param needle The character to search.
1792 * @param replacement The replacement character.
1793 * @param startIdx The index where the search starts. Optional and defaults \c 0.
1794 *
1795 * @return The number of replacements that where performed.
1796 ******************************************************************************************/
1797 ALIB_API
1798 integer SearchAndReplace( TChar needle,
1799 TChar replacement,
1800 integer startIdx = 0 );
1801
1802 /** ****************************************************************************************
1803 * Replaces up to \p{maxReplacements} occurrences of string \p{needle} found
1804 * at or behind position \p{startIdx} by string \p{replacement} .
1805 *
1806 * @param needle The string to be searched and replaced.
1807 * @param replacement The replacement string.
1808 * @param startIdx The index where the search starts. Optional and defaults 0.
1809 * @param maxReplacements The maximum number of replacements to perform.
1810 * Optional and defaults to \b %MAX_LEN.
1811 * @param sensitivity Case sensitivity of the comparison.
1812 * Optional and defaults to Case::Sensitive.
1813 *
1814 * @return The number of replacements that where performed.
1815 ******************************************************************************************/
1816 ALIB_API
1818 const TString<TChar>& replacement,
1819 integer startIdx = 0,
1820 integer maxReplacements = MAX_LEN,
1821 lang::Case sensitivity = lang::Case::Sensitive );
1822
1823 /** ****************************************************************************************
1824 * Converts all or a region of characters in the Buffer to upper case.
1825 *
1826 * @param regionStart Start of the region to be converted. Defaults to 0
1827 * @param regionLength Length of the region to be converted. Defaults to \b %MAX_LEN.
1828 *
1829 * @return \c *this to allow concatenated calls.
1830 ******************************************************************************************/
1831 template <bool TCheck= true>
1832 TAString& ToUpper( integer regionStart= 0, integer regionLength =MAX_LEN )
1833 {
1834 if constexpr ( TCheck )
1835 {
1836 if ( TString<TChar>::AdjustRegion( regionStart, regionLength ) )
1837 return *this;
1838 }
1839 else
1840 {
1841 #if ALIB_DEBUG
1842 integer rs= regionStart;
1843 integer rl= regionLength;
1845 ALIB_ASSERT_ERROR( rs == regionStart && rl == regionLength, "STRINGS",
1846 "Non-checking invocation: ", "Invalid region given" )
1847 #endif
1848 }
1849
1853 return *this;
1854 }
1855
1856
1857 /** ****************************************************************************************
1858 * Converts all or a region of characters in the Buffer to lower case.
1859 *
1860 * @param regionStart Start of the region to be converted. Defaults to 0
1861 * @param regionLength Length of the region to be converted. Defaults to \b %MAX_LEN.
1862 *
1863 * @return \c *this to allow concatenated calls.
1864 ******************************************************************************************/
1865 template <bool TCheck= true>
1866 TAString& ToLower( integer regionStart= 0, integer regionLength =MAX_LEN )
1867 {
1868 if constexpr ( TCheck )
1869 {
1870 if ( TString<TChar>::AdjustRegion( regionStart, regionLength ) )
1871 return *this;
1872 }
1873 else
1874 {
1875 #if ALIB_DEBUG
1876 integer rs= regionStart;
1877 integer rl= regionLength;
1879 ALIB_ASSERT_ERROR( rs == regionStart && rl == regionLength, "STRINGS",
1880 "Non-checking invocation: ", "Invalid region given" )
1881 #endif
1882 }
1883
1887 return *this;
1888 }
1889
1890 /** ****************************************************************************************
1891 * Reverses the order of the characters of this string (or a region hereof).
1892 *
1893 * @param regionStart Start of the region to be reversed. Defaults to 0
1894 * @param regionLength Length of the region to be reversed. Defaults to \b %MAX_LEN.
1895 *
1896 * @return \c *this to allow concatenated calls.
1897 ******************************************************************************************/
1898 template <bool TCheck= true>
1899 TAString& Reverse( integer regionStart= 0, integer regionLength =MAX_LEN )
1900 {
1901 if constexpr ( TCheck )
1902 {
1903 if ( TString<TChar>::AdjustRegion( regionStart, regionLength ) )
1904 return *this;
1905 }
1906 else
1907 {
1908 #if ALIB_DEBUG
1909 integer rs= regionStart;
1910 integer rl= regionLength;
1912 ALIB_ASSERT_ERROR( rs == regionStart && rl == regionLength, "STRINGS",
1913 "Non-checking invocation: ", "Invalid region given" )
1914 #endif
1915 }
1916
1920 return *this;
1921 }
1922
1923 /** ############################################################################################
1924 * @name std::iterator_traits
1925 #############################################################################################*/
1926 public:
1927 using TString<TChar>::begin;
1928 using TString<TChar>::end;
1929 using TString<TChar>::rbegin;
1930 using TString<TChar>::rend;
1931
1932 /**
1933 * A \c std::iterator_traits type, implementing the standard library concept of
1934 * \https{RandomAccessIterator,en.cppreference.com/w/cpp/concept/RandomAccessIterator}.
1935 * While parent class \b %String provides a constant iterator only, this class exposes
1936 * an iterator that allows the modification of the character an iterator references.
1937 */
1939
1940 /** Same as #Iterator, but working from the end to the start of the string. */
1941 using ReverseIterator = std::reverse_iterator<Iterator>;
1942
1944 /** Returns an iterator pointing to a constant character at the start of this string.
1945 * @return The start of this string. */
1947
1948 /** Returns an iterator pointing behind this string.
1949 * @return The end of this string. */
1953
1954 /** Returns a reverse iterator pointing to a constant character at the end of this string.
1955 * @return The last character of this string. */
1957
1958 /** Returns a reverse iterator pointing before the start of this string.
1959 * @return The character before this string. */
1961
1962}; // class TAString
1963
1964//! @cond NO_DOX
1965
1966
1967#if (ALIB_CPP_STANDARD >= 20 && !defined(_MSC_VER)) && !defined(ALIB_DOX)
1968// The following operators are re-implementations of those found with class String.
1969// They are needed to mitigate typical C++ 20 comparison operator ambiguities.
1970// Note: We do not use a template for nchar-, wchar- and xchar- versions, for compatibility
1971// reasons and to increase compile speed
1972// Attn: See note at operators in string.hpp
1973
1974// AString/char*
1975inline bool operator== (const TAString<nchar>& lhs, const nchar* rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1976inline bool operator== (const TAString<wchar>& lhs, const wchar* rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1977inline bool operator== (const TAString<xchar>& lhs, const xchar* rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1978inline auto operator<=> (const TAString<nchar>& lhs, const nchar* rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1979inline auto operator<=> (const TAString<wchar>& lhs, const wchar* rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1980inline auto operator<=> (const TAString<xchar>& lhs, const xchar* rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1981
1982// AString/CString
1983inline bool operator== (const TAString<nchar>& lhs, const NCString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1984inline bool operator== (const TAString<wchar>& lhs, const WCString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1985inline bool operator== (const TAString<xchar>& lhs, const XCString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1986inline auto operator<=> (const TAString<nchar>& lhs, const NCString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1987inline auto operator<=> (const TAString<wchar>& lhs, const WCString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1988inline auto operator<=> (const TAString<xchar>& lhs, const XCString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1989
1990// AString/AString
1991inline bool operator== (const TAString<nchar>& lhs, const NAString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1992inline bool operator== (const TAString<wchar>& lhs, const WAString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1993inline bool operator== (const TAString<xchar>& lhs, const XAString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ) == 0; }
1994inline auto operator<=> (const TAString<nchar>& lhs, const NAString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1995inline auto operator<=> (const TAString<wchar>& lhs, const WAString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1996inline auto operator<=> (const TAString<xchar>& lhs, const XAString& rhs) { return lhs.CompareTo<true,lang::Case::Sensitive>( rhs ); }
1997
1998#endif
1999
2000#if ALIB_DEBUG_STRINGS
2001extern template ALIB_API void TAString<nchar>::dbgCheck () const;
2002extern template ALIB_API void TAString<wchar>::dbgCheck () const;
2003extern template ALIB_API void TAString<xchar>::dbgCheck () const;
2004#endif
2005
2006// #################################################################################################
2007// NAString implementations
2008// #################################################################################################
2009
2010// instantiations
2011extern template ALIB_API void TAString<nchar>::GrowBufferAtLeastBy( integer minimumGrowth );
2012extern template ALIB_API void TAString<nchar>::SetBuffer ( integer );
2015extern template ALIB_API integer TAString<nchar>::SearchAndReplace ( const TString<nchar>&,const TString<nchar>&,integer,integer,lang::Case );
2016extern template ALIB_API TAString<nchar>& TAString<nchar>::Trim ( const TCString<nchar>& );
2017extern template ALIB_API integer TAString<nchar>::TrimAt ( integer,const TCString<nchar>& );
2018
2019// specializations
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);
2024
2025
2026// #################################################################################################
2027// WAString implementations
2028// #################################################################################################
2029
2030// instantiations
2031extern template ALIB_API void TAString<wchar>::GrowBufferAtLeastBy( integer minimumGrowth );
2032extern template ALIB_API void TAString<wchar>::SetBuffer ( integer );
2035extern template ALIB_API integer TAString<wchar>::SearchAndReplace ( const TString<wchar>&,const TString<wchar>&,integer,integer,lang::Case );
2036extern template ALIB_API TAString<wchar>& TAString<wchar>::Trim ( const TCString<wchar>& );
2037extern template ALIB_API integer TAString<wchar>::TrimAt ( integer,const TCString<wchar>& );
2038
2039// specializations
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 );
2044
2045// #################################################################################################
2046// XAString implementations
2047// #################################################################################################
2048
2049// instantiations
2050extern template ALIB_API void TAString<xchar>::GrowBufferAtLeastBy( integer minimumGrowth );
2051extern template ALIB_API void TAString<xchar>::SetBuffer ( integer );
2054extern template ALIB_API integer TAString<xchar>::SearchAndReplace ( const TString<xchar>&,const TString<xchar>&,integer,integer,lang:: Case );
2055extern template ALIB_API TAString<xchar>& TAString<xchar>::Trim ( const TCString<xchar>& );
2056extern template ALIB_API integer TAString<xchar>::TrimAt ( integer,const TCString<xchar>& );
2057
2058// specializations
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 );
2063
2064//! @endcond
2065
2066/**
2067 * This is a simple utility class that can be used in situations where a \alib{strings;TAString;AString}
2068 * is intermediately extended and later shortened back to its original length.
2069 * With the use of this class, C++ stack-unwinding is used to ensure that the length is reset
2070 * in all execution paths including exception handling, etc.
2071 *
2072 * \see Macro \ref ALIB_STRING_RESETTER which automatically creates a unique identifier for
2073 * the otherwise unused instances of this type.
2074 *
2075 * @tparam TChar The character type of the \b AString that is to be reset.<br>
2076 */
2077template<typename TChar>
2078class TStringLengthResetter
2079{
2080 protected:
2081 TAString<TChar>& aString; ///< The \b AString to reset.
2082 integer originalLength; ///< The \b The original length of the string.
2083
2084 private:
2085 /** Private new to disallow heap allocation.
2086 * @return Never called. */
2087 void* operator new (size_t);
2088 /** Private new to disallow heap allocation.
2089 * @return Never called. */
2090 void* operator new (size_t, void*);
2091 /** Private new to disallow heap allocation.
2092 * @return Never called. */
2093 void* operator new[](size_t);
2094 /** Private new to disallow heap allocation.
2095 * @return Never called. */
2096 void* operator new[](size_t, void*);
2097 /** Private assignment operator. */
2098 void operator = (const TStringLengthResetter& );
2099
2100 public:
2101 /** Constructor taking the string. Stores the current length in field #originalLength.
2102 * @param pAString The String to take the length of and reset on destruction. */
2104 : aString(pAString)
2105 , originalLength(pAString.Length())
2106 {}
2107
2108 /** Destructor. Restores the string's original length. */
2110 { aString.ShortenTo(originalLength); }
2111
2112 /** Resets the strings to the original length prior to destruction of this object.
2113 * \note With using macro \ref ALIB_STRING_RESETTER, this method is not invocable, because
2114 * the name of the object is not available in this case. But this method is not
2115 * a true member of the usual use case of this class. */
2117 { aString.ShortenTo(originalLength); }
2118
2119 /** Returns the original length.
2120 * @return The length of the \b AString when this object was constructed. */
2122 { return originalLength; }
2123}; // class TStringLengthResetter
2124
2125
2126#define ALIB_STRING_RESETTER(astring) \
2127alib::strings::TStringLengthResetter< \
2128 std::remove_reference<decltype(astring)>::type::CharType> \
2129 ALIB_IDENTIFIER(astring)(astring)
2130
2131}} // namespace [alib::strings]
2132
2133
2134#if defined(_MSC_VER)
2135 #pragma warning( pop )
2136#endif
2137
2138
2140
2141#endif // HPP_ALIB_STRINGS_ASTRING
TAString & ShortenTo(integer newLength)
Definition astring.hpp:908
ALIB_API integer TrimAt(integer idx, const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
Definition astring.cpp:283
integer Capacity() const
Definition astring.hpp:710
TAString & _(const TAppendable &src)
Definition astring.hpp:1285
bool dbgWarnWhenExternalBufferIsReplaced
Definition astring.hpp:340
void GrowBufferAtLeastBy(integer minimumGrowth)
Definition astring.cpp:74
ALIB_API TAString & Trim(const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
Definition astring.cpp:306
std::reverse_iterator< Iterator > ReverseIterator
Definition astring.hpp:1941
TAString & ToLower(integer regionStart=0, integer regionLength=MAX_LEN)
Definition astring.hpp:1866
constexpr TAString(TChar *extBuffer, integer extBufferSize)
Definition astring.hpp:376
TAString & Delete(integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1490
bool HasInternalBuffer() const
Definition astring.hpp:730
ALIB_WARNINGS_RESTORE ReverseIterator rbegin()
Definition astring.hpp:1956
TAString(const TAString &copy)
Definition astring.hpp:403
TAString & DeleteEnd(integer regionLength)
Definition astring.hpp:1589
TAString & Append(const TCharSrc *src, integer srcLength)
TAString & operator<<(const TAppendable &src)
Definition astring.hpp:1298
TAString & ToUpper(integer regionStart=0, integer regionLength=MAX_LEN)
Definition astring.hpp:1832
typename TString< TChar >::template TRandomAccessIterator< TChar > Iterator
Definition astring.hpp:1938
TAString(const TAppendable &src)
Definition astring.hpp:460
TAString & Append(const TChar *src, integer srcLength)
Definition astring.hpp:961
TAString & operator=(const TAString &copy)
Definition astring.hpp:576
TAString & InsertChars(TChar c, integer qty, integer pos)
Definition astring.hpp:1438
TAString & TrimStart(const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
Definition astring.hpp:1655
void SetCharAt(integer idx, TChar c)
Definition astring.hpp:803
TAString & ReplaceSubstring(const TString< TChar > &src, integer regionStart, integer regionLength)
Definition astring.hpp:1708
ReverseIterator rend()
Definition astring.hpp:1960
ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE Iterator begin()
Definition astring.hpp:1946
TAString & Append(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1012
TAString & InsertChars(TChar c, integer qty)
Definition astring.hpp:1405
TAString & TrimEnd(const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
Definition astring.hpp:1679
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1056
TAString & DeleteStart(integer regionLength)
Definition astring.hpp:1547
TChar & operator[](integer idx)
Definition astring.hpp:835
TAString(TAString &&move) noexcept
Definition astring.hpp:417
void DbgDisableBufferReplacementWarning()
Definition astring.hpp:353
void EnsureRemainingCapacity(integer spaceNeeded)
Definition astring.hpp:680
TChar * VBuffer() const
Definition astring.hpp:780
ALIB_API void SetBuffer(integer newCapacity)
Definition astring.cpp:107
TAString & Append(const TAppendable &src)
Definition astring.hpp:1262
void SetLength(integer newLength)
Definition astring.hpp:861
TAString & Reverse(integer regionStart=0, integer regionLength=MAX_LEN)
Definition astring.hpp:1899
ALIB_API integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0)
Definition astring.cpp:330
TAString & InsertAt(const TString< TChar > &src, integer pos)
Definition astring.hpp:1366
TAString & ReplaceRegion(TChar c, integer regionStart, integer regionLength)
Definition astring.hpp:1763
const TChar * Terminate() const
Definition astring.hpp:758
TAString & Reset(const TAppendable &src)
Definition astring.hpp:1330
integer originalLength
The The original length of the string.
Definition astring.hpp:2082
TStringLengthResetter(TAString< TChar > &pAString)
Definition astring.hpp:2103
TAString< TChar > & aString
The AString to reset.
Definition astring.hpp:2081
constexpr bool IsNull() const
Definition string.hpp:395
constexpr bool IsEmpty() const
Definition string.hpp:414
const TChar * buffer
Definition string.hpp:129
constexpr bool IsNotEmpty() const
Definition string.hpp:420
constexpr integer Length() const
Definition string.hpp:357
constexpr bool IsNotNull() const
Definition string.hpp:402
integer CopyTo(TChar *dest) const
Definition string.hpp:1974
bool AdjustRegion(integer &regionStart, integer &regionLength) const
Definition string.hpp:1994
constexpr TString() noexcept=default
constexpr const TChar * Buffer() const
Definition string.hpp:350
#define ALIB_WARNING(...)
Definition alib.hpp:981
#define ATMP_RETURN_IF_2TP(TReturn, TParam1, TParam2,...)
Definition tmp.hpp:81
#define ATMP_RCV( T)
Definition tmp.hpp:40
#define ATMP_VOID_IF(Cond)
Definition tmp.hpp:52
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_API
Definition alib.hpp:538
#define ATMP_RCVP( T)
Definition tmp.hpp:43
#define ATMP_RCVR( T)
Definition tmp.hpp:41
#define ATMP_EQ( T, TEqual)
Definition tmp.hpp:32
#define ATMP_IS_PTR(T)
Definition tmp.hpp:27
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ALIB_DBG(...)
Definition alib.hpp:457
#define ALIB_STRING_DBG_CHK(instance)
#define ATMP_SELECT_IF_1TP(TParam, ...)
Definition tmp.hpp:57
#define ALIB_DEBUG_STRINGS
Definition prepro.dox:41
PLATFORM_SPECIFIC character
@ KeepWithSender
Keeps responsibility, e.g. when passing an object.
bool operator==(const String &lhs, const String &rhs)
Definition string.hpp:2319
static constexpr integer MAX_LEN
Definition string.hpp:45
bool operator<=>(const String &lhs, const String &rhs)
Definition string.hpp:2349
Definition alib.cpp:57
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.
Definition integers.hpp:286
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)
Definition chararray.hpp:96
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)