Embedded Template Library 1.0
Loading...
Searching...
No Matches
basic_string.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) 2016 John Wellbelove
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_BASIC_STRING_INCLUDED
32#define ETL_BASIC_STRING_INCLUDED
33
34#include "platform.h"
35#include "algorithm.h"
36#include "alignment.h"
37#include "array.h"
38#include "binary.h"
39#include "error_handler.h"
40#include "exception.h"
41#include "flags.h"
42#include "integral_limits.h"
43#include "iterator.h"
44#include "memory.h"
45#include "string_utilities.h"
46#include "type_traits.h"
47
48#include <stddef.h>
49#include <stdint.h>
50#include <string.h>
51
52#if ETL_USING_LIBC_WCHAR_H
53 #include <wchar.h>
54#endif
55
56#if ETL_USING_STL && ETL_USING_CPP17
57 #include <string_view>
58#endif
59
60#if ETL_USING_STD_OSTREAM
61 #include <ostream>
62#endif
63
64#include "private/minmax_push.h"
65
66//*****************************************************************************
70//*****************************************************************************
71
72// Forward declaration of string_view
73namespace etl
74{
75 template <typename T, typename TTraits>
77}
78
79namespace etl
80{
81 //***************************************************************************
84 //***************************************************************************
85 class string_exception : public etl::exception
86 {
87 public:
88
89 string_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
90 : exception(reason_, file_name_, line_number_)
91 {
92 }
93 };
94
95 //***************************************************************************
98 //***************************************************************************
99 class string_out_of_bounds : public etl::string_exception
100 {
101 public:
102
103 string_out_of_bounds(string_type file_name_, numeric_type line_number_)
104 : string_exception(ETL_ERROR_TEXT("string:bounds", ETL_BASIC_STRING_FILE_ID"B"), file_name_, line_number_)
105 {
106 }
107 };
108
109 //***************************************************************************
112 //***************************************************************************
113 class string_iterator : public etl::string_exception
114 {
115 public:
116
117 string_iterator(string_type file_name_, numeric_type line_number_)
118 : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_BASIC_STRING_FILE_ID"C"), file_name_, line_number_)
119 {
120 }
121 };
122
123 //***************************************************************************
126 //***************************************************************************
127 class string_truncation : public etl::string_exception
128 {
129 public:
130
131 string_truncation(string_type file_name_, numeric_type line_number_)
132 : string_exception(ETL_ERROR_TEXT("string:truncation", ETL_BASIC_STRING_FILE_ID"D"), file_name_, line_number_)
133 {
134 }
135 };
136
137 //***************************************************************************
140 //***************************************************************************
142 {
143 //*************************************************************************
144 template <typename T = void>
146 {
147 public:
148
149 typedef size_t size_type;
150
151 static ETL_CONSTANT uint_least8_t IS_TRUNCATED = etl::bit<0>::value;
152 static ETL_CONSTANT uint_least8_t CLEAR_AFTER_USE = etl::bit<1>::value;
153
154 static ETL_CONSTANT size_type npos = etl::integral_limits<size_type>::max;
155 };
156
157 template <typename T>
158 ETL_CONSTANT uint_least8_t string_base_statics<T>::IS_TRUNCATED;
159
160 template <typename T>
161 ETL_CONSTANT uint_least8_t string_base_statics<T>::CLEAR_AFTER_USE;
162
163 template <typename T>
164 ETL_CONSTANT typename string_base_statics<T>::size_type string_base_statics<T>::npos;
165 } // namespace private_basic_string
166
167 //***************************************************************************
169 {
170 public:
171
172 typedef size_t size_type;
173
174 //*************************************************************************
177 //*************************************************************************
178 size_type size() const
179 {
180 return current_size;
181 }
182
183 //*************************************************************************
186 //*************************************************************************
187 size_type length() const
188 {
189 return current_size;
190 }
191
192 //*************************************************************************
195 //*************************************************************************
196 bool empty() const
197 {
198 return (current_size == 0);
199 }
200
201 //*************************************************************************
204 //*************************************************************************
205 bool full() const
206 {
207 return current_size == CAPACITY;
208 }
209
210 //*************************************************************************
213 //*************************************************************************
214 size_type capacity() const
215 {
216 return CAPACITY;
217 }
218
219 //*************************************************************************
222 //*************************************************************************
223 size_type max_size() const
224 {
225 return CAPACITY;
226 }
227
228 //*************************************************************************
231 //*************************************************************************
232 size_type available() const
233 {
234 return max_size() - size();
235 }
236
237 //*************************************************************************
240 //*************************************************************************
241 bool is_truncated() const
242 {
243#if ETL_HAS_STRING_TRUNCATION_CHECKS
244 return flags.test<IS_TRUNCATED>();
245#else
246 return false;
247#endif
248 }
249
250 //*************************************************************************
254 //*************************************************************************
255 ETL_DEPRECATED
256 bool truncated() const
257 {
258 return is_truncated();
259 }
260
261#if ETL_HAS_STRING_TRUNCATION_CHECKS
262 //*************************************************************************
264 //*************************************************************************
266 {
267 flags.set<IS_TRUNCATED, false>();
268 }
269#endif
270
271#if ETL_HAS_STRING_CLEAR_AFTER_USE
272 //*************************************************************************
274 //*************************************************************************
276 {
277 flags.set<CLEAR_AFTER_USE>();
278 }
279#endif
280
281 //*************************************************************************
283 //*************************************************************************
284 bool is_secure() const
285 {
286#if ETL_HAS_STRING_CLEAR_AFTER_USE
287 return flags.test<CLEAR_AFTER_USE>();
288#else
289 return false;
290#endif
291 }
292
293 protected:
294
295 //*************************************************************************
297 //*************************************************************************
298 string_base(size_type max_size_)
299 : current_size(0)
300 , CAPACITY(max_size_)
301 {
302 }
303
304#if ETL_HAS_STRING_TRUNCATION_CHECKS
305 //*************************************************************************
307 //*************************************************************************
308 void set_truncated(bool status)
309 {
310 flags.set<IS_TRUNCATED>(status);
311 }
312#endif
313
314 //*************************************************************************
316 //*************************************************************************
318
319 size_type current_size;
320 const size_type CAPACITY;
321
322#if ETL_HAS_STRING_TRUNCATION_CHECKS || ETL_HAS_STRING_CLEAR_AFTER_USE
324#endif
325 };
326
327 //***************************************************************************
332 //***************************************************************************
333 template <typename T>
335 {
336 public:
337
338 typedef ibasic_string<T> interface_type;
339
340 typedef T value_type;
341 typedef T& reference;
342 typedef const T& const_reference;
343 typedef T* pointer;
344 typedef const T* const_pointer;
345 typedef T* iterator;
346 typedef const T* const_iterator;
347 typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
348 typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
349
350 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
351
352 //*********************************************************************
355 //*********************************************************************
356 iterator begin()
357 {
358 return &p_buffer[0];
359 }
360
361 //*********************************************************************
364 //*********************************************************************
365 const_iterator begin() const
366 {
367 return &p_buffer[0];
368 }
369
370 //*********************************************************************
373 //*********************************************************************
374 iterator end()
375 {
376 return &p_buffer[current_size];
377 }
378
379 //*********************************************************************
382 //*********************************************************************
383 const_iterator end() const
384 {
385 return &p_buffer[current_size];
386 }
387
388 //*********************************************************************
391 //*********************************************************************
392 const_iterator cbegin() const
393 {
394 return &p_buffer[0];
395 }
396
397 //*********************************************************************
400 //*********************************************************************
401 const_iterator cend() const
402 {
403 return &p_buffer[current_size];
404 }
405
406 //*********************************************************************
409 //*********************************************************************
410 reverse_iterator rbegin()
411 {
412 return reverse_iterator(end());
413 }
414
415 //*********************************************************************
418 //*********************************************************************
419 const_reverse_iterator rbegin() const
420 {
421 return const_reverse_iterator(end());
422 }
423
424 //*********************************************************************
427 //*********************************************************************
428 reverse_iterator rend()
429 {
430 return reverse_iterator(begin());
431 }
432
433 //*********************************************************************
436 //*********************************************************************
437 const_reverse_iterator rend() const
438 {
439 return const_reverse_iterator(begin());
440 }
441
442 //*********************************************************************
445 //*********************************************************************
446 const_reverse_iterator crbegin() const
447 {
448 return const_reverse_iterator(cend());
449 }
450
451 //*********************************************************************
454 //*********************************************************************
455 const_reverse_iterator crend() const
456 {
457 return const_reverse_iterator(cbegin());
458 }
459
460 //*********************************************************************
464 //*********************************************************************
465 void resize(size_type new_size)
466 {
467 resize(new_size, 0);
468 }
469
470 //*********************************************************************
475 //*********************************************************************
476 void resize(size_type new_size, T value)
477 {
478 if (new_size > CAPACITY)
479 {
480#if ETL_HAS_STRING_TRUNCATION_CHECKS
481 set_truncated(true);
482
483 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
484 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
485 #endif
486#endif
487 }
488
489 new_size = etl::min(new_size, CAPACITY);
490
491 // Size up?
492 if (new_size > current_size)
493 {
494 etl::fill(p_buffer + current_size, p_buffer + new_size, value);
495 }
496
497 current_size = new_size;
498 p_buffer[new_size] = 0;
499 cleanup();
500 }
501
502 //*********************************************************************
504 //*********************************************************************
505 template <typename TOperation>
506 void resize_and_overwrite(size_type new_size, TOperation operation)
507 {
508 if (new_size > CAPACITY)
509 {
510 ETL_ASSERT_FAIL(ETL_ERROR(string_out_of_bounds));
511 }
512
513 current_size = operation(p_buffer, new_size);
514 p_buffer[current_size] = '\0';
515 cleanup();
516 }
517
518 //*********************************************************************
522 //*********************************************************************
523 void uninitialized_resize(size_type new_size)
524 {
525 new_size = etl::min(new_size, CAPACITY);
526
527 current_size = new_size;
528 p_buffer[new_size] = 0;
529 }
530
531 //*********************************************************************
535 //*********************************************************************
536 void fill(T value)
537 {
538 etl::fill(begin(), end(), value);
539 }
540
541 //*********************************************************************
545 //*********************************************************************
546 reference operator[](size_type i)
547 {
548 ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds));
549 return p_buffer[i];
550 }
551
552 //*********************************************************************
556 //*********************************************************************
557 const_reference operator[](size_type i) const
558 {
559 ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds));
560 return p_buffer[i];
561 }
562
563 //*********************************************************************
569 //*********************************************************************
570 reference at(size_type i)
571 {
572 ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
573 return p_buffer[i];
574 }
575
576 //*********************************************************************
582 //*********************************************************************
583 const_reference at(size_type i) const
584 {
585 ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
586 return p_buffer[i];
587 }
588
589 //*********************************************************************
592 //*********************************************************************
593 reference front()
594 {
595 ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds));
596 return p_buffer[0];
597 }
598
599 //*********************************************************************
602 //*********************************************************************
603 const_reference front() const
604 {
605 ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds));
606 return p_buffer[0];
607 }
608
609 //*********************************************************************
612 //*********************************************************************
613 reference back()
614 {
615 ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds));
616 return p_buffer[size() - 1];
617 }
618
619 //*********************************************************************
622 //*********************************************************************
623 const_reference back() const
624 {
625 ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds));
626 return p_buffer[size() - 1];
627 }
628
629 //*********************************************************************
632 //*********************************************************************
633 pointer data()
634 {
635 return p_buffer;
636 }
637
638 //*********************************************************************
641 //*********************************************************************
642 ETL_CONSTEXPR const_pointer data() const
643 {
644 return p_buffer;
645 }
646
647 //*********************************************************************
650 //*********************************************************************
651 pointer data_end()
652 {
653 return p_buffer + current_size;
654 }
655
656 //*********************************************************************
659 //*********************************************************************
660 const_pointer data_end() const
661 {
662 return p_buffer + current_size;
663 }
664
665 //*********************************************************************
669 //*********************************************************************
670 void assign(const etl::ibasic_string<T>& other)
671 {
672 if (&other != this)
673 {
674 clear();
675 append_impl(begin(), other.begin(), other.end(), other.is_truncated(), other.is_secure());
676 }
677 }
678
679 //*********************************************************************
685 //*********************************************************************
686 void assign(const etl::ibasic_string<T>& other, size_type subposition, size_type sublength)
687 {
688 if (&other != this)
689 {
690 clear();
691
692 if (sublength == npos)
693 {
694 sublength = other.size() - subposition;
695 }
696
697 ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds));
698
699 append_impl(begin(), other.begin() + subposition, other.begin() + subposition + sublength, other.is_truncated(), other.is_secure());
700 }
701 }
702
703 //*********************************************************************
710 //*********************************************************************
711 template <typename TIterator>
712 void assign(TIterator first, TIterator last)
713 {
714 append_impl(begin(), first, last, false, false);
715 }
716
717 //*********************************************************************
721 //*********************************************************************
722 void assign(const_pointer str)
723 {
724 append_impl(begin(), str, false, false);
725 }
726
727 //*********************************************************************
732 //*********************************************************************
733 void assign(const_pointer str, size_type n)
734 {
735 append_impl(begin(), str, str + n, false, false);
736 }
737
738 //*********************************************************************
740 //*********************************************************************
741 template <typename TOtherTraits>
743 {
744 append_impl(begin(), view.begin(), view.end(), false, false);
745 }
746
747 //*********************************************************************
752 //*********************************************************************
753 void assign(size_type n, T c)
754 {
755 clear();
756
757#if ETL_HAS_STRING_TRUNCATION_CHECKS
759
760 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
761 ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation));
762 #endif
763#endif
764
765 n = etl::min(n, CAPACITY);
766
767 etl::fill_n(begin(), n, c);
768 current_size = n;
769 p_buffer[current_size] = 0;
770 }
771
772 //*************************************************************************
774 //*************************************************************************
775 void clear()
776 {
777 initialise();
778 cleanup();
779 }
780
781 //*********************************************************************
785 //*********************************************************************
786 void push_back(T value)
787 {
788 if (current_size != CAPACITY)
789 {
790 p_buffer[current_size++] = value;
791 p_buffer[current_size] = 0;
792 }
793 else
794 {
795#if ETL_HAS_STRING_TRUNCATION_CHECKS
796 set_truncated(true);
797
798 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
799 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
800 #endif
801#endif
802 }
803 }
804
805 //*************************************************************************
808 //*************************************************************************
809 void pop_back()
810 {
811 if (current_size != 0)
812 {
813 p_buffer[--current_size] = 0;
814 }
815 }
816
817 //*********************************************************************
820 //*********************************************************************
822 {
823 append_impl(end(), str.begin(), str.end(), str.is_truncated(), str.is_secure());
824
825 return *this;
826 }
827
828 //*********************************************************************
833 //*********************************************************************
834 ibasic_string& append(const ibasic_string& str, size_type subposition, size_type sublength = npos)
835 {
836 if (sublength == npos)
837 {
838 sublength = str.size() - subposition;
839 }
840
841 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
842
843 append_impl(end(), str.begin() + subposition, str.begin() + subposition + sublength, str.is_truncated(), str.is_secure());
844
845 return *this;
846 }
847
848 //*********************************************************************
852 //*********************************************************************
853 template <class TIterator>
854 ibasic_string& append(TIterator first, TIterator last)
855 {
856 append_impl(end(), first, last, false, false);
857
858 return *this;
859 }
860
861 //*********************************************************************
864 //*********************************************************************
865 ibasic_string& append(const_pointer str)
866 {
867 append_impl(end(), str, false, false);
868
869 return *this;
870 }
871
872 //*********************************************************************
876 //*********************************************************************
877 ibasic_string& append(const_pointer str, size_type n)
878 {
879 append_impl(end(), str, str + n, false, false);
880
881 return *this;
882 }
883
884 //*********************************************************************
887 //*********************************************************************
888 template <typename TOtherTraits>
890 {
891 append_impl(end(), view.begin(), view.end(), false, false);
892
893 return *this;
894 }
895
896 //*********************************************************************
900 //*********************************************************************
901 ibasic_string& append(size_type n, T c)
902 {
903 size_type free_space = CAPACITY - current_size;
904
905#if ETL_HAS_STRING_TRUNCATION_CHECKS
906 set_truncated(n > free_space);
907
908 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
909 ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation));
910 #endif
911#endif
912
913 n = etl::min(n, size_t(free_space));
914
915 etl::fill_n(end(), n, c);
916 current_size += n;
917 p_buffer[current_size] = 0;
918
919 return *this;
920 }
921
922 //*********************************************************************
926 //*********************************************************************
927 iterator insert(const_iterator position, T value)
928 {
929 ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds));
930
931 // Quick hack, as iterators are pointers.
932 iterator insert_position = to_iterator(position);
933
935 {
936 // Not full yet.
937 if (position != end())
938 {
939 // Insert in the middle.
940 ++current_size;
941 etl::mem_move(insert_position, end() - 1, insert_position + 1);
942 *insert_position = value;
943 }
944 else
945 {
946 // Insert at the end.
947 *insert_position = value;
948 ++current_size;
949 }
950 }
951 else
952 {
953 // Already full.
954 if (position != end())
955 {
956 // Insert in the middle.
957 etl::mem_move(insert_position, end() - 1, insert_position + 1);
958 *insert_position = value;
959 }
960
961#if ETL_HAS_STRING_TRUNCATION_CHECKS
962 set_truncated(true);
963
964 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
965 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
966 #endif
967#endif
968 }
969
970 p_buffer[current_size] = 0;
971
972 return insert_position;
973 }
974
975 //*********************************************************************
980 //*********************************************************************
981 iterator insert(const_iterator position, size_type n, T value)
982 {
983 ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds));
984
985 iterator position_ = to_iterator(position);
986
987 if (n == 0)
988 {
989 return position_;
990 }
991
992 // Quick hack, as iterators are pointers.
993 iterator insert_position = to_iterator(position);
994 const size_type start = static_cast<size_type>(etl::distance(cbegin(), position));
995
996 // No effect.
997 if (start >= CAPACITY)
998 {
999#if ETL_HAS_STRING_TRUNCATION_CHECKS
1000 set_truncated(true);
1001
1002 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1003 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1004 #endif
1005#endif
1006 return to_iterator(position);
1007 }
1008
1009 // Fills the string to the end?
1010 if ((start + n) >= CAPACITY)
1011 {
1012 if ((current_size + n) > CAPACITY)
1013 {
1014#if ETL_HAS_STRING_TRUNCATION_CHECKS
1015 set_truncated(true);
1016
1017 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1018 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1019 #endif
1020#endif
1021 }
1022
1024 etl::fill(insert_position, end(), value);
1025 }
1026 else
1027 {
1028 // Lets do some shifting.
1029 const size_type shift_amount = n;
1030 const size_type to_position = start + shift_amount;
1031 const size_type remaining_characters = current_size - start;
1032 const size_type max_shift_characters = CAPACITY - start - shift_amount;
1033 const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters);
1034
1035 // Will the string truncate?
1036 if ((start + shift_amount + remaining_characters) > CAPACITY)
1037 {
1039
1040#if ETL_HAS_STRING_TRUNCATION_CHECKS
1041 set_truncated(true);
1042
1043 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1044 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1045 #endif
1046#endif
1047 }
1048 else
1049 {
1050 current_size += shift_amount;
1051 }
1052
1053 etl::mem_move(insert_position, insert_position + characters_to_shift, begin() + to_position);
1054 etl::fill(insert_position, insert_position + shift_amount, value);
1055 }
1056
1057 p_buffer[current_size] = 0;
1058
1059 return position_;
1060 }
1061
1062 //*********************************************************************
1069 //*********************************************************************
1070 template <typename TIterator>
1071 iterator insert(const_iterator position, TIterator first, TIterator last)
1072 {
1073 ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds));
1074 ETL_ASSERT_CHECK_EXTRA(first <= last, ETL_ERROR(string_iterator));
1075
1076 iterator position_ = to_iterator(position);
1077
1078 if (first == last)
1079 {
1080 return position_;
1081 }
1082
1083 const size_type start = static_cast<size_type>(etl::distance(begin(), position_));
1084 const size_type n = static_cast<size_type>(etl::distance(first, last));
1085
1086 // No effect.
1087 if (start >= CAPACITY)
1088 {
1089#if ETL_HAS_STRING_TRUNCATION_CHECKS
1090 set_truncated(true);
1091
1092 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1093 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1094 #endif
1095#endif
1096 return position_;
1097 }
1098
1099 // Fills the string to the end?
1100 if ((start + n) >= CAPACITY)
1101 {
1102 if (((current_size + n) > CAPACITY))
1103 {
1104#if ETL_HAS_STRING_TRUNCATION_CHECKS
1105 set_truncated(true);
1106
1107 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1108 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1109 #endif
1110#endif
1111 }
1112
1114
1115 position_ = copy_characters(first, static_cast<size_t>(etl::distance(position_, end())), position_);
1116 }
1117 else
1118 {
1119 // Lets do some shifting.
1120 const size_type shift_amount = n;
1121 const size_type to_position = start + shift_amount;
1122 const size_type remaining_characters = current_size - start;
1123 const size_type max_shift_characters = CAPACITY - start - shift_amount;
1124 const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters);
1125
1126 // Will the string truncate?
1127 if ((start + shift_amount + remaining_characters) > CAPACITY)
1128 {
1130
1131#if ETL_HAS_STRING_TRUNCATION_CHECKS
1132 set_truncated(true);
1133
1134 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1135 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1136 #endif
1137#endif
1138 }
1139 else
1140 {
1141 current_size += shift_amount;
1142 }
1143
1144 etl::mem_move(position_, position_ + characters_to_shift, begin() + to_position);
1145 // etl::copy_backward(position_, position_ + characters_to_shift,
1146 // begin() + to_position + characters_to_shift);
1147
1148 position_ = copy_characters(first, static_cast<size_t>(etl::distance(first, last)), position_);
1149 }
1150
1151 p_buffer[current_size] = 0;
1152
1153 return position_;
1154 }
1155
1156 //*********************************************************************
1162 //*********************************************************************
1163 template <typename TOtherTraits>
1164 iterator insert(const_iterator position, const etl::basic_string_view<T, TOtherTraits>& view)
1165 {
1166 return insert(position, view.begin(), view.end());
1167 }
1168
1169 //*********************************************************************
1173 //*********************************************************************
1174 etl::ibasic_string<T>& insert(size_type position, const etl::ibasic_string<T>& str)
1175 {
1176 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1177
1178 insert(begin() + position, str.cbegin(), str.cend());
1179
1180#if ETL_HAS_STRING_TRUNCATION_CHECKS
1181 if (str.is_truncated())
1182 {
1183 set_truncated(true);
1184
1185 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1186 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1187 #endif
1188 }
1189#endif
1190
1191 return *this;
1192 }
1193
1194 //*********************************************************************
1198 //*********************************************************************
1199 template <typename TOtherTraits>
1201 {
1202 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1203
1204 insert(begin() + position, view.cbegin(), view.cend());
1205
1206 return *this;
1207 }
1208
1209 //*********************************************************************
1216 //*********************************************************************
1217 etl::ibasic_string<T>& insert(size_type position, const etl::ibasic_string<T>& str, size_type subposition, size_type sublength)
1218 {
1219 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1220 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1221
1222 if ((sublength == npos) || (subposition + sublength > str.size()))
1223 {
1224 sublength = str.size() - subposition;
1225 }
1226
1227 insert(begin() + position, str.cbegin() + subposition, str.cbegin() + subposition + sublength);
1228
1229#if ETL_HAS_STRING_TRUNCATION_CHECKS
1230 if (str.is_truncated())
1231 {
1232 set_truncated(true);
1233
1234 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1235 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1236 #endif
1237 }
1238#endif
1239
1240 return *this;
1241 }
1242
1243 //*********************************************************************
1249 //*********************************************************************
1250 template <typename TOtherTraits>
1251 etl::ibasic_string<T>& insert(size_type position, const etl::basic_string_view<T, TOtherTraits>& view, size_type subposition, size_type sublength)
1252 {
1253 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1254 ETL_ASSERT(subposition <= view.size(), ETL_ERROR(string_out_of_bounds));
1255
1256 if ((sublength == npos) || (subposition + sublength > view.size()))
1257 {
1258 sublength = view.size() - subposition;
1259 }
1260
1261 insert(begin() + position, view.cbegin() + subposition, view.cbegin() + subposition + sublength);
1262
1263 return *this;
1264 }
1265
1266 //*********************************************************************
1270 //*********************************************************************
1271 etl::ibasic_string<T>& insert(size_type position, const_pointer s)
1272 {
1273 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1274
1275 insert(begin() + position, s, s + etl::strlen(s));
1276 return *this;
1277 }
1278
1279 //*********************************************************************
1285 //*********************************************************************
1286 etl::ibasic_string<T>& insert(size_type position, const_pointer s, size_type n)
1287 {
1288 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1289
1290 insert(begin() + position, s, s + n);
1291 return *this;
1292 }
1293
1294 //*********************************************************************
1299 //*********************************************************************
1300 etl::ibasic_string<T>& insert(size_type position, size_type n, value_type c)
1301 {
1302 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1303
1304 insert(begin() + position, n, c);
1305 return *this;
1306 }
1307
1308 //*********************************************************************
1313 //*********************************************************************
1314 etl::ibasic_string<T>& erase(size_type position, size_type length_ = npos)
1315 {
1316 ETL_ASSERT_CHECK_EXTRA(position <= size(), ETL_ERROR(string_out_of_bounds));
1317
1318 // Limit the length.
1319 length_ = etl::min(length_, size() - position);
1320
1321 erase(begin() + position, begin() + position + length_);
1322
1323 return *this;
1324 }
1325
1326 //*********************************************************************
1331 //*********************************************************************
1332 iterator erase(iterator i_element)
1333 {
1334 ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(string_out_of_bounds));
1335
1336 etl::mem_move(i_element + 1, end(), i_element);
1337 p_buffer[--current_size] = 0;
1338
1339 return i_element;
1340 }
1341
1342 //*********************************************************************
1347 //*********************************************************************
1348 iterator erase(const_iterator i_element)
1349 {
1350 ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(string_out_of_bounds));
1351
1352 iterator i_element_(to_iterator(i_element));
1353
1354 etl::mem_move(i_element + 1, end(), i_element_);
1355 p_buffer[--current_size] = 0;
1356
1357 return i_element_;
1358 }
1359
1360 //*********************************************************************
1368 //*********************************************************************
1369 iterator erase(const_iterator first, const_iterator last)
1370 {
1371 ETL_ASSERT_CHECK_EXTRA(cbegin() <= first && first <= last && last <= cend(), ETL_ERROR(string_out_of_bounds));
1372
1373 iterator first_ = to_iterator(first);
1374 iterator last_ = to_iterator(last);
1375
1376 if (first_ == last_)
1377 {
1378 return first_;
1379 }
1380
1381 etl::mem_move(last_, end(), first_);
1382 size_type n_delete = static_cast<size_type>(etl::distance(first_, last_));
1383
1384 current_size -= n_delete;
1385 p_buffer[current_size] = 0;
1386 cleanup();
1387
1388 return first_;
1389 }
1390
1391 //*********************************************************************
1393 //*********************************************************************
1394 const_pointer c_str() const
1395 {
1396 return p_buffer;
1397 }
1398
1399 //*********************************************************************
1404 //*********************************************************************
1405 size_type copy(pointer dest, size_type count, size_type pos = 0) const
1406 {
1407 if (pos < size())
1408 {
1409 if (count != npos)
1410 {
1411 count = etl::min(count, size() - pos);
1412 }
1413 else
1414 {
1415 count = size() - pos;
1416 }
1417
1418 etl::mem_move(p_buffer + pos, count, dest);
1419
1420 return count;
1421 }
1422 else
1423 {
1424 return 0U;
1425 }
1426 }
1427
1428 //*********************************************************************
1432 //*********************************************************************
1433 size_type find(const ibasic_string<T>& str, size_type pos = 0) const
1434 {
1435 return find_impl(str.begin(), str.end(), str.size(), pos);
1436 }
1437
1438 //*********************************************************************
1442 //*********************************************************************
1443 template <typename TOtherTraits>
1444 size_type find(const etl::basic_string_view<T, TOtherTraits>& view, size_type pos = 0) const
1445 {
1446 return find_impl(view.begin(), view.end(), view.size(), pos);
1447 }
1448
1449 //*********************************************************************
1453 //*********************************************************************
1454 size_type find(const_pointer s, size_type pos = 0) const
1455 {
1456 size_t sz = etl::strlen(s);
1457
1458 return find_impl(s, s + sz, sz, pos);
1459 }
1460
1461 //*********************************************************************
1466 //*********************************************************************
1467 size_type find(const_pointer s, size_type pos, size_type n) const
1468 {
1469 return find_impl(s, s + n, n, pos);
1470 }
1471
1472 //*********************************************************************
1476 //*********************************************************************
1477 size_type find(T c, size_type position = 0) const
1478 {
1479 const_iterator i = etl::find(begin() + position, end(), c);
1480
1481 if (i != end())
1482 {
1483 return static_cast<size_type>(etl::distance(begin(), i));
1484 }
1485 else
1486 {
1487 return npos;
1488 }
1489 }
1490
1491 //*********************************************************************
1495 //*********************************************************************
1496 size_type rfind(const ibasic_string<T>& str, size_type position = npos) const
1497 {
1498 return rfind_impl(str.rbegin(), str.rend(), str.size(), position);
1499 }
1500
1501 //*********************************************************************
1505 //*********************************************************************
1506 template <typename TOtherTraits>
1507 size_type rfind(const etl::basic_string_view<T, TOtherTraits>& view, size_type pos = 0) const
1508 {
1509 return rfind_impl(view.rbegin(), view.rend(), view.size(), pos);
1510 }
1511
1512 //*********************************************************************
1516 //*********************************************************************
1517 size_type rfind(const_pointer s, size_type position = npos) const
1518 {
1519 size_type len = etl::strlen(s);
1520
1521 const_reverse_iterator srbegin(s + len);
1522 const_reverse_iterator srend(s);
1523
1524 return rfind_impl(srbegin, srend, len, position);
1525 }
1526
1527 //*********************************************************************
1531 //*********************************************************************
1532 size_type rfind(const_pointer s, size_type position, size_type length_) const
1533 {
1534 const_reverse_iterator srbegin(s + length_);
1535 const_reverse_iterator srend(s);
1536
1537 return rfind_impl(srbegin, srend, length_, position);
1538 }
1539
1540 //*********************************************************************
1544 //*********************************************************************
1545 size_type rfind(T c, size_type position = npos) const
1546 {
1547 if (position >= size())
1548 {
1549 position = size();
1550 }
1551
1552 position = size() - position;
1553
1554 const_reverse_iterator i = etl::find(rbegin() + static_cast<difference_type>(position), rend(), c);
1555
1556 if (i != rend())
1557 {
1558 return size() - static_cast<size_type>(etl::distance(rbegin(), i)) - 1;
1559 }
1560 else
1561 {
1562 return npos;
1563 }
1564 }
1565
1566 //*********************************************************************
1568 //*********************************************************************
1569 bool contains(const etl::ibasic_string<T>& str) const
1570 {
1571 return find(str) != npos;
1572 }
1573
1574 //*********************************************************************
1576 //*********************************************************************
1577 template <typename TOtherTraits>
1579 {
1580 return find(view) != npos;
1581 }
1582
1583 //*********************************************************************
1585 //*********************************************************************
1586 bool contains(const_pointer s) const
1587 {
1588 return find(s) != npos;
1589 }
1590
1591 //*********************************************************************
1593 //*********************************************************************
1594 bool contains(value_type c) const
1595 {
1596 return find(c) != npos;
1597 }
1598
1599 //*********************************************************************
1601 //*********************************************************************
1602 bool starts_with(const etl::ibasic_string<T>& str) const
1603 {
1604 return compare(0, str.size(), str) == 0;
1605 }
1606
1607 //*********************************************************************
1609 //*********************************************************************
1610 template <typename TOtherTraits>
1612 {
1613 return compare(0, view.size(), view) == 0;
1614 }
1615
1616 //*********************************************************************
1618 //*********************************************************************
1619 bool starts_with(const_pointer s) const
1620 {
1621 size_t len = etl::strlen(s);
1622
1623 return compare(0, len, s, len) == 0;
1624 }
1625
1626 //*********************************************************************
1628 //*********************************************************************
1629 bool starts_with(value_type c) const
1630 {
1631 return !empty() && (front() == c);
1632 }
1633
1634 //*********************************************************************
1636 //*********************************************************************
1637 bool ends_with(const etl::ibasic_string<T>& str) const
1638 {
1639 if (str.size() > size())
1640 {
1641 return false;
1642 }
1643
1644 return compare(size() - str.size(), str.size(), str) == 0;
1645 }
1646
1647 //*********************************************************************
1649 //*********************************************************************
1650 template <typename TOtherTraits>
1652 {
1653 if (view.size() > size())
1654 {
1655 return false;
1656 }
1657
1658 return compare(size() - view.size(), view.size(), view) == 0;
1659 }
1660
1661 //*********************************************************************
1663 //*********************************************************************
1664 bool ends_with(const_pointer s) const
1665 {
1666 size_t len = etl::strlen(s);
1667
1668 if (len > size())
1669 {
1670 return false;
1671 }
1672
1673 return compare(size() - len, len, s, len) == 0;
1674 }
1675
1676 //*********************************************************************
1678 //*********************************************************************
1679 bool ends_with(value_type c) const
1680 {
1681 return !empty() && (back() == c);
1682 }
1683
1684 //*********************************************************************
1689 //*********************************************************************
1690 ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str)
1691 {
1692 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1693
1694 // Limit the length.
1695 length_ = etl::min(length_, size() - position);
1696
1697 return replace_impl(begin() + position, begin() + position + length_, str.begin(), str.size(), str.is_truncated());
1698 }
1699
1700 //*********************************************************************
1705 //*********************************************************************
1706 template <typename TOtherTraits>
1707 ibasic_string& replace(size_type position, size_type length_, const etl::basic_string_view<T, TOtherTraits>& view)
1708 {
1709 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1710
1711 // Limit the length.
1712 length_ = etl::min(length_, size() - position);
1713
1714 return replace_impl(begin() + position, begin() + position + length_, view.begin(), view.size(), false);
1715 }
1716
1717 //*********************************************************************
1722 //*********************************************************************
1723 ibasic_string& replace(const_iterator first, const_iterator last, const ibasic_string& str)
1724 {
1725 return replace_impl(first, last, str.begin(), str.size(), str.is_truncated());
1726 }
1727
1728 //*********************************************************************
1733 //*********************************************************************
1734 template <typename TOtherTraits>
1735 ibasic_string& replace(const_iterator first, const_iterator last, const etl::basic_string_view<T, TOtherTraits>& view)
1736 {
1737 return replace_impl(first, last, view.begin(), view.size(), false);
1738 }
1739
1740 //*********************************************************************
1743 //*********************************************************************
1744 ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength)
1745 {
1746 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1747 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1748
1749 // Limit the lengths.
1750 length_ = etl::min(length_, size() - position);
1751 sublength = etl::min(sublength, str.size() - subposition);
1752
1753 return replace_impl(begin() + position, begin() + position + length_, str.begin() + subposition, sublength, str.is_truncated());
1754 }
1755
1756 //*********************************************************************
1759 //*********************************************************************
1760 template <typename TOtherTraits>
1761 ibasic_string& replace(size_type position, size_type length_, const etl::basic_string_view<T, TOtherTraits>& view, size_type subposition,
1762 size_type sublength)
1763 {
1764 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1765 ETL_ASSERT(subposition <= view.size(), ETL_ERROR(string_out_of_bounds));
1766
1767 // Limit the lengths.
1768 length_ = etl::min(length_, size() - position);
1769 sublength = etl::min(sublength, view.size() - subposition);
1770
1771 return replace_impl(begin() + position, begin() + position + length_, view.begin() + subposition, sublength, false);
1772 }
1773
1774 //*********************************************************************
1776 //*********************************************************************
1777 ibasic_string& replace(size_type position, size_type length_, const_pointer s)
1778 {
1779 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1780
1781 // Limit the length.
1782 length_ = etl::min(length_, size() - position);
1783
1784 return replace_impl(begin() + position, begin() + position + length_, s, etl::strlen(s), false);
1785 }
1786
1787 //*********************************************************************
1795 //*********************************************************************
1796 ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s, size_type n)
1797 {
1798 return replace_impl(first, last, s, n, false);
1799 }
1800
1801 //*********************************************************************
1803 //*********************************************************************
1804 template <typename TIterator>
1805 typename etl::enable_if<etl::is_same<TIterator, const_pointer>::value, ibasic_string>::type& replace(const_iterator first, const_iterator last,
1806 TIterator s)
1807 {
1808 return replace_impl(first, last, s, etl::strlen(s), false);
1809 }
1810
1811 //*********************************************************************
1813 //*********************************************************************
1814 template <size_t Size>
1815 ibasic_string& replace(const_iterator first, const_iterator last, const value_type (&literal)[Size])
1816 {
1817 return replace_impl(first, last, literal, Size, false);
1818 }
1819
1820 //*********************************************************************
1823 //*********************************************************************
1824 ibasic_string& replace(size_type position, size_type length_, const_pointer s, size_type n)
1825 {
1826 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1827
1828 // Limit the length.
1829 length_ = etl::min(length_, size() - position);
1830
1831 return replace_impl(begin() + position, begin() + position + length_, s, n, false);
1832 }
1833
1834 //*********************************************************************
1836 //*********************************************************************
1837 ibasic_string& replace(size_type position, size_type length_, size_type n, value_type c)
1838 {
1839 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1840
1841 // Limit the length.
1842 length_ = etl::min(length_, size() - position);
1843
1844 // Erase the bit we want to replace.
1845 erase(position, length_);
1846
1847 // Insert the new stuff.
1848 insert(position, n, c);
1849
1850 return *this;
1851 }
1852
1853 //*********************************************************************
1855 //*********************************************************************
1856 ibasic_string& replace(const_iterator first, const_iterator last, size_type n, value_type c)
1857 {
1858 // Quick hack, as iterators are pointers.
1859 iterator first_ = to_iterator(first);
1860 iterator last_ = to_iterator(last);
1861
1862 // Erase the bit we want to replace.
1863 erase(first_, last_);
1864
1865 // Insert the new stuff.
1866 insert(first_, n, c);
1867
1868 return *this;
1869 }
1870
1871 //*********************************************************************
1874 //*********************************************************************
1875 template <typename TIterator>
1876 ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace)
1877 {
1878 // Quick hack, as iterators are pointers.
1879 iterator first_ = to_iterator(first);
1880 iterator last_ = to_iterator(last);
1881
1882 // Erase the bit we want to replace.
1883 erase(first_, last_);
1884
1885 // Insert the new stuff.
1886 insert(first_, first_replace, last_replace);
1887
1888 return *this;
1889 }
1890
1891 //*************************************************************************
1893 //*************************************************************************
1894 int compare(const ibasic_string& str) const
1895 {
1896 return compare(p_buffer, p_buffer + size(), str.p_buffer, str.p_buffer + str.size());
1897 }
1898
1899 //*************************************************************************
1901 //*************************************************************************
1902 template <typename TOtherTraits>
1904 {
1905 return compare(p_buffer, p_buffer + size(), view.data(), view.data() + view.size());
1906 }
1907
1908 //*************************************************************************
1910 //*************************************************************************
1911 int compare(size_type position, size_type length_, const ibasic_string& str) const
1912 {
1913 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1914
1915 // Limit the length.
1916 length_ = etl::min(length_, size() - position);
1917
1918 return compare(p_buffer + position, p_buffer + position + length_, str.p_buffer, str.p_buffer + str.size());
1919 }
1920
1921 //*************************************************************************
1923 //*************************************************************************
1924 template <typename TOtherTraits>
1925 int compare(size_type position, size_type length_, const etl::basic_string_view<T, TOtherTraits>& view) const
1926 {
1927 return compare(p_buffer + position, p_buffer + position + length_, view.data(), view.data() + view.size());
1928 }
1929
1930 //*************************************************************************
1932 //*************************************************************************
1933 int compare(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength) const
1934 {
1935 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1936 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1937
1938 // Limit the lengths.
1939 length_ = etl::min(length_, size() - position);
1940 sublength = etl::min(sublength, str.size() - subposition);
1941
1942 return compare(p_buffer + position, p_buffer + position + length_, str.p_buffer + subposition, str.p_buffer + subposition + sublength);
1943 }
1944
1945 //*************************************************************************
1948 //*************************************************************************
1949 template <typename TOtherTraits>
1950 int compare(size_type position, size_type length_, const etl::basic_string_view<T, TOtherTraits>& view, size_type subposition,
1951 size_type sublength) const
1952 {
1953 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1954 ETL_ASSERT(subposition <= view.size(), ETL_ERROR(string_out_of_bounds));
1955
1956 // Limit the lengths.
1957 length_ = etl::min(length_, size() - position);
1958 sublength = etl::min(sublength, view.size() - subposition);
1959
1960 return compare(p_buffer + position, p_buffer + position + length_, view.data() + subposition, view.data() + subposition + sublength);
1961 }
1962
1963 //*************************************************************************
1965 //*************************************************************************
1966 int compare(const value_type* s) const
1967 {
1968 return compare(p_buffer, p_buffer + size(), s, s + etl::strlen(s));
1969 }
1970
1971 //*************************************************************************
1973 //*************************************************************************
1974 int compare(size_type position, size_type length_, const_pointer s) const
1975 {
1976 return compare(p_buffer + position, p_buffer + position + length_, s, s + etl::strlen(s));
1977 }
1978
1979 //*************************************************************************
1981 //*************************************************************************
1982 int compare(size_type position, size_type length_, const_pointer s, size_type n) const
1983 {
1984 return compare(p_buffer + position, p_buffer + position + length_, s, s + n);
1985 }
1986
1987 //*********************************************************************
1991 //*********************************************************************
1992 size_type find_first_of(const ibasic_string<T>& str, size_type position = 0) const
1993 {
1994 return find_first_of(str.c_str(), position, str.size());
1995 }
1996
1997 //*********************************************************************
2001 //*********************************************************************
2002 size_type find_first_of(const_pointer s, size_type position = 0) const
2003 {
2004 return find_first_of(s, position, etl::strlen(s));
2005 }
2006
2007 //*********************************************************************
2011 //*********************************************************************
2012 template <typename TOtherTraits>
2013 size_type find_first_of(const etl::basic_string_view<T, TOtherTraits>& view, size_type position = 0) const
2014 {
2015 return find_first_of(view.data(), position, view.size());
2016 }
2017
2018 //*********************************************************************
2023 //*********************************************************************
2024 size_type find_first_of(const_pointer s, size_type position, size_type n) const
2025 {
2026 if (position < size())
2027 {
2028 for (size_type i = position; i < size(); ++i)
2029 {
2030 for (size_type j = 0; j < n; ++j)
2031 {
2032 if (p_buffer[i] == s[j])
2033 {
2034 return i;
2035 }
2036 }
2037 }
2038 }
2039
2040 return npos;
2041 }
2042
2043 //*********************************************************************
2047 //*********************************************************************
2048 size_type find_first_of(value_type c, size_type position = 0) const
2049 {
2050 if (position < size())
2051 {
2052 for (size_type i = position; i < size(); ++i)
2053 {
2054 if (p_buffer[i] == c)
2055 {
2056 return i;
2057 }
2058 }
2059 }
2060
2061 return npos;
2062 }
2063
2064 //*********************************************************************
2068 //*********************************************************************
2069 size_type find_last_of(const ibasic_string<T>& str, size_type position = npos) const
2070 {
2071 return find_last_of(str.c_str(), position, str.size());
2072 }
2073
2074 //*********************************************************************
2078 //*********************************************************************
2079 size_type find_last_of(const_pointer s, size_type position = npos) const
2080 {
2081 return find_last_of(s, position, etl::strlen(s));
2082 }
2083
2084 //*********************************************************************
2088 //*********************************************************************
2089 template <typename TOtherTraits>
2090 size_type find_last_of(const etl::basic_string_view<T, TOtherTraits>& view, size_type position = npos) const
2091 {
2092 return find_last_of(view.data(), position, view.size());
2093 }
2094
2095 //*********************************************************************
2100 //*********************************************************************
2101 size_type find_last_of(const_pointer s, size_type position, size_type n) const
2102 {
2103 if (empty())
2104 {
2105 return npos;
2106 }
2107
2108 position = etl::min(position, size() - 1);
2109
2110 const_reverse_iterator it = rbegin() + static_cast<difference_type>(size() - position - 1);
2111
2112 while (it != rend())
2113 {
2114 for (size_type j = 0; j < n; ++j)
2115 {
2116 if (p_buffer[position] == s[j])
2117 {
2118 return position;
2119 }
2120 }
2121
2122 ++it;
2123 --position;
2124 }
2125
2126 return npos;
2127 }
2128
2129 //*********************************************************************
2133 //*********************************************************************
2134 size_type find_last_of(value_type c, size_type position = npos) const
2135 {
2136 if (empty())
2137 {
2138 return npos;
2139 }
2140
2141 position = etl::min(position, size() - 1);
2142
2143 const_reverse_iterator it = rbegin() + static_cast<difference_type>(size() - position - 1);
2144
2145 while (it != rend())
2146 {
2147 if (p_buffer[position] == c)
2148 {
2149 return position;
2150 }
2151
2152 ++it;
2153 --position;
2154 }
2155
2156 return npos;
2157 }
2158
2159 //*********************************************************************
2163 //*********************************************************************
2164 size_type find_first_not_of(const ibasic_string<T>& str, size_type position = 0) const
2165 {
2166 return find_first_not_of(str.c_str(), position, str.size());
2167 }
2168
2169 //*********************************************************************
2173 //*********************************************************************
2174 size_type find_first_not_of(const_pointer s, size_type position = 0) const
2175 {
2176 return find_first_not_of(s, position, etl::strlen(s));
2177 }
2178
2179 //*********************************************************************
2183 //*********************************************************************
2184 template <typename TOtherTraits>
2185 size_type find_first_not_of(const etl::basic_string_view<T, TOtherTraits>& view, size_type position = 0) const
2186 {
2187 return find_first_not_of(view.data(), position, view.size());
2188 }
2189
2190 //*********************************************************************
2195 //*********************************************************************
2196 size_type find_first_not_of(const_pointer s, size_type position, size_type n) const
2197 {
2198 if (position < size())
2199 {
2200 for (size_type i = position; i < size(); ++i)
2201 {
2202 bool found = false;
2203
2204 for (size_type j = 0; j < n; ++j)
2205 {
2206 if (p_buffer[i] == s[j])
2207 {
2208 found = true;
2209 }
2210 }
2211
2212 if (!found)
2213 {
2214 return i;
2215 }
2216 }
2217 }
2218
2219 return npos;
2220 }
2221
2222 //*********************************************************************
2226 //*********************************************************************
2227 size_type find_first_not_of(value_type c, size_type position = 0) const
2228 {
2229 if (position < size())
2230 {
2231 for (size_type i = position; i < size(); ++i)
2232 {
2233 if (*(p_buffer + i) != c)
2234 {
2235 return i;
2236 }
2237 }
2238 }
2239
2240 return npos;
2241 }
2242
2243 //*********************************************************************
2247 //*********************************************************************
2248 size_type find_last_not_of(const ibasic_string<T>& str, size_type position = npos) const
2249 {
2250 return find_last_not_of(str.c_str(), position, str.size());
2251 }
2252
2253 //*********************************************************************
2257 //*********************************************************************
2258 size_type find_last_not_of(const_pointer s, size_type position = npos) const
2259 {
2260 return find_last_not_of(s, position, etl::strlen(s));
2261 }
2262
2263 //*********************************************************************
2267 //*********************************************************************
2268 template <typename TOtherTraits>
2269 size_type find_last_not_of(const etl::basic_string_view<T, TOtherTraits>& view, size_type position = npos) const
2270 {
2271 return find_last_not_of(view.data(), position, view.size());
2272 }
2273
2274 //*********************************************************************
2279 //*********************************************************************
2280 size_type find_last_not_of(const_pointer s, size_type position, size_type n) const
2281 {
2282 if (empty())
2283 {
2284 return npos;
2285 }
2286
2287 position = etl::min(position, size() - 1);
2288
2289 const_reverse_iterator it = rbegin() + static_cast<difference_type>(size() - position - 1);
2290
2291 while (it != rend())
2292 {
2293 bool found = false;
2294
2295 for (size_type j = 0; j < n; ++j)
2296 {
2297 if (p_buffer[position] == s[j])
2298 {
2299 found = true;
2300 }
2301 }
2302
2303 if (!found)
2304 {
2305 return position;
2306 }
2307
2308 ++it;
2309 --position;
2310 }
2311
2312 return npos;
2313 }
2314
2315 //*********************************************************************
2316 //
2317 //*********************************************************************
2318 size_type find_last_not_of(value_type c, size_type position = npos) const
2319 {
2320 if (empty())
2321 {
2322 return npos;
2323 }
2324
2325 position = etl::min(position, size() - 1);
2326
2327 const_reverse_iterator it = rbegin() + static_cast<difference_type>(size() - position - 1);
2328
2329 while (it != rend())
2330 {
2331 if (p_buffer[position] != c)
2332 {
2333 return position;
2334 }
2335
2336 ++it;
2337 --position;
2338 }
2339
2340 return npos;
2341 }
2342
2343 //*************************************************************************
2345 //*************************************************************************
2347 {
2348 if (&rhs != this)
2349 {
2350 assign(rhs);
2351 }
2352
2353 return *this;
2354 }
2355
2356 //*************************************************************************
2358 //*************************************************************************
2359 ibasic_string& operator=(const_pointer rhs)
2360 {
2361 assign(rhs);
2362
2363 return *this;
2364 }
2365
2366 //*************************************************************************
2368 //*************************************************************************
2369 template <typename TOtherTraits>
2371 {
2372 assign(view);
2373
2374 return *this;
2375 }
2376
2377 //*************************************************************************
2379 //*************************************************************************
2381 {
2382 append(rhs);
2383
2384 return *this;
2385 }
2386
2387 //*************************************************************************
2389 //*************************************************************************
2390 template <typename TOtherTraits>
2392 {
2393 append(rhs);
2394
2395 return *this;
2396 }
2397
2398 //*************************************************************************
2400 //*************************************************************************
2401 ibasic_string& operator+=(const_pointer rhs)
2402 {
2403 append(rhs);
2404
2405 return *this;
2406 }
2407
2408 //*************************************************************************
2410 //*************************************************************************
2412 {
2413 append(size_type(1), rhs);
2414
2415 return *this;
2416 }
2417
2418#if ETL_HAS_ISTRING_REPAIR
2419 //*************************************************************************
2421 //*************************************************************************
2422 virtual void repair() = 0;
2423#endif
2424
2425 //*********************************************************************
2427 //*********************************************************************
2429 {
2430#if ETL_HAS_STRING_TRUNCATION_CHECKS
2431 set_truncated(false);
2432#endif
2433 etl::mem_set(&p_buffer[current_size], &p_buffer[CAPACITY + 1U], char(0));
2434 }
2435
2436 //*********************************************************************
2440 //*********************************************************************
2442 {
2443#if ETL_HAS_STRING_TRUNCATION_CHECKS
2444 set_truncated(p_buffer[CAPACITY] != T(0));
2445#endif
2446
2447 p_buffer[CAPACITY] = T(0); // Ensure a terminating null.
2448 current_size = etl::strlen(p_buffer);
2449 }
2450
2451 protected:
2452
2453 //*********************************************************************
2455 //*********************************************************************
2456 ibasic_string(T* p_buffer_, size_type MAX_SIZE_)
2457 : string_base(MAX_SIZE_)
2458 , p_buffer(p_buffer_)
2459 {
2460 }
2461
2462 //*********************************************************************
2464 //*********************************************************************
2466 {
2467 current_size = 0U;
2468 p_buffer[0] = 0;
2469#if ETL_HAS_STRING_TRUNCATION_CHECKS
2470 set_truncated(false);
2471#endif
2472 }
2473
2474 //*************************************************************************
2476 //*************************************************************************
2477 void repair_buffer(T* p_buffer_)
2478 {
2479 p_buffer = p_buffer_;
2480 }
2481
2482 private:
2483
2484 //*********************************************************************
2488 //*********************************************************************
2489 ibasic_string& replace_impl(const_iterator first, const_iterator last, const_pointer s, size_type length, bool other_truncated)
2490 {
2491 // Trivial no-op cases
2492 if ((first == last) && (s == ETL_NULLPTR || length == 0U))
2493 {
2494 return *this;
2495 }
2496
2497 // Invalid range?
2498 if (first > last)
2499 {
2500 return *this;
2501 }
2502
2503 // Quick hack, as iterators are pointers.
2504 iterator first_ = to_iterator(first);
2505 iterator last_ = to_iterator(last);
2506
2507 // If source pointer is inside our current buffer we take the safe
2508 // (legacy) path to preserve correct semantics for overlapping self use.
2509 const bool source_overlaps = (s != ETL_NULLPTR) && (s >= p_buffer) && (s < p_buffer + current_size);
2510
2511 if (source_overlaps)
2512 {
2513 // Legacy behaviour (may be slightly less efficient, but correct).
2514 // Erase range then insert up to 'length' characters from 's'.
2515 erase(first_, last_);
2516
2517 if (s != ETL_NULLPTR && length != 0U)
2518 {
2519 // 'insert' can truncate & set flags.
2520 insert(p_buffer + (first_ - p_buffer), s, s + length);
2521 }
2522
2523 return *this;
2524 }
2525
2526 // Calculate the remove parameters.
2527 const size_type remove_index = size_type(first_ - p_buffer);
2528 const size_type remove_length = size_type(last_ - first_);
2529 const size_type free_space = CAPACITY - remove_index; // Free space is the space from the remove
2530 // index to the end of the buffer.
2531
2532 size_type insert_length = (s == ETL_NULLPTR) ? 0U : length;
2533
2534 // Limit the insert length to the available free space.
2535 if (insert_length > free_space)
2536 {
2537 insert_length = free_space;
2538 }
2539
2540 // Calculate the tail parameters.
2541 size_type tail_index = remove_index + remove_length;
2542 size_type tail_length = current_size - tail_index;
2543 size_type tail_space = free_space - insert_length;
2544
2545#if ETL_HAS_STRING_TRUNCATION_CHECKS
2546 set_truncated((insert_length != length) || (tail_space < tail_length) || is_truncated() || other_truncated);
2547#endif
2548
2549 // The some or all of tail may be erased if the space remaining for it is
2550 // smaller than the tail length.
2551 if (tail_space < tail_length)
2552 {
2553 tail_length = tail_space;
2554 }
2555
2556 // Three cases: same size, grow, shrink.
2557 if (insert_length == remove_length)
2558 {
2559 // Size unchanged: simple overwrite.
2560 etl::mem_copy(s, insert_length, &p_buffer[remove_index]);
2561 }
2562 else if (insert_length > remove_length)
2563 {
2564 // Grow: shift tail right then copy.
2565 // Shift tail (backwards to handle overlap safely).
2566 etl::mem_move(&p_buffer[tail_index], tail_length, &p_buffer[remove_index + insert_length]);
2567
2568 // Copy new data.
2569 etl::mem_copy(s, insert_length, &p_buffer[remove_index]);
2570 }
2571 else // insert_length < remove_length
2572 {
2573 // Shrink: overwrite then shift tail left.
2574 // Copy new data.
2575 etl::mem_copy(s, insert_length, &p_buffer[remove_index]);
2576
2577 // Move tail left.
2578 etl::mem_move(&p_buffer[tail_index], tail_length, &p_buffer[remove_index + insert_length]);
2579 }
2580
2581 current_size = remove_index + insert_length + tail_length;
2582 p_buffer[current_size] = value_type(0);
2583
2584 cleanup();
2585
2586 return *this;
2587 }
2588
2589 //*************************************************************************
2591 //*************************************************************************
2592 static int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2)
2593 {
2594 typedef typename etl::make_unsigned<value_type>::type type;
2595
2596 difference_type length1 = etl::distance(first1, last1);
2597 difference_type length2 = etl::distance(first2, last2);
2598 difference_type compare_length = etl::min(length1, length2);
2599
2600 // First compare the string characters.
2601 while (compare_length != 0)
2602 {
2603 if (static_cast<type>(*first1) < static_cast<type>(*first2))
2604 {
2605 // Compared character is lower.
2606 return -1;
2607 }
2608 else if (static_cast<type>(*first1) > static_cast<type>(*first2))
2609 {
2610 // Compared character is higher.
2611 return 1;
2612 }
2613
2614 ++first1;
2615 ++first2;
2616 --compare_length;
2617 }
2618
2619 // Then compare the string lengths.
2620 if (length1 < length2)
2621 {
2622 // First string is shorter.
2623 return -1;
2624 }
2625
2626 if (length1 > length2)
2627 {
2628 // First string is longer.
2629 return 1;
2630 }
2631
2632 // Strings are the same length.
2633 return 0;
2634 }
2635
2636 //*************************************************************************
2638 //*************************************************************************
2639 void cleanup()
2640 {
2641#if ETL_HAS_STRING_CLEAR_AFTER_USE
2642 if (is_secure())
2643 {
2644 etl::memory_clear_range(&p_buffer[current_size], &p_buffer[CAPACITY]);
2645 }
2646#endif
2647 }
2648
2649 //*************************************************************************
2651 //*************************************************************************
2653
2654 //*************************************************************************
2656 //*************************************************************************
2657 T* p_buffer;
2658
2659 //*************************************************************************
2661 //*************************************************************************
2662#if defined(ETL_POLYMORPHIC_STRINGS) || defined(ETL_POLYMORPHIC_CONTAINERS) || defined(ETL_ISTRING_REPAIR_ENABLE)
2663
2664 public:
2665
2666 virtual
2667#else
2668
2669 protected:
2670#endif
2672 {
2673#if ETL_HAS_STRING_CLEAR_AFTER_USE
2674 if (is_secure())
2675 {
2676 clear();
2677 }
2678#endif
2679 }
2680
2681 protected:
2682
2683 //*************************************************************************
2685 //*************************************************************************
2686 iterator to_iterator(const_iterator itr) const
2687 {
2688 return const_cast<iterator>(itr);
2689 }
2690
2691 //*************************************************************************
2693 //*************************************************************************
2694 bool is_within_buffer(const_pointer ptr) const
2695 {
2696 return (ptr >= p_buffer) && (ptr <= (p_buffer + CAPACITY));
2697 }
2698
2699 private:
2700
2701 //*********************************************************************
2704 //*********************************************************************
2705 template <typename TIterator1>
2706 static
2707 typename etl::enable_if< etl::is_pointer<typename etl::remove_reference<TIterator1>::type>::value
2710 copy_characters(TIterator1 from, size_t n, iterator to)
2711 {
2712 etl::mem_move(from, n, to);
2713
2714 return to + n;
2715 }
2716
2717 //*********************************************************************
2720 //*********************************************************************
2721 template <typename TIterator1>
2722 static
2723 typename etl::enable_if< !(etl::is_pointer<typename etl::remove_reference<TIterator1>::type>::value
2724 && sizeof(typename etl::remove_pointer< typename etl::remove_cvref<TIterator1>::type>::type) == sizeof(value_type)),
2725 iterator>::type
2726 copy_characters(TIterator1 from, size_t n, iterator to)
2727 {
2729 size_t count = 0;
2730
2731 while (count != n)
2732 {
2733 *to++ = static_cast<value_type>(*from++);
2734 ++count;
2735 }
2736
2738 return to;
2739 }
2740
2741 //*********************************************************************
2744 //*********************************************************************
2745 template <typename TIterator>
2746 typename etl::enable_if< !etl::is_pointer< typename etl::remove_reference<TIterator>::type>::value>::type
2747 append_impl(iterator position, TIterator first, TIterator last, bool truncated, bool secure)
2748 {
2749 difference_type start = etl::distance(p_buffer, position);
2750 difference_type count = etl::distance(first, last);
2751 difference_type free_space = etl::distance(position, p_buffer + CAPACITY);
2752
2753#if ETL_IS_DEBUG_BUILD
2754 ETL_ASSERT(count >= 0, ETL_ERROR(string_iterator));
2755#endif
2756
2757#if ETL_HAS_STRING_TRUNCATION_CHECKS
2758 set_truncated((count > free_space) || this->is_truncated() || truncated);
2759
2760 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
2761 ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation));
2762 #endif
2763#else
2764 (void)truncated;
2765#endif
2766
2767#if ETL_HAS_STRING_CLEAR_AFTER_USE
2768 if (secure)
2769 {
2770 set_secure();
2771 }
2772#else
2773 (void)secure;
2774#endif
2775
2776 // Limit the actual distance to the capacity.
2777 count = etl::min(count, free_space);
2778 copy_characters(first, size_t(count), position);
2779 current_size = size_t(start + count);
2780 p_buffer[current_size] = 0;
2781
2782 cleanup();
2783 }
2784
2785 //*********************************************************************
2787 //*********************************************************************
2788 void append_impl(iterator position, const_pointer src, bool truncated, bool secure)
2789 {
2790 if (src == ETL_NULLPTR)
2791 {
2792 clear();
2793 return;
2794 }
2795
2796 append_impl(position, src, get_string_length(src), truncated, secure);
2797 }
2798
2799 //*********************************************************************
2801 //*********************************************************************
2802 void append_impl(iterator position, const_pointer src, size_t length, bool truncated, bool secure)
2803 {
2804 size_t start = static_cast<size_t>(etl::distance(p_buffer, position));
2805 size_t free_space = static_cast<size_t>(etl::distance(position, p_buffer + CAPACITY));
2806 size_t count = etl::min(length, free_space);
2807
2808#if ETL_IS_DEBUG_BUILD
2809 ETL_ASSERT(start <= CAPACITY, ETL_ERROR(string_iterator));
2810#endif
2811
2812 etl::mem_move(src, count, position);
2813
2814 current_size = start + count;
2815 p_buffer[current_size] = 0;
2816
2817#if ETL_HAS_STRING_TRUNCATION_CHECKS
2818 set_truncated((length > free_space) || truncated);
2819 #if ETL_HAS_ERROR_ON_STRING_TRUNCATION
2820 ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation));
2821 #endif
2822#else
2823 (void)truncated;
2824#endif
2825
2826#if ETL_HAS_STRING_CLEAR_AFTER_USE
2827 if (secure)
2828 {
2829 set_secure();
2830 }
2831#else
2832 (void)secure;
2833#endif
2834
2835 cleanup();
2836 }
2837
2838 //*********************************************************************
2840 //*********************************************************************
2841 template <typename TIterator>
2842 typename etl::enable_if< etl::is_pointer< typename etl::remove_reference<TIterator>::type>::value>::type
2843 append_impl(iterator position, TIterator first, TIterator last, bool truncated, bool secure)
2844 {
2845 append_impl(position, first, size_t(etl::distance(first, last)), truncated || is_truncated(), secure);
2846 }
2847
2848 //*************************************************************************
2850 //*************************************************************************
2851 template <typename TIterator>
2852 size_type find_impl(TIterator first, TIterator last, size_type sz, size_type pos = 0) const
2853 {
2854 if ((pos + sz) > size())
2855 {
2856 return npos;
2857 }
2858
2859 const_iterator iposition = etl::search(begin() + pos, end(), first, last);
2860
2861 if (iposition == end())
2862 {
2863 return npos;
2864 }
2865 else
2866 {
2867 return static_cast<size_type>(etl::distance(begin(), iposition));
2868 }
2869 }
2870
2871 //*************************************************************************
2873 //*************************************************************************
2874 template <typename TIterator>
2875 size_type rfind_impl(TIterator rfirst, TIterator rlast, size_type sz, size_type pos = 0) const
2876 {
2877 if (sz > size())
2878 {
2879 return npos;
2880 }
2881
2882 if (pos >= size())
2883 {
2884 pos = size();
2885 }
2886
2887 pos = size() - pos;
2888
2889 const_reverse_iterator iposition = etl::search(rbegin() + static_cast<difference_type>(pos), rend(), rfirst, rlast);
2890
2891 if (iposition == rend())
2892 {
2893 return npos;
2894 }
2895 else
2896 {
2897 return size() - sz - static_cast<size_type>(etl::distance(rbegin(), iposition));
2898 }
2899 }
2900
2901 //*********************************************************************
2903 //*********************************************************************
2904 template <typename U>
2905 static typename etl::enable_if<sizeof(U) == sizeof(char), size_t>::type get_string_length(const U* str)
2906 {
2907 return ::strlen(reinterpret_cast<const char*>(str));
2908 }
2909
2910#if ETL_USING_LIBC_WCHAR_H
2911 //*********************************************************************
2913 //*********************************************************************
2914 template <typename U>
2915 static typename etl::enable_if<sizeof(U) == sizeof(wchar_t), size_t>::type get_string_length(const U* str)
2916 {
2917 return ::wcslen(reinterpret_cast<const wchar_t*>(str));
2918 }
2919#endif
2920
2921 //*********************************************************************
2923 //*********************************************************************
2924 template <typename U>
2925 static
2926#if ETL_USING_LIBC_WCHAR_H
2927 typename etl::enable_if<(sizeof(U) != sizeof(char)) && (sizeof(U) != sizeof(wchar_t)), size_t>::type
2928#else
2929 typename etl::enable_if<(sizeof(U) != sizeof(char)), size_t>::type
2930#endif
2931 get_string_length(const U* str)
2932 {
2933 if (str == ETL_NULLPTR)
2934 {
2935 return 0;
2936 }
2937
2938 const U* end = str;
2939
2940 while (*end++ != 0)
2941 {
2942 // Do nothing.
2943 }
2944
2945 return size_t(end - str) - 1;
2946 }
2947 };
2948
2949 //***************************************************************************
2955 //***************************************************************************
2956 template <typename T>
2958 {
2959 return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
2960 }
2961
2962 //***************************************************************************
2968 //***************************************************************************
2969 template <typename T>
2970 bool operator==(const etl::ibasic_string<T>& lhs, const T* rhs)
2971 {
2972 return (lhs.size() == etl::strlen(rhs)) && etl::equal(lhs.begin(), lhs.end(), rhs);
2973 }
2974
2975 //***************************************************************************
2981 //***************************************************************************
2982 template <typename T>
2983 bool operator==(const T* lhs, const etl::ibasic_string<T>& rhs)
2984 {
2985 return (rhs.size() == etl::strlen(lhs)) && etl::equal(rhs.begin(), rhs.end(), lhs);
2986 }
2987
2988 //***************************************************************************
2994 //***************************************************************************
2995 template <typename T>
2997 {
2998 return !(lhs == rhs);
2999 }
3000
3001 //***************************************************************************
3007 //***************************************************************************
3008 template <typename T>
3009 bool operator!=(const etl::ibasic_string<T>& lhs, const T* rhs)
3010 {
3011 return !(lhs == rhs);
3012 }
3013
3014 //***************************************************************************
3020 //***************************************************************************
3021 template <typename T>
3022 bool operator!=(const T* lhs, const etl::ibasic_string<T>& rhs)
3023 {
3024 return !(lhs == rhs);
3025 }
3026
3027 //***************************************************************************
3033 //***************************************************************************
3034 template <typename T>
3036 {
3037 return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
3038 }
3039
3040 //***************************************************************************
3046 //***************************************************************************
3047 template <typename T>
3048 bool operator<(const etl::ibasic_string<T>& lhs, const T* rhs)
3049 {
3050 return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs));
3051 }
3052
3053 //***************************************************************************
3059 //***************************************************************************
3060 template <typename T>
3061 bool operator<(const T* lhs, const etl::ibasic_string<T>& rhs)
3062 {
3063 return etl::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end());
3064 }
3065
3066 //***************************************************************************
3072 //***************************************************************************
3073 template <typename T>
3075 {
3076 return (rhs < lhs);
3077 }
3078
3079 //***************************************************************************
3085 //***************************************************************************
3086 template <typename T>
3087 bool operator>(const etl::ibasic_string<T>& lhs, const T* rhs)
3088 {
3089 return (rhs < lhs);
3090 }
3091
3092 //***************************************************************************
3098 //***************************************************************************
3099 template <typename T>
3100 bool operator>(const T* lhs, const etl::ibasic_string<T>& rhs)
3101 {
3102 return (rhs < lhs);
3103 }
3104
3105 //***************************************************************************
3112 //***************************************************************************
3113 template <typename T>
3115 {
3116 return !(lhs > rhs);
3117 }
3118
3119 //***************************************************************************
3126 //***************************************************************************
3127 template <typename T>
3128 bool operator<=(const etl::ibasic_string<T>& lhs, const T* rhs)
3129 {
3130 return !(lhs > rhs);
3131 }
3132
3133 //***************************************************************************
3140 //***************************************************************************
3141 template <typename T>
3142 bool operator<=(const T* lhs, const etl::ibasic_string<T>& rhs)
3143 {
3144 return !(lhs > rhs);
3145 }
3146
3147 //***************************************************************************
3154 //***************************************************************************
3155 template <typename T>
3157 {
3158 return !(lhs < rhs);
3159 }
3160
3161 //***************************************************************************
3168 //***************************************************************************
3169 template <typename T>
3170 bool operator>=(const etl::ibasic_string<T>& lhs, const T* rhs)
3171 {
3172 return !(lhs < rhs);
3173 }
3174
3175 //***************************************************************************
3182 //***************************************************************************
3183 template <typename T>
3184 bool operator>=(const T* lhs, const etl::ibasic_string<T>& rhs)
3185 {
3186 return !(lhs < rhs);
3187 }
3188
3189 //***************************************************************************
3195 //***************************************************************************
3196#if ETL_USING_STD_OSTREAM
3197 template <typename T>
3198 std::basic_ostream<T, std::char_traits<T> >& operator<<(std::basic_ostream<T, std::char_traits<T> >& os, const etl::ibasic_string<T>& str)
3199 {
3200 os.write(str.data(), static_cast<std::streamsize>(str.size()));
3201 return os;
3202 }
3203#endif
3204} // namespace etl
3205
3206#include "private/minmax_pop.h"
3207
3208#endif
String view.
Definition string_view.h:117
ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT
Returns a const iterator to the beginning of the array.
Definition string_view.h:239
ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT
Returns the size of the array.
Definition string_view.h:307
ETL_CONSTEXPR const_reverse_iterator rend() const ETL_NOEXCEPT
Returns a const reverse iterator to the end of the array.
Definition string_view.h:279
ETL_CONSTEXPR const_pointer data() const ETL_NOEXCEPT
Returns a const pointer to the first element of the internal storage.
Definition string_view.h:223
ETL_CONSTEXPR const_iterator end() const ETL_NOEXCEPT
Returns a const iterator to the end of the array.
Definition string_view.h:247
ETL_CONSTEXPR const_iterator begin() const ETL_NOEXCEPT
Returns a const iterator to the beginning of the array.
Definition string_view.h:231
ETL_CONSTEXPR const_reverse_iterator rbegin() const ETL_NOEXCEPT
Returns a const reverse iterator to the reverse beginning of the array.
Definition string_view.h:263
Definition flags.h:51
Definition basic_string.h:335
int compare(size_type position, size_type length_, const ibasic_string &str) const
Compare position / length with string.
Definition basic_string.h:1911
ibasic_string & append(TIterator first, TIterator last)
Definition basic_string.h:854
size_type find_last_of(const_pointer s, size_type position=npos) const
Definition basic_string.h:2079
size_type rfind(const_pointer s, size_type position=npos) const
Definition basic_string.h:1517
ibasic_string & replace(const_iterator first, const_iterator last, const etl::basic_string_view< T, TOtherTraits > &view)
Definition basic_string.h:1735
etl::enable_if< etl::is_same< TIterator, const_pointer >::value, ibasic_string >::type & replace(const_iterator first, const_iterator last, TIterator s)
Replace characters from 'first' to 'last' with pointed to string.
Definition basic_string.h:1805
etl::ibasic_string< T > & insert(size_type position, const etl::ibasic_string< T > &str)
Definition basic_string.h:1174
ibasic_string & replace(const_iterator first, const_iterator last, const value_type(&literal)[Size])
Replace characters from 'first' 'last' with pointed to literal string.
Definition basic_string.h:1815
size_type find_last_not_of(const_pointer s, size_type position=npos) const
Definition basic_string.h:2258
size_type find(const_pointer s, size_type pos=0) const
Definition basic_string.h:1454
ibasic_string & operator=(const ibasic_string &rhs)
Assignment operator.
Definition basic_string.h:2346
ibasic_string & append(const ibasic_string &str, size_type subposition, size_type sublength=npos)
Definition basic_string.h:834
const_reverse_iterator rbegin() const
Definition basic_string.h:419
bool contains(const etl::ibasic_string< T > &str) const
Checks that the string is within this string.
Definition basic_string.h:1569
reference operator[](size_type i)
Definition basic_string.h:546
void assign(const etl::ibasic_string< T > &other, size_type subposition, size_type sublength)
Definition basic_string.h:686
etl::ibasic_string< T > & insert(size_type position, const etl::basic_string_view< T, TOtherTraits > &view, size_type subposition, size_type sublength)
Definition basic_string.h:1251
pointer data_end()
Definition basic_string.h:651
iterator erase(const_iterator first, const_iterator last)
Definition basic_string.h:1369
iterator insert(const_iterator position, TIterator first, TIterator last)
Definition basic_string.h:1071
bool is_within_buffer(const_pointer ptr) const
Checks if a pointer is within the buffer.
Definition basic_string.h:2694
bool contains(value_type c) const
Checks that character is within this string.
Definition basic_string.h:1594
size_type find_last_of(const ibasic_string< T > &str, size_type position=npos) const
Definition basic_string.h:2069
size_type find_first_of(value_type c, size_type position=0) const
Definition basic_string.h:2048
bool starts_with(const etl::ibasic_string< T > &str) const
Checks that the string is the start of this string.
Definition basic_string.h:1602
size_type find(T c, size_type position=0) const
Definition basic_string.h:1477
ibasic_string & replace(size_type position, size_type length_, const etl::basic_string_view< T, TOtherTraits > &view, size_type subposition, size_type sublength)
Definition basic_string.h:1761
bool ends_with(value_type c) const
Checks that the character is the end of this string.
Definition basic_string.h:1679
void pop_back()
Definition basic_string.h:809
size_type rfind(const ibasic_string< T > &str, size_type position=npos) const
Definition basic_string.h:1496
bool contains(const_pointer s) const
Checks that text is within this string.
Definition basic_string.h:1586
etl::ibasic_string< T > & insert(size_type position, const etl::basic_string_view< T, TOtherTraits > &view)
Definition basic_string.h:1200
void resize_and_overwrite(size_type new_size, TOperation operation)
Resizes the string and overwrites to data using the operation.
Definition basic_string.h:506
void initialize_free_space()
Clears the free space to string terminator value.
Definition basic_string.h:2428
ibasic_string & replace(size_type position, size_type length_, const_pointer s, size_type n)
Definition basic_string.h:1824
iterator to_iterator(const_iterator itr) const
Convert from const_iterator to iterator.
Definition basic_string.h:2686
ibasic_string & replace(size_type position, size_type length_, size_type n, value_type c)
Replace characters from 'position' of 'length' with 'n' copies of 'c'.
Definition basic_string.h:1837
const_reference operator[](size_type i) const
Definition basic_string.h:557
ibasic_string & replace(const_iterator first, const_iterator last, const ibasic_string &str)
Definition basic_string.h:1723
size_type find_first_of(const ibasic_string< T > &str, size_type position=0) const
Definition basic_string.h:1992
size_type find_first_of(const etl::basic_string_view< T, TOtherTraits > &view, size_type position=0) const
Definition basic_string.h:2013
const_reference back() const
Definition basic_string.h:623
void assign(const_pointer str, size_type n)
Definition basic_string.h:733
const_iterator begin() const
Definition basic_string.h:365
size_type find_last_of(const_pointer s, size_type position, size_type n) const
Definition basic_string.h:2101
bool ends_with(const etl::basic_string_view< T, TOtherTraits > &view) const
Checks that the view is the end of this string.
Definition basic_string.h:1651
reverse_iterator rbegin()
Definition basic_string.h:410
ibasic_string & replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace)
Definition basic_string.h:1876
void resize(size_type new_size)
Definition basic_string.h:465
size_type find_last_not_of(const_pointer s, size_type position, size_type n) const
Definition basic_string.h:2280
ibasic_string & replace(size_type position, size_type length_, const etl::basic_string_view< T, TOtherTraits > &view)
Definition basic_string.h:1707
size_type find_first_not_of(const_pointer s, size_type position=0) const
Definition basic_string.h:2174
size_type rfind(T c, size_type position=npos) const
Definition basic_string.h:1545
etl::ibasic_string< T > & erase(size_type position, size_type length_=npos)
Definition basic_string.h:1314
int compare(const value_type *s) const
Compare with C string.
Definition basic_string.h:1966
int compare(size_type position, size_type length_, const_pointer s) const
Compare position / length with C string.
Definition basic_string.h:1974
iterator insert(const_iterator position, size_type n, T value)
Definition basic_string.h:981
ibasic_string & append(const etl::basic_string_view< T, TOtherTraits > &view)
Definition basic_string.h:889
const_reference at(size_type i) const
Definition basic_string.h:583
void assign(const etl::basic_string_view< T, TOtherTraits > &view)
Assigns values to the string from a view.
Definition basic_string.h:742
ibasic_string & operator+=(const_pointer rhs)
+= operator.
Definition basic_string.h:2401
void clear()
Clears the string.
Definition basic_string.h:775
int compare(size_type position, size_type length_, const ibasic_string &str, size_type subposition, size_type sublength) const
Compare position / length with string / subposition / sublength.
Definition basic_string.h:1933
reverse_iterator rend()
Definition basic_string.h:428
ibasic_string & operator=(const etl::basic_string_view< T, TOtherTraits > &view)
Assignment operator.
Definition basic_string.h:2370
size_type find_last_of(const etl::basic_string_view< T, TOtherTraits > &view, size_type position=npos) const
Definition basic_string.h:2090
iterator erase(iterator i_element)
Definition basic_string.h:1332
ibasic_string & append(const_pointer str, size_type n)
Definition basic_string.h:877
const_reverse_iterator crend() const
Definition basic_string.h:455
bool contains(const etl::basic_string_view< T, TOtherTraits > &view) const
Checks that the view is within this string.
Definition basic_string.h:1578
reference at(size_type i)
Definition basic_string.h:570
size_type rfind(const etl::basic_string_view< T, TOtherTraits > &view, size_type pos=0) const
Definition basic_string.h:1507
bool starts_with(value_type c) const
Checks that the character is the start of this string.
Definition basic_string.h:1629
int compare(const etl::basic_string_view< T, TOtherTraits > &view) const
Compare with etl::basic_string_view.
Definition basic_string.h:1903
~ibasic_string()
Destructor.
Definition basic_string.h:2671
size_type find(const_pointer s, size_type pos, size_type n) const
Definition basic_string.h:1467
size_type find_first_of(const_pointer s, size_type position=0) const
Definition basic_string.h:2002
ibasic_string & replace(size_type position, size_type length_, const ibasic_string &str, size_type subposition, size_type sublength)
Definition basic_string.h:1744
iterator begin()
Definition basic_string.h:356
iterator end()
Definition basic_string.h:374
ibasic_string & replace(const_iterator first, const_iterator last, size_type n, value_type c)
Replace characters from 'first' of 'last' with 'n' copies of 'c'.
Definition basic_string.h:1856
ibasic_string & replace(const_iterator first, const_iterator last, const_pointer s, size_type n)
Definition basic_string.h:1796
void assign(TIterator first, TIterator last)
Definition basic_string.h:712
etl::ibasic_string< T > & insert(size_type position, const etl::ibasic_string< T > &str, size_type subposition, size_type sublength)
Definition basic_string.h:1217
size_type find(const ibasic_string< T > &str, size_type pos=0) const
Definition basic_string.h:1433
void push_back(T value)
Definition basic_string.h:786
size_type find_first_not_of(const_pointer s, size_type position, size_type n) const
Definition basic_string.h:2196
const_reverse_iterator crbegin() const
Definition basic_string.h:446
iterator insert(const_iterator position, T value)
Definition basic_string.h:927
ibasic_string & operator=(const_pointer rhs)
Assignment operator.
Definition basic_string.h:2359
etl::ibasic_string< T > & insert(size_type position, const_pointer s, size_type n)
Definition basic_string.h:1286
ibasic_string & replace(size_type position, size_type length_, const ibasic_string &str)
Definition basic_string.h:1690
ibasic_string(T *p_buffer_, size_type MAX_SIZE_)
Constructor.
Definition basic_string.h:2456
bool ends_with(const_pointer s) const
Checks that the string is the end of this string.
Definition basic_string.h:1664
etl::ibasic_string< T > & insert(size_type position, size_type n, value_type c)
Definition basic_string.h:1300
const_reverse_iterator rend() const
Definition basic_string.h:437
size_type find_last_not_of(const ibasic_string< T > &str, size_type position=npos) const
Definition basic_string.h:2248
size_type find(const etl::basic_string_view< T, TOtherTraits > &view, size_type pos=0) const
Definition basic_string.h:1444
const_pointer data_end() const
Definition basic_string.h:660
void assign(const etl::ibasic_string< T > &other)
Definition basic_string.h:670
const_iterator cend() const
Definition basic_string.h:401
const_pointer c_str() const
Return a pointer to a C string.
Definition basic_string.h:1394
void resize(size_type new_size, T value)
Definition basic_string.h:476
ETL_CONSTEXPR const_pointer data() const
Definition basic_string.h:642
const_reference front() const
Definition basic_string.h:603
ibasic_string & operator+=(const etl::basic_string_view< T, TOtherTraits > &rhs)
+= operator.
Definition basic_string.h:2391
pointer data()
Definition basic_string.h:633
size_type find_first_not_of(value_type c, size_type position=0) const
Definition basic_string.h:2227
ibasic_string & append(const_pointer str)
Definition basic_string.h:865
ibasic_string & append(size_type n, T c)
Definition basic_string.h:901
size_type find_first_not_of(const ibasic_string< T > &str, size_type position=0) const
Definition basic_string.h:2164
size_type find_last_of(value_type c, size_type position=npos) const
Definition basic_string.h:2134
size_type copy(pointer dest, size_type count, size_type pos=0) const
Definition basic_string.h:1405
ibasic_string & append(const ibasic_string &str)
Definition basic_string.h:821
size_type find_last_not_of(const etl::basic_string_view< T, TOtherTraits > &view, size_type position=npos) const
Definition basic_string.h:2269
ibasic_string & operator+=(T rhs)
+= operator.
Definition basic_string.h:2411
ibasic_string & replace(size_type position, size_type length_, const_pointer s)
Replace characters from 'position' of 'length' with pointed to string.
Definition basic_string.h:1777
reference front()
Definition basic_string.h:593
reference back()
Definition basic_string.h:613
bool starts_with(const_pointer s) const
Checks that the string is the start of this string.
Definition basic_string.h:1619
const_iterator cbegin() const
Definition basic_string.h:392
size_type find_first_not_of(const etl::basic_string_view< T, TOtherTraits > &view, size_type position=0) const
Definition basic_string.h:2185
int compare(size_type position, size_type length_, const etl::basic_string_view< T, TOtherTraits > &view, size_type subposition, size_type sublength) const
Definition basic_string.h:1950
void assign(size_type n, T c)
Definition basic_string.h:753
void initialise()
Initialise the string.
Definition basic_string.h:2465
bool starts_with(const etl::basic_string_view< T, TOtherTraits > &view) const
Checks that the view is the start of this string.
Definition basic_string.h:1611
ibasic_string & operator+=(const ibasic_string &rhs)
+= operator.
Definition basic_string.h:2380
void trim_to_terminator()
Definition basic_string.h:2441
void uninitialized_resize(size_type new_size)
Definition basic_string.h:523
int compare(size_type position, size_type length_, const_pointer s, size_type n) const
Compare position / length with C string / n.
Definition basic_string.h:1982
size_type rfind(const_pointer s, size_type position, size_type length_) const
Definition basic_string.h:1532
bool ends_with(const etl::ibasic_string< T > &str) const
Checks that the string is the end of this string.
Definition basic_string.h:1637
size_type find_first_of(const_pointer s, size_type position, size_type n) const
Definition basic_string.h:2024
int compare(const ibasic_string &str) const
Compare with string.
Definition basic_string.h:1894
const_iterator end() const
Definition basic_string.h:383
iterator erase(const_iterator i_element)
Definition basic_string.h:1348
int compare(size_type position, size_type length_, const etl::basic_string_view< T, TOtherTraits > &view) const
Compare position / length with etl::basic_string_view.
Definition basic_string.h:1925
etl::ibasic_string< T > & insert(size_type position, const_pointer s)
Definition basic_string.h:1271
void assign(const_pointer str)
Definition basic_string.h:722
void fill(T value)
Definition basic_string.h:536
void repair_buffer(T *p_buffer_)
Fix the internal pointers after a low level memory copy.
Definition basic_string.h:2477
iterator insert(const_iterator position, const etl::basic_string_view< T, TOtherTraits > &view)
Definition basic_string.h:1164
Definition basic_string.h:169
void set_secure()
Sets the 'secure' flag to the requested state.
Definition basic_string.h:275
bool is_secure() const
Gets the 'secure' state flag.
Definition basic_string.h:284
const size_type CAPACITY
The maximum number of elements in the string.
Definition basic_string.h:320
bool full() const
Definition basic_string.h:205
~string_base()
Destructor.
Definition basic_string.h:317
ETL_DEPRECATED bool truncated() const
Definition basic_string.h:256
void set_truncated(bool status)
Sets the 'truncated' flag.
Definition basic_string.h:308
size_type max_size() const
Definition basic_string.h:223
string_base(size_type max_size_)
Constructor.
Definition basic_string.h:298
void clear_truncated()
Clears the 'truncated' flag.
Definition basic_string.h:265
size_type length() const
Definition basic_string.h:187
size_type current_size
The current number of elements in the string.
Definition basic_string.h:319
size_type available() const
Definition basic_string.h:232
bool empty() const
Definition basic_string.h:196
size_type capacity() const
Definition basic_string.h:214
bool is_truncated() const
Definition basic_string.h:241
size_type size() const
Definition basic_string.h:178
Definition basic_string.h:86
Definition basic_string.h:114
Definition basic_string.h:100
Definition basic_string.h:128
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
Definition integral_limits.h:517
void memory_clear_range(volatile T *begin, size_t n)
Definition memory.h:2986
Definition basic_string.h:142
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1078
T * mem_move(const T *sb, const T *se, T *db) ETL_NOEXCEPT
Definition memory.h:3302
std::basic_ostream< T, std::char_traits< T > > & operator<<(std::basic_ostream< T, std::char_traits< T > > &os, const etl::ibasic_string< T > &str)
Definition basic_string.h:3198
etl::enable_if< etl::is_pointer< TPointer >::value &&!etl::is_const< TPointer >::value &&etl::is_integral< T >::value &&sizeof(T)==1, TPointer >::type mem_set(TPointer db, const TPointer de, T value) ETL_NOEXCEPT
Definition memory.h:3399
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1130
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1144
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
T * mem_copy(const T *sb, const T *se, T *db) ETL_NOEXCEPT
Definition memory.h:3260
ETL_CONSTEXPR14 size_t strlen(const T *t) ETL_NOEXCEPT
Alternative strlen for all character types.
Definition char_traits.h:293
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1103
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1117
iterator
Definition iterator.h:482
remove_pointer
Definition type_traits.h:147