Embedded Template Library 1.0
Loading...
Searching...
No Matches
string_utilities.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2020 John Wellbelove, John Lagerquist
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_STRING_UTILITIES_INCLUDED
32#define ETL_STRING_UTILITIES_INCLUDED
33
34#include "platform.h"
35#include "algorithm.h"
36#include "enum_type.h"
37#include "memory.h"
38#include "char_traits.h"
39#include "optional.h"
40
41#include <ctype.h>
42#include <stdint.h>
43
44#include "private/minmax_push.h"
45
46namespace etl
47{
48 //***************************************************************************
50 //***************************************************************************
52 {
53 enum enum_type
54 {
55 LEFT,
56 RIGHT,
57 };
58
59 ETL_DECLARE_ENUM_TYPE(string_pad_direction, int)
60 ETL_ENUM_TYPE(LEFT, "left")
61 ETL_ENUM_TYPE(RIGHT, "right")
62 ETL_END_ENUM_TYPE
63 };
64
65 //***************************************************************************
67 //***************************************************************************
68 template <typename TChar>
69 struct whitespace;
70
71 template <>
73 {
74 static ETL_CONSTEXPR const char* value()
75 {
76 return " \t\n\r\f\v";
77 }
78 };
79
80#if ETL_USING_CPP20
81 template <>
82 struct whitespace<char8_t>
83 {
84 static ETL_CONSTEXPR const char8_t* value()
85 {
86 return u8" \t\n\r\f\v";
87 }
88 };
89#endif
90
91 template <>
93 {
94 static ETL_CONSTEXPR const wchar_t* value()
95 {
96 return L" \t\n\r\f\v";
97 }
98 };
99
100#if ETL_USING_CPP11
101 template <>
102 struct whitespace<char16_t>
103 {
104 static ETL_CONSTEXPR const char16_t* value()
105 {
106 return u" \t\n\r\f\v";
107 }
108 };
109
110 template <>
111 struct whitespace<char32_t>
112 {
113 static ETL_CONSTEXPR const char32_t* value()
114 {
115 return U" \t\n\r\f\v";
116 }
117 };
118#endif
119
120#if ETL_USING_CPP17
121 template <typename TChar>
122 inline constexpr const TChar* whitespace_v = whitespace<TChar>::value();
123#endif
124
125 //***************************************************************************
128 //***************************************************************************
129 template <typename TIString>
130 void trim_from_left(TIString& s, typename TIString::const_pointer trim_characters)
131 {
132 typename TIString::size_type position = s.find_first_not_of(trim_characters);
133 s.erase(0U, position);
134 }
135
136 //***************************************************************************
139 //***************************************************************************
140 template <typename TIString>
145
146 //***************************************************************************
149 //***************************************************************************
150 template <typename TStringView>
151 TStringView trim_from_view_left(const TStringView& view, typename TStringView::const_pointer trim_characters)
152 {
153 typename TStringView::size_type first = view.find_first_not_of(trim_characters);
154
155 typename TStringView::const_pointer pbegin = view.data() + view.size();
156
157 if (first != TStringView::npos)
158 {
159 pbegin = view.data() + first;
160 }
161
162 return TStringView(pbegin, etl::distance(pbegin, view.data() + view.size()));
163 }
164
165 //***************************************************************************
168 //***************************************************************************
169 template <typename TStringView>
174
175 //***************************************************************************
178 //***************************************************************************
179 template <typename TIString>
180 void trim_left(TIString& s, typename TIString::const_pointer delimiters)
181 {
182 typename TIString::size_type p = s.find_first_of(delimiters);
183
184 if (p == TIString::npos)
185 {
186 s.clear();
187 }
188 else
189 {
190 s.erase(0, p);
191 }
192 }
193
194 //***************************************************************************
197 //***************************************************************************
198 template <typename TStringView>
199 TStringView trim_view_left(const TStringView& view, typename TStringView::const_pointer delimiters)
200 {
201 typename TStringView::size_type first = view.find_first_of(delimiters);
202
203 typename TStringView::const_pointer pbegin = view.data();
204
205 if (first != TStringView::npos)
206 {
207 pbegin += first;
208 return TStringView(pbegin, view.size() - first);
209 }
210 else
211 {
212 return TStringView(pbegin, typename TStringView::size_type(0U));
213 }
214 }
215
216 //***************************************************************************
219 //***************************************************************************
220 template <typename TIString>
221 void trim_from_right(TIString& s, typename TIString::const_pointer trim_characters)
222 {
223 s.erase(s.find_last_not_of(trim_characters) + 1);
224 }
225
226 //***************************************************************************
229 //***************************************************************************
230 template <typename TIString>
235
236 //***************************************************************************
239 //***************************************************************************
240 template <typename TStringView>
241 TStringView trim_from_view_right(const TStringView& view, typename TStringView::const_pointer trim_characters)
242 {
243 typename TStringView::size_type last = view.find_last_not_of(trim_characters) + 1;
244
245 typename TStringView::const_pointer pend = view.data();
246
247 if (last != TStringView::npos)
248 {
249 pend += last;
250 }
251
252 return TStringView(view.data(), etl::distance(view.data(), pend));
253 }
254
255 //***************************************************************************
258 //***************************************************************************
259 template <typename TStringView>
264
265 //***************************************************************************
267 //***************************************************************************
268 template <typename TIString>
269 void trim_right(TIString& s, typename TIString::const_pointer delimiters)
270 {
271 typename TIString::size_type p = s.find_last_of(delimiters);
272
273 if (p == TIString::npos)
274 {
275 s.clear();
276 }
277 else
278 {
279 ++p;
280
281 if (p != s.size())
282 {
283 s.erase(p);
284 }
285 }
286 }
287
288 //***************************************************************************
290 //***************************************************************************
291 template <typename TStringView>
292 TStringView trim_view_right(const TStringView& view, typename TStringView::const_pointer delimiters)
293 {
294 typename TStringView::size_type last = view.find_last_of(delimiters) + 1;
295
296 typename TStringView::const_pointer pend = view.data();
297
298 if (last != TStringView::npos)
299 {
300 pend += last;
301 return TStringView(view.data(), etl::distance(view.data(), pend));
302 }
303 else
304 {
305 return TStringView(view.data(), typename TStringView::size_type(0U));
306 }
307 }
308
309 //***************************************************************************
312 //***************************************************************************
313 template <typename TIString>
314 void trim_from(TIString& s, typename TIString::const_pointer trim_characters)
315 {
318 }
319
320 //***************************************************************************
323 //***************************************************************************
324 template <typename TIString>
329
330 //***************************************************************************
333 //***************************************************************************
334 template <typename TStringView>
335 TStringView trim_from_view(const TStringView& view, typename TStringView::const_pointer trim_characters)
336 {
337 typename TStringView::size_type first = view.find_first_not_of(trim_characters);
338 typename TStringView::size_type last = view.find_last_not_of(trim_characters) + 1;
339
340 typename TStringView::const_pointer pbegin = view.data();
341 typename TStringView::const_pointer pend = view.data();
342
343 if (first != TStringView::npos)
344 {
345 pbegin += first;
346 }
347
348 if (last != TStringView::npos)
349 {
350 pend += last;
351 }
352
353 return TStringView(pbegin, etl::distance(pbegin, pend));
354 }
355
356 //***************************************************************************
359 //***************************************************************************
360 template <typename TStringView>
365
366 //***************************************************************************
369 //***************************************************************************
370 template <typename TIString>
371 void trim(TIString& s, typename TIString::const_pointer delimiters)
372 {
375 }
376
377 //***************************************************************************
380 //***************************************************************************
381 template <typename TStringView>
382 TStringView trim_view(const TStringView& view, typename TStringView::const_pointer delimiters)
383 {
384 typename TStringView::size_type first = view.find_first_of(delimiters);
385 typename TStringView::size_type last = view.find_last_of(delimiters) + 1;
386
387 typename TStringView::const_pointer pbegin = view.data();
388 typename TStringView::const_pointer pend = view.data();
389
390 if (first != TStringView::npos)
391 {
392 pbegin += first;
393 }
394
395 if (last != TStringView::npos)
396 {
397 pend += last;
398 }
399
400 return TStringView(pbegin, etl::distance(pbegin, pend));
401 }
402
403 //***************************************************************************
405 //***************************************************************************
406 template <typename TIString>
407 void left_n(TIString& s, typename TIString::size_type n)
408 {
409 n = (n > s.size()) ? s.size() : n;
410
411 s.erase(s.begin() + n, s.end());
412 }
413
414 //***************************************************************************
416 //***************************************************************************
417 template <typename TStringView>
418 TStringView left_n_view(const TStringView& view, typename TStringView::size_type n)
419 {
420 n = (n > view.size()) ? view.size() : n;
421
422 return TStringView(etl::addressof(*view.begin()), n);
423 }
424
425 //***************************************************************************
427 //***************************************************************************
428 template <typename TIString>
429 void right_n(TIString& s, typename TIString::size_type n)
430 {
431 n = (n > s.size()) ? s.size() : n;
432
433 s.erase(s.begin(), s.end() - n);
434 }
435
436 //***************************************************************************
438 //***************************************************************************
439 template <typename TStringView>
440 TStringView right_n_view(const TStringView& view, typename TStringView::size_type n)
441 {
442 n = (n > view.size()) ? view.size() : n;
443
444 return TStringView(view.data() + view.size() - n, n);
445 }
446
447 //***************************************************************************
450 //***************************************************************************
451 template <typename TIString>
452 void reverse(TIString& s)
453 {
454 etl::reverse(s.begin(), s.end());
455 }
456
457 //***************************************************************************
459 //***************************************************************************
460 template <typename TIString, typename TPair>
462 const TPair* pairsbegin,
463 const TPair* pairsend)
464 {
465 while (pairsbegin != pairsend)
466 {
467 etl::replace(s.begin(), s.end(), pairsbegin->first, pairsbegin->second);
468 ++pairsbegin;
469 }
470 }
471
472 //***************************************************************************
474 //***************************************************************************
475 template <typename TIString, typename TPair>
477 const TPair* pairsbegin,
478 const TPair* pairsend)
479 {
480 while (pairsbegin != pairsend)
481 {
482 const typename TIString::value_type* p_old = pairsbegin->first;
483 const typename TIString::value_type* p_new = pairsbegin->second;
484
485 typename TIString::size_type position = 0U;
486
487 do
488 {
489 position = s.find(p_old, position);
490 if (position != TIString::npos)
491 {
492 s.replace(position, typename TIString::size_type(etl::strlen(p_old)), p_new, typename TIString::size_type(etl::strlen(p_new)));
493 position += typename TIString::size_type(etl::strlen(p_new));
494 }
495 } while (position != TIString::npos);
496
497 ++pairsbegin;
498 }
499 }
500
501 //*********************************************************************
503 //*********************************************************************
504 template <typename TIterator, typename TPointer>
506 {
507 TIterator itr(first);
508
509 while (itr != last)
510 {
512
513 while (*pd != 0)
514 {
515 if (*itr == *pd)
516 {
517 return itr;
518 }
519
520 ++pd;
521 }
522
523 ++itr;
524 }
525
526 return last;
527 }
528
529 //*********************************************************************
531 //*********************************************************************
532 template <typename TIString, typename TPointer>
533 typename TIString::iterator find_first_of(TIString& s, TPointer delimiters)
534 {
535 return find_first_of(s.begin(), s.end(), delimiters);
536 }
537
538 //*********************************************************************
540 //*********************************************************************
541 template <typename TIString, typename TPointer>
542 typename TIString::const_iterator find_first_of(const TIString& s, TPointer delimiters)
543 {
544 return find_first_of(s.begin(), s.end(), delimiters);
545 }
546
547 //*********************************************************************
549 //*********************************************************************
550 template <typename TIterator, typename TPointer>
552 {
553 TIterator itr(first);
554
555 while (itr != last)
556 {
558
559 bool found = false;
560
561 while (*pd != 0)
562 {
563 if (*itr == *pd)
564 {
565 found = true;
566 break;
567 }
568
569 ++pd;
570 }
571
572 if (!found)
573 {
574 return itr;
575 }
576
577 ++itr;
578 }
579
580 return last;
581 }
582
583 //*********************************************************************
585 //*********************************************************************
586 template <typename TIString, typename TPointer>
587 typename TIString::iterator find_first_not_of(TIString& s, TPointer delimiters)
588 {
589 return find_first_not_of(s.begin(), s.end(), delimiters);
590 }
591
592 //*********************************************************************
594 //*********************************************************************
595 template <typename TIString, typename TPointer>
596 typename TIString::const_iterator find_first_not_of(const TIString& s, TPointer delimiters)
597 {
598 return find_first_not_of(s.begin(), s.end(), delimiters);
599 }
600
601 //*********************************************************************
603 //*********************************************************************
604 template <typename TIterator, typename TPointer>
606 {
607 if (first == last)
608 {
609 return last;
610 }
611
612 TIterator itr(last);
613 TIterator end(first);
614
615 do
616 {
617 --itr;
618
620
621 while (*pd != 0)
622 {
623 if (*itr == *pd)
624 {
625 return itr;
626 }
627
628 ++pd;
629 }
630 } while (itr != end);
631
632 return last;
633 }
634
635 //*********************************************************************
637 //*********************************************************************
638 template <typename TIString, typename TPointer>
639 typename TIString::iterator find_last_of(TIString& s, TPointer delimiters)
640 {
641 return find_last_of(s.begin(), s.end(), delimiters);
642 }
643
644 //*********************************************************************
646 //*********************************************************************
647 template <typename TIString, typename TPointer>
648 typename TIString::const_iterator find_last_of(const TIString& s, TPointer delimiters)
649 {
650 return find_last_of(s.begin(), s.end(), delimiters);
651 }
652
653 //*********************************************************************
655 //*********************************************************************
656 template <typename TIterator, typename TPointer>
658 {
659 if (first == last)
660 {
661 return last;
662 }
663
664 TIterator itr(last);
665 TIterator end(first);
666
667 do
668 {
669 --itr;
670
672
673 bool found = false;
674
675 while (*pd != 0)
676 {
677 if (*itr == *pd)
678 {
679 found = true;
680 break;
681 }
682
683 ++pd;
684 }
685
686 if (!found)
687 {
688 return itr;
689 }
690 } while (itr != end);
691
692 return last;
693 }
694
695 //*********************************************************************
697 //*********************************************************************
698 template <typename TIString, typename TPointer>
699 typename TIString::iterator find_last_not_of(TIString& s, TPointer delimiters)
700 {
701 return find_last_not_of(s.begin(), s.end(), delimiters);
702 }
703
704 //*********************************************************************
706 //*********************************************************************
707 template <typename TIString, typename TPointer>
708 typename TIString::const_iterator find_last_not_of(const TIString& s, TPointer delimiters)
709 {
710 return find_last_not_of(s.begin(), s.end(), delimiters);
711 }
712
713 //***************************************************************************
715 //***************************************************************************
716 template <typename TInput, typename TStringView>
718 {
719 typedef typename TInput::const_pointer const_pointer;
720
721 bool token_found = false;
722 typename TStringView::size_type position = 0U;
724 const_pointer begin_ptr = input.data();
725
726 if (begin_ptr == ETL_NULLPTR)
727 {
729 }
730
731 const_pointer end_ptr = begin_ptr + input.size();
732
733 while (!token_found)
734 {
735 // Does the last view have valid data?
736 if (view.data() != ETL_NULLPTR)
737 {
738 position = etl::distance(begin_ptr, view.data() + view.size() + 1U);
739
740 // Have we reached the end of the string?
741 if (position > input.size())
742 {
744 }
745 }
746
747 // Look for the next token.
748 const_pointer first_ptr = begin_ptr + position;
750
751 view = TStringView(first_ptr, etl::distance(first_ptr, last_ptr));
752
753 token_found = ((view.size() != 0U) || !ignore_empty_tokens);
754 }
755
757 }
758
759 //***************************************************************************
761 //***************************************************************************
762 template <typename TIString>
763 void pad_left(TIString& s, typename TIString::size_type required_size, typename TIString::value_type pad_char)
764 {
765 required_size = etl::min(required_size, s.max_size());
766
767 if (required_size > s.size())
768 {
769 required_size -= s.size();
770 s.insert(typename TIString::size_type(0U), required_size, pad_char);
771 }
772 }
773
774 //***************************************************************************
776 //***************************************************************************
777 template <typename TIString>
778 void pad_right(TIString& s, typename TIString::size_type required_size, typename TIString::value_type pad_char)
779 {
780 required_size = etl::min(required_size, s.max_size());
781
782 if (required_size > s.size())
783 {
784 required_size -= s.size();
785 s.insert(s.size(), required_size, pad_char);
786 }
787 }
788
789 //***************************************************************************
791 //***************************************************************************
792 template <typename TIString>
793 void pad(TIString& s, typename TIString::size_type required_size, string_pad_direction pad_direction, typename TIString::value_type pad_char)
794 {
795 switch (int(pad_direction))
796 {
797 case string_pad_direction::LEFT:
798 {
800 break;
801 }
802
803 case string_pad_direction::RIGHT:
804 {
806 break;
807 }
808
809 default:
810 {
811 break;
812 }
813 }
814 }
815
816 //***************************************************************************
818 //***************************************************************************
819 template <typename TString>
821 {
822 etl::transform(s.begin(), s.end(), s.begin(), ::toupper);
823 }
824
825 //***************************************************************************
827 //***************************************************************************
828 template <typename TString>
830 {
831 etl::transform(s.begin(), s.end(), s.begin(), ::tolower);
832 }
833
834 //***************************************************************************
836 //***************************************************************************
837 template <typename TString>
839 {
840 typename TString::iterator itr = s.begin();
841
842 *itr = typename TString::value_type(::toupper(*itr));
843 ++itr;
844
845 etl::transform(itr, s.end(), itr, ::tolower);
846 }
847}
848
849#include "private/minmax_pop.h"
850
851#endif
ETL_CONSTEXPR17 etl::enable_if<!etl::is_same< T, etl::nullptr_t >::value, T >::type * addressof(T &t)
Definition addressof.h:52
bitset_ext
Definition absolute.h:38
TIterator find_first_not_of(TIterator first, TIterator last, TPointer delimiters)
Find first not of any of delimiters within the string.
Definition string_utilities.h:551
void trim_from_left(TIString &s, typename TIString::const_pointer trim_characters)
Definition string_utilities.h:130
TStringView trim_from_view_right(const TStringView &view, typename TStringView::const_pointer trim_characters)
Definition string_utilities.h:241
void trim(TIString &s, typename TIString::const_pointer delimiters)
Definition string_utilities.h:371
TIterator find_first_of(TIterator first, TIterator last, TPointer delimiters)
Find first of any of delimiters within the string.
Definition string_utilities.h:505
void to_lower_case(TString &s)
to_lower_case
Definition string_utilities.h:829
void trim_whitespace_right(TIString &s)
Definition string_utilities.h:231
void pad_right(TIString &s, typename TIString::size_type required_size, typename TIString::value_type pad_char)
pad_right
Definition string_utilities.h:778
void pad(TIString &s, typename TIString::size_type required_size, string_pad_direction pad_direction, typename TIString::value_type pad_char)
pad
Definition string_utilities.h:793
void right_n(TIString &s, typename TIString::size_type n)
Get up to the last n characters.
Definition string_utilities.h:429
void trim_left(TIString &s, typename TIString::const_pointer delimiters)
Definition string_utilities.h:180
TStringView left_n_view(const TStringView &view, typename TStringView::size_type n)
Get a view of up to the first n characters.
Definition string_utilities.h:418
void replace_characters(TIString &s, const TPair *pairsbegin, const TPair *pairsend)
replace_characters
Definition string_utilities.h:461
void to_sentence_case(TString &s)
to_sentence_case
Definition string_utilities.h:838
TIterator find_last_of(TIterator first, TIterator last, TPointer delimiters)
Find last of any of delimiters within the string.
Definition string_utilities.h:605
void trim_from_right(TIString &s, typename TIString::const_pointer trim_characters)
Definition string_utilities.h:221
TStringView trim_view(const TStringView &view, typename TStringView::const_pointer delimiters)
Definition string_utilities.h:382
ETL_CONSTEXPR14 size_t strlen(const T *t)
Alternative strlen for all character types.
Definition char_traits.h:285
TStringView trim_view_whitespace(const TStringView &view)
Definition string_utilities.h:361
TStringView trim_view_left(const TStringView &view, typename TStringView::const_pointer delimiters)
Definition string_utilities.h:199
void trim_right(TIString &s, typename TIString::const_pointer delimiters)
trim_right
Definition string_utilities.h:269
TStringView trim_view_whitespace_right(TStringView &view)
Definition string_utilities.h:260
TStringView trim_from_view(const TStringView &view, typename TStringView::const_pointer trim_characters)
Definition string_utilities.h:335
void trim_whitespace_left(TIString &s)
Definition string_utilities.h:141
void pad_left(TIString &s, typename TIString::size_type required_size, typename TIString::value_type pad_char)
pad_left
Definition string_utilities.h:763
TStringView trim_view_whitespace_left(TStringView &s)
Definition string_utilities.h:170
etl::optional< TStringView > get_token(const TInput &input, typename TInput::const_pointer delimiters, const etl::optional< TStringView > &last_view, bool ignore_empty_tokens)
get_token
Definition string_utilities.h:717
TIterator find_last_not_of(TIterator first, TIterator last, TPointer delimiters)
Find last not of any of delimiters within the string.
Definition string_utilities.h:657
void left_n(TIString &s, typename TIString::size_type n)
Get up to the first n characters.
Definition string_utilities.h:407
void to_upper_case(TString &s)
to_upper_case
Definition string_utilities.h:820
void trim_whitespace(TIString &s)
Definition string_utilities.h:325
TStringView right_n_view(const TStringView &view, typename TStringView::size_type n)
Get a view of up to the last n characters.
Definition string_utilities.h:440
void trim_from(TIString &s, typename TIString::const_pointer trim_characters)
Definition string_utilities.h:314
TStringView trim_from_view_left(const TStringView &view, typename TStringView::const_pointer trim_characters)
Definition string_utilities.h:151
void replace_strings(TIString &s, const TPair *pairsbegin, const TPair *pairsend)
replace_strings
Definition string_utilities.h:476
TStringView trim_view_right(const TStringView &view, typename TStringView::const_pointer delimiters)
trim_view_right
Definition string_utilities.h:292
ETL_CONSTEXPR TContainer::iterator end(TContainer &container)
Definition iterator.h:992
pair holds two objects of arbitrary type
Definition utility.h:164
T1 first
first is a copy of the first object
Definition utility.h:168
T2 second
second is a copy of the second object
Definition utility.h:169
string_pad_direction
Definition string_utilities.h:52
whitespace
Definition string_utilities.h:69