ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
string.inl
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-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8
9//##################################################################################################
10// forward declarations
11//##################################################################################################
12ALIB_EXPORT namespace alib::strings {
13template<typename TChar>
14requires alib::characters::IsCharacter<TChar> class TString;
15template<typename TChar> class TCString;
16template<typename TChar> class TSubstring;
17template<typename TChar, typename TAllocator>
18requires alib::lang::IsAllocator<TAllocator> class TAString;
19template<typename TChar> struct TNumberFormat;
20}
21
22ALIB_EXPORT namespace alib::strings {
23
24/// This the type trait is tested by implicit "auto cast" operators.
25/// Those might be disabled for specific combinations of types.
26///
27/// For example, implicit casting from class \b AString to sibling types \b CString and
28/// \b Substring has to be forbidden, because both are also constructible implicitly from
29/// this class and hence an ambiguity between implicit cast and implicit construction would
30/// arise.
31///
32/// Custom classes (i.e., if derived from class \alib{strings;TAString}) might encounter
33/// similar problems.
34/// In that case, this type-traits type may be specialized to mitigate compilation issues.
35///
36/// @tparam TFrom The type that allows implicit auto-casts.
37/// @tparam TImOrExplict Denotes if implicit or explicit casts are suppressed.
38/// @tparam TTo The destination type that auto-casts should be suppressed for.
39template<typename TFrom,
40 characters::Policy TImOrExplict,
41 typename TTo>
42struct NoAutoCastTraits : std::false_type {};
43
44// specializations for AString and CString
45template<typename TChar, typename TAllocator> struct NoAutoCastTraits<TAString<TChar, TAllocator>, characters::Policy::Implicit, TCString<TChar> > : std::true_type {};
46template<typename TChar, typename TAllocator> struct NoAutoCastTraits<TAString<TChar, TAllocator>, characters::Policy::Implicit, TSubstring<TChar> > : std::true_type {};
47template<typename TChar> struct NoAutoCastTraits<TCString<TChar> , characters::Policy::Implicit, TSubstring<TChar> > : std::true_type {};
48
49
50/// The maximum length of an \alib string.
51inline constexpr integer MAX_LEN = (std::numeric_limits<integer>::max)();
52
53//==================================================================================================
54/// This class is the base class of all \ref alib_strings_classes "ALib string classes".
55/// Objects of this type represent character strings whose data is allocated outside their scope.
56/// In particular, the class does not allocate a character array buffer to store and manipulate
57/// string data.
58///
59/// Once constructed, objects of this class are immutable, except for the possibility to assign
60/// a complete new object value.
61/// This means there is no interface to change the single two data members #buffer and #length.
62/// The immutable nature of this type is lifted by derived types. While class
63/// \alib{strings;TSubstring;Substring} allows changing the start and
64/// length of the string represented, class \alib{strings;TAString;AString} holds a copy of the
65/// data and consequently allows modifying the string stored.<br>
66///
67/// \see
68/// For an introduction into the \alib string classes see this module's
69/// \ref alib_mod_strings "Programmer's Manual".
70///
71/// @tparam TChar The \ref alib_characters_chars "character type" of this string.
72/// Alias names for specializations along the different character types
73/// are provided in namespace #alib with type definitions
74/// \alib{String},
75/// \alib{NString},
76/// \alib{WString},
77/// \alib{XString},
78/// \alib{ComplementString}, and
79/// \alib{StrangeString}.
80//==================================================================================================
81template<typename TChar>
84{
85 public:
86 /// Exposes template parameter \p{TChar} to the outer world in a \c std compatible way.
87 using value_type = TChar;
88
89 /// The type defining sizes of strings.
91
92 // Debug warnings
93 #if ALIB_DEBUG_STRINGS && !DOXYGEN
94 void dbgCheck() const;
95 #endif
96
97 //################################################################################################
98 // protected fields
99 //################################################################################################
100 protected:
101 #if !DOXYGEN
102 union
103 {
104 const TChar* buffer;
105 TChar* vbuffer;
106 };
107 #else
108 /// Pointer to an array of constant character values.
109 /// This array holds the string that an instance of this type is representing.<br>
110 /// Read access to this field is granted with the method #Buffer.
111 ///
112 /// For technical reasons, this documentation unfortunately omits the important fact that
113 /// this field is part of an anonymous union declared like this:
114 ///
115 /// union
116 /// {
117 /// const TChar* buffer;
118 /// TChar* vbuffer;
119 /// };
120 ///
121 /// Hence, the field can also be interpreted as a pointer to an array of <b>non-constant</b>
122 /// character values.
123 /// Derived classes might use the sibling version \b vbuffer to modify the contents of
124 /// the string if it is assured that such memory is writable.
125 /// This is, for example, done extensively by the implementation of class
126 /// \alib{strings;TAString;AString}.
127 ///
128 /// \note
129 /// It might not be considered pure/nice OO-design to prepare a feature of specialized
130 /// classes in a non-abstract base class, as done here. But the alternative would have
131 /// been to force derived classes to perform re-interpret casts or even worse tricks
132 /// to rightfully access a writeable buffer.
133 const TChar* buffer;
134 #endif
135
136 /// The length of the character string represented.
137 /// Read access to this field is granted with the method #Length.
139
140 //################################################################################################
141 // Constructors
142 //################################################################################################
143 public:
144
145 /// Defaulted default constructor. Leaves this instance \b uninitialized and undefined.
146 /// In other words, the methods #Buffer and #Length give random results.
147 constexpr TString() noexcept =default;
148
149 /// Defaulted copy constructor
150 constexpr TString(const TString&) noexcept =default;
151
152 /// Defaulted move constructor
153 constexpr TString( TString&&) noexcept =default;
154
155 /// Defaulted copy assignment operator.
156 /// @return A reference to <c>this</c> instance.
157 constexpr TString& operator=(const TString&) noexcept =default;
158
159 /// Defaulted move assignment operator.
160 /// @return A reference to <c>this</c> instance.
161 constexpr TString& operator=( TString&&) noexcept =default;
162
163
164 /// Constructor accepting a pointer to a character array and a string length.
165 ///
166 /// @param pBuffer Pointer to the start of the character string to represent.
167 /// @param pLength The length of the character string to represent.
168 constexpr TString( const TChar* pBuffer, integer pLength ) noexcept
169 : buffer(pBuffer)
170 , length(pLength) {}
171
172 /// Constructor accepting \c nullptr. Constructs a nulled string.
173 constexpr TString(lang::IsNullptr auto const &) noexcept
174 : buffer( nullptr ), length( 0 ) {}
175
176 /// Templated \b implicit constructor accepting a \c const reference to an object of a
177 /// type that satisfies the concept \alib{characters;IsImplicitArraySource}.
178 ///
179 /// Custom types can be enabled for this constructor by specializing the traits-type
180 /// \alib{characters;ArrayTraits}, which is used for both;
181 /// the implementation of the concept, and
182 /// the implementation of this constructor itself.
183 ///
184 /// @tparam T The type of the given \p{src}.
185 /// Requires satisfying the concept \alib{characters;IsImplicitArraySource}.
186 /// Deduced by the compiler.
187 /// @param src The source of the string data to copy.
188 template <typename T>
190 constexpr TString(const T& src) noexcept
191 : buffer( characters::ArrayTraits<std::remove_cv_t<T>,TChar>::Buffer( src ) )
192 , length( characters::ArrayTraits<std::remove_cv_t<T>,TChar>::Length( src ) ) {}
193
194 /// Templated \b explicit constructor accepting a \c const reference to an object of a
195 /// type that satisfies the concept \alib{characters;IsExplicitArraySource}.
196 ///
197 /// Custom types can be enabled for this constructor by specializing the traits-type
198 /// \alib{characters;ArrayTraits}, which is used for both;
199 /// the implementation of the concept, and
200 /// the implementation of this constructor itself.
201 ///
202 /// @tparam T The type of the given \p{src}.
203 /// Requires satisfying the concept \alib{characters;IsExplicitArraySource}.
204 /// Deduced by the compiler.
205 /// @param src The source of the string data to copy.
206 template<typename T>
208 constexpr explicit TString(const T& src) noexcept
209 : buffer( characters::ArrayTraits<std::remove_cv_t<T>,TChar>::Buffer( src ) )
210 , length( characters::ArrayTraits<std::remove_cv_t<T>,TChar>::Length( src ) ) {}
211
212 /// Templated \b explicit constructor accepting a \b mutable reference to an object of a
213 /// type that satisfies the concept \alib{characters;IsMutableArraySource}.
214 ///
215 /// Custom types can be enabled for this constructor by specializing the traits-type
216 /// \alib{characters;ArrayTraits}, which is used for both;
217 /// the implementation of the concept, and
218 /// the implementation of this constructor itself.
219 ///
220 /// @tparam T The type of the given \p{src}.
221 /// Requires satisfying the concept \alib{characters;IsMutableArraySource}.
222 /// Deduced by the compiler.
223 /// @param src The source of the string data to copy.
224 template<typename T>
226 constexpr explicit TString( T& src) noexcept
227 : buffer( characters::ArrayTraits<std::remove_cv_t<T>,TChar>::Buffer( src ) )
228 , length( characters::ArrayTraits<std::remove_cv_t<T>,TChar>::Length( src ) ) {}
229
230 /// Constructor which allocates memory, copies the given string's contents, and
231 /// lets this string represent this new character array.<br>
232 /// Note that it is up to the using code to duly deallocate the memory, because the
233 /// destructor of this type does not do so.
234 /// @see Methods #Allocate and #Free for information how to use allocated string objects.
235 ///
236 /// @tparam TAllocator The type of the given \p{allocator}, as prototyped with
237 /// \alib{lang;Allocator}.
238 /// Requires satisfying the concept \alib{lang;IsAllocator}.
239 /// Deduced by the compiler.
240 /// @param allocator The allocator to use.
241 /// @param copy The string to copy to the new memory allocated.
242 template<typename TAllocator>
244 TString( TAllocator& allocator, const TString<TChar>& copy ) {
245 if( (length= copy.length) == 0 ) {
246 buffer= copy.buffer;
247 return;
248 }
249
250 auto* newBuf= allocator().template AllocArray<TChar>( copy.length);
251 copy.CopyTo( newBuf );
252 buffer= newBuf;
253 }
254
255 //######################################### casting back ########################################
256
257 /// Templated \b implicit <c>cast operator</c> constructing an instance of type \p{T} from
258 /// this string instance.
259 /// This operator requires the type \p{T} satisfying the concept
260 /// \alib{characters;IsImplicitArrayCast}.
261 ///
262 /// Custom types can be enabled for this operator by specializing the traits-type
263 /// \alib{characters;ArrayTraits}, which is used for both;
264 /// the implementation of the concept, and
265 /// the implementation of this operator itself.
266 ///
267 /// @tparam T The type to implicitly cast this instance to.
268 /// Requires satisfying the concept \alib{characters;IsImplicitArrayCast}.
269 /// Deduced by the compiler.
270 /// @return A value of type \p{T}.
271 template< typename T>
275 std::remove_cv_t<T> >::value )
276
277 constexpr operator T() const
279
280 /// Templated \b explicit <c>cast operator</c> constructing an instance of type \p{T} from
281 /// this string instance.
282 /// This operator requires the type \p{T} satisfying the concept
283 /// \alib{characters;IsExplicitArrayCast}.
284 ///
285 /// Custom types can be enabled for this operator by specializing the traits-type
286 /// \alib{characters;ArrayTraits}, which is used for both;
287 /// the implementation of the concept, and
288 /// the implementation of this operator itself.
289 ///
290 /// @tparam T The type to explicitly cast this instance to.
291 /// Deduced by the compiler.
292 /// @return A value of type \p{T}.
293 template< typename T>
297 std::remove_cv_t<T> >::value )
298 constexpr explicit operator T() const
300
301
302 //##############################################################################################
303 /// @name Buffer Access, Length, and State
304 //##############################################################################################
305
306 /// Returns a pointer to the first character of the string we are representing.
307 /// \note The string is not guaranteed to be zero-terminated.
308 ///
309 /// @return The start of the character array comprising the string represented by this
310 /// object.
311 constexpr const TChar* Buffer() const { return buffer; }
312
313 /// Returns the length of the string that this object represents.
314 ///
315 /// @return The length of the string represented by this object.
316 constexpr integer Length() const { return length; }
317
318 /// Returns the length of the string if represented as a wide character string.
319 /// If template parameter \p{TChar} equals \c wchar, then this is identical with #Length.
320 /// Otherwise the calculation is done using
321 /// - <em>mbsnrtowcs()</em>
322 /// (without providing a conversion buffer) on glibc platforms (e.g., Linux)
323 /// - <em>MultiByteToWideChar()</em>
324 /// (without providing a conversion buffer) on the Windows platform.
325 ///
326 /// If the conversion fails, \c -1 is returned.
327 ///
328 /// \note
329 /// On GNU/Linux and Mac OS, it might be necessary to invoke standard C method
330 /// <em>setlocale()</em> once, before using this method, to successfully calculate
331 /// the length.
332 /// This by default is done during \ref alib_mod_bs "library initialization",
333 /// if performed on class \alib{camp;Basecamp}.
334 ///
335 /// @return The length of string when it was converted to wide characters.
336 /// If counting failed (what means that a corresponding conversion would also fail)
337 /// the #Length is returned.
339
340
341 /// Returns \c true if field #buffer equals \c nullptr, \c false otherwise.
342 /// Note that a \e nulled string is also considered \ref IsEmpty "empty".
343 ///
344 /// \see
345 /// Details on the concept of \e nulled and \e empty strings are documented in chapter
346 /// \ref alib_strings_details_nulled_vsempty of this module's
347 /// \ref alib_mod_strings "Programmer's Manual".
348 ///
349 /// @return \c true if no buffer is allocated.
350 constexpr bool IsNull() const { return buffer == nullptr; }
351
352 /// Returns \c true if field #buffer does not equal \c nullptr, \c false otherwise.
353 ///
354 /// @return The negated value of method #IsNull.
355 constexpr bool IsNotNull() const { return buffer != nullptr; }
356
357 /// Returns \c true if this string is of zero length.
358 /// Note that a \e nulled string is also considered empty.
359 ///
360 /// \see
361 /// Details on the concept of \e nulled and \e empty strings are documented in chapter
362 /// \ref alib_strings_details_nulled_vsempty of this module's
363 /// \ref alib_mod_strings "Programmer's Manual".
364 /// @return \c true if the actual length equals zero.
365 constexpr bool IsEmpty() const { return length == 0; }
366
367 /// Returns \c true if this string has a length of \c 1 or more.
368 /// @return \c true if the actual length does not equal zero.
369 constexpr bool IsNotEmpty() const { return length != 0; }
370
371
372
373
374 /// Returns a new string object representing a substring of the string that this object
375 /// represents.
376 ///
377 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
378 /// If \c false is given, no range check is performed.
379 /// @param regionStart The start of the substring within this string.
380 /// @param regionLength The length of the substring to return.
381 /// Defaults to \alib{strings;MAX_LEN}.
382 /// @return A string representing a region of this string.
383 template <typename TCheck= CHK>
384 TString<TChar> Substring(integer regionStart, integer regionLength =MAX_LEN ) const {
386
387 if constexpr ( TCheck::value ) {
388 AdjustRegion( regionStart, regionLength );
389 } else {
390 #if ALIB_DEBUG
391 integer rs= regionStart;
392 integer rl= regionLength;
393 AdjustRegion( rs, rl );
394 ALIB_ASSERT_ERROR( rs == regionStart && rl == regionLength, "STRINGS",
395 "Non-checking invocation: ", "Invalid region {}/{} given. Adjusted: {}/{}",
396 regionStart, regionLength, rs, rl )
397 #endif
398 }
399
400 return TString<TChar>( buffer + regionStart, regionLength );
401 }
402
403 //##############################################################################################
404 /// @name Character Access
405 //##############################################################################################
406
407 /// Retrieves the character at the given index. A range check is performed. If this fails,
408 /// \c '\0' is returned.
409 ///
410 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
411 /// If \c false is given, no range check is performed.
412 /// @param idx The index of the character to read.
413 /// @return The character at the given index, or '\0' if index out of range.
414 template <typename TCheck= CHK>
415 TChar CharAt( integer idx ) const {
416 if constexpr ( TCheck::value )
417 return ( idx >= 0 && idx < length ) ? *(buffer + idx )
418 : '\0' ;
419 ALIB_ASSERT_ERROR( idx >= 0 && idx < length, "STRINGS",
420 "Non checking version: Index out of range: 0 <= {} < {}.", idx, length )
421
422 return *(buffer + idx );
423 }
424
425 /// Retrieves the first character.
426 /// In the case of an empty or \e nulled string, '\0' is returned.
427 ///
428 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
429 /// If \alib{NC} is given, no check for an empty string object is performed.
430 /// @return The first character of the %String.
431 /// If this instance's length is zero, '\0' is returned.
432 template <typename TCheck= CHK>
433 TChar CharAtStart() const {
434 if constexpr ( TCheck::value )
435 return length > 0 ? *(buffer)
436 : '\0';
437
438 ALIB_ASSERT_ERROR( length > 0, "STRINGS", "Non checking invocation on empty string" )
439 return *(buffer);
440 }
441
442
443 /// Retrieves the last character. In the case of an empty string, '\0' is returned.
444 ///
445 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
446 /// If \alib{NC} is given, no check for an empty or \e nulled object is
447 /// performed.
448 ///
449 /// @return The last character of the %String.
450 /// If this instance's length is zero, '\0' is returned.
451 template <typename TCheck= CHK>
452 TChar CharAtEnd() const {
453 if constexpr ( TCheck::value )
454 return length > 0 ? *(buffer + length - 1)
455 : '\0';
456
457 ALIB_ASSERT_ERROR( length > 0, "STRINGS", "Non checking invocation on empty string" )
458 return *(buffer + length - 1);
459 }
460
461 /// Reads a character at a given index.
462 ///
463 /// \note
464 /// Unlike method #CharAt, this operator does <em>not</em> perform do range check on
465 /// parameter \p{idx}.
466 /// The rationale for this is that derived mutable types (e.g., class %AString),
467 /// may provide a mutable (non-<c>const</c>) version of this operator, returning a
468 /// reference to the character to provide write access. Such reference
469 /// to a character could not be given if the index was out of range.
470 /// This way, a check in the derived type could likewise not be implemented.
471 ///
472 /// \note
473 /// As a result, this operator is equivalent to the non-checking version of method
474 /// #CharAt<\c false>. For safe access to characters in the buffer use #CharAt
475 /// (with template parameter \p{TCheck} being \alib{CHK}) which returns <c>'\0'</c> in the
476 /// case of that \p{idx} is out of bounds.
477 ///
478 /// \note
479 /// Still, in debug-compilations this operator \ref alib_mod_assert "raises an ALib error"
480 /// if \p{idx} is out of bounds.
481 ///
482 /// @param idx The index of the character within this object's buffer.
483 /// @returns If the character contained at index \p{idx}.
484 TChar operator[] (integer idx) const {
485 ALIB_ASSERT_ERROR( idx >= 0 && idx < length, "STRINGS",
486 "Index out of bounds: 0 <= {} < {}.", idx, length )
487 return buffer[idx];
488 }
489
490 //##############################################################################################
491 /// @name Hashing
492 //##############################################################################################
493 /// Computes a hash number for the contained string.
494 ///
495 /// \note
496 /// If this library is compiled using C++17, internally this method is using
497 /// <c>std::hash<std::string_view<TChar>></c>. Otherwise a compatible hash function
498 /// is used.
499 /// \see Alternative method #HashcodeIgnoreCase.
500 ///
501 /// @return A hash number which is equal for two instances with the same content.
502 std::size_t Hashcode() const;
503
504 /// Computes a hash number for the contained string converted to upper case letters.
505 ///
506 /// \see Alternative method #Hashcode.
507 ///
508 /// @return A hash number which is equal for two instances with have the same content
509 /// if converted to upper case letters.
510 std::size_t HashcodeIgnoreCase() const;
511
512 //##############################################################################################
513 /// @name Comparison Methods
514 //##############################################################################################
515 /// Compares this string with a
516 /// \ref alib_strings_cc_construction_string "string-like object".
517 ///
518 /// \c true is returned if this and the compared string are \e nulled or empty.
519 /// If only one is \e nulled or empty, \c false is returned.
520 ///
521 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
522 /// If \alib{NC} is given, no check for a \e nulled is performed
523 /// on this string as well as on \p{rhs}.
524 /// @tparam TSensitivity Determines if comparison is case-sensitive (the default) or not.
525 /// @param rhs The object to compare.
526 ///
527 /// @return \c true, if the contents of this string and the string representation of the
528 /// given \p{rhs} are equal.
529 template <typename TCheck = CHK,
530 lang::Case TSensitivity = lang::Case::Sensitive>
531 bool Equals( const TString<TChar>& rhs ) const {
533
534 if constexpr ( TCheck::value ) {
535 if ( IsNull() && rhs.IsNull() )
536 return true;
537
538 if ( ( IsNull() != rhs.IsNull() ) )
539 return false;
540 }
541 #if ALIB_DEBUG
542 else
543 { // we do not use IsNull() here, for not having a call noted in performance tools
544 ALIB_ASSERT_ERROR( buffer != nullptr,"STRINGS", "Non checking but this is nulled." )
545 ALIB_ASSERT_ERROR( rhs.buffer != nullptr,"STRINGS", "Non checking but rhs is nulled." )
546 }
547 #endif
548
549 if ( length != rhs.length )
550 return false;
551
552 if ( length == 0 )
553 return true;
554
555 if constexpr (TSensitivity == lang::Case::Sensitive ) {
556 // note: this warning 'suddenly' needed to be silenced with GCC 14.2.1, but only in
557 // release builds, in cases where TCheck was true, and thus null-checks
558 // were performed, and in fact this code was not reached.
560 return characters::Equal ( buffer, rhs.buffer, length );
562 }
563 else
565 }
566
567 /// Compares this string with a
568 /// \ref alib_strings_cc_construction_string "string-like object".
569 ///
570 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
571 /// If \alib{NC} is given, no check for a \e nulled object (this) is
572 /// performed and this string must not be of zero length
573 /// (while \p{rhs} might be of zero length).
574 /// @tparam TSensitivity Determines if comparison is case-sensitive (the default) or not.
575 /// @param rhs The object to compare.
576 ///
577 /// @return
578 /// - 0 if this and \p{rhs} are \e nulled or if both have a length of 0 or if both
579 /// share the same content
580 /// - <0 if this is \e nulled and \p{rhs} is not or if this is smaller than \p{rhs}.
581 /// - >0 if this is not \e nulled but \p{rhs} is or if this is greater than \p{rhs}.
582 template <typename TCheck = CHK,
583 lang::Case TSensitivity = lang::Case::Sensitive>
584 int CompareTo( const TString<TChar>& rhs ) const {
586
587 // check \c nullptr arguments
588 if (TCheck::value && IsNull() ) return rhs.IsNull() ? 0 : -1;
589 if (TCheck::value && rhs.IsNull() ) return +1;
590
591 // zero length ?
592 if ( TCheck::value && length == 0 ) return rhs.length == 0 ? 0 : -1;
593 if ( rhs.length == 0 ) return +1;
594
595 bool thisIsShorter= ( length < rhs.length);
596 integer shortLen = thisIsShorter ? length : rhs.length;
597
598 int cmpVal= (TSensitivity == lang::Case::Sensitive)
599 ? characters::Compare ( buffer, rhs.buffer, shortLen )
600 : characters::CompareIgnoreCase( buffer, rhs.buffer, shortLen );
601
602 if ( cmpVal != 0 || length == rhs.length )
603 return cmpVal;
604 return thisIsShorter ? -1 : 1;
605 }
606
607 /// Compares this string with a region of another
608 /// \ref alib_strings_cc_construction_string "string-like object".
609 ///
610 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
611 /// If \alib{NC} is given, no check for a \e nulled comparison
612 /// object is performed and this string must not be empty.
613 /// Furthermore, no check is performed whether the given region
614 /// fits to parameter \p{rhs}. This also means that the default
615 /// value must not be used with <em>TCheck==\alib{NC}</em>.
616 /// @tparam TSensitivity Determines if comparison is case-sensitive (the default) or not.
617 /// @param rhs The string to compare this string with.
618 /// @param rhsRegionStart The start of the region in \p{rhs} to compare this object
619 /// with.
620 /// @param rhsRegionLength The length of the region in \p{rhs} to compare this object
621 /// with.
622 /// Defaults to \alib{strings;MAX_LEN}.
623 ///
624 /// @return
625 /// - 0 if this and \p{rhs} are \e nulled or if both have a length of 0 or if both
626 /// share the same content
627 /// - <0 if this is \e nulled and \p{rhs} is not or if this is smaller than \p{rhs}.
628 /// - >0 if this is not \e nulled but \p{rhs} is or if this is greater than \p{rhs}.
629 template < typename TCheck = CHK,
630 lang::Case TSensitivity = lang::Case::Sensitive>
631 int CompareTo( const TString& rhs,
632 integer rhsRegionStart,
633 integer rhsRegionLength =MAX_LEN ) const {
634 if constexpr ( TCheck::value ) {
635 TString cmpSub( rhs.buffer, 0);
636 rhs.AdjustRegion( rhsRegionStart, rhsRegionLength );
637 cmpSub.buffer+= rhsRegionStart;
638 cmpSub.length= rhsRegionLength;
639
640 return CompareTo<CHK, TSensitivity>( cmpSub );
641 }
642 else
643 return CompareTo<NC, TSensitivity>( TString( rhs.buffer + rhsRegionStart,
644 rhsRegionLength ) );
645 }
646
647 /// Compares a region of this object with a region of another
648 /// \ref alib_strings_cc_construction_string "string-like object".
649 ///
650 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
651 /// If \alib{NC} is given, no check for a \e nulled comparison
652 /// object is performed and this string must not be empty.
653 /// Furthermore, no check is performed whether the given regions fit
654 /// to this object respectively the other region to the object given
655 /// with parameter \p{rhs}.
656 /// This also means that the default value of \p{regionLength} must
657 /// not be used in this case.
658 /// @tparam TSensitivity Determines if comparison is case-sensitive (the default) or not.
659 /// @param rhs The string to compare this string with.
660 /// @param rhsRegionStart The start of the region in \p{rhs} to compare this object
661 /// with.
662 /// @param rhsRegionLength The length of the region in \p{rhs} to compare this object
663 /// with.
664 /// @param regionStart The start of the region in this object to compare with
665 /// @param regionLength The length of the region in this object to compare with.
666 /// Defaults to \alib{strings;MAX_LEN}.
667 ///
668 /// @return
669 /// - 0 if this and \p{rhs} are \e nulled or if both have a length of 0 or if both
670 /// share the same content
671 /// - <0 if this is \e nulled and \p{rhs} is not or if this is smaller than \p{rhs}.
672 /// - >0 if this is not \e nulled but \p{rhs} is or if this is greater than \p{rhs}.
673 template < typename TCheck = CHK,
674 lang::Case TSensitivity = lang::Case::Sensitive>
675 int CompareTo( const TString& rhs,
676 integer rhsRegionStart,
677 integer rhsRegionLength,
678 integer regionStart,
679 integer regionLength =MAX_LEN ) const {
680 if constexpr ( TCheck::value ) {
681 TString cmpSub( rhs.buffer, 0);
682 rhs.AdjustRegion( rhsRegionStart, rhsRegionLength );
683 cmpSub.buffer+= rhsRegionStart;
684 cmpSub.length= rhsRegionLength;
685
686 AdjustRegion( regionStart, regionLength );
687 return TString( buffer + regionStart, regionLength ).CompareTo<CHK, TSensitivity>( cmpSub );
688 }
689
690 return TString( buffer + regionStart, regionLength )
691 .CompareTo<NC, TSensitivity>( TString( rhs.buffer + rhsRegionStart,
692 rhsRegionLength ) );
693 }
694
695 /// Returns \c true, if the contents of the given
696 /// \ref alib_strings_cc_construction_string "string-like object" is found at the given
697 /// position.
698 ///
699 /// \note
700 /// The following rules apply:
701 /// - If \p{pos} is out of range or \p{needle} is \e nulled, \c false is returned.
702 /// (This check only done if \p{TCheck} equals \alib{CHK}.)
703 /// - Otherwise, if the length of \p{needle} is 0, \c true is returned.
704 ///
705 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
706 /// If \c <false> is given, no check on parameter
707 /// \p{pos} is performed and \p{needle} must not be \e nulled.
708 /// @tparam TSensitivity Determines if comparison is case-sensitive (the default) or not.
709 /// @param needle The string to compare with. If it is \ref IsEmpty "empty", \c true
710 /// is returned.
711 /// @param pos The position to search for needle.
712 /// @return \c true if \p{needle} is found at the given position. False otherwise.
713 template< typename TCheck = CHK,
714 lang::Case TSensitivity = lang::Case::Sensitive >
715 bool ContainsAt( const TString& needle, integer pos ) const {
716 integer needleLength= needle.length;
718 if constexpr ( TCheck::value ) {
719 if ( pos < 0 || pos + needleLength > length || needle.IsNull () )
720 return false;
721 if ( needleLength == 0 )
722 return true;
723 } else {
724 ALIB_ASSERT_ERROR( pos >= 0 && pos + needleLength <= length,
725 "STRINGS", "Non checking and index out of range: 0 <= {}, {} <= {}.",
726 pos, pos + needleLength, length )
727 ALIB_ASSERT_ERROR( needleLength != 0,
728 "STRINGS", "Non checking and emtpy compare string" )
729 }
730
731 return TSensitivity == lang::Case::Sensitive
732 ? characters::Equal ( buffer + pos, needle.buffer, needleLength )
733 : characters::CompareIgnoreCase( buffer + pos, needle.buffer, needleLength ) == 0 ;
734 }
735
736 /// Returns \c true, if this string starts with the contents of the
737 /// \ref alib_strings_cc_construction_string "string-like object" given with parameter
738 /// \p{needle}.
739 /// In the special case that \p{needle} is \ref IsEmpty "empty", \c true is returned.
740 ///
741 /// @tparam TSensitivity Determines if comparison is case-sensitive (the default) or not.
742 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
743 /// If \c <false> is given, the given needle must not be empty
744 /// and must not be longer than this string!
745 /// \p{pos} is performed and \p{needle} must not be \e nulled.
746 /// @param needle The string to compare the start of this string with.
747 /// If \e nulled or empty, \c true is returned.
748 /// @return \c true if \p{needle} is found at the start of this string, \c false otherwise.
749 template<typename TCheck = CHK,
750 lang::Case TSensitivity =lang::Case::Sensitive>
751 bool StartsWith( const TString& needle ) const {
752 if constexpr ( TCheck::value ) {
753 if ( needle.length > length )
754 return false;
755 if ( needle.length == 0 )
756 return true;
757 } else {
758 ALIB_ASSERT_ERROR( needle.length <= length, "STRINGS",
759 "Non checking and needle longer than this string: {} > {}",
760 needle.length, length )
761 ALIB_ASSERT_ERROR( needle.length != 0 , "STRINGS",
762 "Non checking and emtpy needle given." )
763 }
764
765 if constexpr ( TSensitivity == lang::Case::Sensitive )
766 return characters::Equal ( buffer, needle.buffer, needle.length );
767 else
768 return characters::CompareIgnoreCase( buffer, needle.buffer, needle.length ) == 0;
769 }
770
771 /// Returns \c true, if this string ends with the string found in parameter \p{needle}.
772 /// If \p{needle} is \ref IsEmpty "empty", \c true is returned.
773 ///
774 /// @tparam TSensitivity Determines if comparison is case-sensitive (the default) or not.
775 /// @param needle The string to compare the end of this string with.
776 /// If \e nulled or empty, \c true is returned.
777 /// @return \c true if \p{needle} is found at the end of this, \c false otherwise.
778 template<typename TCheck = CHK,
779 lang::Case TSensitivity =lang::Case::Sensitive>
780 bool EndsWith( const TString& needle ) const {
781 if constexpr ( TCheck::value ) {
782 if ( needle.length > length )
783 return false;
784 if ( needle.length == 0 )
785 return true;
786 } else {
787 ALIB_ASSERT_ERROR( needle.length <= length, "STRINGS",
788 "Non checking and needle longer than this string: {} > {}",
789 needle.length, length )
790 ALIB_ASSERT_ERROR( needle.length != 0 , "STRINGS",
791 "Non checking and emtpy needle given." )
792 }
793
794 if constexpr ( TSensitivity == lang::Case::Sensitive )
795 return characters::Equal ( buffer + length - needle.length, needle.buffer, needle.length );
796 else
797 return characters::CompareIgnoreCase( buffer + length - needle.length, needle.buffer, needle.length ) == 0;
798 }
799
800 //##############################################################################################
801 /// @name Search
802 //##############################################################################################
803
804 /// Searches a character starting from a given position.
805 ///
806 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
807 /// If \c false is given, no range check is performed.
808 /// @param needle The character to search for.
809 /// @param startIdx The index in this to start searching the character.
810 /// Defaults to \c 0.
811 ///
812 /// @return \c -1 if the character \p{needle} is not found.
813 /// Otherwise the index of its first occurrence.
814 template <typename TCheck= CHK>
815 integer IndexOf( TChar needle, integer startIdx = 0 ) const {
817
818 if constexpr ( TCheck::value ) {
819 // adjust range, if empty return -1
820 if ( startIdx < 0 ) startIdx= 0;
821 else if ( startIdx >= length ) return -1;
822 } else {
823 ALIB_ASSERT_ERROR( startIdx >= 0 && startIdx < length, "STRINGS",
824 "Non checking and index out of range: 0 <= {} < {}.", startIdx, length )
825 }
826
827 const TChar* result= characters::Search( buffer + startIdx, length - startIdx, needle );
828
829 return result != nullptr ? result - buffer
830 : -1;
831 }
832
833 /// Searches a character within a region of this.
834 ///
835 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
836 /// If \c false is given, no range check is performed.
837 /// @param needle The character to search for.
838 /// @param regionStart The start of the region to search the character in.
839 /// @param regionLength The length of the region to search the character in.
840 /// @return \c -1 if the character \p{needle} is not found.
841 /// Otherwise the index of its first occurrence.
842 template <typename TCheck= CHK>
843 integer IndexOf( TChar needle, integer regionStart, integer regionLength ) const {
845
846 if constexpr ( TCheck::value ) {
847 // adjust range, if empty return -1
848 if ( AdjustRegion( regionStart, regionLength ) )
849 return -1;
850 } else {
851 #if ALIB_DEBUG
852 integer rs= regionStart;
853 integer rl= regionLength;
855 && rs == regionStart && rl == regionLength, "STRINGS",
856 "Non-checking invocation: ", "Invalid region {}/{} given. Adjusted: {}/{}",
857 regionStart, regionLength, rs, rl )
858 #endif
859 }
860
861 const TChar* result= characters::Search( buffer + regionStart, regionLength, needle );
862
863 return result != nullptr ? result - buffer
864 : -1;
865 }
866
867 /// Like \alib{strings::TString;IndexOf} but in case the character is not found, this
868 /// method returns the length of this string instead of \c -1.
869 /// Depending on the invocation context, the choice for the right version of this method may
870 /// lead to shorter and more efficient code.
871 ///
872 /// @param needle The character to search for.
873 /// @return This string's #Length if character \p{needle} is not found.
874 /// Otherwise the index of first occurrence.
875 integer IndexOfOrLength( TChar needle ) const {
877 const TChar* result= characters::Search( buffer, length, needle );
878
879 return result != nullptr ? result - buffer
880 : length;
881 }
882
883 /// Like \alib{strings::TString;IndexOf} but in case the character is not found, this
884 /// method returns the length of this string instead of \c -1.
885 /// Depending on the invocation context, the choice for the right version of this method may
886 /// lead to shorter and more efficient code.
887 ///
888 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
889 /// If \c false is given, no range check is performed.
890 /// @param needle The character to search for.
891 /// @param startIdx The index in this to start searching the character.
892 /// @return This string's #Length if character \p{needle} is not found.
893 /// Otherwise the index of first occurrence.
894 template <typename TCheck= CHK>
895 integer IndexOfOrLength( TChar needle, integer startIdx ) const {
897 if constexpr ( TCheck::value ) {
898 // adjust range, if empty return -1
899 if ( startIdx < 0 ) startIdx= 0;
900 else if ( startIdx >= length ) return length;
901 } else {
902 ALIB_ASSERT_ERROR( startIdx >= 0 && startIdx < length, "STRINGS",
903 "Non checking and index out of range: 0 <= {} < {}.", startIdx, length )
904 }
905
906 const TChar* result= characters::Search( buffer + startIdx, length - startIdx, needle );
907 return result != nullptr ? result - buffer
908 : length;
909 }
910
911 /// Searches a character starting backwards from the end or a given start index.
912 ///
913 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
914 /// If \c false is given, no range check is performed.
915 /// Consequently, in this case, optional parameter startIndex must be
916 /// provided.
917 ///
918 /// @param needle The character to search for.
919 /// @param startIndex The index within this string to start searching the character.
920 /// Defaults to \alib{strings;MAX_LEN}.
921 ///
922 /// @return \c -1 if the character \p{needle} is not found.
923 /// Otherwise, the index of its last occurrence.
924 template <typename TCheck= CHK>
925 integer LastIndexOf( TChar needle, integer startIndex =MAX_LEN ) const {
927
928 if constexpr ( TCheck::value ) {
929 // adjust range, if empty return -1
930 if ( startIndex < 0 ) return -1;
931 if ( startIndex >= length ) startIndex= length-1;
932 } else {
933 ALIB_ASSERT_ERROR( startIndex >= 0 && startIndex < length, "STRINGS",
934 "Non checking and index out of range: 0 <= {} < {}.", startIndex, length )
935 }
936
937 while( startIndex >= 0 && buffer[ startIndex ] != needle )
938 --startIndex;
939
940 return startIndex;
941 }
942
943 /// Returns the index of the first character which is included, respectively <em>not</em>
944 /// included in a set of characters given as a
945 /// \ref alib_strings_cc_construction_string "string-like object".
946 ///
947 /// \note
948 /// In derived class \b %CString, a faster version of this method (using \c std::strpbrk()
949 /// respectively \c std::strspn()) is available.
950 /// So, if performance is important and repetitive calls are performed, it might be
951 /// advisable to hold this string and the needles in a zero-terminated string buffer,
952 /// for example, in an \b AString.
953 ///
954 /// This method searches forwards. For backwards search, see #LastIndexOf.
955 ///
956 /// @tparam TInclusion Denotes whether the search returns the first index that holds a value
957 /// that is included or that is not excluded in the set of needle
958 /// characters.
959 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
960 /// If \c <false> is given, no parameter checks are performed.
961 /// @param needles Pointer to a zero-terminated set of characters to be taken into
962 /// account.
963 /// @param startIdx The index to start the search at. If the given value is less than 0,
964 /// it is set to 0. If it exceeds the length of the string, the length of
965 /// the string is returned.
966 /// Defaults to 0.
967 ///
968 /// @return The index of the first character found which is included, respectively not
969 /// included, in the given set of characters.
970 /// If nothing is found, -1 is returned.
971 template <lang::Inclusion TInclusion,
972 typename TCheck = CHK>
973 integer IndexOfAny( const TString& needles, integer startIdx= 0 ) const {
974 if constexpr ( TCheck::value ) {
975 if ( startIdx < 0 ) startIdx= 0;
976 if ( startIdx >= length ) return -1;
977 } else {
978 ALIB_ASSERT_ERROR( startIdx >= 0 && startIdx < length && needles.Length() != 0,
979 "STRINGS", "Non checking and illegal parameters: 0 <= {} < {}. Needles: {}",
980 startIdx, length, needles.Length() )
981 }
982
983
984 integer idx= TInclusion == lang::Inclusion::Include
985 ? characters::IndexOfAnyIncluded( buffer + startIdx, length - startIdx, needles.Buffer(), needles.Length() )
986 : characters::IndexOfAnyExcluded( buffer + startIdx, length - startIdx, needles.Buffer(), needles.Length() );
987
988 return idx == -1 ? -1 : startIdx + idx;
989 }
990
991 /// Returns the index of the last character which is included, respectively <em>not</em>
992 /// included in set of characters given as a
993 /// \ref alib_strings_cc_construction_string "string-like object".
994 ///
995 /// This method searches backwards starting at the given index. For forwards search, see
996 /// #IndexOfAny.
997 ///
998 /// @tparam TInclusion Denotes whether the search returns the first index that holds a value
999 /// that is included or that is not excluded in the set of needle
1000 /// characters.
1001 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
1002 /// If \c <false> is given, no parameter checks are performed.
1003 /// @param needles Pointer to a zero-terminated set of characters to be searched for.
1004 /// @param startIdx The index to start the search at. The value is cropped to be in
1005 /// the bounds of 0 and the length of this object minus one.
1006 /// Defaults to \alib{strings;MAX_LEN}.
1007 ///
1008 /// @return The index of the first character found which is included, respectively not
1009 /// included, in the given set of characters.
1010 /// If nothing is found, -1 is returned.
1011 template <lang::Inclusion TInclusion,
1012 typename TCheck = CHK>
1013 integer LastIndexOfAny( const TString& needles, integer startIdx =MAX_LEN ) const {
1014 if constexpr ( TCheck::value ) {
1015 if ( startIdx < 0 ) return -1;
1016 if ( startIdx >= length ) startIdx= length - 1;
1017 } else {
1018 ALIB_ASSERT_ERROR( startIdx >= 0 && startIdx < length && needles.Length() != 0,
1019 "STRINGS", "Non checking and illegal parameters: 0 <= {} < {}. Needles: {}",
1020 startIdx, length, needles.Length() )
1021 }
1022
1023 if constexpr ( TInclusion == lang::Inclusion::Include )
1024 return characters::LastIndexOfAnyInclude( Buffer(), startIdx, needles.Buffer(), needles.Length() );
1025 else
1026 return characters::LastIndexOfAnyExclude( Buffer(), startIdx, needles.Buffer(), needles.Length() );
1027 }
1028
1029 /// Searches the given \ref alib_strings_cc_construction_string "string-like object"
1030 /// in this string.
1031 ///
1032 /// If \p{needle} is empty, the adjusted value of \p{startIdx} is returned.
1033 ///
1034 /// @tparam TSensitivity Case sensitivity of the comparison.
1035 /// Optional and defaults to \b Case::Sensitive.
1036 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
1037 /// If \c false is given, parameter \p{needle} must not be empty and
1038 /// \p{startIdx} must be in the range of [0 ... #Length() - needle.Length()].
1039 /// This also implies that this string must not be empty.
1040 /// @param needle The string to search for.
1041 /// @param startIdx The index to start the search at. Optional and defaults to \c 0.
1042 /// @param endIdx The index where the search ends. Precisely, the index of the
1043 /// first character that is not found.
1044 /// Defaults to \alib{strings;MAX_LEN}.
1045 ///
1046 /// @return If the checking of parameters failed or the string is not found, \c -1 is
1047 /// returned. Otherwise the index of the first occurrence of \p{needle}.
1048 template<typename TCheck = CHK,
1049 lang::Case TSensitivity = lang::Case::Sensitive>
1050 integer IndexOf( const TString& needle,
1051 integer startIdx= 0,
1052 integer endIdx = strings::MAX_LEN ) const {
1053 if constexpr ( TCheck::value ) {
1054 if ( needle.IsNull() )
1055 return -1;
1056 if ( startIdx < 0 ) startIdx= 0;
1057 endIdx= (std::min) (endIdx, length - needle.Length() + 1 );
1058 if ( startIdx >= endIdx ) return -1;
1059 } else {
1060 // this default parameter is still corrected. Optimized out anyhow.
1061 if( endIdx == strings::MAX_LEN)
1062 endIdx= length - needle.Length() + 1;
1063
1064 ALIB_ASSERT_ERROR( startIdx >= 0 && startIdx <= length
1065 && endIdx <= length
1066 && needle.IsNotNull(),
1067 "STRINGS", "Non checking and illegal parameters: 0 <= {} <= {}, {} <= {}. Needles: {}",
1068 startIdx, length, endIdx, length, needle.Length() )
1069 }
1070
1071
1072 return indexOfString<TSensitivity>(needle, startIdx, endIdx);
1073 }
1074
1075 /// Searches the first difference of a substring of this string and a
1076 /// \ref alib_strings_cc_construction_string "string-like object" given with parameter
1077 /// \p{needle}.
1078 /// If no difference is found, then the index of the first character behind the substring
1079 /// is returned.
1080 ///
1081 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
1082 /// If \c false is given, no range check is performed.
1083 /// @param needle The substring to search for.
1084 /// @param sensitivity Letter case sensitivity of the comparison.
1085 /// Optional and defaults to \b Case::Sensitive.
1086 /// @param startIdx The index in this string to start the comparison with \p{needle}.
1087 /// Optional and defaults to \c 0.
1088 ///
1089 /// @return The index of the first difference found or \p{idx} plus the length of \p{needle}.
1090 template <typename TCheck= CHK>
1092 lang::Case sensitivity = lang::Case::Sensitive,
1093 integer startIdx = 0 ) const {
1095
1096 if constexpr ( TCheck::value ) {
1097 // adjust range, if empty return -1
1098 if ( startIdx < 0 ) startIdx= 0;
1099 else if ( startIdx >= length ) return startIdx;
1100 } else {
1101 ALIB_ASSERT_ERROR( startIdx >= 0 && startIdx < length, "STRINGS",
1102 "Non checking and index out of range: 0 <= {} < {}.", startIdx, length )
1103 }
1104
1105 return characters::IndexOfFirstDifference( buffer + startIdx, length - startIdx,
1106 needle.buffer , needle.length,
1107 sensitivity );
1108 }
1109
1110 /// The method searches the next matching \p{closer}-character while taking nested pairs of
1111 /// \p{opener} and \p{closer} characters into account.
1112 ///
1113 /// Before the invocation of this method, the initial \p{opener} has to be known already
1114 /// and the given \p{idx} has to point to the first character behind the opener, where the
1115 /// search for an according \p{closer} is to be started.
1116 ///
1117 /// This method is useful to scan a string for pairs of opening and closing brackets, while
1118 /// the found segment may contain nested pairs of the same brackets.
1119 ///
1120 /// @param opener The character that represents the opening bracket, e.g., <c>'{'</c>.
1121 /// @param closer The character that represents the closing bracket, e.g., <c>'}'</c>.
1122 /// @param idx Index pointing to first character behind the (first) \p{opener}.
1123 ///
1124 /// @return The index of the corresponding closing character. If none was found, a negative
1125 /// value is returned.
1126 /// In the latter case the negated (absolute) value is indicating the number of
1127 /// still open (nested) brackets.
1128 integer IndexOfSegmentEnd( TChar opener, TChar closer, integer idx ) const;
1129
1130
1131 /// Counts all occurrences of character \p{needle} in the range from \p{startPos} to the end
1132 /// of the string.
1133 ///
1134 /// For empty strings \p{needle}, \c 0 is returned.
1135 ///
1136 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
1137 /// If \c false is given, no range check is performed.
1138 /// @param needle The character to search for.
1139 /// @param startPos The index to start the counting.
1140 /// Optional and defaults to \c 0.
1141 ///
1142 /// @return The index of the first difference in \p{needle}.
1143 template <typename TCheck= CHK>
1144 integer CountChar( TChar needle,
1145 integer startPos = 0 ) const {
1147 if constexpr ( TCheck::value ) {
1148 // adjust range, if empty return -1
1149 if ( startPos < 0 ) startPos= 0;
1150 else if ( startPos >= length ) return 0;
1151 } else {
1152 ALIB_ASSERT_ERROR( startPos >= 0 && startPos < length, "STRINGS",
1153 "Non checking and index out of range: 0 <= {} < {}.", startPos, length )
1154 }
1155
1156
1157 int result= 0;
1158 while( startPos < length && (startPos= IndexOf<NC>( needle, startPos )) >= 0 ) {
1159 ++startPos;
1160 ++result;
1161 }
1162
1163 return result;
1164 }
1165
1166 /// Counts all occurrences of character \p{needle}, unless followed by character \p{omit}
1167 /// in the range from \p{startPos} to the end of the string.
1168 ///
1169 /// For empty strings \p{needle}, \c 0 is returned.
1170 /// Also, for empty strings \p{omit}, \c 0 is returned.
1171 ///
1172 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
1173 /// If \c false is given, no range check is performed.
1174 /// @param needle The character to search for.
1175 /// @param omit Omit occurrence if the given character follows.
1176 /// @param startPos The index to start the counting.
1177 ///
1178 /// @return The index of the first difference in \p{needle}.
1179 template <typename TCheck= CHK>
1180 integer CountChar( TChar needle,
1181 TChar omit,
1182 integer startPos ) const {
1184 if constexpr ( TCheck::value ) {
1185 // adjust range, if empty return -1
1186 if ( startPos < 0 ) startPos= 0;
1187 else if ( startPos >= length ) return 0;
1188 } else {
1189 ALIB_ASSERT_ERROR( startPos >= 0 && startPos < length, "STRINGS",
1190 "Non checking and index out of range: 0 <= {} < {}.", startPos, length )
1191 }
1192
1193 int result= 0;
1194 while( startPos < length && (startPos= IndexOf<NC>( needle, startPos )) >= 0 ) {
1195 ++startPos;
1196 if( startPos < Length() && *(buffer + startPos) == omit )
1197 continue;
1198
1199 ++result;
1200 }
1201
1202 return result;
1203 }
1204
1205 /// Counts all occurrences of \p{needle} from \p{startPos} to the end of the string.
1206 ///
1207 /// For empty strings \p{needle}, \c 0 is returned.
1208 ///
1209 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
1210 /// If \c false is given, parameter \p{startIdx} must be valid and
1211 /// \p{needle} must not be empty.
1212 /// @tparam TSensitivity Case sensitivity of the comparison.
1213 /// Optional and defaults to \b Case::Sensitive.
1214 /// @param needle The string to search for.
1215 /// @param startPos The index to start the counting.
1216 /// Optional and defaults to \c 0.
1217 ///
1218 /// @return The index of the first difference in \p{needle}.
1219 template< typename TCheck = CHK,
1220 lang::Case TSensitivity = lang::Case::Sensitive >
1221 integer Count( const TString& needle,
1222 integer startPos = 0 ) const {
1224 integer nLen= needle.Length();
1225 if( nLen == 0 )
1226 return 0;
1227 if constexpr ( TCheck::value ) {
1228 if ( startPos < 0 ) startPos= 0;
1229 if ( startPos + nLen > length ) return 0;
1230 } else {
1231 ALIB_ASSERT_ERROR( startPos >= 0 && startPos < length, "STRINGS",
1232 "Non checking and index out of range: 0 <= {} < {}.", startPos, length )
1233 }
1234
1235 int result= 0;
1236 while( (startPos= IndexOf<NC, TSensitivity>( needle, startPos )) >= 0 ) {
1237 startPos+= needle.Length();
1238 ++result;
1239 }
1240
1241 return result;
1242 }
1243
1244 /// Counts all occurrences of \p{needle}, unless followed by \p{omit}, starting at
1245 /// \p{startPos} to the end of the string.
1246 ///
1247 /// For empty strings \p{needle}, \c 0 is returned.
1248 /// Also, for empty strings \p{omit}, \c 0 is returned.
1249 ///
1250 /// @tparam TSensitivity Case sensitivity of the comparison.
1251 /// Optional and defaults to \b Case::Sensitive.
1252 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
1253 /// If \c false is given, parameter \p{startPos} must be valid and
1254 /// \p{needle} must not be empty.
1255 /// @param needle The string to search for.
1256 /// @param omit Omit occurrence if the given string follows.
1257 /// @param startPos The index to start the counting.
1258 /// Optional and defaults to \c 0.
1259 ///
1260 /// @return The index of the first difference in \p{needle}.
1261 template<typename TCheck = CHK,
1262 lang::Case TSensitivity = lang::Case::Sensitive>
1263 integer Count( const TString& needle,
1264 const TString& omit,
1265 integer startPos = 0 ) const {
1267 integer nLen= needle.Length();
1268 if ( nLen == 0 )
1269 return 0;
1270 if constexpr ( TCheck::value ) {
1271 if ( startPos < 0 ) startPos= 0;
1272 if ( startPos + nLen > length ) return 0;
1273 } else {
1274 ALIB_ASSERT_ERROR( startPos >= 0 && startPos < length, "STRINGS",
1275 "Non checking and index out of range: 0 <= {} < {}.", startPos, length )
1276 }
1277
1278
1279 int result= 0;
1280 while( (startPos= IndexOf<NC , TSensitivity>( needle, startPos )) >= 0 ) {
1281 startPos+= nLen;
1282 if( startPos + omit.Length() <= Length()
1283 && ( omit.IsEmpty()
1284 || ContainsAt<NC>( omit, startPos ) ) )
1285 continue;
1286
1287 ++result;
1288 }
1289
1290 return result;
1291 }
1292
1293 //##############################################################################################
1294 /// @name Parsing Numbers
1295 //##############################################################################################
1296
1297 /// Parses an integral value consisting of characters \c '0' to \c '9' from this string.
1298 /// <br>Unlike with #ParseInt or #ParseDec, no sign, whitespaces, or group characters are
1299 /// accepted.
1300 ///
1301 /// @param startIdx The start index from where the integral value is tried to be parsed.
1302 /// Optional and defaults to \c 0.
1303 /// @param[out] newIdx Optional output variable that will point to the first character
1304 /// in this string after the float number that was parsed.
1305 /// If parsing fails, it will be set to the value of parameter startIdx.
1306 /// Therefore, this parameter can be used to check if a value was found.
1307 ///
1308 /// @return The parsed value. In addition, the parameter \p{newIdx} is set to point
1309 /// to the first character behind any found integer number.
1310 ALIB_DLL
1311 uint64_t ParseDecDigits( integer startIdx =0, integer* newIdx= nullptr ) const;
1312
1313
1314 /// Parses an integral value in decimal, binary, hexadecimal or octal format from
1315 /// the string
1316 ///
1317 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
1318 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
1319 /// which is configured to not using - and therefore also not parsing - grouping characters.
1320 ///
1321 /// Optional output parameter \p{newIdx} may be used to detect if parsing was successful.
1322 /// If not, it receives the value of \p{startIdx}, even if leading whitespaces had been
1323 /// read.
1324 ///
1325 /// For more information on number conversion, see class
1326 /// \alib{strings;TNumberFormat;NumberFormat}. All of its interface methods
1327 /// have a corresponding implementation within class \b %AString.
1328 ///
1329 /// @param startIdx The start index for parsing.
1330 /// Optional and defaults to \c 0.
1331 /// @param numberFormat The format definition. Defaults to \c nullptr.
1332 /// @param[out] newIdx Optional output variable that will point to the first
1333 /// character in this string after the number parsed.
1334 /// On failure, it will be set to the initial value \p{startIdx}.
1335 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1336 /// point to the first character behind the parsed number.
1337 ALIB_DLL
1338 int64_t ParseInt( integer startIdx =0, TNumberFormat<TChar>* numberFormat= nullptr,
1339 integer* newIdx= nullptr ) const;
1340
1341 /// Overloaded version of
1342 /// \alib{strings;TString::ParseInt(integer,TNumberFormat<TChar>*,integer*)const;ParseInt}
1343 /// providing default values for omitted parameters.
1344 ///
1345 /// @param numberFormat The format definition. Defaults to \c nullptr.
1346 /// @param[out] newIdx Optional output variable that will point to the first
1347 /// character in this string after the number parsed.
1348 /// On failure, it will be set to the initial value \c 0.
1349 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1350 /// point to the first character behind the parsed number.
1351 int64_t ParseInt( TNumberFormat<TChar>* numberFormat, integer* newIdx= nullptr ) const
1352 { return ParseInt( 0, numberFormat, newIdx ); }
1353
1354 /// Overloaded version of
1355 /// \alib{strings;TString::ParseInt(integer,TNumberFormat<TChar>*,integer*)const;ParseInt}
1356 /// providing default values for omitted parameters.
1357 ///
1358 /// @param[out] newIdx Optional output variable that will point to the first
1359 /// character in this string after the number parsed.
1360 /// On failure, it will be set to the initial value \c 0.
1361 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1362 /// point to the first character behind the parsed number.
1363 int64_t ParseInt( integer* newIdx ) const { return ParseInt( 0, nullptr, newIdx ); }
1364
1365
1366 /// Overloaded version of
1367 /// \alib{strings;TString::ParseInt(integer,TNumberFormat<TChar>*,integer*)const;ParseInt}
1368 /// providing default values for omitted parameters.
1369 ///
1370 /// @param startIdx The start index for parsing.
1371 /// Optional and defaults to \c 0.
1372 /// @param[out] newIdx Optional output variable that will point to the first
1373 /// character in this string after the number parsed.
1374 /// On failure, it will be set to the initial value \p{startIdx}.
1375 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1376 /// point to the first character behind the parsed number.
1377 int64_t ParseInt( integer startIdx, integer* newIdx ) const
1378 { return ParseInt( startIdx, nullptr, newIdx ); }
1379
1380 /// Reads an unsigned 64-bit integer in standard decimal format at the given position
1381 /// from this %AString.
1382 ///
1383 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
1384 /// \alib{strings;TNumberFormat::Computational}
1385 /// which is configured to not using - and therefore also not parsing - grouping characters.
1386 ///
1387 /// Optional output parameter \p{newIdx} may be used to detect if parsing was successful.
1388 /// If not, it receives the value of \p{startIdx}, even if leading whitespaces had been
1389 /// read.
1390 ///
1391 /// Sign literals \c '-' or \c '+' are \b not accepted and parsing will fail.
1392 /// For reading signed integral values, see methods #ParseInt, for floating point numbers
1393 /// #ParseFloat.
1394 ///
1395 /// For more information on number conversion, see class
1396 /// \alib{strings;TNumberFormat;NumberFormat}. All number-parsing interface methods
1397 /// have a corresponding implementation within this class.
1398 ///
1399 /// @param startIdx The start index for parsing.
1400 /// Optional and defaults to \c 0.
1401 /// @param numberFormat The format definition. Defaults to \c nullptr.
1402 /// @param[out] newIdx Optional output variable that will point to the first
1403 /// character in this string after the number parsed.
1404 /// On failure, it will be set to the initial value \p{startIdx}.
1405 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1406 /// point to the first character behind the parsed number.
1407 ALIB_DLL
1408 uint64_t ParseDec( integer startIdx =0, TNumberFormat<TChar>* numberFormat= nullptr,
1409 integer* newIdx= nullptr ) const;
1410
1411 /// Overloaded version of
1412 /// \alib{strings;TString::ParseDec(integer,TNumberFormat<TChar>*,integer*)const;ParseDec}
1413 /// providing default values for omitted parameters.
1414 ///
1415 /// @param numberFormat The format definition. Defaults to \c nullptr.
1416 /// @param[out] newIdx Optional output variable that will point to the first
1417 /// character in this string after the number parsed.
1418 /// On failure, it will be set to the initial value \c 0.
1419 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1420 /// point to the first character behind the parsed number.
1421 uint64_t ParseDec( TNumberFormat<TChar>* numberFormat, integer* newIdx= nullptr ) const
1422 { return ParseDec( 0, numberFormat, newIdx ); }
1423
1424 /// Overloaded version of
1425 /// \alib{strings;TString::ParseDec(integer,TNumberFormat<TChar>*,integer*)const;ParseDec}
1426 /// providing default values for omitted parameters.
1427 ///
1428 /// @param[out] newIdx Optional output variable that will point to the first
1429 /// character in this string after the number parsed.
1430 /// On failure, it will be set to the initial value \c 0.
1431 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1432 /// point to the first character behind the parsed number.
1433 uint64_t ParseDec( integer* newIdx ) const { return ParseDec( 0, nullptr, newIdx ); }
1434
1435
1436 /// Overloaded version of
1437 /// \alib{strings;TString::ParseDec(integer,TNumberFormat<TChar>*,integer*)const;ParseDec}
1438 /// providing default values for omitted parameters.
1439 ///
1440 /// @param startIdx The start index for parsing.
1441 /// Optional and defaults to \c 0.
1442 /// @param[out] newIdx Optional output variable that will point to the first
1443 /// character in this string after the number parsed.
1444 /// On failure, it will be set to the initial value \p{startIdx}.
1445 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1446 /// point to the first character behind the parsed number.
1447 uint64_t ParseDec( integer startIdx, integer* newIdx ) const
1448 { return ParseDec( startIdx, nullptr, newIdx ); }
1449
1450 /// Reads an unsigned 64-bit integer in binary format at the given position
1451 /// from this string.
1452 ///
1453 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
1454 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
1455 /// which is configured to not using - and therefore also not parsing - grouping characters.
1456 ///
1457 /// Optional output parameter \p{newIdx} may be used to detect if parsing was successful.
1458 /// If not, it receives the value of \p{startIdx}, even if leading whitespaces had been
1459 /// read.
1460 ///
1461 /// For more information on number conversion, see class
1462 /// \alib{strings;TNumberFormat;NumberFormat}. All number-parsing interface methods
1463 /// have a corresponding implementation within this class.
1464 ///
1465 /// @param startIdx The start index for parsing.
1466 /// Optional and defaults to \c 0.
1467 /// @param numberFormat The format definition. Defaults to \c nullptr.
1468 /// @param[out] newIdx Optional output variable that will point to the first
1469 /// character in this string after the number parsed.
1470 /// On failure, it will be set to the initial value \p{startIdx}.
1471 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1472 /// point to the first character behind the parsed number.
1473 ALIB_DLL
1474 uint64_t ParseBin( integer startIdx =0, TNumberFormat<TChar>* numberFormat= nullptr,
1475 integer* newIdx= nullptr ) const;
1476
1477
1478 /// Overloaded version of
1479 /// \alib{strings;TString::ParseBin(integer,TNumberFormat<TChar>*,integer*)const;ParseBin}
1480 /// providing default values for omitted parameters.
1481 ///
1482 /// @param numberFormat The format definition. Defaults to \c nullptr.
1483 /// @param[out] newIdx Optional output variable that will point to the first
1484 /// character in this string after the number parsed.
1485 /// On failure, it will be set to the initial value \c 0.
1486 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1487 /// point to the first character behind the parsed number.
1488 uint64_t ParseBin( TNumberFormat<TChar>* numberFormat, integer* newIdx= nullptr ) const
1489 { return ParseBin( 0, numberFormat, newIdx ); }
1490
1491 /// Overloaded version of
1492 /// \alib{strings;TString::ParseBin(integer,TNumberFormat<TChar>*,integer*)const;ParseBin}
1493 /// providing default values for omitted parameters.
1494 ///
1495 /// @param[out] newIdx Optional output variable that will point to the first
1496 /// character in this string after the number parsed.
1497 /// On failure, it will be set to the initial value \c 0.
1498 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1499 /// point to the first character behind the parsed number.
1500 uint64_t ParseBin( integer* newIdx ) const { return ParseBin( 0, nullptr, newIdx ); }
1501
1502
1503 /// Overloaded version of
1504 /// \alib{strings;TString::ParseBin(integer,TNumberFormat<TChar>*,integer*)const;ParseBin}
1505 /// providing default values for omitted parameters.
1506 ///
1507 /// @param startIdx The start index for parsing.
1508 /// Optional and defaults to \c 0.
1509 /// @param[out] newIdx Optional output variable that will point to the first
1510 /// character in this string after the number parsed.
1511 /// On failure, it will be set to the initial value \p{startIdx}.
1512 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1513 /// point to the first character behind the parsed number.
1514 uint64_t ParseBin( integer startIdx, integer* newIdx ) const
1515 { return ParseBin( startIdx, nullptr, newIdx ); }
1516
1517 /// Reads an unsigned 64-bit integer in hexadecimal format at the given position
1518 /// from this string.
1519 ///
1520 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
1521 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
1522 /// which is configured to not using - and therefore also not parsing - grouping characters.
1523 ///
1524 /// Optional output parameter \p{newIdx} may be used to detect if parsing was successful.
1525 /// If not, it receives the value of \p{startIdx}, even if leading whitespaces had been
1526 /// read.
1527 ///
1528 /// For more information on number conversion, see class
1529 /// \alib{strings;TNumberFormat;NumberFormat}. All number-parsing interface methods
1530 /// have a corresponding implementation within this class.
1531 ///
1532 /// @param startIdx The start index for parsing.
1533 /// Optional and defaults to \c 0.
1534 /// @param numberFormat The format definition. Defaults to \c nullptr.
1535 /// @param[out] newIdx Optional output variable that will point to the first
1536 /// character in this string after the number parsed.
1537 /// On failure, it will be set to the initial value \p{startIdx}.
1538 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1539 /// point to the first character behind the parsed number.
1540 ALIB_DLL
1541 uint64_t ParseHex( integer startIdx =0, TNumberFormat<TChar>* numberFormat= nullptr,
1542 integer* newIdx= nullptr ) const;
1543
1544
1545 /// Overloaded version of
1546 /// \alib{strings;TString::ParseHex(integer,TNumberFormat<TChar>*,integer*)const;ParseHex}
1547 /// providing default values for omitted parameters.
1548 ///
1549 /// @param numberFormat The format definition. Defaults to \c nullptr.
1550 /// @param[out] newIdx Optional output variable that will point to the first
1551 /// character in this string after the number parsed.
1552 /// On failure, it will be set to the initial value \c 0.
1553 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1554 /// point to the first character behind the parsed number.
1555 uint64_t ParseHex( TNumberFormat<TChar>* numberFormat, integer* newIdx= nullptr ) const
1556 { return ParseHex( 0, numberFormat, newIdx ); }
1557
1558 /// Overloaded version of
1559 /// \alib{strings;TString::ParseHex(integer,TNumberFormat<TChar>*,integer*)const;ParseHex}
1560 /// providing default values for omitted parameters.
1561 ///
1562 /// @param[out] newIdx Optional output variable that will point to the first
1563 /// character in this string after the number parsed.
1564 /// On failure, it will be set to the initial value \c 0.
1565 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1566 /// point to the first character behind the parsed number.
1567 uint64_t ParseHex( integer* newIdx ) const { return ParseHex( 0, nullptr, newIdx ); }
1568
1569
1570 /// Overloaded version of
1571 /// \alib{strings;TString::ParseHex(integer,TNumberFormat<TChar>*,integer*)const;ParseHex}
1572 /// providing default values for omitted parameters.
1573 ///
1574 /// @param startIdx The start index for parsing.
1575 /// Optional and defaults to \c 0.
1576 /// @param[out] newIdx Optional output variable that will point to the first
1577 /// character in this string after the number parsed.
1578 /// On failure, it will be set to the initial value \p{startIdx}.
1579 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1580 /// point to the first character behind the parsed number.
1581 uint64_t ParseHex( integer startIdx, integer* newIdx ) const
1582 { return ParseHex( startIdx, nullptr, newIdx ); }
1583
1584 /// Reads an unsigned 64-bit integer in octal format at the given position
1585 /// from this string.
1586 ///
1587 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
1588 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
1589 /// which is configured to not using - and therefore also not parsing - grouping characters.
1590 ///
1591 /// Optional output parameter \p{newIdx} may be used to detect if parsing was successful.
1592 /// If not, it receives the value of \p{startIdx}, even if leading whitespaces had been
1593 /// read.
1594 ///
1595 /// For more information on number conversion, see class
1596 /// \alib{strings;TNumberFormat;NumberFormat}. All number-parsing interface methods
1597 /// have a corresponding implementation within this class.
1598 ///
1599 /// @param startIdx The start index for parsing.
1600 /// Optional and defaults to \c 0.
1601 /// @param numberFormat The format definition. Defaults to \c nullptr.
1602 /// @param[out] newIdx Optional output variable that will point to the first
1603 /// character in this string after the number parsed.
1604 /// On failure, it will be set to the initial value \p{startIdx}.
1605 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1606 /// point to the first character behind the parsed number.
1607 ALIB_DLL
1608 uint64_t ParseOct( integer startIdx =0, TNumberFormat<TChar>* numberFormat= nullptr,
1609 integer* newIdx= nullptr ) const;
1610
1611
1612 /// Overloaded version of
1613 /// \alib{strings;TString::ParseOct(integer,TNumberFormat<TChar>*,integer*)const;ParseOct}
1614 /// providing default values for omitted parameters.
1615 ///
1616 /// @param numberFormat The format definition. Defaults to \c nullptr.
1617 /// @param[out] newIdx Optional output variable that will point to the first
1618 /// character in this string after the number parsed.
1619 /// On failure, it will be set to the initial value \c 0.
1620 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1621 /// point to the first character behind the parsed number.
1622 uint64_t ParseOct( TNumberFormat<TChar>* numberFormat, integer* newIdx= nullptr ) const
1623 { return ParseOct( 0, numberFormat, newIdx ); }
1624
1625 /// Overloaded version of
1626 /// \alib{strings;TString::ParseOct(integer,TNumberFormat<TChar>*,integer*)const;ParseOct}
1627 /// providing default values for omitted parameters.
1628 ///
1629 /// @param[out] newIdx Optional output variable that will point to the first
1630 /// character in this string after the number parsed.
1631 /// On failure, it will be set to the initial value \c 0.
1632 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1633 /// point to the first character behind the parsed number.
1634 uint64_t ParseOct( integer* newIdx ) const { return ParseOct( 0, nullptr, newIdx ); }
1635
1636
1637 /// Overloaded version of
1638 /// \alib{strings;TString::ParseOct(integer,TNumberFormat<TChar>*,integer*)const;ParseOct}
1639 /// providing default values for omitted parameters.
1640 ///
1641 /// @param startIdx The start index for parsing.
1642 /// Optional and defaults to \c 0.
1643 /// @param[out] newIdx Optional output variable that will point to the first
1644 /// character in this string after the number parsed.
1645 /// On failure, it will be set to the initial value \p{startIdx}.
1646 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1647 /// point to the first character behind the parsed number.
1648 uint64_t ParseOct( integer startIdx, integer* newIdx ) const
1649 { return ParseOct( startIdx, nullptr, newIdx ); }
1650
1651 /// Reads a floating point number at the given position from this string.
1652 ///
1653 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
1654 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
1655 /// which is configured to 'international' settings (not using the locale) and therefore
1656 /// also not parsing grouping characters.
1657 ///
1658 /// Optional output parameter \p{newIdx} may be used to detect if parsing was successful.
1659 /// If not, it receives the value of \p{startIdx}, even if leading whitespaces had been
1660 /// read.
1661 ///
1662 /// For more information on number conversion, see class
1663 /// \alib{strings;TNumberFormat;NumberFormat}. All number-parsing interface methods
1664 /// have a corresponding implementation within this class.
1665 ///
1666 /// @param startIdx The start index for parsing.
1667 /// Optional and defaults to \c 0.
1668 /// @param numberFormat The format definition. Defaults to \c nullptr.
1669 /// @param[out] newIdx Optional output variable that will point to the first
1670 /// character in this string after the number parsed.
1671 /// On failure, it will be set to the initial value \p{startIdx}.
1672 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1673 /// point to the first character behind the parsed number.
1674 ALIB_DLL
1675 double ParseFloat( integer startIdx =0, TNumberFormat<TChar>* numberFormat= nullptr,
1676 integer* newIdx= nullptr ) const;
1677
1678 /// Overloaded version of
1679 /// \alib{strings;TString::ParseFloat(integer,TNumberFormat<TChar>*,integer*)const;ParseFloat}
1680 /// providing default values for omitted parameters.
1681 ///
1682 /// @param numberFormat The format definition. Defaults to \c nullptr.
1683 /// @param[out] newIdx Optional output variable that will point to the first
1684 /// character in this string after the number parsed.
1685 /// On failure, it will be set to the initial value \c 0.
1686 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1687 /// point to the first character behind the parsed number.
1688 double ParseFloat( TNumberFormat<TChar>* numberFormat, integer* newIdx= nullptr ) const
1689 { return ParseFloat( 0, numberFormat, newIdx ); }
1690
1691 /// Overloaded version of
1692 /// \alib{strings;TString::ParseFloat(integer,TNumberFormat<TChar>*,integer*)const;ParseFloat}
1693 /// providing default values for omitted parameters.
1694 ///
1695 /// @param[out] newIdx Optional output variable that will point to the first
1696 /// character in this string after the number parsed.
1697 /// On failure, it will be set to the initial value \c 0.
1698 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1699 /// point to the first character behind the parsed number.
1700 double ParseFloat( integer* newIdx ) const { return ParseFloat( 0, nullptr, newIdx ); }
1701
1702
1703 /// Overloaded version of
1704 /// \alib{strings;TString::ParseFloat(integer,TNumberFormat<TChar>*,integer*)const;ParseFloat}
1705 /// providing default values for omitted parameters.
1706 ///
1707 /// @param startIdx The start index for parsing.
1708 /// Optional and defaults to \c 0.
1709 /// @param[out] newIdx Optional output variable that will point to the first
1710 /// character in this string after the number parsed.
1711 /// On failure, it will be set to the initial value \p{startIdx}.
1712 /// @return The parsed value. In addition, the output parameter \b newIdx is set to
1713 /// point to the first character behind the parsed number.
1714 double ParseFloat( integer startIdx, integer* newIdx ) const
1715 { return ParseFloat( startIdx, nullptr, newIdx ); }
1716
1717 //##############################################################################################
1718 /// @name Conversion
1719 //##############################################################################################
1720
1721 /// Copies this string's contents into a given character buffer.
1722 /// It is the caller's responsibility that \p{dest} is large enough, write-enabled, etc.
1723 ///
1724 /// @param dest The destination buffer.
1725 /// @return The length of this string.
1726 integer CopyTo( TChar* dest ) const {
1727 characters::Copy( buffer, length, dest );
1728 return length;
1729 }
1730
1731 /// Sets this String to a copy of the given string, allocated in given \p{allocator}.
1732 ///
1733 /// \note
1734 /// In case the given \p{copy} is empty or nulled, no allocation is performed and this
1735 /// string is set to empty. Still, the pointer to the buffer is copied.
1736 /// Thus, this string behaves in respect to the method #IsNull the same as the given
1737 /// string \p{copy}.
1738 ///
1739 /// @tparam TAllocator The type of the given \p{allocator}, as prototyped with
1740 /// \alib{lang;Allocator}. Deduced by the compiler.
1741 /// @param allocator The allocator to use.
1742 /// @param copy The string to copy to the new memory allocated.
1743 template<typename TAllocator>
1745 void Allocate( TAllocator& allocator, const TString<TChar>& copy ) {
1746 if( (length= copy.length) == 0 ) {
1747 buffer= copy.buffer;
1748 return;
1749 }
1750
1751 auto* newBuf= allocator().template AllocArray<TChar>( copy.length );
1752 copy.CopyTo( newBuf );
1753 buffer= newBuf;
1754 }
1755
1756 /// Deallocates this String's memory in \p{allocator} and sets this instance to \e nulled.
1757 /// \note
1758 /// In case this instance is empty or nulled, no deallocation is performed.
1759 /// This should not happen with due usage, which is:
1760 /// - A string is allocated using the method #Allocate on another instance.
1761 /// - For the allocated string, this method is to be called, passing the same allocator.
1762 ///
1763 /// \note
1764 /// Nevertheless, because the method #Allocate likewise does not perform an allocation call
1765 /// in the case an empty string was given, it is valid use to allocate and later deallocate
1766 /// empty strings.
1767 /// @tparam TAllocator The type of the given \p{allocator}, as prototyped with
1768 /// \alib{lang;Allocator}. Deduced by the compiler.
1769 /// @param allocator The allocator to use.
1770 template<typename TAllocator>
1772 void Free( TAllocator& allocator ) {
1773 if( length == 0 || buffer == nullptr )
1774 return;
1775 allocator().FreeArray( buffer, length );
1776 }
1777
1778 public:
1779 //##############################################################################################
1780 /// @name Helper Methods
1781 //##############################################################################################
1782
1783 /// Adjusts a region given as in/out parameters, to fit to this object's range [0..length].
1784 ///
1785 /// @param[in,out] regionStart The proposed region start which might get adjusted to fit to
1786 /// range [0..length].
1787 /// @param[in,out] regionLength The proposed region length which might get adjusted to fit to
1788 /// range [0..length].
1789 ///
1790 /// @return Returns \c true, if the adjusted region is empty.
1791 bool AdjustRegion( integer& regionStart, integer& regionLength ) const {
1792 // if start exceeds string, set to empty range at the end of the string and return true
1793 if (regionStart >= length) {
1794 regionStart= length;
1795 regionLength= 0;
1796 return true; // indicate empty
1797 }
1798
1799 // if negative start, cut it from the length
1800 if (regionStart < 0 ) {
1801 regionLength+= regionStart;
1802 regionStart= 0;
1803 }
1804
1805 // adjust length
1806 if ( regionLength < 0 ) {
1807 regionLength= 0;
1808 return true;
1809 }
1810
1811 integer maxRegionLength= length - regionStart;
1812 if ( regionLength > maxRegionLength )
1813 regionLength= maxRegionLength;
1814
1815 // return true if adjusted region is empty
1816 return regionLength == 0;
1817 }
1818
1819 //################################################################################################
1820 // std::iterator_traits
1821 //################################################################################################
1822
1823 /// Implementation of \c std::iterator_traits for class \b %TString and its descendents.
1824 /// Base class \b String exposes #const_iterator which uses
1825 /// <c>const TChar*</c> and <c>const TChar&</c> for template types \p{TPointer} and
1826 /// \p{TReference}. Descendant classes may expose a mutable
1827 /// version (e.g., \alib{strings;TAString;AString}).
1828 ///
1829 /// As the name of the class indicates, this iterator satisfies the C++ standard library
1830 /// concept
1831 /// \https{RandomAccessIterator,en.cppreference.com/w/cpp/concept/RandomAccessIterator}.
1832 template<typename TCharConstOrMutable>
1834 {
1835 public:
1836 using iterator_category = std::random_access_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
1837 using value_type = TCharConstOrMutable; ///< Implementation of <c>std::iterator_traits</c>.
1838 using difference_type = integer; ///< Implementation of <c>std::iterator_traits</c>.
1839 using pointer = TCharConstOrMutable*; ///< Implementation of <c>std::iterator_traits</c>.
1840 using reference = TCharConstOrMutable&; ///< Implementation of <c>std::iterator_traits</c>.
1841
1842 protected:
1843 /// The pointer into the buffer is all we store.
1844 TCharConstOrMutable* p;
1845 public:
1846 /// Constructor.
1847 /// @param start Pointer to the initial character.
1848 explicit TRandomAccessIterator( TCharConstOrMutable* start = nullptr ) : p(start) {}
1849
1850 //############################ To satisfy concept of InputIterator ##########################
1851
1852 /// Prefix increment operator.
1853 /// @return A reference to this object.
1854 TRandomAccessIterator& operator++() { ++p; return *this; }
1855
1856 /// Postfix increment operator.
1857 /// @return An iterator value that is not increased, yet.
1859
1860 /// Comparison operator.
1861 /// @param other The iterator to compare ourselves to.
1862 /// @return \c true if this and the given iterator are pointing to the same character
1863 /// in the same array, \c false otherwise.
1864 bool operator==(TRandomAccessIterator other) const { return p == other.p; }
1865
1866 /// Comparison operator.
1867 /// @param other The iterator to compare ourselves to.
1868 /// @return \c true if this and given iterator are not equal, \c false otherwise.
1869 bool operator!=(TRandomAccessIterator other) const { return !(*this == other); }
1870
1871 /// Retrieves the character that this iterator references.
1872 /// @return The character value.
1873 TCharConstOrMutable& operator*() const { return *p; }
1874
1875 /// Retrieves the character that this iterator references.
1876 /// @return The character value.
1877 TCharConstOrMutable& operator*() { return *p; }
1878
1879
1880 //######################## To satisfy concept of BidirectionalIterator ######################
1881
1882 /// Prefix decrement operator.
1883 /// @return A reference to this object.
1884 TRandomAccessIterator& operator--() { --p; return *this; }
1885
1886
1887 /// Postfix decrement operator.
1888 /// @return The iterator value prior the decrement operation.
1890
1891
1892 //######################## To satisfy concept of RandomAccessIterator #######################
1893
1894 /// Addition assignment.
1895 /// @param n The value to subtract.
1896 /// @return A reference to this iterator.
1897 TRandomAccessIterator& operator+=(integer n) { p+= n; return *this; }
1898
1899 /// Subtraction assignment.
1900 /// @param n The value to subtract.
1901 /// @return A reference to this iterator.
1902 TRandomAccessIterator& operator-=(integer n) { p-= n; return *this; }
1903
1904 /// Addition.
1905 /// @param n The value to subtract.
1906 /// @return The resulting iterator value.
1908
1909 /// Subtraction.
1910 /// @param n The value to subtract.
1911 /// @return The resulting iterator value.
1913
1914 /// Difference (distance) from this iterator to the given one.
1915 /// @param other The iterator to subtract
1916 /// @return The difference between (distance of) this and the given iterator.
1917 integer operator-(TRandomAccessIterator other) const { return p - other.p; }
1918
1919 /// Subscript operator.
1920 /// @param n The distance to add.
1921 /// @return Reference to the character referenced by this iterator plus the distance
1922 /// given.
1923 TCharConstOrMutable& operator[]( integer n ) const { return *( p + n ); }
1924
1925 //#### Comparison operators (also needed to satisfy concept of RandomAccessIterator) ###
1926
1927 /// Compares this iterator with the given one.
1928 /// @param other The iterator to compare
1929 /// @return \c true if this iterator is \e smaller than \p{other},
1930 /// \c false otherwise.
1931 bool operator<(TRandomAccessIterator other) const { return p < other.p; }
1932
1933 /// Compares this iterator with the given one.
1934 /// @param other The iterator to compare
1935 /// @return \c true if this iterator is \e smaller than or equal to \p{other},
1936 /// \c false otherwise.
1937 bool operator<=(TRandomAccessIterator other) const { return p <= other.p; }
1938
1939 /// Compares this iterator with the given one.
1940 /// @param other The iterator to compare
1941 /// @return \c true if this iterator is \e greater than \p{other},
1942 /// \c false otherwise.
1943 bool operator>(TRandomAccessIterator other) const { return p > other.p; }
1944
1945 /// Compares this iterator with the given one.
1946 /// @param other The iterator to compare
1947 /// @return \c true if this iterator is \e greater than or equal to \p{other},
1948 /// \c false otherwise.
1949 bool operator>=(TRandomAccessIterator other) const { return p >= other.p; }
1950 };
1951
1952 /// The constant iterator exposed by this character container. A Mutable version is
1953 /// found only in descendant classes (e.g., \alib{strings;TAString;AString}).
1954 using const_iterator = TRandomAccessIterator<const TChar>;
1955
1956 /// The constant reverse iterator exposed by this character container. A Mutable version is
1957 /// found only in descendant classes (e.g., \alib{strings;TAString;AString}).
1958 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1959
1960
1961 //##############################################################################################
1962 /// @name std::iterator_traits
1963 /// @{
1964 //##############################################################################################
1965 /// Returns an iterator pointing to a constant character at the start of this string.
1966 /// @return The start of this string.
1968
1969 /// Returns an iterator pointing to a constant character at the start of this string.
1970 /// @return The start of this string.
1972
1973 /// Returns an iterator pointing behind this string.
1974 /// @return The end of this string.
1976
1977 /// Returns an iterator pointing behind this string.
1978 /// @return The end of this string.
1981 /// Returns a reverse iterator pointing to a constant character at the end of this string.
1982 /// @return The last character of this string.
1984
1985 /// Returns a reverse iterator pointing before the start of this string.
1986 /// @return The character before this string.
1988
1989 /// Returns a reverse iterator pointing to a constant character at the end of this string.
1990 /// @return The last character of this string.
1992
1993 /// Returns a reverse iterator pointing before the start of this string.
1994 /// @return The character before this string.
1996
1997 /// Returns #Length as \c size_t. Added for compatibility with the standard library.
1998 /// @return The character before this string.
1999 size_type size() const { return Length(); }
2000
2001 //##############################################################################################
2002 /// @}
2003 //##############################################################################################
2004
2005 /// Constructs this string using start and end iterators.
2006 ///
2007 /// @param start An iterator referencing the start of the string.
2008 /// @param end An iterator referencing the end of the string.
2010 : buffer( &*start)
2011 , length( end-start >= 0 ? end-start : 0 ) {}
2012
2013 protected:
2014 #if !DOXYGEN
2015 ALIB_WARNINGS_IGNORE_DOCS // needed due to a bug in current clang
2016 #endif
2017
2018 /// Implementation of the substring search function.
2019 /// \attention This protected method expects valid (in range) parameters!
2020 /// Parameter \p{endIdx} must be smaller or equal to the length of this string
2021 /// minus the length of \p{needle} plus \c 1.
2022 /// @tparam TSensitivity The letter case sensitivity of the search.
2023 /// @param needle The substring to search.
2024 /// @param startIdx The start index of the search.
2025 /// @param endIdx The index where the search ends. Precisely, the index of the
2026 /// first character that is not found.
2027 /// @return The index of the first occurrence of \p{needle}, respectively \c -1 if not found.
2028 template<lang::Case TSensitivity =lang::Case::Sensitive>
2030 indexOfString( const TString& needle, integer startIdx, integer endIdx ) const;
2031
2032 #if !DOXYGEN
2034 #endif
2035}; // class TString
2036
2037//##################################################################################################
2038// Specializations of ArrayTraits for class TString
2039//##################################################################################################
2040} namespace alib::characters {
2041
2042#if !DOXYGEN
2043template<typename TChar> struct ArrayTraits<strings::TString<TChar>, TChar>
2044{
2045 using T= strings::TString<TChar>;
2046 static constexpr Policy Access = Policy::Implicit;
2047 static constexpr Policy Construction = Policy::Implicit;
2048 static constexpr const TChar* Buffer (const T& src) { return src.Buffer(); }
2049 static constexpr integer Length (const T& src) { return src.Length(); }
2050 static constexpr T Construct(const TChar* b, integer l) { return T(b, l); }
2051};
2052
2053template<typename TChar> struct ZTArrayTraits<strings::TString<TChar>, TChar>
2054{
2055 using T= strings::TString<TChar>;
2056 static constexpr Policy Access = Policy::ExplicitOnly;
2057 static constexpr Policy Construction = Policy::ExplicitOnly;
2058 static constexpr const TChar* Buffer(const T& src) { return src.Buffer(); }
2059 static constexpr integer Length(const T& src) { return src.Length(); }
2060 static constexpr T Construct(const TChar* b, integer l ) { return T(b, l); }
2061};
2062#endif // !DOXYGEN
2063
2064} namespace alib::strings {
2065//##################################################################################################
2066/// @name Comparison Operators
2067//##################################################################################################
2068#if DOXYGEN
2069
2070//==================================================================================================
2071/// Starship operator and <c>==</c> operator for \alib Strings and compatible types.
2072///
2073/// The operators use methods
2074/// \alib{strings::TString;Equals;lhs.Equals<CHK, lang::Case::Sensitive>(rhs)}, and
2075/// \alib{strings::TString;CompareTo;lhs.CompareTo<CHK, lang::Case::Sensitive>(rhs)} for evaluation.
2076///
2077/// For performance-critical sections, the original methods may be used where template
2078/// parameter \p{TCheck} can be set to \alib{NC}.
2079///
2080/// \note For avoiding redundancy, only <c>operator<=></c> is listed here in the documentation.
2081/// Internally, different overloads with different requirements are used and, of course,
2082/// <b>operator==</b> is likewise given.<br>
2083/// Furthermore, all operators are available for the derived string types
2084/// \b %CString, \b %AString and \b %Substring likewise.
2085///
2086/// @param lhs The left-hand operand of string-like type.
2087/// @param rhs The right-hand operand of string-like type.
2088/// @returns The result of the comparison.
2089//==================================================================================================
2090auto operator<=> (const String& lhs, const String& rhs) {}
2091#else
2092
2093// Note(25/01/17):
2094// Clang strangely did not find the following templated operators when they resided in an
2095// exported namespace.
2096// The workaround was to not export the namespace but export each operator instead.
2097// We think this is wrong behavior and not aligned with the language specification.
2098} namespace alib::strings {
2099
2101template<typename TChar>
2102bool operator== (const TString<TChar>& lhs, const TString<TChar>& rhs)
2103{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
2104
2106template<typename TChar, typename T>
2107requires (!std::is_same_v<T, TString<TChar>>)
2108bool operator== (const TString<TChar>& lhs, const T& rhs)
2109{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
2110
2112template<typename TChar>
2113auto operator<=> (const TString<TChar>& lhs, const TString<TChar>& rhs)
2114{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
2115
2117template<typename TChar, typename T>
2118requires (!std::same_as<TString<TChar>, T>)
2119auto operator<=> (const TString<TChar>& lhs, const T& rhs)
2120{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
2121
2122} ALIB_EXPORT namespace alib::strings {
2123#endif // DOXYGEN
2124
2125
2126//##################################################################################################
2127// Template instantiation declarations
2128//##################################################################################################
2129#if !DOXYGEN
2130
2131template<> ALIB_DLL integer TString<nchar>::WStringLength () const;
2132extern template ALIB_DLL integer TString<nchar>::indexOfString<lang::Case::Sensitive>( const TString<nchar >&, integer, integer ) const;
2133extern template ALIB_DLL integer TString<nchar>::indexOfString<lang::Case::Ignore >( const TString<nchar >&, integer, integer ) const;
2134extern template ALIB_DLL integer TString<nchar>::IndexOfSegmentEnd ( nchar, nchar, integer ) const;
2135extern template ALIB_DLL uint64_t TString<nchar>::ParseDecDigits ( integer, integer* ) const;
2136extern template ALIB_DLL int64_t TString<nchar>::ParseInt ( integer, TNumberFormat<nchar>*, integer* ) const;
2137extern template ALIB_DLL uint64_t TString<nchar>::ParseDec ( integer, TNumberFormat<nchar>*, integer* ) const;
2138extern template ALIB_DLL uint64_t TString<nchar>::ParseBin ( integer, TNumberFormat<nchar>*, integer* ) const;
2139extern template ALIB_DLL uint64_t TString<nchar>::ParseHex ( integer, TNumberFormat<nchar>*, integer* ) const;
2140extern template ALIB_DLL uint64_t TString<nchar>::ParseOct ( integer, TNumberFormat<nchar>*, integer* ) const;
2141extern template ALIB_DLL double TString<nchar>::ParseFloat ( integer, TNumberFormat<nchar>*, integer* ) const;
2142extern template ALIB_DLL size_t TString<nchar>::Hashcode () const;
2143extern template ALIB_DLL size_t TString<nchar>::HashcodeIgnoreCase () const;
2144
2145template<> inline integer TString<wchar>::WStringLength () const { return length; }
2146extern template ALIB_DLL integer TString<wchar>::indexOfString<lang::Case::Sensitive>(const TString<wchar>&, integer, integer ) const;
2147extern template ALIB_DLL integer TString<wchar>::indexOfString<lang::Case::Ignore >(const TString<wchar>&, integer, integer ) const;
2148extern template ALIB_DLL integer TString<wchar>::IndexOfSegmentEnd (wchar, wchar, integer ) const;
2149extern template ALIB_DLL uint64_t TString<wchar>::ParseDecDigits ( integer, integer* ) const;
2150extern template ALIB_DLL int64_t TString<wchar>::ParseInt ( integer, TNumberFormat<wchar>*, integer* ) const;
2151extern template ALIB_DLL uint64_t TString<wchar>::ParseDec ( integer, TNumberFormat<wchar>*, integer* ) const;
2152extern template ALIB_DLL uint64_t TString<wchar>::ParseBin ( integer, TNumberFormat<wchar>*, integer* ) const;
2153extern template ALIB_DLL uint64_t TString<wchar>::ParseHex ( integer, TNumberFormat<wchar>*, integer* ) const;
2154extern template ALIB_DLL uint64_t TString<wchar>::ParseOct ( integer, TNumberFormat<wchar>*, integer* ) const;
2155extern template ALIB_DLL double TString<wchar>::ParseFloat ( integer, TNumberFormat<wchar>*, integer* ) const;
2156extern template ALIB_DLL size_t TString<wchar>::Hashcode () const;
2157extern template ALIB_DLL size_t TString<wchar>::HashcodeIgnoreCase () const;
2158
2159template<> ALIB_DLL integer TString<xchar>::WStringLength () const;
2160extern template ALIB_DLL integer TString<xchar>::indexOfString<lang::Case::Sensitive>( const TString<xchar >&, integer, integer ) const;
2161extern template ALIB_DLL integer TString<xchar>::indexOfString<lang::Case::Ignore >( const TString<xchar >&, integer, integer ) const;
2162extern template ALIB_DLL integer TString<xchar>::IndexOfSegmentEnd ( xchar, xchar, integer ) const;
2163extern template ALIB_DLL uint64_t TString<xchar>::ParseDecDigits ( integer, integer* ) const;
2164extern template ALIB_DLL int64_t TString<xchar>::ParseInt ( integer, TNumberFormat<xchar>*, integer* ) const;
2165extern template ALIB_DLL uint64_t TString<xchar>::ParseDec ( integer, TNumberFormat<xchar>*, integer* ) const;
2166extern template ALIB_DLL uint64_t TString<xchar>::ParseBin ( integer, TNumberFormat<xchar>*, integer* ) const;
2167extern template ALIB_DLL uint64_t TString<xchar>::ParseHex ( integer, TNumberFormat<xchar>*, integer* ) const;
2168extern template ALIB_DLL uint64_t TString<xchar>::ParseOct ( integer, TNumberFormat<xchar>*, integer* ) const;
2169extern template ALIB_DLL double TString<xchar>::ParseFloat ( integer, TNumberFormat<xchar>*, integer* ) const;
2170extern template ALIB_DLL size_t TString<xchar>::Hashcode () const;
2171extern template ALIB_DLL size_t TString<xchar>::HashcodeIgnoreCase () const;
2172
2173//##################################################################################################
2174// debug members
2175//##################################################################################################
2176#if ALIB_DEBUG_STRINGS
2177 extern template ALIB_DLL void TString<nchar>::dbgCheck() const;
2178 extern template ALIB_DLL void TString<wchar>::dbgCheck() const;
2179 extern template ALIB_DLL void TString<xchar>::dbgCheck() const;
2180#endif
2181
2182#endif //!DOXYGEN
2183
2184//##################################################################################################
2185// TString aliases
2186//##################################################################################################
2187} ALIB_EXPORT namespace alib {
2188/// Type alias in namespace \b alib.
2189using String = strings::TString <character>;
2190
2191/// Type alias in namespace \b alib.
2192using ComplementString = strings::TString <complementChar>;
2193
2194/// Type alias in namespace \b alib.
2195using StrangeString = strings::TString <strangeChar>;
2196
2197/// Type alias in namespace \b alib.
2198using NString = strings::TString <nchar>;
2199
2200/// Type alias in namespace \b alib.
2201using WString = strings::TString <wchar>;
2202
2203/// Type alias in namespace \b alib.
2204using XString = strings::TString <xchar>;
2205}
2206//##################################################################################################
2207// TString Constants
2208//##################################################################################################
2209namespace alib::strings {
2210#if DOXYGEN
2211//==================================================================================================
2212/// This template class has three specializations for types \alib{characters;nchar},
2213/// \alib{characters;wchar}, and \alib{characters;xchar}, which each provides the static method
2214/// #EmptyString.
2215/// (The only non-zero-terminated string-constant needed/supported by \alib.)
2216///
2217/// The class is useful to implement methods that are templated with the character type they use
2218/// and that are in need of an empty string instance.
2219///
2220/// In non-templated code (that works with fixed or logical character sizes), the following
2221/// \c constexpr namespace constants are rather to be used:
2222/// \alib{EMPTY_STRING}, \alib{EMPTY_COMPLEMENT_STRING}, \alib{EMPTY_STRANGE_STRING},
2223/// \alib{EMPTY_NSTRING}, \alib{EMPTY_WSTRING}, and \alib{EMPTY_XSTRING}.
2224///
2225/// Nulled strings are not defined here, as they any time can be constructed using \c nullptr.
2226/// To improve readability, \c constexpr namespace variable are given with \alib{NULL_STRING},
2227/// \alib{NULL_COMPLEMENT_STRING}, \alib{NULL_STRANGE_STRING}, \alib{NULL_NSTRING},
2228/// \alib{NULL_WSTRING}, and \alib{NULL_XSTRING}.
2229///
2230/// @see
2231/// Manual chapter \ref alib_strings_details_constants.
2232///
2233/// @tparam TChar The \ref alib_characters_chars "character type".
2234//==================================================================================================
2235template<typename TChar> struct StringConstantsTraits {
2236 ///@return An empty string.
2237 constexpr static String<TChar> EmptyString();
2238};
2239#else // DOXYGEN
2240template<typename TChar> struct StringConstantsTraits {};
2241template<> struct StringConstantsTraits<nchar> { constexpr static NString EmptyString() { return "" ; } };
2242template<> struct StringConstantsTraits<wchar> { constexpr static WString EmptyString() { return A_WCHAR(""); } };
2243template<> struct StringConstantsTraits<xchar> { constexpr static XString EmptyString() { return A_XCHAR(""); } };
2244#endif //!DOXYGEN
2245
2246} // namespace [alib::strings]
2247
2248ALIB_EXPORT namespace alib {
2249
2250/// An empty string of the default character type.
2252
2253/// An empty string of the complement character type.
2255
2256/// An empty string of the strange character type.
2258
2259/// An empty string of the narrow character type.
2261
2262/// An empty string of the wide character type.
2264
2265/// An empty string of the complement character type.
2267
2268// doxygen would consider the constructor call as a function call
2269#if DOXYGEN
2270/// A \e nulled string of the default character type.
2271inline constexpr String NULL_STRING;
2272
2273/// A \e nulled string of the complement character type.
2275
2276/// A \e nulled string of the strange character type.
2278
2279/// A \e nulled string of the narrow character type.
2280inline constexpr NString NULL_NSTRING;
2281
2282/// A \e nulled string of the wide character type.
2283inline constexpr WString NULL_WSTRING;
2284
2285/// A \e nulled string of the complement character type.
2286inline constexpr XString NULL_XSTRING;
2287#else
2288inline constexpr String NULL_STRING(nullptr);
2289inline constexpr ComplementString NULL_COMPLEMENT_STRING(nullptr);
2290inline constexpr StrangeString NULL_STRANGE_STRING(nullptr);
2291inline constexpr NString NULL_NSTRING(nullptr);
2292inline constexpr WString NULL_WSTRING(nullptr);
2293inline constexpr XString NULL_XSTRING(nullptr);
2294#endif
2295
2296
2297} // namespace [alib]
TRandomAccessIterator operator--(int)
Definition string.inl:1889
bool operator>=(TRandomAccessIterator other) const
Definition string.inl:1949
TRandomAccessIterator operator+(integer n) const
Definition string.inl:1907
bool operator!=(TRandomAccessIterator other) const
Definition string.inl:1869
TCharConstOrMutable * pointer
Implementation of std::iterator_traits.
Definition string.inl:1839
TRandomAccessIterator & operator-=(integer n)
Definition string.inl:1902
integer operator-(TRandomAccessIterator other) const
Definition string.inl:1917
TCharConstOrMutable value_type
Implementation of std::iterator_traits.
Definition string.inl:1837
bool operator==(TRandomAccessIterator other) const
Definition string.inl:1864
TRandomAccessIterator operator++(int)
Definition string.inl:1858
TCharConstOrMutable & reference
Implementation of std::iterator_traits.
Definition string.inl:1840
TRandomAccessIterator & operator+=(integer n)
Definition string.inl:1897
TRandomAccessIterator(TCharConstOrMutable *start=nullptr)
Definition string.inl:1848
integer difference_type
Implementation of std::iterator_traits.
Definition string.inl:1838
bool operator<=(TRandomAccessIterator other) const
Definition string.inl:1937
TRandomAccessIterator operator-(integer n) const
Definition string.inl:1912
bool operator>(TRandomAccessIterator other) const
Definition string.inl:1943
TCharConstOrMutable & operator*() const
Definition string.inl:1873
bool operator<(TRandomAccessIterator other) const
Definition string.inl:1931
TCharConstOrMutable & operator[](integer n) const
Definition string.inl:1923
std::random_access_iterator_tag iterator_category
Implementation of std::iterator_traits.
Definition string.inl:1836
int64_t ParseInt(integer startIdx, integer *newIdx) const
Definition string.inl:1377
TChar operator[](integer idx) const
Definition string.inl:484
int CompareTo(const TString &rhs, integer rhsRegionStart, integer rhsRegionLength=MAX_LEN) const
Definition string.inl:631
integer CopyTo(TChar *dest) const
Definition string.inl:1726
TString(TAllocator &allocator, const TString< TChar > &copy)
Definition string.inl:244
double ParseFloat(integer startIdx, integer *newIdx) const
Definition string.inl:1714
constexpr TString(lang::IsNullptr auto const &) noexcept
Constructor accepting nullptr. Constructs a nulled string.
Definition string.inl:173
uint64_t ParseDec(integer startIdx, integer *newIdx) const
Definition string.inl:1447
uint64_t ParseHex(integer startIdx, integer *newIdx) const
Definition string.inl:1581
const_iterator cbegin() const
Definition string.inl:1971
uint64_t ParseBin(integer *newIdx) const
Definition string.inl:1500
const_reverse_iterator rend() const
Definition string.inl:1987
ALIB_DLL uint64_t ParseDec(integer startIdx=0, TNumberFormat< TChar > *numberFormat=nullptr, integer *newIdx=nullptr) const
integer IndexOfOrLength(TChar needle, integer startIdx) const
Definition string.inl:895
constexpr integer Length() const
Definition string.inl:316
ALIB_DLL double ParseFloat(integer startIdx=0, TNumberFormat< TChar > *numberFormat=nullptr, integer *newIdx=nullptr) const
constexpr bool IsEmpty() const
Definition string.inl:365
bool EndsWith(const TString &needle) const
Definition string.inl:780
TChar CharAtStart() const
Definition string.inl:433
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:815
constexpr bool IsNotNull() const
Definition string.inl:355
ALIB_DLL int64_t ParseInt(integer startIdx=0, TNumberFormat< TChar > *numberFormat=nullptr, integer *newIdx=nullptr) const
constexpr TString(const T &src) noexcept
Definition string.inl:208
const_reverse_iterator rbegin() const
Definition string.inl:1983
uint64_t ParseHex(integer *newIdx) const
Definition string.inl:1567
uint64_t ParseOct(integer startIdx, integer *newIdx) const
Definition string.inl:1648
std::size_t HashcodeIgnoreCase() const
integer IndexOfFirstDifference(const TString &needle, lang::Case sensitivity=lang::Case::Sensitive, integer startIdx=0) const
Definition string.inl:1091
uint64_t ParseDec(TNumberFormat< TChar > *numberFormat, integer *newIdx=nullptr) const
Definition string.inl:1421
uint64_t ParseHex(TNumberFormat< TChar > *numberFormat, integer *newIdx=nullptr) const
Definition string.inl:1555
TRandomAccessIterator< const CharacterType > const_iterator
Definition string.inl:1954
ALIB_DLL integer indexOfString(const TString &needle, integer startIdx, integer endIdx) const
integer CountChar(TChar needle, TChar omit, integer startPos) const
Definition string.inl:1180
std::size_t Hashcode() const
constexpr TString(T &src) noexcept
Definition string.inl:226
TChar CharAt(integer idx) const
Definition string.inl:415
const_reverse_iterator crend() const
Definition string.inl:1995
constexpr bool IsNotEmpty() const
Definition string.inl:369
const_iterator end() const
Definition string.inl:1975
bool AdjustRegion(integer &regionStart, integer &regionLength) const
Definition string.inl:1791
ALIB_DLL uint64_t ParseHex(integer startIdx=0, TNumberFormat< TChar > *numberFormat=nullptr, integer *newIdx=nullptr) const
bool ContainsAt(const TString &needle, integer pos) const
Definition string.inl:715
integer IndexOfAny(const TString &needles, integer startIdx=0) const
Definition string.inl:973
constexpr const CharacterType * Buffer() const
Definition string.inl:311
const_iterator begin() const
Definition string.inl:1967
ALIB_DLL uint64_t ParseBin(integer startIdx=0, TNumberFormat< TChar > *numberFormat=nullptr, integer *newIdx=nullptr) const
integer IndexOf(const TString &needle, integer startIdx=0, integer endIdx=strings::MAX_LEN) const
Definition string.inl:1050
const_iterator cend() const
Definition string.inl:1979
uint64_t ParseOct(TNumberFormat< TChar > *numberFormat, integer *newIdx=nullptr) const
Definition string.inl:1622
integer Count(const TString &needle, integer startPos=0) const
Definition string.inl:1221
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition string.inl:1958
integer IndexOf(TChar needle, integer regionStart, integer regionLength) const
Definition string.inl:843
int64_t ParseInt(integer *newIdx) const
Definition string.inl:1363
integer WStringLength() const
integer LastIndexOf(TChar needle, integer startIndex=MAX_LEN) const
Definition string.inl:925
TChar CharAtEnd() const
Definition string.inl:452
uint64_t ParseBin(integer startIdx, integer *newIdx) const
Definition string.inl:1514
uint64_t ParseOct(integer *newIdx) const
Definition string.inl:1634
void Free(TAllocator &allocator)
Definition string.inl:1772
double ParseFloat(integer *newIdx) const
Definition string.inl:1700
constexpr TString() noexcept=default
TString(const_iterator &start, const_iterator &end)
Definition string.inl:2009
integer IndexOfSegmentEnd(TChar opener, TChar closer, integer idx) const
void Allocate(TAllocator &allocator, const TString< TChar > &copy)
Definition string.inl:1745
int CompareTo(const TString &rhs, integer rhsRegionStart, integer rhsRegionLength, integer regionStart, integer regionLength=MAX_LEN) const
Definition string.inl:675
ALIB_DLL uint64_t ParseDecDigits(integer startIdx=0, integer *newIdx=nullptr) const
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.inl:384
integer CountChar(TChar needle, integer startPos=0) const
Definition string.inl:1144
int64_t ParseInt(TNumberFormat< TChar > *numberFormat, integer *newIdx=nullptr) const
Definition string.inl:1351
uint64_t ParseDec(integer *newIdx) const
Definition string.inl:1433
const_reverse_iterator crbegin() const
Definition string.inl:1991
ALIB_DLL uint64_t ParseOct(integer startIdx=0, TNumberFormat< TChar > *numberFormat=nullptr, integer *newIdx=nullptr) const
bool Equals(const TString< TChar > &rhs) const
Definition string.inl:531
constexpr bool IsNull() const
Definition string.inl:350
constexpr TString(const T &src) noexcept
Definition string.inl:190
bool StartsWith(const TString &needle) const
Definition string.inl:751
integer IndexOfOrLength(TChar needle) const
Definition string.inl:875
integer Count(const TString &needle, const TString &omit, integer startPos=0) const
Definition string.inl:1263
integer LastIndexOfAny(const TString &needles, integer startIdx=MAX_LEN) const
Definition string.inl:1013
uint64_t ParseBin(TNumberFormat< TChar > *numberFormat, integer *newIdx=nullptr) const
Definition string.inl:1488
int CompareTo(const TString< TChar > &rhs) const
Definition string.inl:584
size_type size() const
Definition string.inl:1999
double ParseFloat(TNumberFormat< TChar > *numberFormat, integer *newIdx=nullptr) const
Definition string.inl:1688
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:719
#define ALIB_WARNINGS_IGNORE_DOCS
Definition alib.inl:702
#define ALIB_WARNINGS_ALLOW_NULL_POINTER_PASSING
Definition alib.inl:619
#define A_XCHAR(STR)
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
#define ALIB_STRING_DBG_CHK(instance)
#define A_WCHAR(STR)
const TChar * Search(const TChar *haystack, integer haystackLength, TChar needle)
void Copy(const TChar *src, integer length, TChar *dest)
integer IndexOfFirstDifference(const TChar *haystack, integer haystackLength, const TChar *needle, integer needleLength, lang::Case sensitivity)
integer LastIndexOfAnyExclude(const TChar *haystack, integer startIdx, const TChar *needles, integer needlesLength)
integer LastIndexOfAnyInclude(const TChar *haystack, integer startIdx, const TChar *needles, integer needlesLength)
int Compare(const TChar *lhs, const TChar *rhs, integer cmpLength)
bool Equal(TChar lhs, TRhs rhs)
Definition functions.inl:62
integer IndexOfAnyIncluded(const TChar *haystack, integer haystackLength, const TChar *needles, integer needlesLength)
integer IndexOfAnyExcluded(const TChar *haystack, integer haystackLength, const TChar *needles, integer needlesLength)
int CompareIgnoreCase(const TChar *lhs, const TChar *rhs, integer cmpLength)
platform_specific integer
Definition integers.inl:32
Case
Denotes upper and lower case character treatment.
Inclusion
Denotes how members of a set something should be taken into account.
@ Include
Chooses inclusion.
constexpr integer MAX_LEN
The maximum length of an ALib string.
Definition string.inl:51
auto operator<=>(const String &lhs, const String &rhs)
Definition string.inl:2090
constexpr NString NULL_NSTRING
A nulled string of the narrow character type.
Definition string.inl:2280
constexpr String NULL_STRING
A nulled string of the default character type.
Definition string.inl:2271
constexpr ComplementString NULL_COMPLEMENT_STRING
A nulled string of the complement character type.
Definition string.inl:2274
strings::TString< complementChar > ComplementString
Type alias in namespace alib.
Definition string.inl:2192
constexpr ComplementString EMPTY_COMPLEMENT_STRING
An empty string of the complement character type.
Definition string.inl:2254
constexpr NString EMPTY_NSTRING
An empty string of the narrow character type.
Definition string.inl:2260
constexpr const String EMPTY_STRING
An empty string of the default character type.
Definition string.inl:2251
strings::TString< xchar > XString
Type alias in namespace alib.
Definition string.inl:2204
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2198
constexpr WString NULL_WSTRING
A nulled string of the wide character type.
Definition string.inl:2283
constexpr XString NULL_XSTRING
A nulled string of the complement character type.
Definition string.inl:2286
constexpr StrangeString EMPTY_STRANGE_STRING
An empty string of the strange character type.
Definition string.inl:2257
strings::TString< wchar > WString
Type alias in namespace alib.
Definition string.inl:2201
constexpr WString EMPTY_WSTRING
An empty string of the wide character type.
Definition string.inl:2263
constexpr StrangeString NULL_STRANGE_STRING
A nulled string of the strange character type.
Definition string.inl:2277
constexpr XString EMPTY_XSTRING
An empty string of the complement character type.
Definition string.inl:2266
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
strings::TString< strangeChar > StrangeString
Type alias in namespace alib.
Definition string.inl:2195
See sibling type NC.
Definition chk_nc.inl:33
static constexpr Policy Access
static integer Length(const TStringSource &src)
static TStringSource Construct(const TChar *array, integer length)
static constexpr Policy Construction
static const TChar * Buffer(const TStringSource &src)
static constexpr Policy Construction
static constexpr Policy Access
static const TChar * Buffer(const TStringSource &src)
static TStringSource Construct(const TChar *array, integer length)
static integer Length(const TStringSource &src)
static constexpr String< TChar > EmptyString()