LCOV - code coverage report
Current view: top level - home/jenkins/libs/3rdparty/etl/include/etl - basic_string.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 58 72 80.6 %
Date: 2025-10-07 10:52:16 Functions: 18 21 85.7 %

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

Generated by: LCOV version 1.14