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