ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
substring.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_SUBSTRING
9#define HPP_ALIB_STRINGS_SUBSTRING 1
10
11#if !defined (HPP_ALIB_STRINGS_CSTRING)
13#endif
14
15#if !defined (HPP_ALIB_STRINGS_ATRING)
17#endif
18
19
20namespace alib { namespace strings {
21
22/** ************************************************************************************************
23 * This class specializes parent class \alib{strings;TString;String} to allow reduction of
24 * the length of the represented string by cutting characters from the front or the end.
25 * Such reduction does not affect the character array represented, but only its representation
26 * by instances of this type.
27 *
28 * In other words, the difference to base class \alib{strings;TString;String} is, that this type
29 * allows to increase the pointer to the character array's start and to decrease its stored length.
30 * In all other respects, this class has the same lightweight nature and performance as its base.
31 * Furthermore, the flexible TMP mechanics for seamless construction is exposed from the base
32 * class and likewise available.
33 *
34 * Like base class \alib{strings;TString;String}, the class can not, and therefore does not,
35 * verify that the underlying buffer is (still) properly allocated and contains valid data.
36 * It is up to the user of this class to make sure the buffer stays intact until any referencing
37 * object of this type is disposed.
38 *
39 * @tparam TChar The character type.<br>
40 * Alias names for specializations of this class using character types
41 * \alib{characters;character}, \alib{characters;nchar}, \alib{characters;wchar},
42 * \alib{characters;xchar}, \alib{characters;complementChar} and \alib{characters;strangeChar}
43 * are provided in namespace #alib with type definitions \alib{Substring}, \alib{NSubstring},
44 * \alib{WSubstring}, \alib{XSubstring}, \alib{ComplementSubstring} and
45 * \alib{StrangeSubstring}.
46 **************************************************************************************************/
47template<typename TChar>
48class TSubstring : public TString<TChar>
49{
50 public:
51 #if !defined(ALIB_DOX)
52 // Import parent constructors
53 // Due to a doxygen bug in 1.8.14, we must not tell doxygen that we import overloaded methods.
54 using TString<TChar>::TString;
55 #endif
56
57 /** ****************************************************************************************
58 * Default constructor creating a \ref alib_strings_details_nulled \e "nulled" sub-string.
59 ******************************************************************************************/
61 : TString<TChar>()
62 {}
63
64 /** ****************************************************************************************
65 * Constructor using a string reference.
66 * @param src The source string.
67 ******************************************************************************************/
69 : TString<TChar>(src)
70 {}
71
72 /** ****************************************************************************************
73 * Sets this object to zero length.
74 * @return \c *this to allow concatenated calls.
75 ******************************************************************************************/
77 {
79 return *this;
80 }
81
82 /** ****************************************************************************************
83 * Moves the start to the first character not found in given character set \p{whiteSpaces}.
84 *
85 * @param whiteSpaces The characters used for trimming.
86 * Defaults to \ref alib::DefaultWhitespaces
87 * @return \c *this to allow concatenated calls.
88 ******************************************************************************************/
105
106 /** ****************************************************************************************
107 * Moves the start to the first character not found in given character set \p{whiteSpaces}.
108 *
109 * @param whiteSpaces The characters used for trimming.
110 * Defaults to \ref alib::DefaultWhitespaces
111 * @return \c *this to allow concatenated calls.
112 ******************************************************************************************/
113 TSubstring& TrimEnd( const TCString<TChar>& whiteSpaces
115 {
116 if ( TString<TChar>::length > 0 )
117 {
120 whiteSpaces.Buffer(),
121 whiteSpaces.Length() ) + 1;
122 }
123 return *this;
124 }
125
126 /** ****************************************************************************************
127 * Invokes #TrimStart and #TrimEnd .
128 *
129 * @param whiteSpaces The characters used for trimming.
130 * Defaults to \ref alib::DefaultWhitespaces
131 * @return \c *this to allow concatenated calls.
132 ******************************************************************************************/
133 TSubstring& Trim( const TCString<TChar>& whiteSpaces
135 {
136 return TrimEnd ( whiteSpaces )
137 .TrimStart( whiteSpaces );
138 }
139
140 /** ****************************************************************************************
141 * Retrieve and remove the first character from the sub-string.
142 *
143 * @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
144 * consume operation. Defaults to \b Whitespaces::Keep.
145 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
146 * If \c <false> is added to the method name, no parameter check is
147 * performed.
148 *
149 * @return The character at the start of the represented region.
150 * If this \b %Substring is empty or \e nulled, '\0' is returned.
151 ******************************************************************************************/
152 template < bool TCheck = true,
153 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
155 {
156 if constexpr ( TCheck )
157 {
158 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
159 TrimStart();
161 return '\0';
162 }
163 else
164 {
166 "Non checking but called on empty string" )
167 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
168 TrimStart();
169 }
170
173 return *TString<TChar>::buffer++;
175 }
176
177 /** ****************************************************************************************
178 * Checks if this object starts with the given character \p{consumable}. If it does, this
179 * character is cut from this object.
180 *
181 * @tparam TSensitivity The sensitivity of the comparison.
182 * Defaults to \b Case::Sensitive.
183 * @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
184 * consume operation. Defaults to \b Whitespaces::Keep.
185 * @param consumable The consumable character.
186 * @return \c true, if this object was starting with \p{consumable} and consequently the
187 * string was cut by one.
188 ******************************************************************************************/
189 template< lang::Case TSensitivity= lang::Case::Sensitive,
190 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep>
191 bool ConsumeChar( TChar consumable )
192
193 {
194 if ( TTrimBeforeConsume == lang::Whitespaces::Trim )
195 TrimStart();
196
197 if ( ( TSensitivity == lang::Case::Sensitive && TString<TChar>::CharAtStart() != consumable )
200 return false;
201
206 return true;
207 }
208
209 /** ****************************************************************************************
210 * Checks if this object ends with the given character \p{consumable}. If it does, this
211 * character is cut from the end of object.
212 *
213 * @tparam TSensitivity The sensitivity of the comparison.
214 * Defaults to \b Case::Sensitive.
215 * @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
216 * consume operation. Defaults to \b Whitespaces::Keep.
217 * @param consumable The consumable character.
218 * @return \c true, if this object was starting with \p{consumable} and consequently the
219 * string was cut by one.
220 ******************************************************************************************/
221 template< lang::Case TSensitivity= lang::Case::Sensitive,
222 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep>
223 bool ConsumeCharFromEnd( TChar consumable )
224 {
225 if ( TTrimBeforeConsume == lang::Whitespaces::Trim )
226 TrimEnd();
227
228 if ( ( TSensitivity == lang::Case::Sensitive && TString<TChar>::CharAtEnd() != consumable )
231 return false;
233 return true;
234 }
235
236 /** ****************************************************************************************
237 * Retrieve and remove the last character in the sub-string.
238 *
239 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
240 * If \c <false> is added to the method name, no check whether this
241 * string is empty is performed.
242 *
243 * @tparam TTrimBeforeConsume Determines if the string should be (right-) trimmed before the
244 * consume operation. Defaults to \b Whitespaces::Keep.
245 * @return The character at the start of the represented region.
246 * If this \b %Substring is empty or \e nulled, '\0' is returned.
247 ******************************************************************************************/
248 template <bool TCheck= true,
249 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
251 {
252 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
253 TrimEnd();
254
256 if constexpr ( TCheck )
257 {
259 return '\0';
260 }
261 else
262 {
264 "Non checking but called on empty string" )
265 }
268 }
269
270 /** ****************************************************************************************
271 * Cuts the given number of characters from the beginning of the Substring and optionally
272 * places the portion that was cut in parameter \p{target} (if provided).<br>
273 *
274 * If parameter \p{regionLength} is negative, nothing is cut and optional argument
275 * \p{target} is set empty. If \p{regionLength} is equal or greater than this
276 * object's length, all contents is 'moved' to \p{target}.
277 *
278 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
279 * If \c <false>, parameter \p{regionLength} has to be in the range of
280 * this object's size.
281 *
282 * @param regionLength The length of the region at the start to delete.
283 * @param target An optional target \b %Substring that receives the portion that
284 * is cut from this object. Defaults to nullptr.
285 *
286 * @return The new length of the sub-string.
287 ******************************************************************************************/
288 template <bool TCheck= true>
289 integer ConsumeChars( integer regionLength, TSubstring* target= nullptr )
290 {
291 if constexpr ( TCheck )
292 {
293 if ( regionLength < 0 )
294 {
295 if ( target != nullptr )
296 target->Clear();
298 }
299 if ( regionLength > TString<TChar>::length )
300 regionLength= TString<TChar>::length;
301 }
302 else
303 {
304 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength <= TString<TChar>::length,
305 "STRINGS", "Non checking but regionLength out of bounds" )
306 }
307
308 if ( target != nullptr )
309 *target= this->TString<TChar>::template Substring<false>( 0, regionLength );
310
312 TString<TChar>::buffer+= regionLength;
313 TString<TChar>::length-= regionLength;
316 }
317
318 /** ****************************************************************************************
319 * Cuts the given number of characters from the end of the \b %Substring and optionally
320 * places the portion that was cut in parameter \p{target} (if provided).<br>
321 * Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
322 * is cut and \p{target} is set empty. If \p{regionLength} is greater than this
323 * object's length, all contents is 'moved' to \p{target}.
324 *
325 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
326 * If \c <false> is added to the method name, no parameter check is
327 * performed.
328 *
329 * @param regionLength The length of the region at the start to delete.
330 * @param target An optional target \b %Substring that receives the portion that
331 * is cut from this object. Defaults to nullptr.
332 *
333 * @return The new length of the sub-string.
334 ******************************************************************************************/
335 template <bool TCheck= true>
336 integer ConsumeCharsFromEnd( integer regionLength, TSubstring* target= nullptr )
337 {
338 if constexpr ( TCheck )
339 {
340 if ( regionLength < 0 )
341 {
342 if ( target != nullptr )
343 target->Clear();
345 }
346 if ( regionLength > TString<TChar>::length )
347 regionLength= TString<TChar>::length;
348 }
349 else
350 {
351 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength <= TString<TChar>::length,
352 "STRINGS", "Non checking but regionLength out of bounds" )
353 }
354
355 if ( target != nullptr )
356 *target= this->TString<TChar>::template Substring<false>( TString<TChar>::length - regionLength, regionLength );
357
358 TString<TChar>::length-= regionLength;
360 }
361
362 /** ****************************************************************************************
363 * Cuts the given number of characters from the beginning of the Substring and optionally
364 * places the portion that was cut in parameter \p{target}.<br>
365 * Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
366 * is cut and \p{target} is set empty, respectively left untouched depending on
367 * \p{TTargetData}.
368 *
369 * If \p{regionLength} is greater than this object's length, all contents is 'moved'
370 * to \p{target}.
371 *
372 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
373 * If \c <false> is added to the method name, no parameter check is
374 * performed.
375 *
376 * @tparam TTargetData If \c CurrentData::Keep, \b %AString \p{target} is not cleared
377 * before the result is written. Defaults to \c CurrentData::Clear.
378 * @param regionLength The length of the region at the start to delete.
379 * @param target A target \b %AString that receives the portion that
380 * is cut from this object.
381 * @param separatorWidth This width is added to what is cut from this string, while
382 * \p{target} still receives the portion defined by \p{regionLength}.
383 * Defaults to 0.
384 *
385 * @return The new length of the sub-string.
386 ******************************************************************************************/
387 template <bool TCheck = true,
390 TAString<TChar>& target,
391 integer separatorWidth =0 )
392 {
393 if constexpr ( TTargetData == lang::CurrentData::Clear )
394 target.Reset();
395
396 if constexpr ( TCheck )
397 {
398 if ( separatorWidth < 0 )
399 separatorWidth= 0;
400
401 if ( regionLength < 0 )
403
404 if ( regionLength > TString<TChar>::length - separatorWidth )
405 {
406 regionLength= TString<TChar>::length - separatorWidth;
407 if ( regionLength < 0 )
409 }
410
411 }
412 else
413 {
414 ALIB_ASSERT_ERROR( separatorWidth >= 0,
415 "STRINGS", "Non checking but separator width negative" )
416 ALIB_ASSERT_ERROR( regionLength >= 0
417 && regionLength + separatorWidth <= TString<TChar>::length,
418 "STRINGS", "Non checking but regionLength out of bounds" )
419 }
420
421 target.template _<false>( *this, 0, regionLength );
422
423 regionLength+= separatorWidth;
425 TString<TChar>::buffer+= regionLength ;
426 TString<TChar>::length-= regionLength;
429 }
430
431 /** ****************************************************************************************
432 * Cuts the given number of characters from the beginning of the Substring and optionally
433 * places the portion that was cut in parameter \p{target}.<br>
434 * Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
435 * is cut and \p{target} is set empty, respectively left untouched depending on
436 * \p{TTargetData}.
437 *
438 * If \p{regionLength} is greater than this object's length, all contents is 'moved'
439 * to \p{target}.
440 *
441 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
442 * If \c <false> is added to the method name, no parameter check is
443 * performed.
444 *
445 * @param regionLength The length of the region at the start to delete.
446 * @param target A target \b %String that receives the portion that
447 * is cut from this object.
448 * @param separatorWidth This width is added to what is cut from this string, while
449 * \p{target} still receives the portion defined by \p{regionLength}.
450 * Defaults to 0.
451 *
452 * @return The new length of the sub-string.
453 ******************************************************************************************/
454 template <bool TCheck = true>
456 TString<TChar>& target,
457 integer separatorWidth =0 )
458 {
459 if constexpr ( TCheck )
460 {
461 if ( separatorWidth < 0 )
462 separatorWidth= 0;
463
464 if ( regionLength < 0 )
466
467 if ( regionLength > TString<TChar>::length - separatorWidth )
468 {
469 regionLength= TString<TChar>::length - separatorWidth;
470 if ( regionLength < 0 )
472 }
473 }
474 else
475 {
476 ALIB_ASSERT_ERROR( separatorWidth >= 0,
477 "STRINGS", "Non checking but separator width negative" )
478 ALIB_ASSERT_ERROR( regionLength >= 0
479 && regionLength + separatorWidth <= TString<TChar>::length,
480 "STRINGS", "Non checking but regionLength out of bounds" )
481 }
482
483 target= String( TString<TChar>::buffer, regionLength );
484
485 regionLength+= separatorWidth;
487 TString<TChar>::buffer+= regionLength ;
488 TString<TChar>::length-= regionLength;
491 }
492
493 /** ****************************************************************************************
494 * Cuts the given number of characters from the end of the sub-string and
495 * places the portion that was cut in parameter \p{target}.<br>
496 * Parameter \p{regionLength} is checked to be between 0 and length. If negative, nothing
497 * is cut and \p{target} is set empty, respectively left untouched depending on \p
498 * If \p{regionLength} is greater than this object's length, all contents is 'moved'
499 * to \p{target}.
500 *
501 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
502 * If \c <false> is added to the method name, no parameter check is
503 * performed.
504 * @tparam TTargetData If \c CurrentData::Keep, the parameter \p{target} is not cleared
505 * before the result is written. Defaults to \c CurrentData::Clear.
506 *
507 * @param regionLength The length of the region at the start to delete.
508 * @param target A target \b %AString that receives the portion that
509 * is cut from this object.
510 * @param separatorWidth This width is added to what is cut from this string, while
511 * \p{target} still receives the portion defined by \p{regionLength}.
512 * Defaults to 0.
513 *
514 * @return The new length of the sub-string.
515 ******************************************************************************************/
516 template <bool TCheck = true,
519 AString& target,
520 integer separatorWidth =0 )
521 {
522 if constexpr ( TTargetData == lang::CurrentData::Clear )
523 target.Reset();
524
525 if constexpr ( TCheck )
526 {
527 if ( separatorWidth < 0 ) separatorWidth= 0;
528 if ( regionLength < 0 ) return TString<TChar>::length;
529 if ( regionLength > TString<TChar>::length - separatorWidth ) regionLength= TString<TChar>::length - separatorWidth;
530 if ( regionLength < 0 ) return TString<TChar>::length;
531 }
532 else
533 {
534 ALIB_ASSERT_ERROR( separatorWidth >=0 ,
535 "STRINGS", "Non checking but separator width negative" )
536 ALIB_ASSERT_ERROR( regionLength >=0 && regionLength + separatorWidth <= TString<TChar>::length,
537 "STRINGS", "Non checking but regionLength out of bounds" )
538 }
539
540 target._<false>( *this, TString<TChar>::length - regionLength, regionLength );
541
542 TString<TChar>::length-= regionLength + separatorWidth;
544 }
545
546 /** ****************************************************************************************
547 * Searches \p{separator} and cuts the beginning of this string, including the separator.
548 * What was consumed is returned, excluding the separator.
549 *
550 * If the separator is not found, all of this string is consumed and returned.
551 *
552 * @param separator The separator to search.
553 * Defaults to <c>','</c>.
554 *
555 * @return The token consumed.
556 ******************************************************************************************/
557 TString<TChar> ConsumeToken( TChar separator= ',' )
558 {
560 "STRINGS", "ConsumeToken on nulled Substring" )
561 integer separatorPos= TString<TChar>::IndexOfOrLength( separator );
562 TString<TChar> result = TString<TChar>( TString<TChar>::buffer, separatorPos );
563
565 TString<TChar>::buffer+= separatorPos;
566 TString<TChar>::length-= separatorPos;
567 if( TString<TChar>::length > 0 )
568 {
571 }
573 return result;
574 }
575
576 /** ****************************************************************************************
577 * Checks if this object starts with the given string \p{consumable}. If it does, this
578 * string is cut from this object.
579 *
580 * @tparam TSensitivity The sensitivity of the comparison.
581 * Defaults to \b Case::Sensitive.
582 * @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
583 * consume operation. Defaults to \b Whitespaces::Keep.
584 * @param consumable The consumable string.
585 * @return \c true, if this object was starting with \p{consumable} and consequently the
586 * string was cut.
587 ******************************************************************************************/
588 template< lang::Case TSensitivity= lang::Case::Sensitive,
589 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
590 bool ConsumeString( const TString<TChar>& consumable )
591 {
592 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
593 TrimStart();
594
595 if ( !TString<TChar>::template StartsWith<true,TSensitivity>( consumable ) )
596 return false;
597
599 TString<TChar>::buffer+= consumable.Length();
600 TString<TChar>::length-= consumable.Length();
602 return true;
603 }
604
605 /** ****************************************************************************************
606 * Checks if this object ends with the given string \p{consumable}. If it does, this
607 * string is cut from the end of object.
608 *
609 * @tparam TSensitivity The sensitivity of the comparison.
610 * Defaults to \b Case::Sensitive.
611 * @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
612 * consume operation. Defaults to \b Whitespaces::Keep.
613 * @param consumable The consumable string
614 * @return \c true, if this object was starting with \p{consumable} and consequently the
615 * string was cut.
616 ******************************************************************************************/
617 template< lang::Case TSensitivity= lang::Case::Sensitive,
618 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
619 bool ConsumeStringFromEnd( const TString<TChar>& consumable )
620 {
621 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
622 TrimEnd();
623
624 if ( !TString<TChar>::template EndsWith<true,TSensitivity>( consumable ) )
625 return false;
626 TString<TChar>::length-= consumable.Length();
627 return true;
628 }
629
630 /** ****************************************************************************************
631 * Consumes a minimum of \p{minChars} of string \p{consumable} from the start of this
632 * sub-string. If the minimum characters could not be found, nothing is consumed, otherwise,
633 * the method consumes as much as possible.<br>
634 *
635 * This method is useful read "tokens" from a string that may be abbreviated.
636 * Within \alib this method is for example used with
637 * \ref alib_enums_records_details_serialization "deserialization of enumeration elements".
638 *
639 * @tparam TSensitivity The sensitivity of the comparison.
640 * Defaults to \b Case::Ignore.
641 * @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
642 * first character consume operation.
643 * Defaults to \b Whitespaces::Keep.
644 * @param consumable The consumable string.
645 * @param minChars The minimum amount of characters to consume. If \c 0 or
646 * negative, the length of \p{consumable} is chosen.
647 * Optional and defaults to \c 1.
648 * @return The amount of characters consumed.
649 ******************************************************************************************/
650 template< lang::Case TSensitivity= lang::Case::Ignore,
651 lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
653 int minChars = 1 )
654 {
655 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
656 TrimStart();
657 if ( minChars <= 0 )
658 minChars= static_cast<int>( consumable.Length() );
659
660 if ( minChars == 0 || minChars > consumable.Length() )
661 return 0;
662
663 integer diff= TString<TChar>::IndexOfFirstDifference( consumable, TSensitivity );
664 if( diff < static_cast<integer>( minChars ) )
665 return 0;
666 ConsumeChars( diff );
667 return diff;
668 }
669
670 /** ****************************************************************************************
671 * Consumes a field from the beginning of this sub-string, which is surrounded by
672 * given start end end character identifiers. If both are the same, e.g. \c '"', then
673 * the first occurrence of the end character is used. If they are not the same, e.g.
674 * \c '<' and \c '>', then repeated start characters are counted and consumption only ends
675 * when a corresponding amount of end characters has been found.
676 *
677 * @tparam TTrimBeforeConsume Determines if the string should be (left-) trimmed before the
678 * consume operation. Defaults to \b Whitespaces::Keep.
679 * @param startChar The start character of the field to consume.
680 * @param endChar The end character of the field to consume.
681 * @return The string consumed. \b NullString on error (start/end character not found)
682 ******************************************************************************************/
683 template< lang::Whitespaces TTrimBeforeConsume= lang::Whitespaces::Keep >
684 TString<TChar> ConsumeField( TChar startChar, TChar endChar )
685 {
686 if constexpr ( TTrimBeforeConsume == lang::Whitespaces::Trim )
687 TrimStart();
688
689 integer endIdx;
690 if ( TString<TChar>::CharAtStart() != startChar
691 || (endIdx= TString<TChar>::IndexOfSegmentEnd( startChar, endChar, 1)) < 0 )
692 return nullptr;
693
694
696 TString<TChar> result= TString<TChar>( TString<TChar>::buffer + 1, endIdx - 1 );
697 TString<TChar>::buffer+= (endIdx + 1);
698 TString<TChar>::length-= (endIdx + 1);
700 return result;
701 }
702
703
704 #if defined(ALIB_DOX)
705 /** ****************************************************************************************
706 * Consumes all characters \c '0' to \c '9' at the start of this object and stores the
707 * value they represent in \p{result}.<br>
708 * Unlike methods #ConsumeInt or #ConsumeDec, this method does not consume (accept)
709 * sign-, whitespace- or group-characters.
710 *
711 * @tparam TIntegral The output type.
712 * Must be statically castable from \b uint64_t.
713 * @param [out] result A reference to the result value.
714 *
715 * @return \c true if a number was found and consumed, \c false otherwise.
716 ******************************************************************************************/
717 template<typename TIntegral>
718 inline
719 bool ConsumeDecDigits( TIntegral& result );
720 #else
721 template<typename TIntegral>
722 ATMP_T_IF(bool, ATMP_IS_INT(TIntegral))
723 ConsumeDecDigits( TIntegral& result )
724 {
725 uint64_t resultImpl;
726 bool returnValue= consumeDecDigitsImpl( resultImpl );
727 result= static_cast<TIntegral>( resultImpl );
728 return returnValue;
729 }
730 #endif
731
732 #if defined(ALIB_DOX)
733 /** ****************************************************************************************
734 * Consumes an integral value in decimal, binary, hexadecimal or octal format from the
735 * string.
736 *
737 * Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
738 * \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
739 * which is configured to not using (not allowing) grouping characters.
740 *
741 * For more information on number conversion, see class
742 * \alib{strings;TNumberFormat;NumberFormat}.
743 *
744 * @tparam TIntegral The output type.
745 * Must be statically castable from \b uint64_t.
746 * @param [out] result A reference to the result value.
747 * @param numberFormat The number format to use. Defaults to \c nullptr.
748 * @return \c true if a number was found and consumed, \c false otherwise.
749 ******************************************************************************************/
750 template<typename TIntegral>
751 inline
752 bool ConsumeInt( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr );
753 #else
754 template<typename TIntegral>
755 ATMP_T_IF(bool, ATMP_IS_INT(TIntegral) )
756 ConsumeInt( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr )
757 {
758 int64_t resultImpl;
759 bool returnValue= consumeIntImpl( resultImpl, numberFormat );
760 result= static_cast<TIntegral>( resultImpl );
761 return returnValue;
762 }
763 #endif
764
765 #if defined(ALIB_DOX)
766 /** ****************************************************************************************
767 * Consumes an unsigned integer in standard decimal format from the start of this %AString.
768 *
769 * Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
770 * \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
771 * which is configured to not using (not allowing) grouping characters.
772 *
773 * Sign literals \c '-' or \c '+' are \b not accepted and parsing will fail.
774 * For reading signed integral values, see methods #ConsumeInt, for floating point numbers
775 * #ConsumeFloat.
776 *
777 * For more information on number conversion, see class
778 * \alib{strings;TNumberFormat;NumberFormat}.
779 *
780 * @tparam TIntegral The output type.
781 * Must be statically castable from \b uint64_t.
782 * @param [out] result A reference to the result value.
783 * @param numberFormat The number format to use. Defaults to \c nullptr.
784 * @return \c true if a number was found and consumed, \c false otherwise.
785 ******************************************************************************************/
786 template<typename TIntegral>
787 inline
788 bool ConsumeDec( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr );
789 #else
790 template<typename TIntegral>
791 ATMP_T_IF(bool, ATMP_IS_INT(TIntegral))
792 ConsumeDec( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr )
793 {
794 uint64_t resultImpl;
795 bool returnValue= consumeDecImpl( resultImpl, numberFormat );
796 result= static_cast<TIntegral>( resultImpl );
797 return returnValue;
798 }
799 #endif
800
801 #if defined(ALIB_DOX)
802 /** ****************************************************************************************
803 * Consumes an unsigned integer in binary format from the start of this string.
804 *
805 * Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
806 * \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
807 * which is configured to not using (not allowing) grouping characters.
808 *
809 * For more information on number conversion, see class
810 * \alib{strings;TNumberFormat;NumberFormat}.
811 *
812 * @param [out] result A reference to the result value.
813 * @param numberFormat The number format to use. Defaults to \c nullptr.
814 * @tparam TIntegral The output type.
815 * Must be statically castable from \b uint64_t.
816 * @return \c true if a number was found and consumed, \c false otherwise.
817 ******************************************************************************************/
818 template<typename TIntegral>
819 inline
820 bool ConsumeBin( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr );
821 #else
822 template<typename TIntegral>
823 ATMP_T_IF(bool, ATMP_IS_INT(TIntegral))
824 ConsumeBin( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr )
825 {
826 uint64_t resultImpl;
827 bool returnValue= consumeBinImpl( resultImpl, numberFormat );
828 result= static_cast<TIntegral>( resultImpl );
829 return returnValue;
830 }
831 #endif
832
833 #if defined(ALIB_DOX)
834 /** ****************************************************************************************
835 * Consumes an unsigned integer in hexadecimal format from the start of this string.
836 *
837 * Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
838 * \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
839 * which is configured to not using (not allowing) grouping characters.
840 *
841 * For more information on number conversion, see class
842 * \alib{strings;TNumberFormat;NumberFormat}.
843 *
844 * @tparam TIntegral The output type.
845 * Must be statically castable from \b uint64_t.
846 * @param [out] result A reference to the result value.
847 * @param numberFormat The number format to use. Defaults to \c nullptr.
848 *
849 * @return \c true if a number was found and consumed, \c false otherwise.
850 ******************************************************************************************/
851 template<typename TIntegral>
852 inline
853 bool ConsumeHex( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr );
854 #else
855 template<typename TIntegral>
856 ATMP_T_IF(bool, ATMP_IS_INT(TIntegral))
857 ConsumeHex( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr )
858 {
859 uint64_t resultImpl;
860 bool returnValue= consumeHexImpl( resultImpl, numberFormat );
861 result= static_cast<TIntegral>( resultImpl );
862 return returnValue;
863 }
864 #endif
865
866 #if defined(ALIB_DOX)
867 /** ****************************************************************************************
868 * Consumes an unsigned integer in octal format from the start of this string.
869 *
870 * Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
871 * \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
872 * which is configured to not using (not allowing) grouping characters.
873 *
874 * For more information on number conversion, see class
875 * \alib{strings;TNumberFormat;NumberFormat}.
876 *
877 * @tparam TIntegral The output type.
878 * Must be statically castable from \b uint64_t.
879 * @param [out] result A reference to the result value.
880 * @param numberFormat The number format to use. Defaults to \c nullptr.
881 *
882 * @return \c true if a number was found and consumed, \c false otherwise.
883 ******************************************************************************************/
884 template<typename TIntegral>
885 inline
886 bool ConsumeOct( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr );
887 #else
888 template<typename TIntegral>
889 ATMP_T_IF(bool, ATMP_IS_INT(TIntegral))
890 ConsumeOct( TIntegral& result, TNumberFormat<TChar>* numberFormat= nullptr )
891 {
892 uint64_t resultImpl;
893 bool returnValue= consumeOctImpl( resultImpl, numberFormat );
894 result= static_cast<TIntegral>( resultImpl );
895 return returnValue;
896 }
897 #endif
898
899 /** ****************************************************************************************
900 * Consumes a floating point number from the start of this string.
901 *
902 * on the given \p{numberFormat} instance.<br>
903 * Parameter \p{numberFormat} defaults to \c nullptr. This denotes static singleton
904 * \alib{strings;TNumberFormat::Computational;NumberFormat::Computational}
905 * which is configured to 'international' settings (not using the locale) and therefore
906 * also not parsing grouping characters.
907 *
908 * For more information on parsing options for floating point numbers and number
909 * conversion in general, see class
910 * \alib{strings;TNumberFormat;NumberFormat}.
911 *
912 * @param [out] result A reference to the result value.
913 * @param numberFormat The number format to use. Defaults to \c nullptr.
914 *
915 * @return \c true if a number was found and consumed, \c false otherwise.
916 ******************************************************************************************/
918 bool ConsumeFloat( double& result,
919 TNumberFormat<TChar>* numberFormat =nullptr );
920
921
922 /** ****************************************************************************************
923 * Splits this sub-string into two parts. What remains in this object is the region
924 * from 0 to \p{position}.
925 * \p{target} receives the rest. If \p{separatorWidth} is given, this is subtracted from
926 * the front of \p{target}.
927 *
928 * @tparam TCheck Defaults to \c true which is the normal invocation mode.
929 * If \c <false> is added to the method name, no parameter check is
930 * performed.
931 *
932 * @param position The index where this object is split.
933 * @param target The target sub-string to receive the right part of the string.
934 * @param separatorWidth This does not change what remains in this object, but defines
935 * the number of characters that are cut from the front of the
936 * \p{target}. Defaults to 0.
937 * @param trim If \c true, both sub-strings will be trimmed.
938 *
939 * @return \c *this to allow concatenated calls.
940 ******************************************************************************************/
941 template <bool TCheck= true>
942 TSubstring& Split( integer position, TSubstring& target, integer separatorWidth =0,
943 bool trim= false )
944
945 {
946 if constexpr ( TCheck )
947 {
948 TString<TChar>::AdjustRegion( position, separatorWidth );
949 }
950 else
951 {
952 ALIB_ASSERT_ERROR( position >=0 && position <= TString<TChar>::length,
953 "STRINGS", "Non checking but position out of bounds" )
954 ALIB_ASSERT_ERROR( position + separatorWidth <= TString<TChar>::length,
955 "STRINGS", "Non checking but position + separator width out of bounds" )
956 }
957
958 target= this->TString<TChar>::template Substring<false>( position + separatorWidth,
959 TString<TChar>::length - position - separatorWidth );
960 TString<TChar>::length= position;
961 if( trim )
962 {
963 target.Trim();
964 this ->Trim();
965 }
966 return *this;
967 }
968
969 //##############################################################################################
970 // Protected Methods
971 //##############################################################################################
972 protected:
973 /** ****************************************************************************************
974 * Implementation of #ConsumeDecDigits (the non-inline part).
975 *
976 * @param [out] result A reference to the result value.
977 * @return \c true if a number was found and consumed, \c false otherwise.
978 ******************************************************************************************/
979 ALIB_API bool consumeDecDigitsImpl( uint64_t& result );
980
981 /** ****************************************************************************************
982 * Implementation of #ConsumeInt (the non-inline part).
983 *
984 * @param [out] result A reference to the result value.
985 * @param numberFormat The number format to use.
986 * @return \c true if a number was found and consumed, \c false otherwise.
987 ******************************************************************************************/
988 ALIB_API bool consumeIntImpl( int64_t& result, TNumberFormat<TChar>* numberFormat );
989
990 /** ****************************************************************************************
991 * Implementation of #ConsumeDec (the non-inline part).
992 *
993 * @param [out] result A reference to the result value.
994 * @param numberFormat The number format to use.
995 * @return \c true if a number was found and consumed, \c false otherwise.
996 ******************************************************************************************/
997 ALIB_API bool consumeDecImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
998
999 /** ****************************************************************************************
1000 * Implementation of #ConsumeBin (the non-inline part).
1001 *
1002 * @param [out] result A reference to the result value.
1003 * @param numberFormat The number format to use.
1004 * @return \c true if a number was found and consumed, \c false otherwise.
1005 ******************************************************************************************/
1006 ALIB_API bool consumeBinImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
1007
1008 /** ****************************************************************************************
1009 * Implementation of #ConsumeHex (the non-inline part).
1010 *
1011 * @param [out] result A reference to the result value.
1012 * @param numberFormat The number format to use.
1013 * @return \c true if a number was found and consumed, \c false otherwise.
1014 ******************************************************************************************/
1015 ALIB_API bool consumeHexImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
1016
1017 /** ****************************************************************************************
1018 * Implementation of #ConsumeOct (the non-inline part).
1019 *
1020 * @param [out] result A reference to the result value.
1021 * @param numberFormat The number format to use.
1022 * @return \c true if a number was found and consumed, \c false otherwise.
1023 ******************************************************************************************/
1024 ALIB_API bool consumeOctImpl( uint64_t& result, TNumberFormat<TChar>* numberFormat );
1025
1026
1027}; // class TSubstring
1028
1029extern template ALIB_API bool TSubstring<nchar>::ConsumeFloat ( double& , TNumberFormat<nchar>* );
1030extern template ALIB_API bool TSubstring<nchar>::consumeDecDigitsImpl( uint64_t& );
1031extern template ALIB_API bool TSubstring<nchar>::consumeIntImpl ( int64_t& , TNumberFormat<nchar>* );
1032extern template ALIB_API bool TSubstring<nchar>::consumeDecImpl ( uint64_t& , TNumberFormat<nchar>* );
1033extern template ALIB_API bool TSubstring<nchar>::consumeBinImpl ( uint64_t& , TNumberFormat<nchar>* );
1034extern template ALIB_API bool TSubstring<nchar>::consumeHexImpl ( uint64_t& , TNumberFormat<nchar>* );
1035extern template ALIB_API bool TSubstring<nchar>::consumeOctImpl ( uint64_t& , TNumberFormat<nchar>* );
1036
1037extern template ALIB_API bool TSubstring<wchar>::ConsumeFloat ( double& , TNumberFormat<wchar>* );
1038extern template ALIB_API bool TSubstring<wchar>::consumeDecDigitsImpl( uint64_t& );
1039extern template ALIB_API bool TSubstring<wchar>::consumeIntImpl ( int64_t& , TNumberFormat<wchar>* );
1040extern template ALIB_API bool TSubstring<wchar>::consumeDecImpl ( uint64_t& , TNumberFormat<wchar>* );
1041extern template ALIB_API bool TSubstring<wchar>::consumeBinImpl ( uint64_t& , TNumberFormat<wchar>* );
1042extern template ALIB_API bool TSubstring<wchar>::consumeHexImpl ( uint64_t& , TNumberFormat<wchar>* );
1043extern template ALIB_API bool TSubstring<wchar>::consumeOctImpl ( uint64_t& , TNumberFormat<wchar>* );
1044
1045extern template ALIB_API bool TSubstring<xchar>::ConsumeFloat ( double& , TNumberFormat<xchar>* );
1046extern template ALIB_API bool TSubstring<xchar>::consumeDecDigitsImpl( uint64_t& );
1047extern template ALIB_API bool TSubstring<xchar>::consumeIntImpl ( int64_t& , TNumberFormat<xchar>* );
1048extern template ALIB_API bool TSubstring<xchar>::consumeDecImpl ( uint64_t& , TNumberFormat<xchar>* );
1049extern template ALIB_API bool TSubstring<xchar>::consumeBinImpl ( uint64_t& , TNumberFormat<xchar>* );
1050extern template ALIB_API bool TSubstring<xchar>::consumeHexImpl ( uint64_t& , TNumberFormat<xchar>* );
1051extern template ALIB_API bool TSubstring<xchar>::consumeOctImpl ( uint64_t& , TNumberFormat<xchar>* );
1052
1053} // namespace alib::[strings]
1054
1055/// Type alias in namespace \b alib.
1056using Substring = strings::TSubstring<character>;
1057
1058/// Type alias in namespace \b alib.
1059using NSubstring = strings::TSubstring<nchar>;
1060
1061/// Type alias in namespace \b alib.
1062using WSubstring = strings::TSubstring<wchar>;
1063
1064/// Type alias in namespace \b alib.
1065using XSubstring = strings::TSubstring<xchar>;
1066
1067} // namespace [alib]
1068
1069#endif // HPP_ALIB_STRINGS_SUBSTRING
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1056
integer IndexOfSegmentEnd(TChar opener, TChar closer, integer idx) const
integer IndexOfFirstDifference(const TString &needle, lang::Case sensitivity=lang::Case::Sensitive, integer idx=0) const
Definition string.hpp:1207
constexpr integer Length() const
Definition string.hpp:357
bool AdjustRegion(integer &regionStart, integer &regionLength) const
Definition string.hpp:1994
integer IndexOfOrLength(TChar needle) const
Definition string.hpp:965
constexpr TString() noexcept=default
constexpr const TChar * Buffer() const
Definition string.hpp:350
integer ConsumeChars(integer regionLength, TAString< TChar > &target, integer separatorWidth=0)
bool ConsumeStringFromEnd(const TString< TChar > &consumable)
TSubstring & Trim(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
TString< TChar > ConsumeToken(TChar separator=',')
ALIB_API bool consumeDecDigitsImpl(uint64_t &result)
Definition substring.cpp:28
ALIB_API bool consumeBinImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:73
TString< TChar > ConsumeField(TChar startChar, TChar endChar)
bool ConsumeString(const TString< TChar > &consumable)
TSubstring & Split(integer position, TSubstring &target, integer separatorWidth=0, bool trim=false)
bool ConsumeOct(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
bool ConsumeHex(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
ALIB_API bool ConsumeFloat(double &result, TNumberFormat< TChar > *numberFormat=nullptr)
TSubstring(const TString< TChar > &src)
Definition substring.hpp:68
integer ConsumeCharsFromEnd(integer regionLength, TSubstring *target=nullptr)
integer ConsumePartOf(const TString< TChar > &consumable, int minChars=1)
integer ConsumeChars(integer regionLength, TSubstring *target=nullptr)
bool ConsumeBin(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
bool ConsumeDec(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
bool ConsumeDecDigits(TIntegral &result)
bool ConsumeInt(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
Definition substring.hpp:89
integer ConsumeCharsFromEnd(integer regionLength, AString &target, integer separatorWidth=0)
ALIB_API bool consumeHexImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:89
integer ConsumeChars(integer regionLength, TString< TChar > &target, integer separatorWidth=0)
ALIB_API bool consumeIntImpl(int64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:41
ALIB_API bool consumeDecImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
Definition substring.cpp:57
ALIB_API bool consumeOctImpl(uint64_t &result, TNumberFormat< TChar > *numberFormat)
bool ConsumeCharFromEnd(TChar consumable)
bool ConsumeChar(TChar consumable)
#define ATMP_IS_INT(T)
Definition tmp.hpp:29
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_API
Definition alib.hpp:538
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ATMP_T_IF(T, Cond)
Definition tmp.hpp:53
@ Keep
Keep whitespaces in string.
@ Trim
Trim whitespaces away.
@ Clear
Chooses to clear existing data.
Definition alib.cpp:57
strings::TSubstring< character > Substring
Type alias in namespace alib.
strings::TSubstring< nchar > NSubstring
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
strings::TSubstring< wchar > WSubstring
Type alias in namespace alib.
strings::TSubstring< xchar > XSubstring
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
static integer LastIndexOfAnyExclude(const TChar *haystack, integer startIdx, const TChar *needles, integer needlesLength)
static integer IndexOfAnyExcluded(const TChar *haystack, integer haystackLength, const TChar *needles, integer needlesLength)