Embedded Template Library 1.0
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 "iterator.h"
37#include "functional.h"
38#include "char_traits.h"
39#include "alignment.h"
40#include "array.h"
41#include "algorithm.h"
42#include "type_traits.h"
43#include "error_handler.h"
44#include "integral_limits.h"
45#include "exception.h"
46#include "memory.h"
47#include "exception.h"
48#include "binary.h"
49#include "flags.h"
50
51#include <stddef.h>
52#include <stdint.h>
53#include <string.h>
54
55#include "private/minmax_push.h"
56
57//*****************************************************************************
61//*****************************************************************************
62
63namespace etl
64{
65 //***************************************************************************
68 //***************************************************************************
70 {
71 public:
72
73 string_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
74 : exception(reason_, file_name_, line_number_)
75 {
76 }
77 };
78
79 //***************************************************************************
82 //***************************************************************************
84 {
85 public:
86
87 string_empty(string_type file_name_, numeric_type line_number_)
88 : string_exception(ETL_ERROR_TEXT("string:empty", ETL_BASIC_STRING_FILE_ID"A"), file_name_, line_number_)
89 {
90 }
91 };
92
93 //***************************************************************************
96 //***************************************************************************
98 {
99 public:
100
101 string_out_of_bounds(string_type file_name_, numeric_type line_number_)
102 : string_exception(ETL_ERROR_TEXT("string:bounds", ETL_BASIC_STRING_FILE_ID"B"), file_name_, line_number_)
103 {
104 }
105 };
106
107 //***************************************************************************
110 //***************************************************************************
112 {
113 public:
114
115 string_iterator(string_type file_name_, numeric_type line_number_)
116 : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_BASIC_STRING_FILE_ID"C"), file_name_, line_number_)
117 {
118 }
119 };
120
121 //***************************************************************************
124 //***************************************************************************
126 {
127 public:
128
129 string_truncation(string_type file_name_, numeric_type line_number_)
130 : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_BASIC_STRING_FILE_ID"D"), file_name_, line_number_)
131 {
132 }
133 };
134
135 //***************************************************************************
138 //***************************************************************************
139 namespace private_basic_string
140 {
141 //*************************************************************************
142 template <typename T = void>
144 {
145 public:
146
147 typedef size_t size_type;
148
149 static ETL_CONSTANT uint_least8_t IS_TRUNCATED = etl::bit<0>::value;
150 static ETL_CONSTANT uint_least8_t CLEAR_AFTER_USE = etl::bit<1>::value;
151
152 static ETL_CONSTANT size_type npos = etl::integral_limits<size_type>::max;
153 };
154
155 template <typename T>
156 ETL_CONSTANT uint_least8_t string_base_statics<T>::IS_TRUNCATED;
157
158 template <typename T>
159 ETL_CONSTANT uint_least8_t string_base_statics<T>::CLEAR_AFTER_USE;
160
161 template <typename T>
162 ETL_CONSTANT typename string_base_statics<T>::size_type string_base_statics<T>::npos;
163 }
164
165 //***************************************************************************
167 {
168 public:
169
170 typedef size_t size_type;
171
172 //*************************************************************************
175 //*************************************************************************
176 size_type size() const
177 {
178 return current_size;
179 }
180
181 //*************************************************************************
184 //*************************************************************************
185 size_type length() const
186 {
187 return current_size;
188 }
189
190 //*************************************************************************
193 //*************************************************************************
194 bool empty() const
195 {
196 return (current_size == 0);
197 }
198
199 //*************************************************************************
202 //*************************************************************************
203 bool full() const
204 {
205 return current_size == CAPACITY;
206 }
207
208 //*************************************************************************
211 //*************************************************************************
212 size_type capacity() const
213 {
214 return CAPACITY;
215 }
216
217 //*************************************************************************
220 //*************************************************************************
221 size_type max_size() const
222 {
223 return CAPACITY;
224 }
225
226 //*************************************************************************
229 //*************************************************************************
230 size_type available() const
231 {
232 return max_size() - size();
233 }
234
235#if ETL_HAS_STRING_TRUNCATION_CHECKS
236 //*************************************************************************
240 //*************************************************************************
241 ETL_DEPRECATED
242 bool truncated() const
243 {
244 return flags.test<IS_TRUNCATED>();
245 }
246
247 //*************************************************************************
250 //*************************************************************************
251 bool is_truncated() const
252 {
253 return flags.test<IS_TRUNCATED>();
254 }
255
256 //*************************************************************************
258 //*************************************************************************
260 {
261 flags.set<IS_TRUNCATED, false>();
262 }
263#endif
264
265#if ETL_HAS_STRING_CLEAR_AFTER_USE
266 //*************************************************************************
268 //*************************************************************************
270 {
271 flags.set<CLEAR_AFTER_USE>();
272 }
273
274 //*************************************************************************
276 //*************************************************************************
277 bool is_secure() const
278 {
279 return flags.test<CLEAR_AFTER_USE>();
280 }
281#endif
282
283 protected:
284
285 //*************************************************************************
287 //*************************************************************************
288 string_base(size_type max_size_)
289 : current_size(0)
290 , CAPACITY(max_size_)
291 {
292 }
293
294#if ETL_HAS_STRING_TRUNCATION_CHECKS
295 //*************************************************************************
297 //*************************************************************************
298 void set_truncated(bool status)
299 {
300 flags.set<IS_TRUNCATED>(status);
301 }
302#endif
303
304 //*************************************************************************
306 //*************************************************************************
308 {
309 }
310
311 size_type current_size;
312 const size_type CAPACITY;
313
314#if ETL_HAS_STRING_TRUNCATION_CHECKS || ETL_HAS_STRING_CLEAR_AFTER_USE
316#endif
317 };
318
319 //***************************************************************************
323 //***************************************************************************
324 template <typename T>
326 {
327 public:
328
330
331 typedef T value_type;
332 typedef T& reference;
333 typedef const T& const_reference;
334 typedef T* pointer;
335 typedef const T* const_pointer;
336 typedef T* iterator;
337 typedef const T* const_iterator;
338 typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
339 typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
340
341 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
342
343 //*********************************************************************
346 //*********************************************************************
347 iterator begin()
348 {
349 return &p_buffer[0];
350 }
351
352 //*********************************************************************
355 //*********************************************************************
356 const_iterator begin() const
357 {
358 return &p_buffer[0];
359 }
360
361 //*********************************************************************
364 //*********************************************************************
365 iterator end()
366 {
367 return &p_buffer[current_size];
368 }
369
370 //*********************************************************************
373 //*********************************************************************
374 const_iterator end() const
375 {
376 return &p_buffer[current_size];
377 }
378
379 //*********************************************************************
382 //*********************************************************************
383 const_iterator cbegin() const
384 {
385 return &p_buffer[0];
386 }
387
388 //*********************************************************************
391 //*********************************************************************
392 const_iterator cend() const
393 {
394 return &p_buffer[current_size];
395 }
396
397 //*********************************************************************
400 //*********************************************************************
401 reverse_iterator rbegin()
402 {
403 return reverse_iterator(end());
404 }
405
406 //*********************************************************************
409 //*********************************************************************
410 const_reverse_iterator rbegin() const
411 {
412 return const_reverse_iterator(end());
413 }
414
415 //*********************************************************************
418 //*********************************************************************
419 reverse_iterator rend()
420 {
421 return reverse_iterator(begin());
422 }
423
424 //*********************************************************************
427 //*********************************************************************
428 const_reverse_iterator rend() const
429 {
430 return const_reverse_iterator(begin());
431 }
432
433 //*********************************************************************
436 //*********************************************************************
437 const_reverse_iterator crbegin() const
438 {
439 return const_reverse_iterator(cend());
440 }
441
442 //*********************************************************************
445 //*********************************************************************
446 const_reverse_iterator crend() const
447 {
448 return const_reverse_iterator(cbegin());
449 }
450
451 //*********************************************************************
455 //*********************************************************************
456 void resize(size_type new_size)
457 {
458 resize(new_size, 0);
459 }
460
461 //*********************************************************************
465 //*********************************************************************
466 void resize(size_type new_size, T value)
467 {
468 if (new_size > CAPACITY)
469 {
470#if ETL_HAS_STRING_TRUNCATION_CHECKS
471 set_truncated(true);
472
473#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
474 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
475#endif
476#endif
477 }
478
479 new_size = etl::min(new_size, CAPACITY);
480
481 // Size up?
482 if (new_size > current_size)
483 {
484 etl::fill(p_buffer + current_size, p_buffer + new_size, value);
485 }
486
487 current_size = new_size;
488 p_buffer[new_size] = 0;
489 cleanup();
490 }
491
492 //*********************************************************************
496 //*********************************************************************
497 void uninitialized_resize(size_type new_size)
498 {
499 new_size = etl::min(new_size, CAPACITY);
500
501 current_size = new_size;
502 p_buffer[new_size] = 0;
503 }
504
505 //*********************************************************************
509 //*********************************************************************
510 reference operator [](size_type i)
511 {
512 return p_buffer[i];
513 }
514
515 //*********************************************************************
519 //*********************************************************************
520 const_reference operator [](size_type i) const
521 {
522 return p_buffer[i];
523 }
524
525 //*********************************************************************
530 //*********************************************************************
531 reference at(size_type i)
532 {
533 ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
534 return p_buffer[i];
535 }
536
537 //*********************************************************************
542 //*********************************************************************
543 const_reference at(size_type i) const
544 {
545 ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
546 return p_buffer[i];
547 }
548
549 //*********************************************************************
552 //*********************************************************************
553 reference front()
554 {
555 return p_buffer[0];
556 }
557
558 //*********************************************************************
561 //*********************************************************************
562 const_reference front() const
563 {
564 return p_buffer[0];
565 }
566
567 //*********************************************************************
570 //*********************************************************************
571 reference back()
572 {
573 return p_buffer[current_size - 1];
574 }
575
576 //*********************************************************************
579 //*********************************************************************
580 const_reference back() const
581 {
582 return p_buffer[current_size - 1];
583 }
584
585 //*********************************************************************
588 //*********************************************************************
589 pointer data()
590 {
591 return p_buffer;
592 }
593
594 //*********************************************************************
597 //*********************************************************************
598 const_pointer data() const
599 {
600 return p_buffer;
601 }
602
603 //*********************************************************************
606 //*********************************************************************
607 pointer data_end()
608 {
609 return p_buffer + current_size;
610 }
611
612 //*********************************************************************
615 //*********************************************************************
616 const_pointer data_end() const
617 {
618 return p_buffer + current_size;
619 }
620
621 //*********************************************************************
625 //*********************************************************************
626 void assign(const etl::ibasic_string<T>& other)
627 {
628 assign(other.begin(), other.end());
629
630#if ETL_HAS_STRING_TRUNCATION_CHECKS
631 if (other.is_truncated())
632 {
633 set_truncated(true);
634
635#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
636 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
637#endif
638 }
639#endif
640
641#if ETL_HAS_STRING_CLEAR_AFTER_USE
642 if (other.is_secure())
643 {
644 set_secure();
645 }
646#endif
647
648 cleanup();
649 }
650
651 //*********************************************************************
657 //*********************************************************************
658 void assign(const etl::ibasic_string<T>& other, size_type subposition, size_type sublength)
659 {
660 if (sublength == npos)
661 {
662 sublength = other.size() - subposition;
663 }
664
665 ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds));
666
667 assign(other.begin() + subposition, sublength);
668
669#if ETL_HAS_STRING_TRUNCATION_CHECKS
670 if (other.is_truncated())
671 {
672 this->set_truncated(true);
673
674#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
675 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
676#endif
677 }
678#endif
679
680#if ETL_HAS_STRING_CLEAR_AFTER_USE
681 if (other.is_secure())
682 {
683 set_secure();
684 }
685#endif
686 }
687
688 //*********************************************************************
692 //*********************************************************************
693 void assign(const_pointer other)
694 {
695 initialise();
696
697 while ((*other != 0) && (current_size < CAPACITY))
698 {
699 p_buffer[current_size++] = *other++;
700 }
701
702#if ETL_HAS_STRING_TRUNCATION_CHECKS
703 set_truncated(*other != 0);
704
705#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
706 ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
707#endif
708#endif
709
710 p_buffer[current_size] = 0;
711 }
712
713 //*********************************************************************
718 //*********************************************************************
719 void assign(const_pointer other, size_type length_)
720 {
721 initialise();
722
723#if ETL_HAS_STRING_TRUNCATION_CHECKS
724 set_truncated(length_ > CAPACITY);
725
726#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
727 ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
728#endif
729#endif
730
731 length_ = etl::min(length_, CAPACITY);
732
733 etl::copy_n(other, length_, begin());
734
735 current_size = length_;
736 p_buffer[current_size] = 0;
737 }
738
739 //*********************************************************************
745 //*********************************************************************
746 template <typename TIterator>
747 void assign(TIterator first, TIterator last)
748 {
749#if ETL_IS_DEBUG_BUILD
750 difference_type d = etl::distance(first, last);
751 ETL_ASSERT(d >= 0, ETL_ERROR(string_iterator));
752#endif
753
754 initialise();
755
756 while ((first != last) && (current_size != CAPACITY))
757 {
758 p_buffer[current_size++] = *first++;
759 }
760
761 p_buffer[current_size] = 0;
762
763#if ETL_HAS_STRING_TRUNCATION_CHECKS
764 set_truncated(first != last);
765
766#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
767 ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
768#endif
769#endif
770 }
771
772 //*********************************************************************
777 //*********************************************************************
778 void assign(size_type n, T value)
779 {
780 initialise();
781
782#if ETL_HAS_STRING_TRUNCATION_CHECKS
784
785#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
786 ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
787#endif
788#endif
789
790 n = etl::min(n, CAPACITY);
791
792 etl::fill_n(begin(), n, value);
793 current_size = n;
794 p_buffer[current_size] = 0;
795 }
796
797 //*************************************************************************
799 //*************************************************************************
800 void clear()
801 {
802 initialise();
803 }
804
805 //*********************************************************************
809 //*********************************************************************
810 void push_back(T value)
811 {
812 if (current_size != CAPACITY)
813 {
814 p_buffer[current_size++] = value;
815 p_buffer[current_size] = 0;
816 }
817 else
818 {
819#if ETL_HAS_STRING_TRUNCATION_CHECKS
820 set_truncated(true);
821
822#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
823 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
824#endif
825#endif
826 }
827 }
828
829 //*************************************************************************
832 //*************************************************************************
833 void pop_back()
834 {
835 if (current_size != 0)
836 {
837 p_buffer[--current_size] = 0;
838 }
839 }
840
841 //*********************************************************************
844 //*********************************************************************
846 {
847 insert(end(), str.begin(), str.end());
848
849#if ETL_HAS_STRING_TRUNCATION_CHECKS
850 if (str.is_truncated())
851 {
852 set_truncated(true);
853
854#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
855 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
856#endif
857 }
858#endif
859
860 return *this;
861 }
862
863 //*********************************************************************
868 //*********************************************************************
869 ibasic_string& append(const ibasic_string& str, size_type subposition, size_type sublength = npos)
870 {
871 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
872
873 insert(size(), str, subposition, sublength);
874
875 return *this;
876 }
877
878 //*********************************************************************
881 //*********************************************************************
882 ibasic_string& append(const T* str)
883 {
884 insert(size(), str);
885 return *this;
886 }
887
888 //*********************************************************************
892 //*********************************************************************
893 ibasic_string& append(const T* str, size_type n)
894 {
895 insert(size(), str, n);
896 return *this;
897 }
898
899 //*********************************************************************
903 //*********************************************************************
904 ibasic_string& append(size_type n, T c)
905 {
906 insert(size(), n, c);
907 return *this;
908 }
909
910 //*********************************************************************
914 //*********************************************************************
915 template <class TIterator>
916 ibasic_string& append(TIterator first, TIterator last)
917 {
918 insert(end(), first, last);
919 return *this;
920 }
921
922 //*********************************************************************
926 //*********************************************************************
927 iterator insert(const_iterator position, T value)
928 {
929 // Quick hack, as iterators are pointers.
930 iterator insert_position = to_iterator(position);
931
933 {
934 // Not full yet.
935 if (position != end())
936 {
937 // Insert in the middle.
938 ++current_size;
939 etl::copy_backward(insert_position, end() - 1, end());
940 *insert_position = value;
941 }
942 else
943 {
944 // Insert at the end.
945 *insert_position = value;
946 ++current_size;
947 }
948 }
949 else
950 {
951 // Already full.
952 if (position != end())
953 {
954 // Insert in the middle.
955 etl::copy_backward(insert_position, end() - 1, end());
956 *insert_position = value;
957 }
958
959#if ETL_HAS_STRING_TRUNCATION_CHECKS
960 set_truncated(true);
961
962#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
963 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
964#endif
965#endif
966 }
967
968 p_buffer[current_size] = 0;
969
970 return insert_position;
971 }
972
973 //*********************************************************************
978 //*********************************************************************
979 iterator insert(const_iterator position, size_type n, T value)
980 {
981 iterator position_ = to_iterator(position);
982
983 if (n == 0)
984 {
985 return position_;
986 }
987
988 // Quick hack, as iterators are pointers.
989 iterator insert_position = to_iterator(position);
990 const size_type start = etl::distance(cbegin(), position);
991
992 // No effect.
993 if (start >= CAPACITY)
994 {
995#if ETL_HAS_STRING_TRUNCATION_CHECKS
996 set_truncated(true);
997
998#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
999 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1000#endif
1001#endif
1002 return to_iterator(position);;
1003 }
1004
1005 // Fills the string to the end?
1006 if ((start + n) >= CAPACITY)
1007 {
1008 if ((current_size + n) > CAPACITY)
1009 {
1010#if ETL_HAS_STRING_TRUNCATION_CHECKS
1011 set_truncated(true);
1012
1013#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1014 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1015#endif
1016#endif
1017 }
1018
1020 etl::fill(insert_position, end(), value);
1021 }
1022 else
1023 {
1024 // Lets do some shifting.
1025 const size_type shift_amount = n;
1026 const size_type to_position = start + shift_amount;
1027 const size_type remaining_characters = current_size - start;
1028 const size_type max_shift_characters = CAPACITY - start - shift_amount;
1029 const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters);
1030
1031 // Will the string truncate?
1032 if ((start + shift_amount + remaining_characters) > CAPACITY)
1033 {
1035
1036#if ETL_HAS_STRING_TRUNCATION_CHECKS
1037 set_truncated(true);
1038
1039#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1040 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1041#endif
1042#endif
1043 }
1044 else
1045 {
1046 current_size += shift_amount;
1047 }
1048
1049 etl::copy_backward(insert_position, insert_position + characters_to_shift, begin() + to_position + characters_to_shift);
1050 etl::fill(insert_position, insert_position + shift_amount, value);
1051 }
1052
1053 p_buffer[current_size] = 0;
1054
1055 return position_;
1056 }
1057
1058 //*********************************************************************
1064 //*********************************************************************
1065 template <typename TIterator>
1066 iterator insert(const_iterator position, TIterator first, TIterator last)
1067 {
1068 iterator position_ = to_iterator(position);
1069
1070 if (first == last)
1071 {
1072 return position_;
1073 }
1074
1075 const size_type start = etl::distance(begin(), position_);
1076 const size_type n = etl::distance(first, last);
1077
1078 // No effect.
1079 if (start >= CAPACITY)
1080 {
1081#if ETL_HAS_STRING_TRUNCATION_CHECKS
1082 set_truncated(true);
1083
1084#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1085 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1086#endif
1087#endif
1088 return position_;
1089 }
1090
1091 // Fills the string to the end?
1092 if ((start + n) >= CAPACITY)
1093 {
1094 if (((current_size + n) > CAPACITY))
1095 {
1096#if ETL_HAS_STRING_TRUNCATION_CHECKS
1097 set_truncated(true);
1098
1099#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1100 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1101#endif
1102#endif
1103 }
1104
1106
1107 while (position_ != end())
1108 {
1109 *position_++ = *first++;
1110 }
1111 }
1112 else
1113 {
1114 // Lets do some shifting.
1115 const size_type shift_amount = n;
1116 const size_type to_position = start + shift_amount;
1117 const size_type remaining_characters = current_size - start;
1118 const size_type max_shift_characters = CAPACITY - start - shift_amount;
1119 const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters);
1120
1121 // Will the string truncate?
1122 if ((start + shift_amount + remaining_characters) > CAPACITY)
1123 {
1125
1126#if ETL_HAS_STRING_TRUNCATION_CHECKS
1127 set_truncated(true);
1128
1129#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1130 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1131#endif
1132#endif
1133 }
1134 else
1135 {
1136 current_size += shift_amount;
1137 }
1138
1139 etl::copy_backward(position_, position_ + characters_to_shift, begin() + to_position + characters_to_shift);
1140
1141 while (first != last)
1142 {
1143 *position_++ = *first++;
1144 }
1145 }
1146
1147 p_buffer[current_size] = 0;
1148
1149 return position_;
1150 }
1151
1152 //*********************************************************************
1156 //*********************************************************************
1157 etl::ibasic_string<T>& insert(size_type position, const etl::ibasic_string<T>& str)
1158 {
1159 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1160
1161 insert(begin() + position, str.cbegin(), str.cend());
1162
1163#if ETL_HAS_STRING_TRUNCATION_CHECKS
1164 if (str.is_truncated())
1165 {
1166 set_truncated(true);
1167
1168#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1169 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1170#endif
1171 }
1172#endif
1173
1174 return *this;
1175 }
1176
1177 //*********************************************************************
1183 //*********************************************************************
1184 etl::ibasic_string<T>& insert(size_type position, const etl::ibasic_string<T>& str, size_type subposition, size_type sublength)
1185 {
1186 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1187 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1188
1189 if ((sublength == npos) || (subposition + sublength > str.size()))
1190 {
1191 sublength = str.size() - subposition;
1192 }
1193
1194 insert(begin() + position, str.cbegin() + subposition, str.cbegin() + subposition + sublength);
1195
1196#if ETL_HAS_STRING_TRUNCATION_CHECKS
1197 if (str.is_truncated())
1198 {
1199 set_truncated(true);
1200
1201#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1202 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1203#endif
1204 }
1205#endif
1206
1207 return *this;
1208 }
1209
1210 //*********************************************************************
1214 //*********************************************************************
1215 etl::ibasic_string<T>& insert(size_type position, const_pointer s)
1216 {
1217 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1218
1219 insert(begin() + position, s, s + etl::strlen(s));
1220 return *this;
1221 }
1222
1223 //*********************************************************************
1228 //*********************************************************************
1229 etl::ibasic_string<T>& insert(size_type position, const_pointer s, size_type n)
1230 {
1231 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1232
1233 insert(begin() + position, s, s + n);
1234 return *this;
1235 }
1236
1237 //*********************************************************************
1242 //*********************************************************************
1243 etl::ibasic_string<T>& insert(size_type position, size_type n, value_type c)
1244 {
1245 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1246
1247 insert(begin() + position, n, c);
1248 return *this;
1249 }
1250
1251 //*********************************************************************
1256 //*********************************************************************
1257 etl::ibasic_string<T>& erase(size_type position, size_type length_ = npos)
1258 {
1259 // Limit the length.
1260 length_ = etl::min(length_, size() - position);
1261
1262 erase(begin() + position, begin() + position + length_);
1263
1264 return *this;
1265 }
1266
1267 //*********************************************************************
1271 //*********************************************************************
1272 iterator erase(iterator i_element)
1273 {
1274 etl::copy(i_element + 1, end(), i_element);
1275 p_buffer[--current_size] = 0;
1276
1277 return i_element;
1278 }
1279
1280 //*********************************************************************
1284 //*********************************************************************
1285 iterator erase(const_iterator i_element)
1286 {
1287 iterator i_element_(to_iterator(i_element));
1288
1289 etl::copy(i_element_ + 1, end(), i_element_);
1290 p_buffer[--current_size] = 0;
1291
1292 return i_element_;
1293 }
1294
1295 //*********************************************************************
1302 //*********************************************************************
1303 iterator erase(const_iterator first, const_iterator last)
1304 {
1305 iterator first_ = to_iterator(first);
1306 iterator last_ = to_iterator(last);
1307
1308 if (first_ == last_)
1309 {
1310 return first_;
1311 }
1312
1313 etl::copy(last_, end(), first_);
1314 size_type n_delete = etl::distance(first_, last_);
1315
1316 current_size -= n_delete;
1317 p_buffer[current_size] = 0;
1318 cleanup();
1319
1320 return first_;
1321 }
1322
1323 //*********************************************************************
1325 //*********************************************************************
1326 const_pointer c_str() const
1327 {
1328 return p_buffer;
1329 }
1330
1331 //*********************************************************************
1336 //*********************************************************************
1337 size_type copy(pointer dest, size_type count, size_type pos = 0) const
1338 {
1339 if (pos < size())
1340 {
1341 if (count != npos)
1342 {
1343 count = etl::min(count, size() - pos);
1344 }
1345 else
1346 {
1347 count = size() - pos;
1348 }
1349
1350 etl::copy_n(p_buffer + pos, count, dest);
1351
1352 return count;
1353 }
1354 else
1355 {
1356 return 0U;
1357 }
1358 }
1359
1360 //*********************************************************************
1364 //*********************************************************************
1365 size_type find(const ibasic_string<T>& str, size_type pos = 0) const
1366 {
1367 if ((pos + str.size()) > size())
1368 {
1369 return npos;
1370 }
1371
1372 const_iterator iposition = etl::search(begin() + pos, end(), str.begin(), str.end());
1373
1374 if (iposition == end())
1375 {
1376 return npos;
1377 }
1378 else
1379 {
1380 return etl::distance(begin(), iposition);
1381 }
1382 }
1383
1384 //*********************************************************************
1388 //*********************************************************************
1389 size_type find(const_pointer s, size_type pos = 0) const
1390 {
1391#if ETL_IS_DEBUG_BUILD
1392 if ((pos + etl::strlen(s)) > size())
1393 {
1394 return npos;
1395 }
1396#endif
1397
1398 const_iterator iposition = etl::search(begin() + pos, end(), s, s + etl::strlen(s));
1399
1400 if (iposition == end())
1401 {
1402 return npos;
1403 }
1404 else
1405 {
1406 return etl::distance(begin(), iposition);
1407 }
1408 }
1409
1410 //*********************************************************************
1415 //*********************************************************************
1416 size_type find(const_pointer s, size_type pos, size_type n) const
1417 {
1418#if ETL_IS_DEBUG_BUILD
1419 if ((pos + etl::strlen(s) - n) > size())
1420 {
1421 return npos;
1422 }
1423#endif
1424
1425 const_iterator iposition = etl::search(begin() + pos, end(), s, s + n);
1426
1427 if (iposition == end())
1428 {
1429 return npos;
1430 }
1431 else
1432 {
1433 return etl::distance(begin(), iposition);
1434 }
1435 }
1436
1437 //*********************************************************************
1441 //*********************************************************************
1442 size_type find(T c, size_type position = 0) const
1443 {
1444 const_iterator i = etl::find(begin() + position, end(), c);
1445
1446 if (i != end())
1447 {
1448 return etl::distance(begin(), i);
1449 }
1450 else
1451 {
1452 return npos;
1453 }
1454 }
1455
1456 //*********************************************************************
1460 //*********************************************************************
1461 size_type rfind(const ibasic_string<T>& str, size_type position = npos) const
1462 {
1463 if ((str.size()) > size())
1464 {
1465 return npos;
1466 }
1467
1468 if (position >= size())
1469 {
1470 position = size();
1471 }
1472
1473 position = size() - position;
1474
1475 const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), str.rbegin(), str.rend());
1476
1477 if (iposition == rend())
1478 {
1479 return npos;
1480 }
1481 else
1482 {
1483 return size() - str.size() - etl::distance(rbegin(), iposition);
1484 }
1485 }
1486
1487 //*********************************************************************
1491 //*********************************************************************
1492 size_type rfind(const_pointer s, size_type position = npos) const
1493 {
1494 size_type len = etl::strlen(s);
1495
1496 if (len > size())
1497 {
1498 return npos;
1499 }
1500
1501 if (position >= size())
1502 {
1503 position = size();
1504 }
1505
1506 position = size() - position;
1507
1508 const_reverse_iterator srbegin(s + len);
1509 const_reverse_iterator srend(s);
1510
1511 const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), srbegin, srend);
1512
1513 if (iposition == rend())
1514 {
1515 return npos;
1516 }
1517 else
1518 {
1519 return size() - len - etl::distance(rbegin(), iposition);
1520 }
1521 }
1522
1523 //*********************************************************************
1527 //*********************************************************************
1528 size_type rfind(const_pointer s, size_type position, size_type length_) const
1529 {
1530 if (length_ > size())
1531 {
1532 return npos;
1533 }
1534
1535 if (position >= size())
1536 {
1537 position = size();
1538 }
1539
1540 position = size() - position;
1541
1542 const_reverse_iterator srbegin(s + length_);
1543 const_reverse_iterator srend(s);
1544
1545 const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), srbegin, srend);
1546
1547 if (iposition == rend())
1548 {
1549 return npos;
1550 }
1551 else
1552 {
1553 return size() - length_ - etl::distance(rbegin(), iposition);
1554 }
1555 }
1556
1557 //*********************************************************************
1561 //*********************************************************************
1562 size_type rfind(T c, size_type position = npos) const
1563 {
1564 if (position >= size())
1565 {
1566 position = size();
1567 }
1568
1569 position = size() - position;
1570
1571 const_reverse_iterator i = etl::find(rbegin() + position, rend(), c);
1572
1573 if (i != rend())
1574 {
1575 return size() - etl::distance(rbegin(), i) - 1;
1576 }
1577 else
1578 {
1579 return npos;
1580 }
1581 }
1582
1583 //*********************************************************************
1588 //*********************************************************************
1589 ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str)
1590 {
1591 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1592
1593 // Limit the length.
1594 length_ = etl::min(length_, size() - position);
1595
1596 // Erase the bit we want to replace.
1597 erase(position, length_);
1598
1599 // Insert the new stuff.
1600 insert(position, str);
1601
1602 return *this;
1603 }
1604
1605 //*********************************************************************
1610 //*********************************************************************
1611 ibasic_string& replace(const_iterator first, const_iterator last, const ibasic_string& str)
1612 {
1613 // Quick hack, as iterators are pointers.
1614 iterator first_ = to_iterator(first);
1615 iterator last_ = to_iterator(last);
1616
1617 // Erase the bit we want to replace.
1618 erase(first_, last_);
1619
1620 // Insert the new stuff.
1621 insert(first_, str.begin(), str.end());
1622
1623#if ETL_HAS_STRING_TRUNCATION_CHECKS
1624 if (str.is_truncated())
1625 {
1626 set_truncated(true);
1627
1628#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1629 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1630#endif
1631 }
1632#endif
1633
1634 return *this;
1635 }
1636
1637 //*********************************************************************
1639 //*********************************************************************
1640 ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength)
1641 {
1642 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1643 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1644
1645 // Limit the lengths.
1646 length_ = etl::min(length_, size() - position);
1647 sublength = etl::min(sublength, str.size() - subposition);
1648
1649 // Erase the bit we want to replace.
1650 erase(position, length_);
1651
1652 // Insert the new stuff.
1653 insert(position, str, subposition, sublength);
1654
1655#if ETL_HAS_STRING_TRUNCATION_CHECKS
1656 if (str.is_truncated())
1657 {
1658 set_truncated(true);
1659
1660#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
1661 ETL_ASSERT_FAIL(ETL_ERROR(string_truncation));
1662#endif
1663 }
1664#endif
1665
1666 return *this;
1667 }
1668
1669 //*********************************************************************
1671 //*********************************************************************
1672 ibasic_string& replace(size_type position, size_type length_, const_pointer s)
1673 {
1674 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1675
1676 // Limit the length.
1677 length_ = etl::min(length_, size() - position);
1678
1679 // Erase the bit we want to replace.
1680 erase(position, length_);
1681
1682 // Insert the new stuff.
1683 insert(position, s, etl::strlen(s));
1684
1685 return *this;
1686 }
1687
1688 //*********************************************************************
1690 //*********************************************************************
1691 ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s)
1692 {
1693 // Quick hack, as iterators are pointers.
1694 iterator first_ = to_iterator(first);
1695 iterator last_ = to_iterator(last);
1696
1697 // Erase the bit we want to replace.
1698 erase(first_, last_);
1699
1700 // Insert the new stuff.
1701 insert(first_, s, s + etl::strlen(s));
1702
1703 return *this;
1704 }
1705
1706 //*********************************************************************
1708 //*********************************************************************
1709 ibasic_string& replace(size_type position, size_type length_, const_pointer s, size_type n)
1710 {
1711 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1712
1713 // Limit the length.
1714 length_ = etl::min(length_, size() - position);
1715
1716 // Erase the bit we want to replace.
1717 erase(position, length_);
1718
1719 // Insert the new stuff.
1720 insert(position, s, n);
1721
1722 return *this;
1723 }
1724
1725 //*********************************************************************
1727 //*********************************************************************
1728 ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s, size_type n)
1729 {
1730 // Quick hack, as iterators are pointers.
1731 iterator first_ = to_iterator(first);
1732 iterator last_ = to_iterator(last);
1733
1734 // Erase the bit we want to replace.
1735 erase(first_, last_);
1736
1737 // Insert the new stuff.
1738 insert(first_, s, s + n);
1739
1740 return *this;
1741 }
1742
1743 //*********************************************************************
1745 //*********************************************************************
1746 ibasic_string& replace(size_type position, size_type length_, size_type n, value_type c)
1747 {
1748 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1749
1750 // Limit the length.
1751 length_ = etl::min(length_, size() - position);
1752
1753 // Erase the bit we want to replace.
1754 erase(position, length_);
1755
1756 // Insert the new stuff.
1757 insert(position, n, c);
1758
1759 return *this;
1760 }
1761
1762 //*********************************************************************
1764 //*********************************************************************
1765 ibasic_string& replace(const_iterator first, const_iterator last, size_type n, value_type c)
1766 {
1767 // Quick hack, as iterators are pointers.
1768 iterator first_ = to_iterator(first);
1769 iterator last_ = to_iterator(last);
1770
1771 // Erase the bit we want to replace.
1772 erase(first_, last_);
1773
1774 // Insert the new stuff.
1775 insert(first_, n, c);
1776
1777 return *this;
1778 }
1779
1780 //*********************************************************************
1782 //*********************************************************************
1783 template <typename TIterator>
1784 ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace)
1785 {
1786 // Quick hack, as iterators are pointers.
1787 iterator first_ = to_iterator(first);
1788 iterator last_ = to_iterator(last);
1789
1790 // Erase the bit we want to replace.
1791 erase(first_, last_);
1792
1793 // Insert the new stuff.
1794 insert(first_, first_replace, last_replace);
1795
1796 return *this;
1797 }
1798
1799 //*************************************************************************
1801 //*************************************************************************
1802 int compare(const ibasic_string& str) const
1803 {
1804 return compare(p_buffer,
1805 p_buffer + size(),
1806 str.p_buffer,
1807 str.p_buffer + str.size());
1808 }
1809
1810 //*************************************************************************
1812 //*************************************************************************
1813 int compare(size_type position, size_type length_, const ibasic_string& str) const
1814 {
1815 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1816
1817 // Limit the length.
1818 length_ = etl::min(length_, size() - position);
1819
1820 return compare(p_buffer + position,
1821 p_buffer + position + length_,
1822 str.p_buffer,
1823 str.p_buffer + str.size());
1824 }
1825
1826 //*************************************************************************
1828 //*************************************************************************
1829 int compare(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength) const
1830 {
1831 ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1832 ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1833
1834 // Limit the lengths.
1835 length_ = etl::min(length_, size() - position);
1836 sublength = etl::min(sublength, str.size() - subposition);
1837
1838 return compare(p_buffer + position,
1839 p_buffer + position + length_,
1840 str.p_buffer + subposition,
1841 str.p_buffer + subposition + sublength);
1842 }
1843
1844 //*************************************************************************
1846 //*************************************************************************
1847 int compare(const value_type* s) const
1848 {
1849 return compare(p_buffer,
1850 p_buffer + size(),
1851 s,
1852 s + etl::strlen(s));
1853 }
1854
1855 //*************************************************************************
1857 //*************************************************************************
1858 int compare(size_type position, size_type length_, const_pointer s) const
1859 {
1860 return compare(p_buffer + position,
1861 p_buffer + position + length_,
1862 s,
1863 s + etl::strlen(s));
1864 }
1865
1866 //*************************************************************************
1868 //*************************************************************************
1869 int compare(size_type position, size_type length_, const_pointer s, size_type n) const
1870 {
1871 return compare(p_buffer + position,
1872 p_buffer + position + length_,
1873 s,
1874 s + n);
1875 }
1876
1877 //*********************************************************************
1881 //*********************************************************************
1882 size_type find_first_of(const ibasic_string<T>& str, size_type position = 0) const
1883 {
1884 return find_first_of(str.c_str(), position, str.size());
1885 }
1886
1887 //*********************************************************************
1891 //*********************************************************************
1892 size_type find_first_of(const_pointer s, size_type position = 0) const
1893 {
1894 return find_first_of(s, position, etl::strlen(s));
1895 }
1896
1897 //*********************************************************************
1902 //*********************************************************************
1903 size_type find_first_of(const_pointer s, size_type position, size_type n) const
1904 {
1905 if (position < size())
1906 {
1907 for (size_type i = position; i < size(); ++i)
1908 {
1909 for (size_type j = 0; j < n; ++j)
1910 {
1911 if (p_buffer[i] == s[j])
1912 {
1913 return i;
1914 }
1915 }
1916 }
1917 }
1918
1919 return npos;
1920 }
1921
1922 //*********************************************************************
1926 //*********************************************************************
1927 size_type find_first_of(value_type c, size_type position = 0) const
1928 {
1929 if (position < size())
1930 {
1931 for (size_type i = position; i < size(); ++i)
1932 {
1933 if (p_buffer[i] == c)
1934 {
1935 return i;
1936 }
1937 }
1938 }
1939
1940 return npos;
1941 }
1942
1943 //*********************************************************************
1947 //*********************************************************************
1948 size_type find_last_of(const ibasic_string<T>& str, size_type position = npos) const
1949 {
1950 return find_last_of(str.c_str(), position, str.size());
1951 }
1952
1953 //*********************************************************************
1957 //*********************************************************************
1958 size_type find_last_of(const_pointer s, size_type position = npos) const
1959 {
1960 return find_last_of(s, position, etl::strlen(s));
1961 }
1962
1963 //*********************************************************************
1968 //*********************************************************************
1969 size_type find_last_of(const_pointer s, size_type position, size_type n) const
1970 {
1971 if (empty())
1972 {
1973 return npos;
1974 }
1975
1976 position = etl::min(position, size() - 1);
1977
1978 const_reverse_iterator it = rbegin() + size() - position - 1;
1979
1980 while (it != rend())
1981 {
1982 for (size_type j = 0; j < n; ++j)
1983 {
1984 if (p_buffer[position] == s[j])
1985 {
1986 return position;
1987 }
1988 }
1989
1990 ++it;
1991 --position;
1992 }
1993
1994 return npos;
1995 }
1996
1997 //*********************************************************************
2001 //*********************************************************************
2002 size_type find_last_of(value_type c, size_type position = npos) const
2003 {
2004 if (empty())
2005 {
2006 return npos;
2007 }
2008
2009 position = etl::min(position, size() - 1);
2010
2011 const_reverse_iterator it = rbegin() + size() - position - 1;
2012
2013 while (it != rend())
2014 {
2015 if (p_buffer[position] == c)
2016 {
2017 return position;
2018 }
2019
2020 ++it;
2021 --position;
2022 }
2023
2024 return npos;
2025 }
2026
2027 //*********************************************************************
2031 //*********************************************************************
2032 size_type find_first_not_of(const ibasic_string<T>& str, size_type position = 0) const
2033 {
2034 return find_first_not_of(str.c_str(), position, str.size());
2035 }
2036
2037 //*********************************************************************
2041 //*********************************************************************
2042 size_type find_first_not_of(const_pointer s, size_type position = 0) const
2043 {
2044 return find_first_not_of(s, position, etl::strlen(s));
2045 }
2046
2047 //*********************************************************************
2052 //*********************************************************************
2053 size_type find_first_not_of(const_pointer s, size_type position, size_type n) const
2054 {
2055 if (position < size())
2056 {
2057 for (size_type i = position; i < size(); ++i)
2058 {
2059 bool found = false;
2060
2061 for (size_type j = 0; j < n; ++j)
2062 {
2063 if (p_buffer[i] == s[j])
2064 {
2065 found = true;
2066 }
2067 }
2068
2069 if (!found)
2070 {
2071 return i;
2072 }
2073 }
2074 }
2075
2076 return npos;
2077 }
2078
2079 //*********************************************************************
2083 //*********************************************************************
2084 size_type find_first_not_of(value_type c, size_type position = 0) const
2085 {
2086 if (position < size())
2087 {
2088 for (size_type i = position; i < size(); ++i)
2089 {
2090 if (p_buffer[i] != c)
2091 {
2092 return i;
2093 }
2094 }
2095 }
2096
2097 return npos;
2098 }
2099
2100 //*********************************************************************
2104 //*********************************************************************
2105 size_type find_last_not_of(const ibasic_string<T>& str, size_type position = npos) const
2106 {
2107 return find_last_not_of(str.c_str(), position, str.size());
2108 }
2109
2110 //*********************************************************************
2114 //*********************************************************************
2115 size_type find_last_not_of(const_pointer s, size_type position = npos) const
2116 {
2117 return find_last_not_of(s, position, etl::strlen(s));
2118 }
2119
2120 //*********************************************************************
2125 //*********************************************************************
2126 size_type find_last_not_of(const_pointer s, size_type position, size_type n) const
2127 {
2128 if (empty())
2129 {
2130 return npos;
2131 }
2132
2133 position = etl::min(position, size() - 1);
2134
2135 const_reverse_iterator it = rbegin() + size() - position - 1;
2136
2137 while (it != rend())
2138 {
2139 bool found = false;
2140
2141 for (size_type j = 0; j < n; ++j)
2142 {
2143 if (p_buffer[position] == s[j])
2144 {
2145 found = true;
2146 }
2147 }
2148
2149 if (!found)
2150 {
2151 return position;
2152 }
2153
2154 ++it;
2155 --position;
2156 }
2157
2158 return npos;
2159 }
2160
2161 //*********************************************************************
2162 //
2163 //*********************************************************************
2164 size_type find_last_not_of(value_type c, size_type position = npos) const
2165 {
2166 if (empty())
2167 {
2168 return npos;
2169 }
2170
2171 position = etl::min(position, size() - 1);
2172
2173 const_reverse_iterator it = rbegin() + size() - position - 1;
2174
2175 while (it != rend())
2176 {
2177 if (p_buffer[position] != c)
2178 {
2179 return position;
2180 }
2181
2182 ++it;
2183 --position;
2184 }
2185
2186 return npos;
2187 }
2188
2189 //*************************************************************************
2191 //*************************************************************************
2193 {
2194 if (&rhs != this)
2195 {
2196 assign(rhs);
2197 }
2198
2199 return *this;
2200 }
2201
2202 //*************************************************************************
2204 //*************************************************************************
2205 ibasic_string& operator = (const_pointer rhs)
2206 {
2207 assign(rhs);
2208
2209 return *this;
2210 }
2211
2212 //*************************************************************************
2214 //*************************************************************************
2216 {
2217 append(rhs);
2218
2219 return *this;
2220 }
2221
2222 //*************************************************************************
2224 //*************************************************************************
2225 ibasic_string& operator += (const_pointer rhs)
2226 {
2227 append(rhs);
2228
2229 return *this;
2230 }
2231
2232 //*************************************************************************
2234 //*************************************************************************
2236 {
2237 append(size_type(1), rhs);
2238
2239 return *this;
2240 }
2241
2242#if ETL_HAS_ISTRING_REPAIR
2243 //*************************************************************************
2245 //*************************************************************************
2246 virtual void repair() = 0;
2247#endif
2248
2249 //*********************************************************************
2251 //*********************************************************************
2253 {
2254#if ETL_HAS_STRING_TRUNCATION_CHECKS
2255 set_truncated(false);
2256#endif
2257 etl::fill(&p_buffer[current_size], &p_buffer[CAPACITY + 1U], T(0));
2258 }
2259
2260 //*********************************************************************
2264 //*********************************************************************
2266 {
2267#if ETL_HAS_STRING_TRUNCATION_CHECKS
2268 set_truncated(p_buffer[CAPACITY] != T(0));
2269#endif
2270
2271 p_buffer[CAPACITY] = T(0); // Ensure a terminating null.
2272 current_size = etl::strlen(p_buffer);
2273 }
2274
2275 protected:
2276
2277 //*********************************************************************
2279 //*********************************************************************
2280 ibasic_string(T* p_buffer_, size_type MAX_SIZE_)
2281 : string_base(MAX_SIZE_),
2282 p_buffer(p_buffer_)
2283 {
2284 }
2285
2286 //*********************************************************************
2288 //*********************************************************************
2290 {
2291 current_size = 0U;
2292 cleanup();
2293 p_buffer[0] = 0;
2294#if ETL_HAS_STRING_TRUNCATION_CHECKS
2295 set_truncated(false);
2296#endif
2297 }
2298
2299 //*************************************************************************
2301 //*************************************************************************
2302 void repair_buffer(T* p_buffer_)
2303 {
2304 p_buffer = p_buffer_;
2305 }
2306
2307 private:
2308
2309 //*************************************************************************
2311 //*************************************************************************
2312 int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2) const
2313 {
2314 while ((first1 != last1) && (first2 != last2))
2315 {
2316 if (*first1 < *first2)
2317 {
2318 // Compared character is lower.
2319 return -1;
2320 }
2321 else if (*first1 > *first2)
2322 {
2323 // Compared character is higher.
2324 return 1;
2325 }
2326
2327 ++first1;
2328 ++first2;
2329 }
2330
2331 // We reached the end of one or both of the strings.
2332 if ((first1 == last1) && (first2 == last2))
2333 {
2334 // Same length.
2335 return 0;
2336 }
2337 else if (first1 == last1)
2338 {
2339 // Compared string is shorter.
2340 return -1;
2341 }
2342 else
2343 {
2344 // Compared string is longer.
2345 return 1;
2346 }
2347 }
2348
2349 //*************************************************************************
2351 //*************************************************************************
2352 void cleanup()
2353 {
2354#if ETL_HAS_STRING_CLEAR_AFTER_USE
2355 if (is_secure())
2356 {
2357 etl::memory_clear_range(&p_buffer[current_size], &p_buffer[CAPACITY]);
2358 }
2359#endif
2360 }
2361
2362 //*************************************************************************
2364 //*************************************************************************
2366
2367 //*************************************************************************
2369 //*************************************************************************
2370 T* p_buffer;
2371
2372 //*************************************************************************
2374 //*************************************************************************
2375#if defined(ETL_POLYMORPHIC_STRINGS) || defined(ETL_POLYMORPHIC_CONTAINERS) || defined(ETL_ISTRING_REPAIR_ENABLE)
2376 public:
2377 virtual
2378#else
2379 protected:
2380#endif
2382 {
2383#if ETL_HAS_STRING_CLEAR_AFTER_USE
2384 if (is_secure())
2385 {
2386 initialise();
2387 }
2388#endif
2389 }
2390
2391 protected:
2392
2393 //*************************************************************************
2395 //*************************************************************************
2396 iterator to_iterator(const_iterator itr) const
2397 {
2398 return const_cast<iterator>(itr);
2399 }
2400 };
2401
2402 //***************************************************************************
2408 //***************************************************************************
2409 template <typename T>
2411 {
2412 return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
2413 }
2414
2415 //***************************************************************************
2421 //***************************************************************************
2422 template <typename T>
2423 bool operator ==(const etl::ibasic_string<T>& lhs, const T* rhs)
2424 {
2425 return (lhs.size() == etl::strlen(rhs)) && etl::equal(lhs.begin(), lhs.end(), rhs);
2426 }
2427
2428 //***************************************************************************
2434 //***************************************************************************
2435 template <typename T>
2436 bool operator ==(const T* lhs, const etl::ibasic_string<T>& rhs)
2437 {
2438 return (rhs.size() == etl::strlen(lhs)) && etl::equal(rhs.begin(), rhs.end(), lhs);
2439 }
2440
2441 //***************************************************************************
2447 //***************************************************************************
2448 template <typename T>
2450 {
2451 return !(lhs == rhs);
2452 }
2453
2454 //***************************************************************************
2460 //***************************************************************************
2461 template <typename T>
2462 bool operator !=(const etl::ibasic_string<T>& lhs, const T* rhs)
2463 {
2464 return !(lhs == rhs);
2465 }
2466
2467 //***************************************************************************
2473 //***************************************************************************
2474 template <typename T>
2475 bool operator !=(const T* lhs, const etl::ibasic_string<T>& rhs)
2476 {
2477 return !(lhs == rhs);
2478 }
2479
2480 //***************************************************************************
2486 //***************************************************************************
2487 template <typename T>
2489 {
2490 return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
2491 }
2492
2493 //***************************************************************************
2499 //***************************************************************************
2500 template <typename T>
2501 bool operator <(const etl::ibasic_string<T>& lhs, const T* rhs)
2502 {
2503 return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs));
2504 }
2505
2506 //***************************************************************************
2512 //***************************************************************************
2513 template <typename T>
2514 bool operator <(const T* lhs, const etl::ibasic_string<T>& rhs)
2515 {
2516 return etl::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end());
2517 }
2518
2519
2520 //***************************************************************************
2526 //***************************************************************************
2527 template <typename T>
2529 {
2530 return (rhs < lhs);
2531 }
2532
2533 //***************************************************************************
2539 //***************************************************************************
2540 template <typename T>
2541 bool operator >(const etl::ibasic_string<T>& lhs, const T* rhs)
2542 {
2543 return (rhs < lhs);
2544 }
2545
2546 //***************************************************************************
2552 //***************************************************************************
2553 template <typename T>
2554 bool operator >(const T* lhs, const etl::ibasic_string<T>& rhs)
2555 {
2556 return (rhs < lhs);
2557 }
2558
2559
2560 //***************************************************************************
2566 //***************************************************************************
2567 template <typename T>
2569 {
2570 return !(lhs > rhs);
2571 }
2572
2573 //***************************************************************************
2579 //***************************************************************************
2580 template <typename T>
2581 bool operator <=(const etl::ibasic_string<T>& lhs, const T* rhs)
2582 {
2583 return !(lhs > rhs);
2584 }
2585
2586 //***************************************************************************
2592 //***************************************************************************
2593 template <typename T>
2594 bool operator <=(const T* lhs, const etl::ibasic_string<T>& rhs)
2595 {
2596 return !(lhs > rhs);
2597 }
2598
2599
2600 //***************************************************************************
2606 //***************************************************************************
2607 template <typename T>
2609 {
2610 return !(lhs < rhs);
2611 }
2612
2613 //***************************************************************************
2619 //***************************************************************************
2620 template <typename T>
2621 bool operator >=(const etl::ibasic_string<T>& lhs, const T* rhs)
2622 {
2623 return !(lhs < rhs);
2624 }
2625
2626 //***************************************************************************
2632 //***************************************************************************
2633 template <typename T>
2634 bool operator >=(const T* lhs, const etl::ibasic_string<T>& rhs)
2635 {
2636 return !(lhs < rhs);
2637 }
2638}
2639
2640#include "private/minmax_pop.h"
2641
2642#endif
Definition: flags.h:53
ETL_CONSTEXPR14 flags< T, MASK > & set() ETL_NOEXCEPT
Set the bits.
Definition: flags.h:102
ETL_CONSTEXPR bool test() const ETL_NOEXCEPT
Tests bits.
Definition: flags.h:87
Definition: basic_string.h:326
int compare(size_type position, size_type length_, const ibasic_string &str) const
Compare position / length with string.
Definition: basic_string.h:1813
ibasic_string & append(TIterator first, TIterator last)
Definition: basic_string.h:916
size_type find_last_of(const_pointer s, size_type position=npos) const
Definition: basic_string.h:1958
size_type rfind(const_pointer s, size_type position=npos) const
Definition: basic_string.h:1492
etl::ibasic_string< T > & insert(size_type position, const etl::ibasic_string< T > &str)
Definition: basic_string.h:1157
ibasic_string & append(const T *str)
Definition: basic_string.h:882
size_type find_last_not_of(const_pointer s, size_type position=npos) const
Definition: basic_string.h:2115
size_type find(const_pointer s, size_type pos=0) const
Definition: basic_string.h:1389
ibasic_string & operator=(const ibasic_string &rhs)
Assignment operator.
Definition: basic_string.h:2192
ibasic_string & append(const ibasic_string &str, size_type subposition, size_type sublength=npos)
Definition: basic_string.h:869
const_reverse_iterator rbegin() const
Definition: basic_string.h:410
reference operator[](size_type i)
Definition: basic_string.h:510
void assign(const etl::ibasic_string< T > &other, size_type subposition, size_type sublength)
Definition: basic_string.h:658
pointer data_end()
Definition: basic_string.h:607
iterator erase(const_iterator first, const_iterator last)
Definition: basic_string.h:1303
iterator insert(const_iterator position, TIterator first, TIterator last)
Definition: basic_string.h:1066
size_type find_last_of(const ibasic_string< T > &str, size_type position=npos) const
Definition: basic_string.h:1948
size_type find_first_of(value_type c, size_type position=0) const
Definition: basic_string.h:1927
size_type find(T c, size_type position=0) const
Definition: basic_string.h:1442
void pop_back()
Definition: basic_string.h:833
size_type rfind(const ibasic_string< T > &str, size_type position=npos) const
Definition: basic_string.h:1461
void initialize_free_space()
Clears the free space to string terminator value.
Definition: basic_string.h:2252
ibasic_string & replace(size_type position, size_type length_, const_pointer s, size_type n)
Replace characters from 'position' of 'length' with 'n' characters from pointed to string.
Definition: basic_string.h:1709
iterator to_iterator(const_iterator itr) const
Convert from const_iterator to iterator.
Definition: basic_string.h:2396
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:1746
ibasic_string & replace(const_iterator first, const_iterator last, const ibasic_string &str)
Definition: basic_string.h:1611
size_type find_first_of(const ibasic_string< T > &str, size_type position=0) const
Definition: basic_string.h:1882
const_reference back() const
Definition: basic_string.h:580
const_iterator begin() const
Definition: basic_string.h:356
const_pointer data() const
Definition: basic_string.h:598
size_type find_last_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:1969
reverse_iterator rbegin()
Definition: basic_string.h:401
ibasic_string & replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace)
Replace characters from 'first' of 'last' with characters from 'first_replace' to 'last_replace'.
Definition: basic_string.h:1784
void resize(size_type new_size)
Definition: basic_string.h:456
size_type find_last_not_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:2126
size_type find_first_not_of(const_pointer s, size_type position=0) const
Definition: basic_string.h:2042
size_type rfind(T c, size_type position=npos) const
Definition: basic_string.h:1562
etl::ibasic_string< T > & erase(size_type position, size_type length_=npos)
Definition: basic_string.h:1257
int compare(const value_type *s) const
Compare with C string.
Definition: basic_string.h:1847
int compare(size_type position, size_type length_, const_pointer s) const
Compare position / length with C string.
Definition: basic_string.h:1858
iterator insert(const_iterator position, size_type n, T value)
Definition: basic_string.h:979
const_reference at(size_type i) const
Definition: basic_string.h:543
void clear()
Clears the string.
Definition: basic_string.h:800
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:1829
reverse_iterator rend()
Definition: basic_string.h:419
iterator erase(iterator i_element)
Definition: basic_string.h:1272
const_reverse_iterator crend() const
Definition: basic_string.h:446
reference at(size_type i)
Definition: basic_string.h:531
~ibasic_string()
Destructor.
Definition: basic_string.h:2381
ibasic_string & replace(const_iterator first, const_iterator last, const_pointer s)
Replace characters from 'first' 'last' with pointed to string.
Definition: basic_string.h:1691
size_type find(const_pointer s, size_type pos, size_type n) const
Definition: basic_string.h:1416
size_type find_first_of(const_pointer s, size_type position=0) const
Definition: basic_string.h:1892
ibasic_string & replace(size_type position, size_type length_, const ibasic_string &str, size_type subposition, size_type sublength)
Replace characters from 'position' of 'length' with 'str' from 'subposition' of 'sublength'.
Definition: basic_string.h:1640
iterator begin()
Definition: basic_string.h:347
iterator end()
Definition: basic_string.h:365
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:1765
ibasic_string & replace(const_iterator first, const_iterator last, const_pointer s, size_type n)
Replace characters from 'first' to 'last' with 'n' characters from pointed to string.
Definition: basic_string.h:1728
void assign(TIterator first, TIterator last)
Definition: basic_string.h:747
etl::ibasic_string< T > & insert(size_type position, const etl::ibasic_string< T > &str, size_type subposition, size_type sublength)
Definition: basic_string.h:1184
size_type find(const ibasic_string< T > &str, size_type pos=0) const
Definition: basic_string.h:1365
void push_back(T value)
Definition: basic_string.h:810
size_type find_first_not_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:2053
void assign(size_type n, T value)
Definition: basic_string.h:778
const_reverse_iterator crbegin() const
Definition: basic_string.h:437
iterator insert(const_iterator position, T value)
Definition: basic_string.h:927
etl::ibasic_string< T > & insert(size_type position, const_pointer s, size_type n)
Definition: basic_string.h:1229
ibasic_string & replace(size_type position, size_type length_, const ibasic_string &str)
Definition: basic_string.h:1589
ibasic_string(T *p_buffer_, size_type MAX_SIZE_)
Constructor.
Definition: basic_string.h:2280
etl::ibasic_string< T > & insert(size_type position, size_type n, value_type c)
Definition: basic_string.h:1243
const_reverse_iterator rend() const
Definition: basic_string.h:428
size_type find_last_not_of(const ibasic_string< T > &str, size_type position=npos) const
Definition: basic_string.h:2105
const_pointer data_end() const
Definition: basic_string.h:616
void assign(const etl::ibasic_string< T > &other)
Definition: basic_string.h:626
const_iterator cend() const
Definition: basic_string.h:392
const_pointer c_str() const
Return a pointer to a C string.
Definition: basic_string.h:1326
void assign(const_pointer other, size_type length_)
Definition: basic_string.h:719
void resize(size_type new_size, T value)
Definition: basic_string.h:466
const_reference front() const
Definition: basic_string.h:562
pointer data()
Definition: basic_string.h:589
size_type find_first_not_of(value_type c, size_type position=0) const
Definition: basic_string.h:2084
ibasic_string & append(size_type n, T c)
Definition: basic_string.h:904
size_type find_first_not_of(const ibasic_string< T > &str, size_type position=0) const
Definition: basic_string.h:2032
size_type find_last_of(value_type c, size_type position=npos) const
Definition: basic_string.h:2002
size_type copy(pointer dest, size_type count, size_type pos=0) const
Definition: basic_string.h:1337
ibasic_string & append(const ibasic_string &str)
Definition: basic_string.h:845
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:1672
reference front()
Definition: basic_string.h:553
reference back()
Definition: basic_string.h:571
const_iterator cbegin() const
Definition: basic_string.h:383
void initialise()
Initialise the string.
Definition: basic_string.h:2289
ibasic_string & operator+=(const ibasic_string &rhs)
+= operator.
Definition: basic_string.h:2215
void trim_to_terminator()
Definition: basic_string.h:2265
void uninitialized_resize(size_type new_size)
Definition: basic_string.h:497
ibasic_string & append(const T *str, size_type n)
Definition: basic_string.h:893
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:1869
size_type rfind(const_pointer s, size_type position, size_type length_) const
Definition: basic_string.h:1528
size_type find_first_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:1903
int compare(const ibasic_string &str) const
Compare with string.
Definition: basic_string.h:1802
const_iterator end() const
Definition: basic_string.h:374
iterator erase(const_iterator i_element)
Definition: basic_string.h:1285
etl::ibasic_string< T > & insert(size_type position, const_pointer s)
Definition: basic_string.h:1215
void repair_buffer(T *p_buffer_)
Fix the internal pointers after a low level memory copy.
Definition: basic_string.h:2302
void assign(const_pointer other)
Definition: basic_string.h:693
Definition: basic_string.h:167
void set_secure()
Sets the 'secure' flag to the requested state.
Definition: basic_string.h:269
bool is_secure() const
Gets the 'secure' state flag.
Definition: basic_string.h:277
const size_type CAPACITY
The maximum number of elements in the string.
Definition: basic_string.h:312
bool full() const
Definition: basic_string.h:203
~string_base()
Destructor.
Definition: basic_string.h:307
ETL_DEPRECATED bool truncated() const
Definition: basic_string.h:242
void set_truncated(bool status)
Sets the 'truncated' flag.
Definition: basic_string.h:298
size_type max_size() const
Definition: basic_string.h:221
string_base(size_type max_size_)
Constructor.
Definition: basic_string.h:288
void clear_truncated()
Clears the 'truncated' flag.
Definition: basic_string.h:259
size_type length() const
Definition: basic_string.h:185
size_type current_size
The current number of elements in the string.
Definition: basic_string.h:311
size_type available() const
Definition: basic_string.h:230
bool empty() const
Definition: basic_string.h:194
size_type capacity() const
Definition: basic_string.h:212
bool is_truncated() const
Definition: basic_string.h:251
size_type size() const
Definition: basic_string.h:176
Definition: basic_string.h:84
Definition: basic_string.h:70
Definition: basic_string.h:112
Definition: basic_string.h:98
Definition: basic_string.h:126
Definition: binary.h:392
#define ETL_ASSERT(b, e)
Definition: error_handler.h:316
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition: exception.h:69
Definition: exception.h:47
Definition: integral_limits.h:468
void memory_clear_range(volatile T *begin, size_t n)
Definition: memory.h:1999
bitset_ext
Definition: absolute.h:38
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:684
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:696
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:645
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:633
ETL_CONSTEXPR size_t strlen(const T *t)
Alternative strlen for all character types.
Definition: char_traits.h:267
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:657
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:672