ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
substring.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_strings of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace strings {
9
10//==================================================================================================
11/// This class specializes parent class \alib{strings;TString;String} to allow reduction of
12/// the length of the represented string by cutting characters from the front or the end.
13/// Such reduction does not affect the character array represented, but only its representation
14/// by instances of this type.
15///
16/// In other words, the difference to base class \alib{strings;TString;String} is, that this type
17/// allows increasing the pointer to the character array's start and to decrease its stored length.
18/// In all other respects, this class has the same lightweight nature and performance as its base.
19/// Furthermore, the flexible template programming mechanics for seamless construction are exposed
20/// from the base class and likewise available.
21///
22/// Like base class \alib{strings;TString;String}, the class cannot, and therefore does not,
23/// verify that the underlying buffer is (still) properly allocated and contains valid data.
24/// It is up to the user of this class to make sure the buffer stays intact until any referencing
25/// object of this type is disposed.
26///
27/// @tparam TChar The \ref alib_characters_chars "character type" of this string-type.
28/// Alias names for specializations along the different character types
29/// are provided in namespace #alib with type definitions
30/// \alib{Substring},
31/// \alib{NSubstring},
32/// \alib{WSubstring},
33/// \alib{XSubstring},
34/// \alib{ComplementSubstring}, and
35/// \alib{StrangeSubstring}.
36//==================================================================================================
37template<typename TChar>
38class TSubstring : public TString<TChar>
39{
40 protected:
41 /// The base string-type.
43
44 public:
45 #if !DOXYGEN
46 // Import parent constructors.
47 // Due to a doxygen bug in 1.8.14, we must not tell doxygen that we import overloaded
48 // methods.
49 using base::TString;
50 #endif
51
52 /// Default constructor creating a \ref alib_strings_details_nulled \e "nulled" substring.
54 : base() {}
55
56 /// Constructor using a string reference.
57 /// @param src The source string.
59 : base(src) {}
60
61 /// Sets this object to zero length.
62 /// @return \c *this to allow concatenated calls.
63 TSubstring& Clear() { base::length= 0; return *this; }
64
65 /// Moves the start to the first character not found in given character set \p{whiteSpaces}.
66 ///
67 /// @param whiteSpaces The characters used for trimming.
68 /// Defaults to \ref alib::DEFAULT_WHITESPACES
69 /// @return \c *this to allow concatenated calls.
72 if ( base::length > 0 ) {
75 whiteSpaces.Buffer(),
76 whiteSpaces.Length() );
77 if( idx < 0 )
78 idx= base::length;
79 base::buffer+= idx;
80 base::length-= idx;
81 }
82 return *this;
83 }
84
85 /// Moves the start to the first character not found in given character set \p{whiteSpaces}.
86 ///
87 /// @param whiteSpaces The characters used for trimming.
88 /// Defaults to \ref alib::DEFAULT_WHITESPACES
89 /// @return \c *this to allow concatenated calls.
90 TSubstring& TrimEnd( const TCString<TChar>& whiteSpaces
92 if ( base::length > 0 ) {
94 base::length - 1,
95 whiteSpaces.Buffer(),
96 whiteSpaces.Length() ) + 1;
97 }
98 return *this;
99 }
100
101 /// Invokes #TrimStart and #TrimEnd .
102 ///
103 /// @param whiteSpaces The characters used for trimming.
104 /// Defaults to \ref alib::DEFAULT_WHITESPACES
105 /// @return \c *this to allow concatenated calls.
106 TSubstring& Trim( const TCString<TChar>& whiteSpaces
108 return TrimEnd ( whiteSpaces )
109 .TrimStart( whiteSpaces );
110 }
111
112 /// Retrieve and remove the first character from the substring.
113 ///
114 /// @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
115 /// consume operation. Defaults to \b Whitespaces::Keep.
116 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
117 /// If \c <false> is added to the method name, no parameter check is
118 /// performed.
119 ///
120 /// @return The character at the start of the represented region.
121 /// If this \b %Substring is empty or \e nulled, '\0' is returned.
122 template < typename TCheck = CHK,
123 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
124 TChar ConsumeChar() {
125 if constexpr ( TCheck::value ) {
126 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
127 TrimStart();
128 if( base::IsEmpty() )
129 return '\0';
130 } else {
131 ALIB_ASSERT_ERROR(!base::IsEmpty(),"STRINGS","Non checking but called on empty string" )
132 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
133 TrimStart();
134 }
135
136 --base::length;
137 return *base::buffer++;
138 }
139
140 /// Checks if this object starts with the given character \p{consumable}. If it does, this
141 /// character is cut from this object.
142 ///
143 /// @tparam TSensitivity The sensitivity of the comparison.
144 /// Defaults to \b Case::Sensitive.
145 /// @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
146 /// consume operation. Defaults to \b Whitespaces::Keep.
147 /// @param consumable The consumable character.
148 /// @return \c true, if this object was starting with \p{consumable} and consequently the
149 /// string was cut by one, \c false otherwise.
150 template< lang::Case TSensitivity= lang::Case::Sensitive,
151 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep>
152 bool ConsumeChar( TChar consumable ) {
153 if ( TTrimBeforeConsume == lang::Whitespaces::Trim )
154 TrimStart();
155
156 if ( ( TSensitivity == lang::Case::Sensitive && base::CharAtStart() != consumable )
158 != characters::ToUpper(consumable) ) )
159 return false;
160
161 ++base::buffer;
162 --base::length;
163 return true;
164 }
165
166 /// Checks if this object ends with the given character \p{consumable}. If it does, this
167 /// character is cut from the end of object.
168 ///
169 /// @tparam TSensitivity The sensitivity of the comparison.
170 /// Defaults to \b Case::Sensitive.
171 /// @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
172 /// consume operation. Defaults to \b Whitespaces::Keep.
173 /// @param consumable The consumable character.
174 /// @return \c true, if this object was starting with \p{consumable} and consequently the
175 /// string was cut by one.
176 template< lang::Case TSensitivity= lang::Case::Sensitive,
177 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep>
178 bool ConsumeCharFromEnd( TChar consumable ) {
179 if ( TTrimBeforeConsume == lang::Whitespaces::Trim )
180 TrimEnd();
181
182 if ( ( TSensitivity == lang::Case::Sensitive && base::CharAtEnd() != consumable )
184 != characters::ToUpper(consumable) ) )
185 return false;
186 --base::length;
187 return true;
188 }
189
190 /// Retrieve and remove the last character in the substring.
191 ///
192 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
193 /// If \c <false> is added to the method name, no check whether this
194 /// string is empty is performed.
195 ///
196 /// @tparam TTrimBeforeConsume Determines if the string should be (right-) trimmed before the
197 /// consume operation. Defaults to \b Whitespaces::Keep.
198 /// @return The character at the start of the represented region.
199 /// If this \b %Substring is empty or \e nulled, '\0' is returned.
200 template <typename TCheck= CHK,
201 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
203 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
204 TrimEnd();
205
206 if constexpr ( TCheck::value ) {
207 if( base::IsEmpty() )
208 return '\0';
209 } else {
210 ALIB_ASSERT_ERROR(!base::IsEmpty(),"STRINGS","Non checking but called on empty string" )
211 }
212 return *(base::buffer + --base::length );
213 }
214
215 /// Cuts the given number of characters from the beginning of the Substring and optionally
216 /// places the portion that was cut in parameter \p{target} (if provided).<br>
217 ///
218 /// If parameter \p{regionLength} is negative, nothing is cut and optional argument
219 /// \p{target} is set empty. If \p{regionLength} is equal or greater than this
220 /// object's length, all contents is 'moved' to \p{target}.
221 ///
222 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
223 /// If \c <false>, parameter \p{regionLength} has to be in the range of
224 /// this object's size.
225 ///
226 /// @param regionLength The length of the region at the start to delete.
227 /// @param target An optional target \b %Substring that receives the portion that
228 /// is cut from this object. Defaults to nullptr.
229 ///
230 /// @return The new length of the substring.
231 template <typename TCheck= CHK>
232 integer ConsumeChars( integer regionLength, TSubstring* target= nullptr ) {
233 if constexpr ( TCheck::value ) {
234 if ( regionLength < 0 ) {
235 if ( target != nullptr )
236 target->Clear();
237 return base::length;
238 }
239 if ( regionLength > base::length )
240 regionLength= base::length;
241 } else {
242 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength <= base::length,
243 "Non checking and index out of range: 0 <= {} <= {}.", regionLength, base::length )
244
245 }
246
247 if ( target != nullptr )
248 *target= this->base::template Substring<NC>( 0, regionLength );
249
250 base::buffer+= regionLength;
251 base::length-= regionLength;
252 return base::length;
253 }
254
255 /// Cuts the given number of characters from the end of the \b %Substring and optionally
256 /// places the portion that was cut in parameter \p{target} (if provided).<br>
257 /// Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
258 /// is cut and \p{target} is set empty. If \p{regionLength} is greater than this
259 /// object's length, all contents is 'moved' to \p{target}.
260 ///
261 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
262 /// If \c <false> is added to the method name, no parameter check is
263 /// performed.
264 ///
265 /// @param regionLength The length of the region at the start to delete.
266 /// @param target An optional target \b %Substring that receives the portion that
267 /// is cut from this object. Defaults to nullptr.
268 ///
269 /// @return The new length of the substring.
270 template <typename TCheck= CHK>
271 integer ConsumeCharsFromEnd( integer regionLength, TSubstring* target= nullptr ) {
272 if constexpr ( TCheck::value ) {
273 if ( regionLength < 0 ) {
274 if ( target != nullptr )
275 target->Clear();
276 return base::length;
277 }
278 if ( regionLength > base::length )
279 regionLength= base::length;
280 } else {
281 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength <= base::length,
282 "Non checking and index out of range: 0 <= {} <= {}.", regionLength, base::length )
283 }
284
285 if ( target != nullptr )
286 *target= this->base::template Substring<NC>( base::length - regionLength, regionLength );
287
288 base::length-= regionLength;
289 return base::length;
290 }
291
292 /// Cuts the given number of characters from the beginning of the Substring and optionally
293 /// places the portion that was cut in parameter \p{target}.<br>
294 /// Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
295 /// is cut and \p{target} is set empty, respectively left untouched depending on
296 /// \p{TTargetData}.
297 ///
298 /// If \p{regionLength} is greater than this object's length, all contents is 'moved'
299 /// to \p{target}.
300 ///
301 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
302 /// If \c <false> is added to the method name, no parameter check
303 /// is performed.
304 /// @tparam TTargetData If \c CurrentData::Keep, \b %AString \p{target} is not cleared
305 /// before the result is written. Defaults to \c CurrentData::Clear.
306 /// @tparam TAllocator The allocation type of the \p{target} string, as prototyped with
307 /// \alib{lang;Allocator}. Deduced by the compiler.
308 /// @param regionLength The length of the region at the start to delete.
309 /// @param target A target \b %AString that receives the portion that
310 /// is cut from this object.
311 /// @param separatorWidth This width is added to what is cut from this string, while
312 /// \p{target} still receives the portion defined by \p{regionLength}.
313 /// Defaults to 0.
314 ///
315 /// @return The new length of the substring.
316 template <typename TCheck = CHK,
318 typename TAllocator >
321 integer separatorWidth =0 ) {
322 if constexpr ( TTargetData == lang::CurrentData::Clear )
323 target.Reset();
324
325 if constexpr ( TCheck::value ) {
326 if ( separatorWidth < 0 )
327 separatorWidth= 0;
328
329 if ( regionLength < 0 )
330 return base::length;
331
332 if ( regionLength > base::length - separatorWidth ) {
333 regionLength= base::length - separatorWidth;
334 if ( regionLength < 0 )
335 return base::length;
336 }
337
338 } else {
339 ALIB_ASSERT_ERROR( separatorWidth >= 0, "STRINGS",
340 "Non checking but separator width negative: ", separatorWidth )
341 ALIB_ASSERT_ERROR( regionLength >= 0
342 && regionLength + separatorWidth <= base::length, "STRINGS",
343 "Non checking but regionLength out of bounds: 0 <= {}, {} <= {}.",
344 regionLength, regionLength + separatorWidth, base::length )
345 }
346
347 target.template _<NC>( *this, 0, regionLength );
348
349 regionLength+= separatorWidth;
350 base::buffer+= regionLength ;
351 base::length-= regionLength;
352 return base::length;
353 }
354
355 /// Cuts the given number of characters from the beginning of the Substring and optionally
356 /// places the portion that was cut in parameter \p{target}.<br>
357 /// Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
358 /// is cut and \p{target} is set empty, respectively left untouched depending on
359 /// \p{TTargetData}.
360 ///
361 /// If \p{regionLength} is greater than this object's length, all contents is 'moved'
362 /// to \p{target}.
363 ///
364 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
365 /// If \c <false> is added to the method name, no parameter check is
366 /// performed.
367 ///
368 /// @param regionLength The length of the region at the start to delete.
369 /// @param target A target \b %String that receives the portion that
370 /// is cut from this object.
371 /// @param separatorWidth This width is added to what is cut from this string, while
372 /// \p{target} still receives the portion defined by \p{regionLength}.
373 /// Defaults to 0.
374 ///
375 /// @return The new length of the substring.
376 template <typename TCheck = CHK>
378 TString<TChar>& target,
379 integer separatorWidth =0 ) {
380 if constexpr ( TCheck::value ) {
381 if ( separatorWidth < 0 )
382 separatorWidth= 0;
383
384 if ( regionLength < 0 )
385 return base::length;
386
387 if ( regionLength > base::length - separatorWidth ) {
388 regionLength= base::length - separatorWidth;
389 if ( regionLength < 0 )
390 return base::length;
391 }
392 } else {
393 ALIB_ASSERT_ERROR( separatorWidth >= 0,
394 "STRINGS", "Non checking but separator width negative" )
395 ALIB_ASSERT_ERROR( regionLength >= 0
396 && regionLength + separatorWidth <= base::length, "STRINGS",
397 "Non checking but regionLength out of bounds: 0 <= {}, {} <= {}.",
398 regionLength, regionLength + separatorWidth, base::length )
399 }
400
401 target= String( base::buffer, regionLength );
402
403 regionLength+= separatorWidth;
404 base::buffer+= regionLength ;
405 base::length-= regionLength;
406 return base::length;
407 }
408
409 /// Cuts the given number of characters from the end of the substring and
410 /// places the portion that was cut in parameter \p{target}.<br>
411 /// Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
412 /// is cut and \p{target} is set empty, respectively left untouched depending on \p
413 /// If \p{regionLength} is greater than this object's length, all contents is 'moved'
414 /// to \p{target}.
415 ///
416 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
417 /// If \c <false> is added to the method name, no parameter check is
418 /// performed.
419 /// @tparam TTargetData If \c CurrentData::Keep, the parameter \p{target} is not cleared
420 /// before the result is written. Defaults to \c CurrentData::Clear.
421 /// @tparam TAllocator The allocator-type of the \p{target}.
422 /// Deduced by the compiler.
423 ///
424 /// @param regionLength The length of the region at the start to delete.
425 /// @param target A target \b %AString that receives the portion that
426 /// is cut from this object.
427 /// @param separatorWidth This width is added to what is cut from this string, while
428 /// \p{target} still receives the portion defined by \p{regionLength}.
429 /// Defaults to 0.
430 ///
431 /// @return The new length of the substring.
432 template <typename TCheck = CHK,
434 typename TAllocator >
437 integer separatorWidth =0 ) {
438 if constexpr ( TTargetData == lang::CurrentData::Clear )
439 target.Reset();
440
441 if constexpr ( TCheck::value ) {
442 if ( separatorWidth < 0 ) separatorWidth= 0;
443 if ( regionLength < 0 ) return base::length;
444 if ( regionLength > base::length - separatorWidth ) regionLength= base::length - separatorWidth;
445 if ( regionLength < 0 ) return base::length;
446 } else {
447 ALIB_ASSERT_ERROR( separatorWidth >=0 ,
448 "STRINGS", "Non checking but separator width negative" )
449 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength + separatorWidth <= base::length,
450 "STRINGS", "Non checking but regionLength out of bounds: 0 <= {}, {} <= {}.",
451 regionLength, regionLength + separatorWidth, base::length )
452 }
453
454 target.template _<NC>( *this, base::length - regionLength, regionLength );
455
456 base::length-= regionLength + separatorWidth;
457 return base::length;
458 }
459
460 /// Searches \p{separator} and cuts the beginning of this string.
461 /// What was consumed is returned.
462 ///
463 /// If the separator is \b not found, all of this string is consumed and returned.
464 ///
465 /// @param separator The separator to search. Defaults to <c>','</c>.
466 /// @param includeSeparator Determines if the separator should be consumed as well.
467 /// defaults to \alib{lang;Inclusion;Include}
468 ///
469 /// @return The token consumed.
470 TString<TChar> ConsumeToken( TChar separator= ',',
471 lang::Inclusion includeSeparator = lang::Inclusion::Include ) {
472 ALIB_ASSERT_ERROR( base::IsNotNull() , "STRINGS", "ConsumeToken on nulled Substring" )
473
474 integer separatorPos= base::IndexOfOrLength( separator );
475 base result = base( base::buffer, separatorPos );
476
477 base::buffer+= separatorPos;
478 base::length-= separatorPos;
479 if( includeSeparator == lang::Inclusion::Include
480 && base::length > 0 )
481 {
482 ++base::buffer;
483 --base::length;
484 }
485 return result;
486 }
487
488 /// Checks if this object starts with the given string \p{consumable}. If it does, this
489 /// string is cut from this object.
490 ///
491 /// @tparam TSensitivity The sensitivity of the comparison.
492 /// Defaults to \b Case::Sensitive.
493 /// @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
494 /// consume operation. Defaults to \b Whitespaces::Keep.
495 /// @param consumable The consumable string.
496 /// @return \c true, if this object was starting with \p{consumable} and consequently the
497 /// string was cut.
498 template< lang::Case TSensitivity= lang::Case::Sensitive,
499 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
500 bool ConsumeString( const TString<TChar>& consumable ) {
501 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
502 TrimStart();
503
504 if ( !base::template StartsWith<CHK,TSensitivity>( consumable ) )
505 return false;
506
507 base::buffer+= consumable.Length();
508 base::length-= consumable.Length();
509 return true;
510 }
511
512 /// Checks if this object ends with the given string \p{consumable}. If it does, this
513 /// string is cut from the end of object.
514 ///
515 /// @tparam TSensitivity The sensitivity of the comparison.
516 /// Defaults to \b Case::Sensitive.
517 /// @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
518 /// consume operation. Defaults to \b Whitespaces::Keep.
519 /// @param consumable The consumable string
520 /// @return \c true, if this object was starting with \p{consumable} and consequently the
521 /// string was cut.
522 template< lang::Case TSensitivity= lang::Case::Sensitive,
523 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
524 bool ConsumeStringFromEnd( const TString<TChar>& consumable ) {
525 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
526 TrimEnd();
527
528 if ( !base::template EndsWith<CHK,TSensitivity>( consumable ) )
529 return false;
530 base::length-= consumable.Length();
531 return true;
532 }
533
534 /// Consumes a minimum of \p{minChars} of string \p{consumable} from the start of this
535 /// substring. If the minimum characters could not be found, nothing is consumed, otherwise,
536 /// the method consumes as much as possible.<br>
537 ///
538 /// This method is useful read "tokens" from a string that may be abbreviated.
539 /// Within \alib this method is, for example, used with
540 /// \ref alib_enums_records_details_serialization "deserialization of enumeration elements".
541 ///
542 /// @tparam TSensitivity The sensitivity of the comparison.
543 /// Defaults to \b Case::Ignore.
544 /// @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
545 /// first character consume operation.
546 /// Defaults to \b Whitespaces::Keep.
547 /// @param consumable The consumable string.
548 /// @param minChars The minimum amount of characters to consume. If \c 0 or
549 /// negative, the length of \p{consumable} is chosen.
550 /// Optional and defaults to \c 1.
551 /// @return The amount of characters consumed.
552 template< lang::Case TSensitivity= lang::Case::Ignore,
553 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
555 int minChars = 1 ) {
556 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
557 TrimStart();
558 if ( minChars <= 0 )
559 minChars= int( consumable.Length() );
560
561 if ( minChars == 0 || minChars > consumable.Length() )
562 return 0;
563
564 integer diff= base::IndexOfFirstDifference( consumable, TSensitivity );
565 if( diff < integer( minChars ) )
566 return 0;
567 ConsumeChars( diff );
568 return diff;
569 }
570
571 /// Consumes a field from the beginning of this substring, which is surrounded by
572 /// given \p{startChar} and \p{endChar} identifiers. If both are the same, e.g., \c '"', then
573 /// the first occurrence of the end character is used. If they are not the same, e.g.
574 /// \c '<' and \c '>', then repeated start characters are counted and consumption only ends
575 /// when a corresponding amount of end characters has been found.
576 ///
577 /// @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
578 /// consume operation. Defaults to \b Whitespaces::Keep.
579 /// @param startChar The start character of the field to consume.
580 /// @param endChar The end character of the field to consume.
581 /// @return The string consumed. \b NULL_STRING on error (start/end character not found)
582 template< lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
583 TString<TChar> ConsumeField( TChar startChar, TChar endChar ) {
584 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
585 TrimStart();
586
587 integer endIdx;
588 if ( base::CharAtStart() != startChar
589 || (endIdx= base::IndexOfSegmentEnd( startChar, endChar, 1)) < 0 )
590 return nullptr;
591
592
593 base result= base( base::buffer + 1, endIdx - 1 );
594 base::buffer+= (endIdx + 1);
595 base::length-= (endIdx + 1);
596 return result;
597 }
598
599 /// Consumes all characters \c '0' to \c '9' at the start of this object and stores the
600 /// value they represent in \p{result}.<br>
601 /// Unlike methods #ConsumeInt or #ConsumeDec, this method does not consume (respectively
602 /// accept) sign-, whitespace- or group-characters.
603 ///
604 /// @param [out] result A reference to a variable of an integral type which receives the
605 /// result value.
606 ///
607 /// @return \c true if a number was found and consumed, \c false otherwise.
608 inline bool ConsumeDecDigits( std::integral auto& result ) {
609 uint64_t resultImpl;
610 bool returnValue= consumeDecDigitsImpl( resultImpl );
611 result= static_cast<std::remove_reference_t<decltype(result)>>(resultImpl);
612
613 return returnValue;
614 }
615
616 /// Consumes an integral value in decimal, binary, hexadecimal or octal format from the
617 /// string.
618 ///
619 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
620 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
621 /// which is configured to not using (not allowing) grouping characters.
622 ///
623 /// For more information on number conversion, see class
624 /// \alib{strings;TNumberFormat;NumberFormat}.
625 ///
626 /// @param [out] result A reference to a variable of an integral type which receives the
627 /// result value.
628 /// @param numberFormat The number format to use. Defaults to \c nullptr.
629 /// @return \c true if a number was found and consumed, \c false otherwise.
630 bool ConsumeInt( std::integral auto& result, TNumberFormat<TChar>* numberFormat= nullptr ) {
631 int64_t resultImpl;
632 bool returnValue= consumeIntImpl( resultImpl, numberFormat );
633 result= static_cast<std::remove_reference_t<decltype(result)>>( resultImpl );
634 return returnValue;
635 }
636
637 /// Consumes an unsigned integer in standard decimal format from the start of this %SubString.
638 ///
639 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
640 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
641 /// which is configured to not using (not allowing) grouping characters.
642 ///
643 /// Sign literals \c '-' or \c '+' are \b not accepted and parsing will fail.
644 /// For reading signed integral values, see methods #ConsumeInt, for floating point numbers
645 /// #ConsumeFloat.
646 ///
647 /// For more information on number conversion, see class
648 /// \alib{strings;TNumberFormat;NumberFormat}.
649 ///
650 /// @param [out] result A reference to a variable of an integral type which receives the
651 /// result value.
652 /// @param numberFormat The number format to use. Defaults to \c nullptr.
653 /// @return \c true if a number was found and consumed, \c false otherwise.
654 bool ConsumeDec( std::integral auto& result, TNumberFormat<TChar>* numberFormat= nullptr ) {
655 uint64_t resultImpl;
656 bool returnValue= consumeDecImpl( resultImpl, numberFormat );
657 result= static_cast<std::remove_reference_t<decltype(result)>>( resultImpl );
658 return returnValue;
659 }
660
661 /// Consumes an unsigned integer in binary format from the start of this string.
662 ///
663 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
664 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
665 /// which is configured to not using (not allowing) grouping characters.
666 ///
667 /// For more information on number conversion, see class
668 /// \alib{strings;TNumberFormat;NumberFormat}.
669 ///
670 /// @param [out] result A reference to the result value.
671 /// @param numberFormat The number format to use. Defaults to \c nullptr.
672 /// @return \c true if a number was found and consumed, \c false otherwise.
673 bool ConsumeBin( std::integral auto& result, TNumberFormat<TChar>* numberFormat= nullptr ) {
674 uint64_t resultImpl;
675 bool returnValue= consumeBinImpl( resultImpl, numberFormat );
676 result= static_cast<std::remove_reference_t<decltype(result)>>( resultImpl );
677 return returnValue;
678 }
679
680 /// Consumes an unsigned integer in hexadecimal format from the start of this string.
681 ///
682 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
683 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
684 /// which is configured to not using (not allowing) grouping characters.
685 ///
686 /// For more information on number conversion, see class
687 /// \alib{strings;TNumberFormat;NumberFormat}.
688 ///
689 /// @param [out] result A reference to a variable of an integral type which receives the
690 /// result value.
691 /// @param numberFormat The number format to use. Defaults to \c nullptr.
692 ///
693 /// @return \c true if a number was found and consumed, \c false otherwise.
694 bool ConsumeHex( std::integral auto& result, TNumberFormat<TChar>* numberFormat= nullptr ) {
695 uint64_t resultImpl;
696 bool returnValue= consumeHexImpl( resultImpl, numberFormat );
697 result= static_cast<std::remove_reference_t<decltype(result)>>( resultImpl );
698 return returnValue;
699 }
700
701 /// Consumes an unsigned integer in octal format from the start of this string.
702 ///
703 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
704 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
705 /// which is configured to not use (not allow) grouping characters.
706 ///
707 /// For more information on number conversion, see class
708 /// \alib{strings;TNumberFormat;NumberFormat}.
709 ///
710 /// @param [out] result A reference to a variable of an integral type which receives the
711 /// result value.
712 /// @param numberFormat The number format to use. Defaults to \c nullptr.
713 ///
714 /// @return \c true if a number was found and consumed, \c false otherwise.
715 bool ConsumeOct( std::integral auto& result, TNumberFormat<TChar>* numberFormat= nullptr ) {
716 uint64_t resultImpl;
717 bool returnValue= consumeOctImpl( resultImpl, numberFormat );
718 result= static_cast<std::remove_reference_t<decltype(result)>>( resultImpl );
719 return returnValue;
720 }
721
722 /// Consumes a floating point number from the start of this string.
723 ///
724 /// on the given \p{numberFormat} instance.<br>
725 /// Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
726 /// \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
727 /// which is configured to 'international' settings (not using the locale) and therefore
728 /// also not parsing grouping characters.
729 ///
730 /// For more information on parsing options for floating point numbers and number
731 /// conversion in general, see class
732 /// \alib{strings;TNumberFormat;NumberFormat}.
733 ///
734 /// @param [out] result A reference to the result value.
735 /// @param numberFormat The number format to use. Defaults to \c nullptr.
736 ///
737 /// @return \c true if a number was found and consumed, \c false otherwise.
739 bool ConsumeFloat( double& result,
740 TNumberFormat<TChar>* numberFormat =nullptr );
741
742
743 /// Splits this substring into two parts. What remains in this object is the region
744 /// from 0 to \p{position}.
745 /// \p{target} receives the rest. If \p{separatorWidth} is given, this is subtracted from
746 /// the front of \p{target}.
747 ///
748 /// @tparam TCheck Defaults to \alib{CHK}, which is the normal invocation mode.
749 /// If \c <false> is added to the method name, no parameter check is
750 /// performed.
751 ///
752 /// @param position The index where this object is split.
753 /// @param target The target substring to receive the right part of the string.
754 /// @param separatorWidth This does not change what remains in this object, but defines
755 /// the number of characters that are cut from the front of the
756 /// \p{target}. Defaults to 0.
757 /// @param trim If \c true, both substrings will be trimmed.
758 ///
759 /// @return \c *this to allow concatenated calls.
760 template <typename TCheck= CHK>
761 TSubstring& Split( integer position, TSubstring& target, integer separatorWidth =0,
762 bool trim= false ) {
763 if constexpr ( TCheck::value )
764 base::AdjustRegion( position, separatorWidth );
765 else {
766 ALIB_ASSERT_ERROR( position >=0 && position <= base::length, "STRINGS",
767 "Non checking but position out of bounds: 0 <= {} < {}.", position, base::length )
768 ALIB_ASSERT_ERROR( position + separatorWidth <= base::length, "STRINGS",
769 "Non checking but position + separator width out of bounds: {} <= {}.",
770 position + separatorWidth, base::length )
771 }
772
773 target= this->base::template Substring<NC>( position + separatorWidth,
774 base::length - position - separatorWidth );
775 base::length= position;
776 if( trim ) {
777 target.Trim();
778 this ->Trim();
779 }
780 return *this;
781 }
782
783 //################################################################################################
784 // Protected Methods
785 //################################################################################################
786 protected:
787 /// Implementation of #ConsumeDecDigits (the non-inline part).
788 ///
789 /// @param [out] result A reference to the result value.
790 /// @return \c true if a number was found and consumed, \c false otherwise.
791 ALIB_DLL bool consumeDecDigitsImpl( uint64_t& result );
792
793 /// Implementation of #ConsumeInt (the non-inline part).
794 ///
795 /// @param [out] result A reference to the result value.
796 /// @param numberFormat The number format to use.
797 /// @return \c true if a number was found and consumed, \c false otherwise.
798 ALIB_DLL bool consumeIntImpl( int64_t& result, TNumberFormat<TChar>* numberFormat );
799
800 /// Implementation of #ConsumeDec (the non-inline part).
801 ///
802 /// @param [out] result A reference to the result value.
803 /// @param numberFormat The number format to use.
804 /// @return \c true if a number was found and consumed, \c false otherwise.
805 ALIB_DLL bool consumeDecImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
806
807 /// Implementation of #ConsumeBin (the non-inline part).
808 ///
809 /// @param [out] result A reference to the result value.
810 /// @param numberFormat The number format to use.
811 /// @return \c true if a number was found and consumed, \c false otherwise.
812 ALIB_DLL bool consumeBinImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
813
814 /// Implementation of #ConsumeHex (the non-inline part).
815 ///
816 /// @param [out] result A reference to the result value.
817 /// @param numberFormat The number format to use.
818 /// @return \c true if a number was found and consumed, \c false otherwise.
819 ALIB_DLL bool consumeHexImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
820
821 /// Implementation of #ConsumeOct (the non-inline part).
822 ///
823 /// @param [out] result A reference to the result value.
824 /// @param numberFormat The number format to use.
825 /// @return \c true if a number was found and consumed, \c false otherwise.
826 ALIB_DLL bool consumeOctImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
827}; // class TSubstring
828
829//##################################################################################################
830// TSubstring type aliases
831//##################################################################################################
832}
833/// Type alias in namespace \b alib.
834using Substring = strings::TSubstring <character>;
835
836/// Type alias in namespace \b alib.
837using ComplementSubstring = strings::TSubstring <complementChar>;
838
839/// Type alias in namespace \b alib.
840using StrangeSubstring = strings::TSubstring <strangeChar>;
841
842/// Type alias in namespace \b alib.
843using NSubstring = strings::TSubstring <nchar>;
844
845/// Type alias in namespace \b alib.
846using WSubstring = strings::TSubstring <wchar>;
847
848/// Type alias in namespace \b alib.
849using XSubstring = strings::TSubstring <xchar>;
850
851//##################################################################################################
852// Specializations of ArrayTraits for this class Substring
853//##################################################################################################
854namespace characters {
855#if !DOXYGEN
856template<typename TChar> struct ArrayTraits<strings::TSubstring<TChar>, TChar>
857{
859 static constexpr Policy Access = Policy::Implicit;
860 static constexpr Policy Construction = Policy::Implicit;
861 static constexpr const TChar* Buffer (const T& src) { return src.Buffer(); }
862 static constexpr integer Length (const T& src) { return src.Length(); }
863 static constexpr T Construct(const TChar* b, integer l) { return T(b, l); }
864};
865#endif // !DOXYGEN
866
867} namespace strings {
868
869
870extern template ALIB_DLL bool TSubstring<nchar>::ConsumeFloat ( double& , TNumberFormat<nchar>* );
871extern template ALIB_DLL bool TSubstring<nchar>::consumeDecDigitsImpl( uint64_t& );
872extern template ALIB_DLL bool TSubstring<nchar>::consumeIntImpl ( int64_t& , TNumberFormat<nchar>* );
873extern template ALIB_DLL bool TSubstring<nchar>::consumeDecImpl ( uint64_t& , TNumberFormat<nchar>* );
874extern template ALIB_DLL bool TSubstring<nchar>::consumeBinImpl ( uint64_t& , TNumberFormat<nchar>* );
875extern template ALIB_DLL bool TSubstring<nchar>::consumeHexImpl ( uint64_t& , TNumberFormat<nchar>* );
876extern template ALIB_DLL bool TSubstring<nchar>::consumeOctImpl ( uint64_t& , TNumberFormat<nchar>* );
877
878extern template ALIB_DLL bool TSubstring<wchar>::ConsumeFloat ( double& , TNumberFormat<wchar>* );
879extern template ALIB_DLL bool TSubstring<wchar>::consumeDecDigitsImpl( uint64_t& );
880extern template ALIB_DLL bool TSubstring<wchar>::consumeIntImpl ( int64_t& , TNumberFormat<wchar>* );
881extern template ALIB_DLL bool TSubstring<wchar>::consumeDecImpl ( uint64_t& , TNumberFormat<wchar>* );
882extern template ALIB_DLL bool TSubstring<wchar>::consumeBinImpl ( uint64_t& , TNumberFormat<wchar>* );
883extern template ALIB_DLL bool TSubstring<wchar>::consumeHexImpl ( uint64_t& , TNumberFormat<wchar>* );
884extern template ALIB_DLL bool TSubstring<wchar>::consumeOctImpl ( uint64_t& , TNumberFormat<wchar>* );
885
886extern template ALIB_DLL bool TSubstring<xchar>::ConsumeFloat ( double& , TNumberFormat<xchar>* );
887extern template ALIB_DLL bool TSubstring<xchar>::consumeDecDigitsImpl( uint64_t& );
888extern template ALIB_DLL bool TSubstring<xchar>::consumeIntImpl ( int64_t& , TNumberFormat<xchar>* );
889extern template ALIB_DLL bool TSubstring<xchar>::consumeDecImpl ( uint64_t& , TNumberFormat<xchar>* );
890extern template ALIB_DLL bool TSubstring<xchar>::consumeBinImpl ( uint64_t& , TNumberFormat<xchar>* );
891extern template ALIB_DLL bool TSubstring<xchar>::consumeHexImpl ( uint64_t& , TNumberFormat<xchar>* );
892extern template ALIB_DLL bool TSubstring<xchar>::consumeOctImpl ( uint64_t& , TNumberFormat<xchar>* );
893
894} // namespace alib::[strings]
895} // namespace [alib]
896
897// Note(25/01/17):
898// Clang strangely did not find the following templated operators when they resided in an
899// exported namespace.
900// The workaround was to not export the namespace but export each operator instead.
901// We think this is wrong behavior and not aligned with the language specification.
902#if !DOXYGEN
903namespace alib::strings {
904
906template<typename TChar>
907bool operator== (const TSubstring<TChar>& lhs, const TSubstring<TChar>& rhs)
908{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
909
911template<typename TChar, typename T>
912requires (!std::is_same_v<T, TSubstring<TChar>>)
913bool operator== (const TSubstring<TChar>& lhs, const T& rhs)
914{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
915
917template<typename TChar>
918auto operator<=> (const TSubstring<TChar>& lhs, const TSubstring<TChar>& rhs)
919{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
920
922template<typename TChar, typename T>
923requires (!std::same_as<TSubstring<TChar>, T>)
924auto operator<=> (const TSubstring<TChar>& lhs, const T& rhs)
925{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
926
927} // namespace [alib::strings]
928#endif // !DOXYGEN
constexpr integer Length() const
Definition string.inl:316
constexpr bool IsEmpty() const
Definition string.inl:365
bool EndsWith(const TString &needle) const
Definition string.inl:780
constexpr bool IsNotNull() const
Definition string.inl:355
integer IndexOfFirstDifference(const TString &needle, lang::Case sensitivity=lang::Case::Sensitive, integer startIdx=0) const
Definition string.inl:1091
bool AdjustRegion(integer &regionStart, integer &regionLength) const
Definition string.inl:1791
constexpr const TChar * Buffer() const
Definition string.inl:311
constexpr TString() noexcept=default
integer IndexOfSegmentEnd(character opener, character closer, integer idx) const
bool StartsWith(const TString &needle) const
Definition string.inl:751
integer IndexOfOrLength(TChar needle) const
Definition string.inl:875
TString< TChar > ConsumeField(TChar startChar, TChar endChar)
bool ConsumeString(const TString< TChar > &consumable)
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
Definition substring.inl:70
TSubstring & Split(integer position, TSubstring &target, integer separatorWidth=0, bool trim=false)
ALIB_DLL bool ConsumeFloat(double &result, TNumberFormat< TChar > *numberFormat=nullptr)
integer ConsumeChars(integer regionLength, TAString< TChar, TAllocator > &target, integer separatorWidth=0)
ALIB_DLL bool consumeHexImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:90
bool ConsumeBin(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
bool ConsumeOct(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
ALIB_DLL bool consumeDecDigitsImpl(uint64_t &result)
Definition substring.cpp:37
integer ConsumePartOf(const TString< TChar > &consumable, int minChars=1)
bool ConsumeDecDigits(std::integral auto &result)
bool ConsumeCharFromEnd(TChar consumable)
integer ConsumeChars(integer regionLength, TString< TChar > &target, integer separatorWidth=0)
TSubstring(const TString< TChar > &src)
Definition substring.inl:58
ALIB_DLL bool consumeDecImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:62
TString< TChar > base
The base string-type.
Definition substring.inl:42
bool ConsumeInt(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
ALIB_DLL bool consumeBinImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:76
bool ConsumeDec(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
integer ConsumeChars(integer regionLength, TSubstring *target=nullptr)
bool ConsumeStringFromEnd(const TString< TChar > &consumable)
TSubstring & Trim(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
bool ConsumeHex(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
integer ConsumeCharsFromEnd(integer regionLength, TSubstring *target=nullptr)
bool ConsumeChar(TChar consumable)
ALIB_DLL bool consumeOctImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
integer ConsumeCharsFromEnd(integer regionLength, TAString< TChar, TAllocator > &target, integer separatorWidth=0)
TString< TChar > ConsumeToken(TChar separator=',', lang::Inclusion includeSeparator=lang::Inclusion::Include)
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
Definition substring.inl:90
ALIB_DLL bool consumeIntImpl(int64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:48
TSubstring()
Default constructor creating a 6.1 Nulled Strings "nulled" substring.
Definition substring.inl:53
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
integer LastIndexOfAnyExclude(const TChar *haystack, integer startIdx, const TChar *needles, integer needlesLength)
TChar ToUpper(TChar c)
integer IndexOfAnyExcluded(const TChar *haystack, integer haystackLength, const TChar *needles, integer needlesLength)
Case
Denotes upper and lower case character treatment.
@ Clear
Chooses to clear existing data.
Whitespaces
Denotes whether a string is trimmed or not.
@ Keep
Keep whitespaces in string.
@ Trim
Trim whitespaces away.
Inclusion
Denotes how members of a set something should be taken into account.
@ Include
Chooses inclusion.
strings::TSubstring< xchar > XSubstring
Type alias in namespace alib.
strings::TSubstring< nchar > NSubstring
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
strings::TSubstring< complementChar > ComplementSubstring
Type alias in namespace alib.
strings::TSubstring< wchar > WSubstring
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
strings::TSubstring< strangeChar > StrangeSubstring
Type alias in namespace alib.
See sibling type NC.
Definition chk_nc.inl:33
static constexpr Policy Access
static integer Length(const TStringSource &src)
static TStringSource Construct(const TChar *array, integer length)
static constexpr Policy Construction
static const TChar * Buffer(const TStringSource &src)
static constexpr CString< TChar > DefaultWhitespaces())
"carriage return" and "tabulator", hence " \n\r\t".