Embedded Template Library  1.0
basic_string.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 https://github.com/ETLCPP/etl
8 https://www.etlcpp.com
9 
10 Copyright(c) 2016 jwellbelove
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files(the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions :
18 
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29 ******************************************************************************/
30 
31 #ifndef ETL_BASIC_STRING_INCLUDED
32 #define ETL_BASIC_STRING_INCLUDED
33 
34 #include <stddef.h>
35 #include <stdint.h>
36 #include <string.h>
37 
38 #include "platform.h"
39 
40 #include "algorithm.h"
41 #include "iterator.h"
42 #include "functional.h"
43 #include "char_traits.h"
44 #include "container.h"
45 #include "alignment.h"
46 #include "array.h"
47 #include "algorithm.h"
48 #include "type_traits.h"
49 #include "error_handler.h"
50 #include "integral_limits.h"
51 #include "exception.h"
52 #include "memory.h"
53 #include "exception.h"
54 #include "binary.h"
55 #include "flags.h"
56 
57 #undef ETL_FILE
58 #define ETL_FILE "27"
59 
60 #ifdef ETL_COMPILER_GCC
61 #pragma GCC diagnostic push
62 #pragma GCC diagnostic ignored "-Wunused-variable"
63 #endif
64 
65 #include "private/minmax_push.h"
66 
67 //*****************************************************************************
71 //*****************************************************************************
72 
73 namespace etl
74 {
75  //***************************************************************************
78  //***************************************************************************
80  {
81  public:
82 
83  string_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
84  : exception(reason_, file_name_, line_number_)
85  {
86  }
87  };
88 
89  //***************************************************************************
92  //***************************************************************************
94  {
95  public:
96 
97  string_empty(string_type file_name_, numeric_type line_number_)
98  : string_exception(ETL_ERROR_TEXT("string:empty", ETL_FILE"A"), file_name_, line_number_)
99  {
100  }
101  };
102 
103  //***************************************************************************
106  //***************************************************************************
108  {
109  public:
110 
111  string_out_of_bounds(string_type file_name_, numeric_type line_number_)
112  : string_exception(ETL_ERROR_TEXT("string:bounds", ETL_FILE"B"), file_name_, line_number_)
113  {
114  }
115  };
116 
117  //***************************************************************************
120  //***************************************************************************
122  {
123  public:
124 
125  string_iterator(string_type file_name_, numeric_type line_number_)
126  : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_FILE"C"), file_name_, line_number_)
127  {
128  }
129  };
130 
131  //***************************************************************************
134  //***************************************************************************
136  {
137  public:
138 
139  string_truncation(string_type file_name_, numeric_type line_number_)
140  : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_FILE"D"), file_name_, line_number_)
141  {
142  }
143  };
144 
145  //***************************************************************************
148  //***************************************************************************
150  {
151  public:
152 
153  typedef size_t size_type;
154 
155 #if ETL_CPP11_SUPPORTED
156  static constexpr size_type npos = etl::integral_limits<size_type>::max;
157 #else
158  enum
159  {
161  };
162 #endif
163 
164  //*************************************************************************
167  //*************************************************************************
168  size_type size() const
169  {
170  return current_size;
171  }
172 
173  //*************************************************************************
176  //*************************************************************************
177  size_type length() const
178  {
179  return current_size;
180  }
181 
182  //*************************************************************************
185  //*************************************************************************
186  bool empty() const
187  {
188  return (current_size == 0);
189  }
190 
191  //*************************************************************************
194  //*************************************************************************
195  bool full() const
196  {
197  return current_size == CAPACITY;
198  }
199 
200  //*************************************************************************
203  //*************************************************************************
204  size_type capacity() const
205  {
206  return CAPACITY;
207  }
208 
209  //*************************************************************************
212  //*************************************************************************
213  size_type max_size() const
214  {
215  return CAPACITY;
216  }
217 
218  //*************************************************************************
221  //*************************************************************************
222  size_type available() const
223  {
224  return max_size() - size();
225  }
226 
227 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
228  //*************************************************************************
232  //*************************************************************************
233  ETL_DEPRECATED
234  bool truncated() const
235  {
236  return flags.test<IS_TRUNCATED>();
237  }
238 
239  //*************************************************************************
242  //*************************************************************************
243  bool is_truncated() const
244  {
245  return flags.test<IS_TRUNCATED>();
246  }
247 
248  //*************************************************************************
250  //*************************************************************************
252  {
253  flags.set<IS_TRUNCATED, false>();
254  }
255 #endif
256 
257 #if ETL_STRING_CLEAR_AFTER_USE_ENABLED
258  //*************************************************************************
260  //*************************************************************************
261  void set_secure()
262  {
263  flags.set<CLEAR_AFTER_USE>();
264  }
265 
266  //*************************************************************************
268  //*************************************************************************
269  bool is_secure() const
270  {
271  return flags.test<CLEAR_AFTER_USE>();
272  }
273 #endif
274 
275  protected:
276 
277  //*************************************************************************
279  //*************************************************************************
280  string_base(size_type max_size_)
281  : current_size(0)
282  , CAPACITY(max_size_)
283  {
284  }
285 
286 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
287  //*************************************************************************
289  //*************************************************************************
290  void set_truncated(bool status)
291  {
292  flags.set<IS_TRUNCATED>(status);
293  }
294 #endif
295 
296  //*************************************************************************
298  //*************************************************************************
300  {
301  }
302 
303  static const uint_least8_t IS_TRUNCATED = etl::bit<0>::value;
304  static const uint_least8_t CLEAR_AFTER_USE = etl::bit<1>::value;
305 
306  size_type current_size;
307  const size_type CAPACITY;
308 
309 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED || ETL_STRING_CLEAR_AFTER_USE_ENABLED
311 #endif
312  };
313 
314  //***************************************************************************
318  //***************************************************************************
319  template <typename T>
321  {
322  public:
323 
325 
326  typedef T value_type;
327  typedef T& reference;
328  typedef const T& const_reference;
329  typedef T* pointer;
330  typedef const T* const_pointer;
331  typedef T* iterator;
332  typedef const T* const_iterator;
333  typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
334  typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
335 
336  typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
337 
338  //*********************************************************************
341  //*********************************************************************
342  iterator begin()
343  {
344  return &p_buffer[0];
345  }
346 
347  //*********************************************************************
350  //*********************************************************************
351  const_iterator begin() const
352  {
353  return &p_buffer[0];
354  }
355 
356  //*********************************************************************
359  //*********************************************************************
360  iterator end()
361  {
362  return &p_buffer[current_size];
363  }
364 
365  //*********************************************************************
368  //*********************************************************************
369  const_iterator end() const
370  {
371  return &p_buffer[current_size];
372  }
373 
374  //*********************************************************************
377  //*********************************************************************
378  const_iterator cbegin() const
379  {
380  return &p_buffer[0];
381  }
382 
383  //*********************************************************************
386  //*********************************************************************
387  const_iterator cend() const
388  {
389  return &p_buffer[current_size];
390  }
391 
392  //*********************************************************************
395  //*********************************************************************
396  reverse_iterator rbegin()
397  {
398  return reverse_iterator(end());
399  }
400 
401  //*********************************************************************
404  //*********************************************************************
405  const_reverse_iterator rbegin() const
406  {
407  return const_reverse_iterator(end());
408  }
409 
410  //*********************************************************************
413  //*********************************************************************
414  reverse_iterator rend()
415  {
416  return reverse_iterator(begin());
417  }
418 
419  //*********************************************************************
422  //*********************************************************************
423  const_reverse_iterator rend() const
424  {
425  return const_reverse_iterator(begin());
426  }
427 
428  //*********************************************************************
431  //*********************************************************************
432  const_reverse_iterator crbegin() const
433  {
434  return const_reverse_iterator(cend());
435  }
436 
437  //*********************************************************************
440  //*********************************************************************
441  const_reverse_iterator crend() const
442  {
443  return const_reverse_iterator(cbegin());
444  }
445 
446  //*********************************************************************
450  //*********************************************************************
451  void resize(size_type new_size)
452  {
453  resize(new_size, 0);
454  }
455 
456  //*********************************************************************
460  //*********************************************************************
461  void resize(size_type new_size, T value)
462  {
463  if (new_size > CAPACITY)
464  {
465 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
466  set_truncated(true);
467 
468 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
469  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
470 #endif
471 #endif
472  }
473 
474  new_size = etl::min(new_size, CAPACITY);
475 
476  // Size up?
477  if (new_size > current_size)
478  {
479  etl::fill(p_buffer + current_size, p_buffer + new_size, value);
480  }
481 
482  current_size = new_size;
483  p_buffer[new_size] = 0;
484  cleanup();
485  }
486 
487  //*********************************************************************
491  //*********************************************************************
492  reference operator [](size_type i)
493  {
494  return p_buffer[i];
495  }
496 
497  //*********************************************************************
501  //*********************************************************************
502  const_reference operator [](size_type i) const
503  {
504  return p_buffer[i];
505  }
506 
507  //*********************************************************************
512  //*********************************************************************
513  reference at(size_type i)
514  {
515  ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
516  return p_buffer[i];
517  }
518 
519  //*********************************************************************
524  //*********************************************************************
525  const_reference at(size_type i) const
526  {
527  ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
528  return p_buffer[i];
529  }
530 
531  //*********************************************************************
534  //*********************************************************************
535  reference front()
536  {
537  return p_buffer[0];
538  }
539 
540  //*********************************************************************
543  //*********************************************************************
544  const_reference front() const
545  {
546  return p_buffer[0];
547  }
548 
549  //*********************************************************************
552  //*********************************************************************
553  reference back()
554  {
555  return p_buffer[current_size - 1];
556  }
557 
558  //*********************************************************************
561  //*********************************************************************
562  const_reference back() const
563  {
564  return p_buffer[current_size - 1];
565  }
566 
567  //*********************************************************************
570  //*********************************************************************
571  pointer data()
572  {
573  return p_buffer;
574  }
575 
576  //*********************************************************************
579  //*********************************************************************
580  const_pointer data() const
581  {
582  return p_buffer;
583  }
584 
585  //*********************************************************************
589  //*********************************************************************
590  void assign(const etl::ibasic_string<T>& other)
591  {
592  assign(other.begin(), other.end());
593 
594 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
595  if (other.is_truncated())
596  {
597  set_truncated(true);
598 
599 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
600  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
601 #endif
602  }
603 #endif
604 
605 #if ETL_STRING_CLEAR_AFTER_USE_ENABLED
606  if (other.is_secure())
607  {
608  set_secure();
609  }
610 #endif
611 
612  cleanup();
613  }
614 
615  //*********************************************************************
621  //*********************************************************************
622  void assign(const etl::ibasic_string<T>& other, size_type subposition, size_type sublength)
623  {
624  if (sublength == npos)
625  {
626  sublength = other.size() - subposition;
627  }
628 
629  ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds));
630 
631  assign(other.begin() + subposition, sublength);
632 
633 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
634  if (other.is_truncated())
635  {
636  this->set_truncated(true);
637 
638 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
639  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
640 #endif
641  }
642 #endif
643 
644 #if ETL_STRING_CLEAR_AFTER_USE_ENABLED
645  if (other.is_secure())
646  {
647  set_secure();
648  }
649 #endif
650  }
651 
652  //*********************************************************************
656  //*********************************************************************
657  void assign(const_pointer other)
658  {
659  initialise();
660 
661  while ((*other != 0) && (current_size < CAPACITY))
662  {
663  p_buffer[current_size++] = *other++;
664  }
665 
666 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
667  set_truncated(*other != 0);
668 
669 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
670  ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
671 #endif
672 #endif
673 
674  p_buffer[current_size] = 0;
675  }
676 
677  //*********************************************************************
682  //*********************************************************************
683  void assign(const_pointer other, size_type length_)
684  {
685  initialise();
686 
687 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
688  set_truncated(length_ > CAPACITY);
689 
690 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
691  ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
692 #endif
693 #endif
694 
695  length_ = etl::min(length_, CAPACITY);
696 
697  etl::copy_n(other, length_, begin());
698 
699  current_size = length_;
700  p_buffer[current_size] = 0;
701  }
702 
703  //*********************************************************************
709  //*********************************************************************
710  template <typename TIterator>
711  void assign(TIterator first, TIterator last)
712  {
713 #if defined(ETL_DEBUG)
714  difference_type d = etl::distance(first, last);
715  ETL_ASSERT(d >= 0, ETL_ERROR(string_iterator));
716 #endif
717 
718  initialise();
719 
720  while ((first != last) && (current_size != CAPACITY))
721  {
722  p_buffer[current_size++] = *first++;
723  }
724 
725  p_buffer[current_size] = 0;
726 
727 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
728  set_truncated(first != last);
729 
730 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
731  ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
732 #endif
733 #endif
734  }
735 
736  //*********************************************************************
741  //*********************************************************************
742  void assign(size_type n, T value)
743  {
744  initialise();
745 
746 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
747  set_truncated(n > CAPACITY);
748 
749 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
750  ETL_ASSERT(flags.test<IS_TRUNCATED>() == false, ETL_ERROR(string_truncation))
751 #endif
752 #endif
753 
754  n = etl::min(n, CAPACITY);
755 
756  etl::fill_n(begin(), n, value);
757  current_size = n;
758  p_buffer[current_size] = 0;
759  }
760 
761  //*************************************************************************
763  //*************************************************************************
764  void clear()
765  {
766  initialise();
767  }
768 
769  //*********************************************************************
773  //*********************************************************************
774  void push_back(T value)
775  {
776  if (current_size != CAPACITY)
777  {
778  p_buffer[current_size++] = value;
779  p_buffer[current_size] = 0;
780  }
781  else
782  {
783 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
784  set_truncated(true);
785 
786 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
787  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
788 #endif
789 #endif
790  }
791  }
792 
793  //*************************************************************************
796  //*************************************************************************
797  void pop_back()
798  {
799  if (current_size != 0)
800  {
801  p_buffer[--current_size] = 0;
802  }
803  }
804 
805  //*********************************************************************
808  //*********************************************************************
810  {
811  insert(end(), str.begin(), str.end());
812 
813 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
814  if (str.is_truncated())
815  {
816  set_truncated(true);
817 
818 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
819  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
820 #endif
821  }
822 #endif
823 
824  return *this;
825  }
826 
827  //*********************************************************************
832  //*********************************************************************
833  ibasic_string& append(const ibasic_string& str, size_type subposition, size_type sublength = npos)
834  {
835  ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
836 
837  insert(size(), str, subposition, sublength);
838 
839  return *this;
840  }
841 
842  //*********************************************************************
845  //*********************************************************************
846  ibasic_string& append(const T* str)
847  {
848  insert(size(), str);
849  return *this;
850  }
851 
852  //*********************************************************************
856  //*********************************************************************
857  ibasic_string& append(const T* str, size_type n)
858  {
859  insert(size(), str, n);
860  return *this;
861  }
862 
863  //*********************************************************************
867  //*********************************************************************
868  ibasic_string& append(size_type n, T c)
869  {
870  insert(size(), n, c);
871  return *this;
872  }
873 
874  //*********************************************************************
878  //*********************************************************************
879  template <class TIterator>
880  ibasic_string& append(TIterator first, TIterator last)
881  {
882  insert(end(), first, last);
883  return *this;
884  }
885 
886  //*********************************************************************
890  //*********************************************************************
891  iterator insert(const_iterator position, T value)
892  {
893  // Quick hack, as iterators are pointers.
894  iterator insert_position = const_cast<iterator>(position);
895 
896  if (current_size < CAPACITY)
897  {
898  // Not full yet.
899  if (position != end())
900  {
901  // Insert in the middle.
902  ++current_size;
903  etl::copy_backward(insert_position, end() - 1, end());
904  *insert_position = value;
905  }
906  else
907  {
908  // Insert at the end.
909  *insert_position = value;
910  ++current_size;
911  }
912  }
913  else
914  {
915  // Already full.
916  if (position != end())
917  {
918  // Insert in the middle.
919  etl::copy_backward(insert_position, end() - 1, end());
920  *insert_position = value;
921  }
922 
923 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
924  set_truncated(true);
925 
926 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
927  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
928 #endif
929 #endif
930  }
931 
932  p_buffer[current_size] = 0;
933 
934  return insert_position;
935  }
936 
937  //*********************************************************************
942  //*********************************************************************
943  void insert(const_iterator position, size_type n, T value)
944  {
945  if (n == 0)
946  {
947  return;
948  }
949 
950  // Quick hack, as iterators are pointers.
951  iterator insert_position = const_cast<iterator>(position);
952  const size_type start = etl::distance(cbegin(), position);
953 
954  // No effect.
955  if (start >= CAPACITY)
956  {
957 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
958  set_truncated(true);
959 
960 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
961  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
962 #endif
963 #endif
964  return;
965  }
966 
967  // Fills the string to the end?
968  if ((start + n) >= CAPACITY)
969  {
970  if ((current_size + n) > CAPACITY)
971  {
972 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
973  set_truncated(true);
974 
975 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
976  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
977 #endif
978 #endif
979  }
980 
982  etl::fill(insert_position, end(), value);
983  }
984  else
985  {
986  // Lets do some shifting.
987  const size_type shift_amount = n;
988  const size_type to_position = start + shift_amount;
989  const size_type remaining_characters = current_size - start;
990  const size_type max_shift_characters = CAPACITY - start - shift_amount;
991  const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters);
992 
993  // Will the string truncate?
994  if ((start + shift_amount + remaining_characters) > CAPACITY)
995  {
997 
998 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
999  set_truncated(true);
1000 
1001 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1002  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1003 #endif
1004 #endif
1005  }
1006  else
1007  {
1008  current_size += shift_amount;
1009  }
1010 
1011  etl::copy_backward(insert_position, insert_position + characters_to_shift, begin() + to_position + characters_to_shift);
1012  etl::fill(insert_position, insert_position + shift_amount, value);
1013  }
1014 
1015  p_buffer[current_size] = 0;
1016  }
1017 
1018  //*********************************************************************
1024  //*********************************************************************
1025  template <class TIterator>
1026  void insert(iterator position, TIterator first, TIterator last)
1027  {
1028  if (first == last)
1029  {
1030  return;
1031  }
1032 
1033  const size_type start = etl::distance(begin(), position);
1034  const size_type n = etl::distance(first, last);
1035 
1036  // No effect.
1037  if (start >= CAPACITY)
1038  {
1039 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1040  set_truncated(true);
1041 
1042 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1043  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1044 #endif
1045 #endif
1046  return;
1047  }
1048 
1049  // Fills the string to the end?
1050  if ((start + n) >= CAPACITY)
1051  {
1052  if (((current_size + n) > CAPACITY))
1053  {
1054 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1055  set_truncated(true);
1056 
1057 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1058  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1059 #endif
1060 #endif
1061  }
1062 
1064 
1065  while (position != end())
1066  {
1067  *position++ = *first++;
1068  }
1069  }
1070  else
1071  {
1072  // Lets do some shifting.
1073  const size_type shift_amount = n;
1074  const size_type to_position = start + shift_amount;
1075  const size_type remaining_characters = current_size - start;
1076  const size_type max_shift_characters = CAPACITY - start - shift_amount;
1077  const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters);
1078 
1079  // Will the string truncate?
1080  if ((start + shift_amount + remaining_characters) > CAPACITY)
1081  {
1083 
1084 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1085  set_truncated(true);
1086 
1087 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1088  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1089 #endif
1090 #endif
1091  }
1092  else
1093  {
1094  current_size += shift_amount;
1095  }
1096 
1097  etl::copy_backward(position, position + characters_to_shift, begin() + to_position + characters_to_shift);
1098 
1099  while (first != last)
1100  {
1101  *position++ = *first++;
1102  }
1103  }
1104 
1105  p_buffer[current_size] = 0;
1106  }
1107 
1108  //*********************************************************************
1112  //*********************************************************************
1113  etl::ibasic_string<T>& insert(size_type position, const etl::ibasic_string<T>& str)
1114  {
1115  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1116 
1117  insert(begin() + position, str.cbegin(), str.cend());
1118 
1119 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1120  if (str.is_truncated())
1121  {
1122  set_truncated(true);
1123 
1124 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1125  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1126 #endif
1127  }
1128 #endif
1129 
1130  return *this;
1131  }
1132 
1133  //*********************************************************************
1139  //*********************************************************************
1140  etl::ibasic_string<T>& insert(size_type position, const etl::ibasic_string<T>& str, size_type subposition, size_type sublength)
1141  {
1142  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1143  ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1144 
1145  if ((sublength == npos) || (subposition + sublength > str.size()))
1146  {
1147  sublength = str.size() - subposition;
1148  }
1149 
1150  insert(begin() + position, str.cbegin() + subposition, str.cbegin() + subposition + sublength);
1151 
1152 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1153  if (str.is_truncated())
1154  {
1155  set_truncated(true);
1156 
1157 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1158  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1159 #endif
1160  }
1161 #endif
1162 
1163  return *this;
1164  }
1165 
1166  //*********************************************************************
1170  //*********************************************************************
1171  etl::ibasic_string<T>& insert(size_type position, const_pointer s)
1172  {
1173  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1174 
1175  insert(begin() + position, s, s + etl::strlen(s));
1176  return *this;
1177  }
1178 
1179  //*********************************************************************
1184  //*********************************************************************
1185  etl::ibasic_string<T>& insert(size_type position, const_pointer s, size_type n)
1186  {
1187  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1188 
1189  insert(begin() + position, s, s + n);
1190  return *this;
1191  }
1192 
1193  //*********************************************************************
1198  //*********************************************************************
1199  etl::ibasic_string<T>& insert(size_type position, size_type n, value_type c)
1200  {
1201  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1202 
1203  insert(begin() + position, n, c);
1204  return *this;
1205  }
1206 
1207  //*********************************************************************
1212  //*********************************************************************
1213  etl::ibasic_string<T>& erase(size_type position, size_type length_ = npos)
1214  {
1215  // Limit the length.
1216  length_ = etl::min(length_, size() - position);
1217 
1218  erase(begin() + position, begin() + position + length_);
1219 
1220  return *this;
1221  }
1222 
1223  //*********************************************************************
1227  //*********************************************************************
1228  iterator erase(iterator i_element)
1229  {
1230  etl::copy(i_element + 1, end(), i_element);
1231  p_buffer[--current_size] = 0;
1232 
1233  return i_element;
1234  }
1235 
1236  //*********************************************************************
1243  //*********************************************************************
1244  iterator erase(iterator first, iterator last)
1245  {
1246  if (first == last)
1247  {
1248  return first;
1249  }
1250 
1251  etl::copy(last, end(), first);
1252  size_type n_delete = etl::distance(first, last);
1253 
1254  current_size -= n_delete;
1255  p_buffer[current_size] = 0;
1256  cleanup();
1257 
1258  return first;
1259  }
1260 
1261  //*********************************************************************
1263  //*********************************************************************
1264  const_pointer c_str() const
1265  {
1266  return p_buffer;
1267  }
1268 
1269  //*********************************************************************
1274  //*********************************************************************
1275  size_type copy(pointer s, size_type len, size_type pos = 0)
1276  {
1277  if ((pos + len > size()))
1278  {
1279 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1280  set_truncated(true);
1281 
1282 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1283  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1284 #endif
1285 #endif
1286  }
1287 
1288  size_type endpos = etl::min(pos + len, size());
1289 
1290  for (size_type i = pos; i < endpos; ++i)
1291  {
1292  *s++ = p_buffer[i];
1293  }
1294 
1295  return endpos - pos;
1296  }
1297 
1298  //*********************************************************************
1302  //*********************************************************************
1303  size_type find(const ibasic_string<T>& str, size_type pos = 0) const
1304  {
1305  if ((pos + str.size()) > size())
1306  {
1307  return npos;
1308  }
1309 
1310  const_iterator iposition = etl::search(begin() + pos, end(), str.begin(), str.end());
1311 
1312  if (iposition == end())
1313  {
1314  return npos;
1315  }
1316  else
1317  {
1318  return etl::distance(begin(), iposition);
1319  }
1320  }
1321 
1322  //*********************************************************************
1326  //*********************************************************************
1327  size_type find(const_pointer s, size_type pos = 0) const
1328  {
1329 #if defined(ETL_DEBUG)
1330  if ((pos + etl::strlen(s)) > size())
1331  {
1332  return npos;
1333  }
1334 #endif
1335 
1336  const_iterator iposition = etl::search(begin() + pos, end(), s, s + etl::strlen(s));
1337 
1338  if (iposition == end())
1339  {
1340  return npos;
1341  }
1342  else
1343  {
1344  return etl::distance(begin(), iposition);
1345  }
1346  }
1347 
1348  //*********************************************************************
1353  //*********************************************************************
1354  size_type find(const_pointer s, size_type pos, size_type n) const
1355  {
1356 #if defined(ETL_DEBUG)
1357  if ((pos + etl::strlen(s) - n) > size())
1358  {
1359  return npos;
1360  }
1361 #endif
1362 
1363  const_iterator iposition = etl::search(begin() + pos, end(), s, s + n);
1364 
1365  if (iposition == end())
1366  {
1367  return npos;
1368  }
1369  else
1370  {
1371  return etl::distance(begin(), iposition);
1372  }
1373  }
1374 
1375  //*********************************************************************
1379  //*********************************************************************
1380  size_type find(T c, size_type position = 0) const
1381  {
1382  const_iterator i = etl::find(begin() + position, end(), c);
1383 
1384  if (i != end())
1385  {
1386  return etl::distance(begin(), i);
1387  }
1388  else
1389  {
1390  return npos;
1391  }
1392  }
1393 
1394  //*********************************************************************
1398  //*********************************************************************
1399  size_type rfind(const ibasic_string<T>& str, size_type position = npos) const
1400  {
1401  if ((str.size()) > size())
1402  {
1403  return npos;
1404  }
1405 
1406  if (position >= size())
1407  {
1408  position = size();
1409  }
1410 
1411  position = size() - position;
1412 
1413  const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), str.rbegin(), str.rend());
1414 
1415  if (iposition == rend())
1416  {
1417  return npos;
1418  }
1419  else
1420  {
1421  return size() - str.size() - etl::distance(rbegin(), iposition);
1422  }
1423  }
1424 
1425  //*********************************************************************
1429  //*********************************************************************
1430  size_type rfind(const_pointer s, size_type position = npos) const
1431  {
1432  size_type len = etl::strlen(s);
1433 
1434  if (len > size())
1435  {
1436  return npos;
1437  }
1438 
1439  if (position >= size())
1440  {
1441  position = size();
1442  }
1443 
1444  position = size() - position;
1445 
1446  const_reverse_iterator srbegin(s + len);
1447  const_reverse_iterator srend(s);
1448 
1449  const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), srbegin, srend);
1450 
1451  if (iposition == rend())
1452  {
1453  return npos;
1454  }
1455  else
1456  {
1457  return size() - len - etl::distance(rbegin(), iposition);
1458  }
1459  }
1460 
1461  //*********************************************************************
1465  //*********************************************************************
1466  size_type rfind(const_pointer s, size_type position, size_type length_) const
1467  {
1468  if (length_ > size())
1469  {
1470  return npos;
1471  }
1472 
1473  if (position >= size())
1474  {
1475  position = size();
1476  }
1477 
1478  position = size() - position;
1479 
1480  const_reverse_iterator srbegin(s + length_);
1481  const_reverse_iterator srend(s);
1482 
1483  const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), srbegin, srend);
1484 
1485  if (iposition == rend())
1486  {
1487  return npos;
1488  }
1489  else
1490  {
1491  return size() - length_ - etl::distance(rbegin(), iposition);
1492  }
1493  }
1494 
1495  //*********************************************************************
1499  //*********************************************************************
1500  size_type rfind(T c, size_type position = npos) const
1501  {
1502  if (position >= size())
1503  {
1504  position = size();
1505  }
1506 
1507  position = size() - position;
1508 
1509  const_reverse_iterator i = etl::find(rbegin() + position, rend(), c);
1510 
1511  if (i != rend())
1512  {
1513  return size() - etl::distance(rbegin(), i) - 1;
1514  }
1515  else
1516  {
1517  return npos;
1518  }
1519  }
1520 
1521  //*********************************************************************
1526  //*********************************************************************
1527  ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str)
1528  {
1529  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1530 
1531  // Limit the length.
1532  length_ = etl::min(length_, size() - position);
1533 
1534  // Erase the bit we want to replace.
1535  erase(position, length_);
1536 
1537  // Insert the new stuff.
1538  insert(position, str);
1539 
1540  return *this;
1541  }
1542 
1543  //*********************************************************************
1548  //*********************************************************************
1549  ibasic_string& replace(const_iterator first, const_iterator last, const ibasic_string& str)
1550  {
1551  // Quick hack, as iterators are pointers.
1552  iterator first_ = const_cast<iterator>(first);
1553  iterator last_ = const_cast<iterator>(last);
1554 
1555  // Erase the bit we want to replace.
1556  erase(first_, last_);
1557 
1558  // Insert the new stuff.
1559  insert(first_, str.begin(), str.end());
1560 
1561 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1562  if (str.is_truncated())
1563  {
1564  set_truncated(true);
1565 
1566 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1567  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1568 #endif
1569  }
1570 #endif
1571 
1572  return *this;
1573  }
1574 
1575  //*********************************************************************
1577  //*********************************************************************
1578  ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength)
1579  {
1580  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1581  ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1582 
1583  // Limit the lengths.
1584  length_ = etl::min(length_, size() - position);
1585  sublength = etl::min(sublength, str.size() - subposition);
1586 
1587  // Erase the bit we want to replace.
1588  erase(position, length_);
1589 
1590  // Insert the new stuff.
1591  insert(position, str, subposition, sublength);
1592 
1593 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
1594  if (str.is_truncated())
1595  {
1596  set_truncated(true);
1597 
1598 #if defined(ETL_STRING_TRUNCATION_IS_ERROR)
1599  ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation));
1600 #endif
1601  }
1602 #endif
1603 
1604  return *this;
1605  }
1606 
1607  //*********************************************************************
1609  //*********************************************************************
1610  ibasic_string& replace(size_type position, size_type length_, const_pointer s)
1611  {
1612  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1613 
1614  // Limit the length.
1615  length_ = etl::min(length_, size() - position);
1616 
1617  // Erase the bit we want to replace.
1618  erase(position, length_);
1619 
1620  // Insert the new stuff.
1621  insert(position, s, etl::strlen(s));
1622 
1623  return *this;
1624  }
1625 
1626  //*********************************************************************
1628  //*********************************************************************
1629  ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s)
1630  {
1631  // Quick hack, as iterators are pointers.
1632  iterator first_ = const_cast<iterator>(first);
1633  iterator last_ = const_cast<iterator>(last);
1634 
1635  // Erase the bit we want to replace.
1636  erase(first_, last_);
1637 
1638  // Insert the new stuff.
1639  insert(first_, s, s + etl::strlen(s));
1640 
1641  return *this;
1642  }
1643 
1644  //*********************************************************************
1646  //*********************************************************************
1647  ibasic_string& replace(size_type position, size_type length_, const_pointer s, size_type n)
1648  {
1649  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1650 
1651  // Limit the length.
1652  length_ = etl::min(length_, size() - position);
1653 
1654  // Erase the bit we want to replace.
1655  erase(position, length_);
1656 
1657  // Insert the new stuff.
1658  insert(position, s, n);
1659 
1660  return *this;
1661  }
1662 
1663  //*********************************************************************
1665  //*********************************************************************
1666  ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s, size_type n)
1667  {
1668  // Quick hack, as iterators are pointers.
1669  iterator first_ = const_cast<iterator>(first);
1670  iterator last_ = const_cast<iterator>(last);
1671 
1672  // Erase the bit we want to replace.
1673  erase(first_, last_);
1674 
1675  // Insert the new stuff.
1676  insert(first_, s, s + n);
1677 
1678  return *this;
1679  }
1680 
1681  //*********************************************************************
1683  //*********************************************************************
1684  ibasic_string& replace(size_type position, size_type length_, size_type n, value_type c)
1685  {
1686  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1687 
1688  // Limit the length.
1689  length_ = etl::min(length_, size() - position);
1690 
1691  // Erase the bit we want to replace.
1692  erase(position, length_);
1693 
1694  // Insert the new stuff.
1695  insert(position, n, c);
1696 
1697  return *this;
1698  }
1699 
1700  //*********************************************************************
1702  //*********************************************************************
1703  ibasic_string& replace(const_iterator first, const_iterator last, size_type n, value_type c)
1704  {
1705  // Quick hack, as iterators are pointers.
1706  iterator first_ = const_cast<iterator>(first);
1707  iterator last_ = const_cast<iterator>(last);
1708 
1709  // Erase the bit we want to replace.
1710  erase(first_, last_);
1711 
1712  // Insert the new stuff.
1713  insert(first_, n, c);
1714 
1715  return *this;
1716  }
1717 
1718  //*********************************************************************
1720  //*********************************************************************
1721  template <typename TIterator>
1722  ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace)
1723  {
1724  // Quick hack, as iterators are pointers.
1725  iterator first_ = const_cast<iterator>(first);
1726  iterator last_ = const_cast<iterator>(last);
1727 
1728  // Erase the bit we want to replace.
1729  erase(first_, last_);
1730 
1731  // Insert the new stuff.
1732  insert(first_, first_replace, last_replace);
1733 
1734  return *this;
1735  }
1736 
1737  //*************************************************************************
1739  //*************************************************************************
1740  int compare(const ibasic_string& str) const
1741  {
1742  return compare(p_buffer,
1743  p_buffer + size(),
1744  str.p_buffer,
1745  str.p_buffer + str.size());
1746  }
1747 
1748  //*************************************************************************
1750  //*************************************************************************
1751  int compare(size_type position, size_type length_, const ibasic_string& str) const
1752  {
1753  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1754 
1755  // Limit the length.
1756  length_ = etl::min(length_, size() - position);
1757 
1758  return compare(p_buffer + position,
1759  p_buffer + position + length_,
1760  str.p_buffer,
1761  str.p_buffer + str.size());
1762  }
1763 
1764  //*************************************************************************
1766  //*************************************************************************
1767  int compare(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength) const
1768  {
1769  ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
1770  ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
1771 
1772  // Limit the lengths.
1773  length_ = etl::min(length_, size() - position);
1774  sublength = etl::min(sublength, str.size() - subposition);
1775 
1776  return compare(p_buffer + position,
1777  p_buffer + position + length_,
1778  str.p_buffer + subposition,
1779  str.p_buffer + subposition + sublength);
1780  }
1781 
1782  //*************************************************************************
1784  //*************************************************************************
1785  int compare(const value_type* s) const
1786  {
1787  return compare(p_buffer,
1788  p_buffer + size(),
1789  s,
1790  s + etl::strlen(s));
1791  }
1792 
1793  //*************************************************************************
1795  //*************************************************************************
1796  int compare(size_type position, size_type length_, const_pointer s) const
1797  {
1798  return compare(p_buffer + position,
1799  p_buffer + position + length_,
1800  s,
1801  s + etl::strlen(s));
1802  }
1803 
1804  //*************************************************************************
1806  //*************************************************************************
1807  int compare(size_type position, size_type length_, const_pointer s, size_type n) const
1808  {
1809  return compare(p_buffer + position,
1810  p_buffer + position + length_,
1811  s,
1812  s + n);
1813  }
1814 
1815  //*********************************************************************
1819  //*********************************************************************
1820  size_type find_first_of(const ibasic_string<T>& str, size_type position = 0) const
1821  {
1822  return find_first_of(str.c_str(), position, str.size());
1823  }
1824 
1825  //*********************************************************************
1829  //*********************************************************************
1830  size_type find_first_of(const_pointer s, size_type position = 0) const
1831  {
1832  return find_first_of(s, position, etl::strlen(s));
1833  }
1834 
1835  //*********************************************************************
1840  //*********************************************************************
1841  size_type find_first_of(const_pointer s, size_type position, size_type n) const
1842  {
1843  if (position < size())
1844  {
1845  for (size_type i = position; i < size(); ++i)
1846  {
1847  for (size_type j = 0; j < n; ++j)
1848  {
1849  if (p_buffer[i] == s[j])
1850  {
1851  return i;
1852  }
1853  }
1854  }
1855  }
1856 
1857  return npos;
1858  }
1859 
1860  //*********************************************************************
1864  //*********************************************************************
1865  size_type find_first_of(value_type c, size_type position = 0) const
1866  {
1867  if (position < size())
1868  {
1869  for (size_type i = position; i < size(); ++i)
1870  {
1871  if (p_buffer[i] == c)
1872  {
1873  return i;
1874  }
1875  }
1876  }
1877 
1878  return npos;
1879  }
1880 
1881  //*********************************************************************
1885  //*********************************************************************
1886  size_type find_last_of(const ibasic_string<T>& str, size_type position = npos) const
1887  {
1888  return find_last_of(str.c_str(), position, str.size());
1889  }
1890 
1891  //*********************************************************************
1895  //*********************************************************************
1896  size_type find_last_of(const_pointer s, size_type position = npos) const
1897  {
1898  return find_last_of(s, position, etl::strlen(s));
1899  }
1900 
1901  //*********************************************************************
1906  //*********************************************************************
1907  size_type find_last_of(const_pointer s, size_type position, size_type n) const
1908  {
1909  if (empty())
1910  {
1911  return npos;
1912  }
1913 
1914  position = etl::min(position, size() - 1);
1915 
1916  const_reverse_iterator it = rbegin() + size() - position - 1;
1917 
1918  while (it != rend())
1919  {
1920  for (size_type j = 0; j < n; ++j)
1921  {
1922  if (p_buffer[position] == s[j])
1923  {
1924  return position;
1925  }
1926  }
1927 
1928  ++it;
1929  --position;
1930  }
1931 
1932  return npos;
1933  }
1934 
1935  //*********************************************************************
1939  //*********************************************************************
1940  size_type find_last_of(value_type c, size_type position = npos) const
1941  {
1942  if (empty())
1943  {
1944  return npos;
1945  }
1946 
1947  position = etl::min(position, size() - 1);
1948 
1949  const_reverse_iterator it = rbegin() + size() - position - 1;
1950 
1951  while (it != rend())
1952  {
1953  if (p_buffer[position] == c)
1954  {
1955  return position;
1956  }
1957 
1958  ++it;
1959  --position;
1960  }
1961 
1962  return npos;
1963  }
1964 
1965  //*********************************************************************
1969  //*********************************************************************
1970  size_type find_first_not_of(const ibasic_string<T>& str, size_type position = 0) const
1971  {
1972  return find_first_not_of(str.c_str(), position, str.size());
1973  }
1974 
1975  //*********************************************************************
1979  //*********************************************************************
1980  size_type find_first_not_of(const_pointer s, size_type position = 0) const
1981  {
1982  return find_first_not_of(s, position, etl::strlen(s));
1983  }
1984 
1985  //*********************************************************************
1990  //*********************************************************************
1991  size_type find_first_not_of(const_pointer s, size_type position, size_type n) const
1992  {
1993  if (position < size())
1994  {
1995  for (size_type i = position; i < size(); ++i)
1996  {
1997  bool found = false;
1998 
1999  for (size_type j = 0; j < n; ++j)
2000  {
2001  if (p_buffer[i] == s[j])
2002  {
2003  found = true;
2004  }
2005  }
2006 
2007  if (!found)
2008  {
2009  return i;
2010  }
2011  }
2012  }
2013 
2014  return npos;
2015  }
2016 
2017  //*********************************************************************
2021  //*********************************************************************
2022  size_type find_first_not_of(value_type c, size_type position = 0) const
2023  {
2024  if (position < size())
2025  {
2026  for (size_type i = position; i < size(); ++i)
2027  {
2028  if (p_buffer[i] != c)
2029  {
2030  return i;
2031  }
2032  }
2033  }
2034 
2035  return npos;
2036  }
2037 
2038  //*********************************************************************
2042  //*********************************************************************
2043  size_type find_last_not_of(const ibasic_string<T>& str, size_type position = npos) const
2044  {
2045  return find_last_not_of(str.c_str(), position, str.size());
2046  }
2047 
2048  //*********************************************************************
2052  //*********************************************************************
2053  size_type find_last_not_of(const_pointer s, size_type position = npos) const
2054  {
2055  return find_last_not_of(s, position, etl::strlen(s));
2056  }
2057 
2058  //*********************************************************************
2063  //*********************************************************************
2064  size_type find_last_not_of(const_pointer s, size_type position, size_type n) const
2065  {
2066  if (empty())
2067  {
2068  return npos;
2069  }
2070 
2071  position = etl::min(position, size() - 1);
2072 
2073  const_reverse_iterator it = rbegin() + size() - position - 1;
2074 
2075  while (it != rend())
2076  {
2077  bool found = false;
2078 
2079  for (size_type j = 0; j < n; ++j)
2080  {
2081  if (p_buffer[position] == s[j])
2082  {
2083  found = true;
2084  }
2085  }
2086 
2087  if (!found)
2088  {
2089  return position;
2090  }
2091 
2092  ++it;
2093  --position;
2094  }
2095 
2096  return npos;
2097  }
2098 
2099  //*********************************************************************
2100  //
2101  //*********************************************************************
2102  size_type find_last_not_of(value_type c, size_type position = npos) const
2103  {
2104  if (empty())
2105  {
2106  return npos;
2107  }
2108 
2109  position = etl::min(position, size() - 1);
2110 
2111  const_reverse_iterator it = rbegin() + size() - position - 1;
2112 
2113  while (it != rend())
2114  {
2115  if (p_buffer[position] != c)
2116  {
2117  return position;
2118  }
2119 
2120  ++it;
2121  --position;
2122  }
2123 
2124  return npos;
2125  }
2126 
2127  //*************************************************************************
2129  //*************************************************************************
2131  {
2132  if (&rhs != this)
2133  {
2134  assign(rhs);
2135  }
2136 
2137  return *this;
2138  }
2139 
2140  //*************************************************************************
2142  //*************************************************************************
2143  ibasic_string& operator = (const_pointer rhs)
2144  {
2145  assign(rhs);
2146 
2147  return *this;
2148  }
2149 
2150  //*************************************************************************
2152  //*************************************************************************
2154  {
2155  append(rhs);
2156 
2157  return *this;
2158  }
2159 
2160  //*************************************************************************
2162  //*************************************************************************
2163  ibasic_string& operator += (const_pointer rhs)
2164  {
2165  append(rhs);
2166 
2167  return *this;
2168  }
2169 
2170  //*************************************************************************
2172  //*************************************************************************
2174  {
2175  append(size_type(1), rhs);
2176 
2177  return *this;
2178  }
2179 
2180 #ifdef ETL_ISTRING_REPAIR_ENABLE
2181  //*************************************************************************
2183  //*************************************************************************
2184  virtual void repair() = 0;
2185 #endif
2186 
2187  protected:
2188 
2189  //*********************************************************************
2191  //*********************************************************************
2192  ibasic_string(T* p_buffer_, size_type MAX_SIZE_)
2193  : string_base(MAX_SIZE_),
2194  p_buffer(p_buffer_)
2195  {
2196  }
2197 
2198  //*********************************************************************
2200  //*********************************************************************
2201  void initialise()
2202  {
2203  current_size = 0;
2204  cleanup();
2205  p_buffer[0] = 0;
2206 #if ETL_STRING_TRUNCATION_CHECKS_ENABLED
2207  set_truncated(false);
2208 #endif
2209  }
2210 
2211  //*************************************************************************
2213  //*************************************************************************
2214  void repair_buffer(T* p_buffer_)
2215  {
2216  p_buffer = p_buffer_;
2217  }
2218 
2219  private:
2220 
2221  //*************************************************************************
2223  //*************************************************************************
2224  int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2) const
2225  {
2226  while ((first1 != last1) && (first2 != last2))
2227  {
2228  if (*first1 < *first2)
2229  {
2230  // Compared character is lower.
2231  return -1;
2232  }
2233  else if (*first1 > *first2)
2234  {
2235  // Compared character is higher.
2236  return 1;
2237  }
2238 
2239  ++first1;
2240  ++first2;
2241  }
2242 
2243  // We reached the end of one or both of the strings.
2244  if ((first1 == last1) && (first2 == last2))
2245  {
2246  // Same length.
2247  return 0;
2248  }
2249  else if (first1 == last1)
2250  {
2251  // Compared string is shorter.
2252  return -1;
2253  }
2254  else
2255  {
2256  // Compared string is longer.
2257  return 1;
2258  }
2259  }
2260 
2261  //*************************************************************************
2263  //*************************************************************************
2264  void cleanup()
2265  {
2266 #if ETL_STRING_CLEAR_AFTER_USE_ENABLED
2267  if (is_secure())
2268  {
2269  etl::memory_clear_range(&p_buffer[current_size], &p_buffer[CAPACITY]);
2270  }
2271 #endif
2272  }
2273 
2274  //*************************************************************************
2276  //*************************************************************************
2277  ibasic_string(const ibasic_string&);
2278 
2279  //*************************************************************************
2281  //*************************************************************************
2282  T* p_buffer;
2283 
2284  //*************************************************************************
2286  //*************************************************************************
2287 #if defined(ETL_POLYMORPHIC_STRINGS) || defined(ETL_POLYMORPHIC_CONTAINERS)
2288  public:
2289  virtual
2290 #else
2291  protected:
2292 #endif
2294  {
2295 #if ETL_STRING_CLEAR_AFTER_USE_ENABLED
2296  if (is_secure())
2297  {
2298  initialise();
2299  }
2300 #endif
2301  }
2302  };
2303 
2304  //***************************************************************************
2310  //***************************************************************************
2311  template <typename T>
2313  {
2314  return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
2315  }
2316 
2317  //***************************************************************************
2323  //***************************************************************************
2324  template <typename T>
2325  bool operator ==(const etl::ibasic_string<T>& lhs, const T* rhs)
2326  {
2327  return (lhs.size() == etl::strlen(rhs)) && etl::equal(lhs.begin(), lhs.end(), rhs);
2328  }
2329 
2330  //***************************************************************************
2336  //***************************************************************************
2337  template <typename T>
2338  bool operator ==(const T* lhs, const etl::ibasic_string<T>& rhs)
2339  {
2340  return (rhs.size() == etl::strlen(lhs)) && etl::equal(rhs.begin(), rhs.end(), lhs);
2341  }
2342 
2343 
2344  //***************************************************************************
2350  //***************************************************************************
2351  template <typename T>
2353  {
2354  return !(lhs == rhs);
2355  }
2356 
2357  //***************************************************************************
2363  //***************************************************************************
2364  template <typename T>
2365  bool operator !=(const etl::ibasic_string<T>& lhs, const T* rhs)
2366  {
2367  return !(lhs == rhs);
2368  }
2369 
2370  //***************************************************************************
2376  //***************************************************************************
2377  template <typename T>
2378  bool operator !=(const T* lhs, const etl::ibasic_string<T>& rhs)
2379  {
2380  return !(lhs == rhs);
2381  }
2382 
2383  //***************************************************************************
2389  //***************************************************************************
2390  template <typename T>
2392  {
2393  return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
2394  }
2395 
2396  //***************************************************************************
2402  //***************************************************************************
2403  template <typename T>
2404  bool operator <(const etl::ibasic_string<T>& lhs, const T* rhs)
2405  {
2406  return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs));
2407  }
2408 
2409  //***************************************************************************
2415  //***************************************************************************
2416  template <typename T>
2417  bool operator <(const T* lhs, const etl::ibasic_string<T>& rhs)
2418  {
2419  return etl::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end());
2420  }
2421 
2422 
2423  //***************************************************************************
2429  //***************************************************************************
2430  template <typename T>
2432  {
2433  return (rhs < lhs);
2434  }
2435 
2436  //***************************************************************************
2442  //***************************************************************************
2443  template <typename T>
2444  bool operator >(const etl::ibasic_string<T>& lhs, const T* rhs)
2445  {
2446  return (rhs < lhs);
2447  }
2448 
2449  //***************************************************************************
2455  //***************************************************************************
2456  template <typename T>
2457  bool operator >(const T* lhs, const etl::ibasic_string<T>& rhs)
2458  {
2459  return (rhs < lhs);
2460  }
2461 
2462 
2463  //***************************************************************************
2469  //***************************************************************************
2470  template <typename T>
2472  {
2473  return !(lhs > rhs);
2474  }
2475 
2476  //***************************************************************************
2482  //***************************************************************************
2483  template <typename T>
2484  bool operator <=(const etl::ibasic_string<T>& lhs, const T* rhs)
2485  {
2486  return !(lhs > rhs);
2487  }
2488 
2489  //***************************************************************************
2495  //***************************************************************************
2496  template <typename T>
2497  bool operator <=(const T* lhs, const etl::ibasic_string<T>& rhs)
2498  {
2499  return !(lhs > rhs);
2500  }
2501 
2502 
2503  //***************************************************************************
2509  //***************************************************************************
2510  template <typename T>
2512  {
2513  return !(lhs < rhs);
2514  }
2515 
2516  //***************************************************************************
2522  //***************************************************************************
2523  template <typename T>
2524  bool operator >=(const etl::ibasic_string<T>& lhs, const T* rhs)
2525  {
2526  return !(lhs < rhs);
2527  }
2528 
2529  //***************************************************************************
2535  //***************************************************************************
2536  template <typename T>
2537  bool operator >=(const T* lhs, const etl::ibasic_string<T>& rhs)
2538  {
2539  return !(lhs < rhs);
2540  }
2541 }
2542 
2543 #include "private/minmax_pop.h"
2544 
2545 #ifdef ETL_COMPILER_GCC
2546 #pragma GCC diagnostic pop
2547 #endif
2548 
2549 #undef ETL_FILE
2550 
2551 #endif
Definition: flags.h:55
ETL_CONSTEXPR14 flags< T, MASK > & set() ETL_NOEXCEPT
Set the bits.
Definition: flags.h:104
ETL_CONSTEXPR bool test() const ETL_NOEXCEPT
Tests bits.
Definition: flags.h:89
Definition: basic_string.h:321
int compare(size_type position, size_type length_, const ibasic_string &str) const
Compare position / length with string.
Definition: basic_string.h:1751
etl::ibasic_string< T > & insert(size_type position, const_pointer s, size_type n)
Definition: basic_string.h:1185
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 'subpsotion' of 'sublength'.
Definition: basic_string.h:1578
size_type find_last_of(const_pointer s, size_type position=npos) const
Definition: basic_string.h:1896
size_type rfind(const_pointer s, size_type position=npos) const
Definition: basic_string.h:1430
etl::ibasic_string< T > & insert(size_type position, const_pointer s)
Definition: basic_string.h:1171
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:1629
size_type find_last_not_of(const_pointer s, size_type position=npos) const
Definition: basic_string.h:2053
size_type find(const_pointer s, size_type pos=0) const
Definition: basic_string.h:1327
const_reverse_iterator rbegin() const
Definition: basic_string.h:405
etl::ibasic_string< T > & insert(size_type position, const etl::ibasic_string< T > &str, size_type subposition, size_type sublength)
Definition: basic_string.h:1140
reference operator[](size_type i)
Definition: basic_string.h:492
void assign(const etl::ibasic_string< T > &other, size_type subposition, size_type sublength)
Definition: basic_string.h:622
etl::ibasic_string< T > & insert(size_type position, const etl::ibasic_string< T > &str)
Definition: basic_string.h:1113
etl::ibasic_string< T > & insert(size_type position, size_type n, value_type c)
Definition: basic_string.h:1199
ibasic_string & operator+=(const ibasic_string &rhs)
+= operator.
Definition: basic_string.h:2153
size_type find_last_of(const ibasic_string< T > &str, size_type position=npos) const
Definition: basic_string.h:1886
size_type find_first_of(value_type c, size_type position=0) const
Definition: basic_string.h:1865
size_type find(T c, size_type position=0) const
Definition: basic_string.h:1380
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:1703
ibasic_string & operator=(const ibasic_string &rhs)
Assignment operator.
Definition: basic_string.h:2130
void pop_back()
Definition: basic_string.h:797
size_type rfind(const ibasic_string< T > &str, size_type position=npos) const
Definition: basic_string.h:1399
etl::ibasic_string< T > & erase(size_type position, size_type length_=npos)
Definition: basic_string.h:1213
size_type find_first_of(const ibasic_string< T > &str, size_type position=0) const
Definition: basic_string.h:1820
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:1647
const_reference back() const
Definition: basic_string.h:562
const_iterator begin() const
Definition: basic_string.h:351
const_pointer data() const
Definition: basic_string.h:580
ibasic_string & append(const ibasic_string &str, size_type subposition, size_type sublength=npos)
Definition: basic_string.h:833
size_type find_last_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:1907
reverse_iterator rbegin()
Definition: basic_string.h:396
void resize(size_type new_size)
Definition: basic_string.h:451
size_type find_last_not_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:2064
size_type find_first_not_of(const_pointer s, size_type position=0) const
Definition: basic_string.h:1980
size_type rfind(T c, size_type position=npos) const
Definition: basic_string.h:1500
size_type copy(pointer s, size_type len, size_type pos=0)
Definition: basic_string.h:1275
int compare(const value_type *s) const
Compare with C string.
Definition: basic_string.h:1785
int compare(size_type position, size_type length_, const_pointer s) const
Compare position / length with C string.
Definition: basic_string.h:1796
const_reference at(size_type i) const
Definition: basic_string.h:525
void clear()
Clears the string.
Definition: basic_string.h:764
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:1767
reverse_iterator rend()
Definition: basic_string.h:414
iterator erase(iterator i_element)
Definition: basic_string.h:1228
const_reverse_iterator crend() const
Definition: basic_string.h:441
reference at(size_type i)
Definition: basic_string.h:513
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:1722
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:1610
void insert(iterator position, TIterator first, TIterator last)
Definition: basic_string.h:1026
~ibasic_string()
Destructor.
Definition: basic_string.h:2293
size_type find(const_pointer s, size_type pos, size_type n) const
Definition: basic_string.h:1354
size_type find_first_of(const_pointer s, size_type position=0) const
Definition: basic_string.h:1830
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:1666
iterator begin()
Definition: basic_string.h:342
iterator end()
Definition: basic_string.h:360
void assign(TIterator first, TIterator last)
Definition: basic_string.h:711
void insert(const_iterator position, size_type n, T value)
Definition: basic_string.h:943
size_type find(const ibasic_string< T > &str, size_type pos=0) const
Definition: basic_string.h:1303
void push_back(T value)
Definition: basic_string.h:774
size_type find_first_not_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:1991
void assign(size_type n, T value)
Definition: basic_string.h:742
const_reverse_iterator crbegin() const
Definition: basic_string.h:432
iterator insert(const_iterator position, T value)
Definition: basic_string.h:891
ibasic_string(T *p_buffer_, size_type MAX_SIZE_)
Constructor.
Definition: basic_string.h:2192
const_reverse_iterator rend() const
Definition: basic_string.h:423
size_type find_last_not_of(const ibasic_string< T > &str, size_type position=npos) const
Definition: basic_string.h:2043
void assign(const etl::ibasic_string< T > &other)
Definition: basic_string.h:590
ibasic_string & append(TIterator first, TIterator last)
Definition: basic_string.h:880
const_iterator cend() const
Definition: basic_string.h:387
const_pointer c_str() const
Return a pointer to a C string.
Definition: basic_string.h:1264
void assign(const_pointer other, size_type length_)
Definition: basic_string.h:683
void resize(size_type new_size, T value)
Definition: basic_string.h:461
const_reference front() const
Definition: basic_string.h:544
pointer data()
Definition: basic_string.h:571
size_type find_first_not_of(value_type c, size_type position=0) const
Definition: basic_string.h:2022
size_type find_first_not_of(const ibasic_string< T > &str, size_type position=0) const
Definition: basic_string.h:1970
size_type find_last_of(value_type c, size_type position=npos) const
Definition: basic_string.h:1940
ibasic_string & append(const T *str, size_type n)
Definition: basic_string.h:857
ibasic_string & replace(const_iterator first, const_iterator last, const ibasic_string &str)
Definition: basic_string.h:1549
reference front()
Definition: basic_string.h:535
reference back()
Definition: basic_string.h:553
const_iterator cbegin() const
Definition: basic_string.h:378
void initialise()
Initialise the string.
Definition: basic_string.h:2201
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:1684
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:1807
size_type rfind(const_pointer s, size_type position, size_type length_) const
Definition: basic_string.h:1466
size_type find_first_of(const_pointer s, size_type position, size_type n) const
Definition: basic_string.h:1841
int compare(const ibasic_string &str) const
Compare with string.
Definition: basic_string.h:1740
ibasic_string & append(const T *str)
Definition: basic_string.h:846
const_iterator end() const
Definition: basic_string.h:369
ibasic_string & replace(size_type position, size_type length_, const ibasic_string &str)
Definition: basic_string.h:1527
iterator erase(iterator first, iterator last)
Definition: basic_string.h:1244
void repair_buffer(T *p_buffer_)
Fix the internal pointers after a low level memory copy.
Definition: basic_string.h:2214
ibasic_string & append(size_type n, T c)
Definition: basic_string.h:868
ibasic_string & append(const ibasic_string &str)
Definition: basic_string.h:809
void assign(const_pointer other)
Definition: basic_string.h:657
Definition: basic_string.h:150
void set_secure()
Sets the 'secure' flag to the requested state.
Definition: basic_string.h:261
bool is_secure() const
Gets the 'secure' state flag.
Definition: basic_string.h:269
const size_type CAPACITY
The maximum number of elements in the string.
Definition: basic_string.h:307
bool full() const
Definition: basic_string.h:195
~string_base()
Destructor.
Definition: basic_string.h:299
ETL_DEPRECATED bool truncated() const
Definition: basic_string.h:234
void set_truncated(bool status)
Sets the 'truncated' flag.
Definition: basic_string.h:290
size_type max_size() const
Definition: basic_string.h:213
string_base(size_type max_size_)
Constructor.
Definition: basic_string.h:280
void clear_truncated()
Clears the 'truncated' flag.
Definition: basic_string.h:251
size_type length() const
Definition: basic_string.h:177
size_type current_size
The current number of elements in the string.
Definition: basic_string.h:306
size_type available() const
Definition: basic_string.h:222
bool empty() const
Definition: basic_string.h:186
size_type capacity() const
Definition: basic_string.h:204
bool is_truncated() const
Definition: basic_string.h:243
size_type size() const
Definition: basic_string.h:168
Definition: basic_string.h:94
Definition: basic_string.h:80
Definition: basic_string.h:122
Definition: basic_string.h:108
Definition: basic_string.h:136
Definition: binary.h:361
#define ETL_ASSERT(b, e)
Definition: error_handler.h:290
exception(string_type reason_, string_type file_, numeric_type line_)
Constructor.
Definition: exception.h:67
Definition: exception.h:47
Definition: integral_limits.h:54
void memory_clear_range(volatile T *begin, size_t n)
Definition: memory.h:1827
Definition: absolute.h:37
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:633
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:594
size_t strlen(const T *t)
Alternative strlen for all character types.
Definition: char_traits.h:247
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:582
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:606
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:621