Containers (STL-compatible) StateMachines MessageBus and more for Embedded Systems. See www.etlcpp.com

Revision:
0:b47c2a7920c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/basic_string.h	Fri Mar 16 16:34:18 2018 +0000
@@ -0,0 +1,2226 @@
+///\file
+
+/******************************************************************************
+The MIT License(MIT)
+
+Embedded Template Library.
+https://github.com/ETLCPP/etl
+http://www.etlcpp.com
+
+Copyright(c) 2016 jwellbelove
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions :
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+******************************************************************************/
+
+#ifndef __ETL_BASIC_STRING__
+#define __ETL_BASIC_STRING__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <iterator>
+#include <algorithm>
+#include <functional>
+#include <string.h>
+
+#include "platform.h"
+#include "char_traits.h"
+#include "container.h"
+#include "alignment.h"
+#include "array.h"
+#include "algorithm.h"
+#include "type_traits.h"
+#include "error_handler.h"
+#include "integral_limits.h"
+#include "exception.h"
+
+#define ETL_FILE "27"
+
+#ifdef ETL_COMPILER_GCC
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#endif
+
+#ifdef ETL_COMPILER_MICROSOFT
+#undef min
+#endif
+
+#ifdef ETL_COMPILER_MICROSOFT
+#undef max
+#endif
+
+//*****************************************************************************
+///\defgroup basic_string basic_string
+/// A basic_string with the capacity defined at compile time.
+///\ingroup containers
+//*****************************************************************************
+
+namespace etl
+{
+  //***************************************************************************
+  /// Alternative strlen for all character types.
+  //***************************************************************************
+  template <typename T>
+  size_t strlen(const T* t)
+  {
+    return etl::char_traits<T>::length(t);
+  }
+
+  //***************************************************************************
+  ///\ingroup string
+  /// Exception base for strings
+  //***************************************************************************
+  class string_exception : public etl::exception
+  {
+  public:
+
+    string_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
+      : exception(reason_, file_name_, line_number_)
+    {
+    }
+  };
+
+  //***************************************************************************
+  ///\ingroup string
+  /// String empty exception.
+  //***************************************************************************
+  class string_empty : public etl::string_exception
+  {
+  public:
+
+    string_empty(string_type file_name_, numeric_type line_number_)
+      : string_exception(ETL_ERROR_TEXT("string:empty", ETL_FILE"A"), file_name_, line_number_)
+    {
+    }
+  };
+
+  //***************************************************************************
+  ///\ingroup string
+  /// String out of bounds exception.
+  //***************************************************************************
+  class string_out_of_bounds : public etl::string_exception
+  {
+  public:
+
+    string_out_of_bounds(string_type file_name_, numeric_type line_number_)
+      : string_exception(ETL_ERROR_TEXT("string:bounds", ETL_FILE"B"), file_name_, line_number_)
+    {
+    }
+  };
+
+  //***************************************************************************
+  ///\ingroup string
+  /// String iterator exception.
+  //***************************************************************************
+  class string_iterator : public etl::string_exception
+  {
+  public:
+
+    string_iterator(string_type file_name_, numeric_type line_number_)
+      : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_FILE"C"), file_name_, line_number_)
+    {
+    }
+  };
+
+  //***************************************************************************
+  ///\ingroup string
+  /// The base class for all templated string types.
+  //***************************************************************************
+  class string_base
+  {
+  public:
+
+    typedef size_t size_type;
+
+    enum
+    {
+      npos = etl::integral_limits<size_t>::max
+    };
+
+    //*************************************************************************
+    /// Gets the current size of the string.
+    ///\return The current size of the string.
+    //*************************************************************************
+    size_type size() const
+    {
+      return current_size;
+    }
+
+    //*************************************************************************
+    /// Gets the current size of the string.
+    ///\return The current size of the string.
+    //*************************************************************************
+    size_type length() const
+    {
+      return current_size;
+    }
+
+    //*************************************************************************
+    /// Checks the 'empty' state of the string.
+    ///\return <b>true</b> if empty.
+    //*************************************************************************
+    bool empty() const
+    {
+      return (current_size == 0);
+    }
+
+    //*************************************************************************
+    /// Checks the 'full' state of the string.
+    ///\return <b>true</b> if full.
+    //*************************************************************************
+    bool full() const
+    {
+      return current_size == CAPACITY;
+    }
+
+    //*************************************************************************
+    /// Returns the capacity of the string.
+    ///\return The capacity of the string.
+    //*************************************************************************
+    size_type capacity() const
+    {
+      return CAPACITY;
+    }
+
+    //*************************************************************************
+    /// Returns the maximum possible size of the string.
+    ///\return The maximum size of the string.
+    //*************************************************************************
+    size_type max_size() const
+    {
+      return CAPACITY;
+    }
+
+    //*************************************************************************
+    /// Returns the remaining capacity.
+    ///\return The remaining capacity.
+    //*************************************************************************
+    size_t available() const
+    {
+      return max_size() - size();
+    }
+
+    //*************************************************************************
+    /// Returns whether the string was truncated by the last operation.
+    ///\return Whether the string was truncated by the last operation.
+    //*************************************************************************
+    size_t truncated() const
+    {
+      return is_truncated;
+    }
+
+  protected:
+
+    //*************************************************************************
+    /// Constructor.
+    //*************************************************************************
+    string_base(size_type max_size_)
+      : is_truncated(false),
+        current_size(0),
+        CAPACITY(max_size_)
+    {
+    }
+
+    bool            is_truncated; ///< Set to true if the operation truncated the string.
+    size_type       current_size; ///< The current number of elements in the string.
+    const size_type CAPACITY;     ///< The maximum number of elements in the string.
+  };
+
+  //***************************************************************************
+  /// The base class for specifically sized strings.
+  /// Can be used as a reference type for all strings containing a specific type.
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  class ibasic_string : public etl::string_base
+  {
+  public:
+
+    typedef T                                     value_type;
+    typedef T&                                    reference;
+    typedef const T&                              const_reference;
+    typedef T*                                    pointer;
+    typedef const T*                              const_pointer;
+    typedef T*                                    iterator;
+    typedef const T*                              const_iterator;
+    typedef std::reverse_iterator<iterator>       reverse_iterator;
+    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+    typedef size_t                                size_type;
+
+    typedef typename std::iterator_traits<iterator>::difference_type difference_type;
+
+    //*********************************************************************
+    /// Returns an iterator to the beginning of the string.
+    ///\return An iterator to the beginning of the string.
+    //*********************************************************************
+    iterator begin()
+    {
+      return &p_buffer[0];
+    }
+
+    //*********************************************************************
+    /// Returns a const_iterator to the beginning of the string.
+    ///\return A const iterator to the beginning of the string.
+    //*********************************************************************
+    const_iterator begin() const
+    {
+      return &p_buffer[0];
+    }
+
+    //*********************************************************************
+    /// Returns an iterator to the end of the string.
+    ///\return An iterator to the end of the string.
+    //*********************************************************************
+    iterator end()
+    {
+      return &p_buffer[current_size];
+    }
+
+    //*********************************************************************
+    /// Returns a const_iterator to the end of the string.
+    ///\return A const iterator to the end of the string.
+    //*********************************************************************
+    const_iterator end() const
+    {
+      return &p_buffer[current_size];
+    }
+
+    //*********************************************************************
+    /// Returns a const_iterator to the beginning of the string.
+    ///\return A const iterator to the beginning of the string.
+    //*********************************************************************
+    const_iterator cbegin() const
+    {
+      return &p_buffer[0];
+    }
+
+    //*********************************************************************
+    /// Returns a const_iterator to the end of the string.
+    ///\return A const iterator to the end of the string.
+    //*********************************************************************
+    const_iterator cend() const
+    {
+      return &p_buffer[current_size];
+    }
+
+    //*********************************************************************
+    /// Returns an reverse iterator to the reverse beginning of the string.
+    ///\return Iterator to the reverse beginning of the string.
+    //*********************************************************************
+    reverse_iterator rbegin()
+    {
+      return reverse_iterator(end());
+    }
+
+    //*********************************************************************
+    /// Returns a const reverse iterator to the reverse beginning of the string.
+    ///\return Const iterator to the reverse beginning of the string.
+    //*********************************************************************
+    const_reverse_iterator rbegin() const
+    {
+      return const_reverse_iterator(end());
+    }
+
+    //*********************************************************************
+    /// Returns a reverse iterator to the end + 1 of the string.
+    ///\return Reverse iterator to the end + 1 of the string.
+    //*********************************************************************
+    reverse_iterator rend()
+    {
+      return reverse_iterator(begin());
+    }
+
+    //*********************************************************************
+    /// Returns a const reverse iterator to the end + 1 of the string.
+    ///\return Const reverse iterator to the end + 1 of the string.
+    //*********************************************************************
+    const_reverse_iterator rend() const
+    {
+      return const_reverse_iterator(begin());
+    }
+
+    //*********************************************************************
+    /// Returns a const reverse iterator to the reverse beginning of the string.
+    ///\return Const reverse iterator to the reverse beginning of the string.
+    //*********************************************************************
+    const_reverse_iterator crbegin() const
+    {
+      return const_reverse_iterator(cend());
+    }
+
+    //*********************************************************************
+    /// Returns a const reverse iterator to the end + 1 of the string.
+    ///\return Const reverse iterator to the end + 1 of the string.
+    //*********************************************************************
+    const_reverse_iterator crend() const
+    {
+      return const_reverse_iterator(cbegin());
+    }
+
+    //*********************************************************************
+    /// Resizes the string.
+    /// If asserts or exceptions are enabled and the new size is larger than the
+    ///\param new_size The new size.
+    //*********************************************************************
+    void resize(size_t new_size)
+    {
+      resize(new_size, 0);
+    }
+
+    //*********************************************************************
+    /// Resizes the string.
+    ///\param new_size The new size.
+    ///\param value    The value to fill new elements with. Default = default constructed value.
+    //*********************************************************************
+    void resize(size_t new_size, T value)
+    {
+      new_size = std::min(new_size, CAPACITY);
+
+      // Size up?
+      if (new_size > current_size)
+      {
+        std::fill(p_buffer + current_size, p_buffer + new_size, value);
+      }
+
+      current_size = new_size;
+      p_buffer[new_size] = 0;
+    }
+
+    //*********************************************************************
+    /// Returns a reference to the value at index 'i'
+    ///\param i The index.
+    ///\return A reference to the value at index 'i'
+    //*********************************************************************
+    reference operator [](size_t i)
+    {
+      return p_buffer[i];
+    }
+
+    //*********************************************************************
+    /// Returns a const reference to the value at index 'i'
+    ///\param i The index.
+    ///\return A const reference to the value at index 'i'
+    //*********************************************************************
+    const_reference operator [](size_t i) const
+    {
+      return p_buffer[i];
+    }
+
+    //*********************************************************************
+    /// Returns a reference to the value at index 'i'
+    /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range.
+    ///\param i The index.
+    ///\return A reference to the value at index 'i'
+    //*********************************************************************
+    reference at(size_t i)
+    {
+      ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
+      return p_buffer[i];
+    }
+
+    //*********************************************************************
+    /// Returns a const reference to the value at index 'i'
+    /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range.
+    ///\param i The index.
+    ///\return A const reference to the value at index 'i'
+    //*********************************************************************
+    const_reference at(size_t i) const
+    {
+      ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
+      return p_buffer[i];
+    }
+
+    //*********************************************************************
+    /// Returns a reference to the first element.
+    ///\return A reference to the first element.
+    //*********************************************************************
+    reference front()
+    {
+      return p_buffer[0];
+    }
+
+    //*********************************************************************
+    /// Returns a const reference to the first element.
+    ///\return A const reference to the first element.
+    //*********************************************************************
+    const_reference front() const
+    {
+      return p_buffer[0];
+    }
+
+    //*********************************************************************
+    /// Returns a reference to the last element.
+    ///\return A reference to the last element.
+    //*********************************************************************
+    reference back()
+    {
+      return p_buffer[current_size - 1];
+    }
+
+    //*********************************************************************
+    /// Returns a const reference to the last element.
+    ///\return A const reference to the last element.
+    //*********************************************************************
+    const_reference back() const
+    {
+      return p_buffer[current_size - 1];
+    }
+
+    //*********************************************************************
+    /// Returns a pointer to the beginning of the string data.
+    ///\return A pointer to the beginning of the string data.
+    //*********************************************************************
+    pointer data()
+    {
+      return p_buffer;
+    }
+
+    //*********************************************************************
+    /// Returns a const pointer to the beginning of the string data.
+    ///\return A const pointer to the beginning of the string data.
+    //*********************************************************************
+    const_pointer data() const
+    {
+      return p_buffer;
+    }
+
+    //*********************************************************************
+    /// Assigns values to the string.
+    /// Truncates if the string does not have enough free space.
+    ///\param other The other string.
+    //*********************************************************************
+    void assign(const etl::ibasic_string<T>& other)
+    {
+      size_t len = std::min(CAPACITY, other.size());
+      assign(other.begin(), other.begin() + len);
+    }
+
+    //*********************************************************************
+    /// Assigns values to the string.
+    /// Truncates if the string does not have enough free space.
+    ///\param other The other string.
+    ///\param subposition The position to start from.
+    ///\param sublength   The length to copy.
+    //*********************************************************************
+    void assign(const etl::ibasic_string<T>& other, size_t subposition, size_t sublength)
+    {
+      if (sublength == npos)
+      {
+        sublength = other.size() - subposition;
+      }
+
+      ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds));
+
+      assign(other.begin() + subposition, sublength);
+    }
+
+    //*********************************************************************
+    /// Assigns values to the string.
+    /// Truncates if the string does not have enough free space.
+    ///\param other The other string.
+    //*********************************************************************
+    void assign(const_pointer other)
+    {
+      initialise();
+
+      while ((*other != 0) && (current_size < CAPACITY))
+      {
+        p_buffer[current_size++] = *other++;
+      }
+
+      is_truncated = (*other != 0);
+
+      p_buffer[current_size] = 0;
+    }
+
+    //*********************************************************************
+    /// Assigns values to the string.
+    /// Truncates if the string does not have enough free space.
+    ///\param other The other string.
+    ///\param length The length to copy.
+    //*********************************************************************
+    void assign(const_pointer other, size_t length_)
+    {
+      length_ = std::min(length_, CAPACITY);
+
+      initialise();
+
+      etl::copy_n(other, length_, begin());
+
+      current_size = length_;
+      p_buffer[current_size] = 0;
+    }
+
+    //*********************************************************************
+    /// Assigns values to the string.
+    /// If asserts or exceptions are enabled, emits string_iterator if the iterators are reversed.
+    /// Truncates if the string does not have enough free space.
+    ///\param first The iterator to the first element.
+    ///\param last  The iterator to the last element + 1.
+    //*********************************************************************
+    template <typename TIterator>
+    void assign(TIterator first, TIterator last)
+    {
+#if defined(ETL_DEBUG)
+      difference_type d = std::distance(first, last);
+      ETL_ASSERT(d >= 0, ETL_ERROR(string_iterator));
+#endif
+
+      initialise();
+
+      while ((first != last) && (current_size != CAPACITY))
+      {
+        p_buffer[current_size++] = *first++;
+      }
+
+      p_buffer[current_size] = 0;
+    }
+
+    //*********************************************************************
+    /// Assigns values to the string.
+    /// Truncates if the string does not have enough free space.
+    ///\param n     The number of elements to add.
+    ///\param value The value to insert for each element.
+    //*********************************************************************
+    void assign(size_t n, T value)
+    {
+      initialise();
+
+      n = std::min(n, CAPACITY);
+
+      std::fill_n(begin(), n, value);
+      current_size = n;
+      p_buffer[current_size] = 0;
+    }
+
+    //*************************************************************************
+    /// Clears the string.
+    //*************************************************************************
+    void clear()
+    {
+      initialise();
+    }
+
+    //*********************************************************************
+    /// Inserts a value at the end of the string.
+    /// Sets 'truncated' if the string is already full.
+    ///\param value The value to add.
+    //*********************************************************************
+    void push_back(T value)
+    {
+      if (current_size != CAPACITY)
+      {
+        p_buffer[current_size++] = value;
+        is_truncated = false;
+      }
+      else
+      {
+        is_truncated = true;
+      }
+    }
+
+    //*************************************************************************
+    /// Removes an element from the end of the string.
+    /// Does nothing if the string is empty.
+    //*************************************************************************
+    void pop_back()
+    {
+      if (current_size != 0)
+      {
+        p_buffer[--current_size] = 0;
+      }
+    }
+
+    //*********************************************************************
+    /// Appends to the string.
+    ///\param str The string to append.
+    //*********************************************************************
+    ibasic_string& append(const ibasic_string& str)
+    {
+      insert(end(), str.begin(), str.end());
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Appends to the string.
+    ///\param str The string to append.
+    ///\param subposition The position in str.
+    ///\param sublength The number of characters.
+    //*********************************************************************
+    ibasic_string& append(const ibasic_string& str, size_t subposition, size_t sublength = npos)
+    {
+      ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
+
+      insert(size(), str, subposition, sublength);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Appends to the string.
+    ///\param str The string to append.
+    //*********************************************************************
+    ibasic_string& append(const T* str)
+    {
+      insert(size(), str);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Appends to the string.
+    ///\param str The string to append.
+    ///\param n   The number of characters.
+    //*********************************************************************
+    ibasic_string& append(const T* str, size_t n)
+    {
+      insert(size(), str, n);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Appends to the string.
+    ///\param n The number of characters.
+    ///\param c The character.
+    //*********************************************************************
+    ibasic_string& append(size_t n, T c)
+    {
+      insert(size(), n, c);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Appends to the string.
+    ///\param first The first of the characters to append.
+    ///\param last  The last + 1 character to add.
+    //*********************************************************************
+    template <class TIterator>
+    ibasic_string& append(TIterator first, TIterator last)
+    {
+      insert(end(), first, last);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Inserts a value to the string.
+    ///\param position The position to insert before.
+    ///\param value    The value to insert.
+    //*********************************************************************
+    iterator insert(const_iterator position, T value)
+    {
+      is_truncated = false;
+
+      // Quick hack, as iterators are pointers.
+      iterator insert_position = const_cast<iterator>(position);
+
+      if (current_size < CAPACITY)
+      {
+        // Not full yet.
+        if (position != end())
+        {
+          // Insert in the middle.
+          ++current_size;
+          std::copy_backward(insert_position, end() - 1, end());
+          *insert_position = value;
+        }
+        else
+        {
+          // Insert at the end.
+          *insert_position = value;
+          ++current_size;
+        }
+      }
+      else
+      {
+        // Already full.
+        if (position != end())
+        {
+          // Insert in the middle.
+          std::copy_backward(insert_position, end() - 1, end());
+          *insert_position = value;
+        }
+
+        is_truncated = true;
+      }
+
+      p_buffer[current_size] = 0;
+
+      return insert_position;
+    }
+
+    //*********************************************************************
+    /// Inserts 'n' values to the string.
+    ///\param position The position to insert before.
+    ///\param n        The number of elements to add.
+    ///\param value    The value to insert.
+    //*********************************************************************
+    void insert(const_iterator position, size_t n, T value)
+    {
+      is_truncated = false;
+
+      if (n == 0)
+      {
+        return;
+      }
+
+      // Quick hack, as iterators are pointers.
+      iterator insert_position = const_cast<iterator>(position);
+      const size_t start = std::distance(cbegin(), position);
+
+      // No effect.
+      if (start == CAPACITY)
+      {
+        return;
+      }
+
+      // Fills the string to the end?
+      if ((start + n) >= CAPACITY)
+      {
+        is_truncated = ((current_size + n) > CAPACITY);
+        current_size = CAPACITY;
+        std::fill(insert_position, end(), value);
+      }
+      else
+      {
+        // Lets do some shifting.
+        const size_t shift_amount = n;
+        const size_t to_position = start + shift_amount;
+        const size_t remaining_characters = current_size - start;
+        const size_t max_shift_characters = CAPACITY - start - shift_amount;
+        const size_t characters_to_shift = std::min(max_shift_characters, remaining_characters);
+
+        // Will the string truncate?
+        if ((start + shift_amount + remaining_characters) > CAPACITY)
+        {
+          current_size = CAPACITY;
+          is_truncated = true;
+        }
+        else
+        {
+          current_size += shift_amount;
+        }
+
+        std::copy_backward(insert_position, insert_position + characters_to_shift, begin() + to_position + characters_to_shift);
+        std::fill(insert_position, insert_position + shift_amount, value);
+      }
+
+      p_buffer[current_size] = 0;
+    }
+
+    //*********************************************************************
+    /// Inserts a range of values to the string.
+    /// If asserts or exceptions are enabled, emits string_full if the string does not have enough free space.
+    ///\param position The position to insert before.
+    ///\param first    The first element to add.
+    ///\param last     The last + 1 element to add.
+    //*********************************************************************
+    template <class TIterator>
+    void insert(iterator position, TIterator first, TIterator last)
+    {
+      is_truncated = false;
+
+      if (first == last)
+      {
+        return;
+      }
+
+      const size_t start = std::distance(begin(), position);
+      const size_t n = std::distance(first, last);
+
+      // No effect.
+      if (start == CAPACITY)
+      {
+        return;
+      }
+
+      // Fills the string to the end?
+      if ((start + n) >= CAPACITY)
+      {
+        is_truncated = ((current_size + n) > CAPACITY);
+        current_size = CAPACITY;
+
+        while (position != end())
+        {
+          *position++ = *first++;
+        }
+      }
+      else
+      {
+        // Lets do some shifting.
+        const size_t shift_amount = n;
+        const size_t to_position = start + shift_amount;
+        const size_t remaining_characters = current_size - start;
+        const size_t max_shift_characters = CAPACITY - start - shift_amount;
+        const size_t characters_to_shift = std::min(max_shift_characters, remaining_characters);
+
+        // Will the string truncate?
+        if ((start + shift_amount + remaining_characters) > CAPACITY)
+        {
+          current_size = CAPACITY;
+          is_truncated = true;
+        }
+        else
+        {
+          current_size += shift_amount;
+        }
+
+        std::copy_backward(position, position + characters_to_shift, begin() + to_position + characters_to_shift);
+
+        while (first != last)
+        {
+          *position++ = *first++;
+        }
+      }
+
+      p_buffer[current_size] = 0;
+    }
+
+    //*********************************************************************
+    /// Inserts a string at the specified position.
+    ///\param position The position to insert before.
+    ///\param str      The string to insert.
+    //*********************************************************************
+    etl::ibasic_string<T>& insert(size_t position, const etl::ibasic_string<T>& str)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      insert(begin() + position, str.cbegin(), str.cend());
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Inserts a string at the specified position from subposition for sublength.
+    ///\param position    The position to insert before.
+    ///\param str         The string to insert.
+    ///\param subposition The subposition to start from.
+    ///\param sublength   The number of characters to insert.
+    //*********************************************************************
+    etl::ibasic_string<T>& insert(size_t position, const etl::ibasic_string<T>& str, size_t subposition, size_t sublength)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+      ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
+
+      if ((sublength == npos) || (subposition + sublength > str.size()))
+      {
+        sublength = str.size() - subposition;
+      }
+
+      insert(begin() + position, str.cbegin() + subposition, str.cbegin() + subposition + sublength);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Inserts a string at the specified position from pointer.
+    ///\param position The position to insert before.
+    ///\param s        The string to insert.
+    //*********************************************************************
+    etl::ibasic_string<T>& insert(size_t position, const_pointer s)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      insert(begin() + position, s, s + strlen(s));
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Inserts a string at the specified position from pointer for n characters.
+    ///\param position The position to insert before.
+    ///\param s        The string to insert.
+    ///\param n        The number of characters to insert.
+    //*********************************************************************
+    etl::ibasic_string<T>& insert(size_t position, const_pointer s, size_t n)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      insert(begin() + position, s, s + n);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Insert n characters of c at position.
+    ///\param position The position to insert before.
+    ///\param n        The number of characters to insert.
+    ///\param c        The character to insert.
+    //*********************************************************************
+    etl::ibasic_string<T>& insert(size_t position, size_t n, value_type c)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      insert(begin() + position, n, c);
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Erases a sequence.
+    ///\param position Position to start from.
+    ///\param length   Number of characters.
+    ///\return A refernce to this string.
+    //*********************************************************************
+    etl::ibasic_string<T>& erase(size_t position, size_t length_ = npos)
+    {
+      // Limit the length.
+      length_ = std::min(length_, size() - position);
+
+      erase(begin() + position, begin() + position + length_);
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Erases an element.
+    ///\param i_element Iterator to the element.
+    ///\return An iterator pointing to the element that followed the erased element.
+    //*********************************************************************
+    iterator erase(iterator i_element)
+    {
+      std::copy(i_element + 1, end(), i_element);
+      p_buffer[--current_size] = 0;
+
+      return i_element;
+    }
+
+    //*********************************************************************
+    /// Erases a range of elements.
+    /// The range includes all the elements between first and last, including the
+    /// element pointed by first, but not the one pointed by last.
+    ///\param first Iterator to the first element.
+    ///\param last  Iterator to the last element.
+    ///\return An iterator pointing to the element that followed the erased element.
+    //*********************************************************************
+    iterator erase(iterator first, iterator last)
+    {
+      std::copy(last, end(), first);
+      size_t n_delete = std::distance(first, last);
+
+      current_size -= n_delete;
+      p_buffer[current_size] = 0;
+
+      return first;
+    }
+
+    //*********************************************************************
+    /// Return a pointer to a C string.
+    //*********************************************************************
+    const_pointer c_str() const
+    {
+      return p_buffer;
+    }
+
+    //*********************************************************************
+    /// Copies a portion of a string.
+    ///\param s   Pointer to the string to copy.
+    ///\param len The number of characters to copy.
+    ///\param pos The position to start copying from.
+    //*********************************************************************
+    size_t copy(pointer s, size_t len, size_t pos = 0)
+    {
+      size_t endpos = std::min(pos + len, size());
+
+      for (size_t i = pos; i < endpos; ++i)
+      {
+        *s++ = p_buffer[i];
+      }
+
+      return endpos - pos;
+    }
+
+    //*********************************************************************
+    /// Find content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find(const ibasic_string<T>& str, size_t pos = 0) const
+    {
+      if ((pos + str.size()) > size())
+      {
+        return npos;
+      }
+
+      const_iterator iposition = std::search(begin() + pos, end(), str.begin(), str.end());
+
+      if (iposition == end())
+      {
+        return npos;
+      }
+      else
+      {
+        return std::distance(begin(), iposition);
+      }
+    }
+
+    //*********************************************************************
+    /// Find content within the string
+    ///\param s   Pointer to the content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find(const_pointer s, size_t pos = 0) const
+    {
+#if defined(ETL_DEBUG)
+      if ((pos + etl::strlen(s)) > size())
+      {
+        return npos;
+      }
+#endif
+
+      const_iterator iposition = std::search(begin() + pos, end(), s, s + etl::strlen(s));
+
+      if (iposition == end())
+      {
+        return npos;
+      }
+      else
+      {
+        return std::distance(begin(), iposition);
+      }
+    }
+
+    //*********************************************************************
+    /// Find content within the string
+    ///\param s   Pointer to the content to find
+    ///\param pos The position to start searching from.
+    ///\param n   The number of characters to search for.
+    //*********************************************************************
+    size_t find(const_pointer s, size_t pos, size_t n) const
+    {
+#if defined(ETL_DEBUG)
+      if ((pos + etl::strlen(s) - n) > size())
+      {
+        return npos;
+      }
+#endif
+
+      const_iterator iposition = std::search(begin() + pos, end(), s, s + n);
+
+      if (iposition == end())
+      {
+        return npos;
+      }
+      else
+      {
+        return std::distance(begin(), iposition);
+      }
+    }
+
+    //*********************************************************************
+    /// Find character within the string
+    ///\param c        The character to find.
+    ///\param position The position to start searching from.
+    //*********************************************************************
+    size_t find(T c, size_t position = 0) const
+    {
+      const_iterator i = std::find(begin() + position, end(), c);
+
+      if (i != end())
+      {
+        return std::distance(begin(), i);
+      }
+      else
+      {
+        return npos;
+      }
+    }
+
+    //*********************************************************************
+    /// Find content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t rfind(const ibasic_string<T>& str, size_t position = npos) const
+    {
+      if ((str.size()) > size())
+      {
+        return npos;
+      }
+
+      if (position >= size())
+      {
+        position = size();
+      }
+
+      position = size() - position;
+
+      const_reverse_iterator iposition = std::search(rbegin() + position, rend(), str.rbegin(), str.rend());
+
+      if (iposition == rend())
+      {
+        return npos;
+      }
+      else
+      {
+        return size() - str.size() - std::distance(rbegin(), iposition);
+      }
+    }
+
+    //*********************************************************************
+    /// Find content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t rfind(const_pointer s, size_t position = npos) const
+    {
+      size_t len = etl::strlen(s);
+
+      if (len > size())
+      {
+        return npos;
+      }
+
+      if (position >= size())
+      {
+        position = size();
+      }
+
+      position = size() - position;
+
+      const_reverse_iterator srbegin(s + len);
+      const_reverse_iterator srend(s);
+
+      const_reverse_iterator iposition = std::search(rbegin() + position, rend(), srbegin, srend);
+
+      if (iposition == rend())
+      {
+        return npos;
+      }
+      else
+      {
+        return size() - len - std::distance(rbegin(), iposition);
+      }
+    }
+
+    //*********************************************************************
+    /// Find content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t rfind(const_pointer s, size_t position, size_t length_) const
+    {
+      if (length_ > size())
+      {
+        return npos;
+      }
+
+      if (position >= size())
+      {
+        position = size();
+      }
+
+      position = size() - position;
+
+      const_reverse_iterator srbegin(s + length_);
+      const_reverse_iterator srend(s);
+
+      const_reverse_iterator iposition = std::search(rbegin() + position, rend(), srbegin, srend);
+
+      if (iposition == rend())
+      {
+        return npos;
+      }
+      else
+      {
+        return size() - length_ - std::distance(rbegin(), iposition);
+      }
+    }
+
+    //*********************************************************************
+    /// Find character within the string
+    ///\param c   The character to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t rfind(T c, size_t position = npos) const
+    {
+      if (position >= size())
+      {
+        position = size();
+      }
+
+      position = size() - position;
+
+      const_reverse_iterator i = std::find(rbegin() + position, rend(), c);
+
+      if (i != rend())
+      {
+        return size() - std::distance(rbegin(), i) - 1;
+      }
+      else
+      {
+        return npos;
+      }
+    }
+
+    //*********************************************************************
+    /// Replace 'length' characters from 'position' with 'str'.
+    ///\param position The position to start from.
+    ///\param length   The number of characters to replace.
+    ///\param str      The string to replace it with.
+    //*********************************************************************
+    ibasic_string& replace(size_t position, size_t length_, const ibasic_string& str)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      // Limit the length.
+      length_ = std::min(length_, size() - position);
+
+      // Erase the bit we want to replace.
+      erase(position, length_);
+
+      // Insert the new stuff.
+      insert(position, str);
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'first' to one before 'last' with 'str'.
+    ///\param first The position to start from.
+    ///\param last  The one after the position to end at.
+    ///\param str   The string to replace it with.
+    //*********************************************************************
+    ibasic_string& replace(const_iterator first, const_iterator last, const ibasic_string& str)
+    {
+      // Quick hack, as iterators are pointers.
+      iterator first_ = const_cast<iterator>(first);
+      iterator last_ = const_cast<iterator>(last);
+
+      // Erase the bit we want to replace.
+      erase(first_, last_);
+
+      // Insert the new stuff.
+      insert(first_, str.begin(), str.end());
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'position' of 'length' with 'str' from 'subpsotion' of 'sublength'.
+    //*********************************************************************
+    ibasic_string& replace(size_t position, size_t length_, const ibasic_string& str, size_t subposition, size_t sublength)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+      ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
+
+      // Limit the lengths.
+      length_ = std::min(length_, size() - position);
+      sublength = std::min(sublength, str.size() - subposition);
+
+      // Erase the bit we want to replace.
+      erase(position, length_);
+
+      // Insert the new stuff.
+      insert(position, str, subposition, sublength);
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'position' of 'length' with pointed to string.
+    //*********************************************************************
+    ibasic_string& replace(size_t position, size_t length_, const_pointer s)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      // Limit the length.
+      length_ = std::min(length_, size() - position);
+
+      // Erase the bit we want to replace.
+      erase(position, length_);
+
+      // Insert the new stuff.
+      insert(position, s, etl::strlen(s));
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'first'  'last' with pointed to string.
+    //*********************************************************************
+    ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s)
+    {
+      // Quick hack, as iterators are pointers.
+      iterator first_ = const_cast<iterator>(first);
+      iterator last_ = const_cast<iterator>(last);
+
+      // Erase the bit we want to replace.
+      erase(first_, last_);
+
+      // Insert the new stuff.
+      insert(first_, s, s + etl::strlen(s));
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'position' of 'length' with 'n' characters from pointed to string.
+    //*********************************************************************
+    ibasic_string& replace(size_t position, size_t length_, const_pointer s, size_t n)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      // Limit the length.
+      length_ = std::min(length_, size() - position);
+
+      // Erase the bit we want to replace.
+      erase(position, length_);
+
+      // Insert the new stuff.
+      insert(position, s, n);
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'first' to 'last' with 'n' characters from pointed to string.
+    //*********************************************************************
+    ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s, size_t n)
+    {
+      // Quick hack, as iterators are pointers.
+      iterator first_ = const_cast<iterator>(first);
+      iterator last_ = const_cast<iterator>(last);
+
+      // Erase the bit we want to replace.
+      erase(first_, last_);
+
+      // Insert the new stuff.
+      insert(first_, s, s + n);
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'position' of 'length' with 'n' copies of 'c'.
+    //*********************************************************************
+    ibasic_string& replace(size_t position, size_t length_, size_t n, value_type c)
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      // Limit the length.
+      length_ = std::min(length_, size() - position);
+
+      // Erase the bit we want to replace.
+      erase(position, length_);
+
+      // Insert the new stuff.
+      insert(position, n, c);
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'first' of 'last' with 'n' copies of 'c'.
+    //*********************************************************************
+    ibasic_string& replace(const_iterator first, const_iterator last, size_t n, value_type c)
+    {
+      // Quick hack, as iterators are pointers.
+      iterator first_ = const_cast<iterator>(first);
+      iterator last_ = const_cast<iterator>(last);
+
+      // Erase the bit we want to replace.
+      erase(first_, last_);
+
+      // Insert the new stuff.
+      insert(first_, n, c);
+
+      return *this;
+    }
+
+    //*********************************************************************
+    /// Replace characters from 'first' of 'last' with characters from 'first_replace' to 'last_replace'.
+    //*********************************************************************
+    template <typename TIterator>
+    ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace)
+    {
+      // Quick hack, as iterators are pointers.
+      iterator first_ = const_cast<iterator>(first);
+      iterator last_ = const_cast<iterator>(last);
+
+      // Erase the bit we want to replace.
+      erase(first_, last_);
+
+      // Insert the new stuff.
+      insert(first_, first_replace, last_replace);
+
+      return *this;
+    }
+
+    //*************************************************************************
+    /// Compare with string.
+    //*************************************************************************
+    int compare(const ibasic_string& str) const
+    {
+      return compare(p_buffer,
+        p_buffer + size(),
+        str.p_buffer,
+        str.p_buffer + str.size());
+    }
+
+    //*************************************************************************
+    /// Compare position / length with string.
+    //*************************************************************************
+    int compare(size_t position, size_t length_, const ibasic_string& str) const
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+
+      // Limit the length.
+      length_ = std::min(length_, size() - position);
+
+      return compare(p_buffer + position,
+        p_buffer + position + length_,
+        str.p_buffer,
+        str.p_buffer + str.size());
+    }
+
+    //*************************************************************************
+    /// Compare position / length with string / subposition / sublength.
+    //*************************************************************************
+    int compare(size_t position, size_t length_, const ibasic_string& str, size_t subposition, size_t sublength) const
+    {
+      ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
+      ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
+
+      // Limit the lengths.
+      length_ = std::min(length_, size() - position);
+      sublength = std::min(sublength, str.size() - subposition);
+
+      return compare(p_buffer + position,
+        p_buffer + position + length_,
+        str.p_buffer + subposition,
+        str.p_buffer + subposition + sublength);
+    }
+
+    //*************************************************************************
+    ///  Compare with C string
+    //*************************************************************************
+    int compare(const value_type* s) const
+    {
+      return compare(p_buffer,
+        p_buffer + size(),
+        s,
+        s + etl::strlen(s));
+    }
+
+    //*************************************************************************
+    /// Compare position / length with C string.
+    //*************************************************************************
+    int compare(size_t position, size_t length_, const_pointer s) const
+    {
+      return compare(p_buffer + position,
+        p_buffer + position + length_,
+        s,
+        s + etl::strlen(s));
+    }
+
+    //*************************************************************************
+    /// Compare position / length with C string / n.
+    //*************************************************************************
+    int compare(size_t position, size_t length_, const_pointer s, size_t n) const
+    {
+      return compare(p_buffer + position,
+        p_buffer + position + length_,
+        s,
+        s + n);;
+    }
+
+    //*********************************************************************
+    /// Find first of any of content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_first_of(const ibasic_string<T>& str, size_t position = 0) const
+    {
+      return find_first_of(str.c_str(), position, str.size());
+    }
+
+    //*********************************************************************
+    /// Find first of any of content within the string
+    ///\param s   Pointer to the content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_first_of(const_pointer s, size_t position = 0) const
+    {
+      return find_first_of(s, position, etl::strlen(s));
+    }
+
+    //*********************************************************************
+    /// Find first of any of content within the string
+    ///\param s   Pointer to the content to find
+    ///\param pos The position to start searching from.
+    ///\param n   The number of characters to search for.
+    //*********************************************************************
+    size_t find_first_of(const_pointer s, size_t position, size_t n) const
+    {
+      if (position < size())
+      {
+        for (size_t i = position; i < size(); ++i)
+        {
+          for (size_t j = 0; j < n; ++j)
+          {
+            if (p_buffer[i] == s[j])
+            {
+              return i;
+            }
+          }
+        }
+      }
+
+      return npos;
+    }
+
+    //*********************************************************************
+    /// Find first of character within the string
+    ///\param c   The character to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_first_of(value_type c, size_t position = 0) const
+    {
+      if (position < size())
+      {
+        for (size_t i = position; i < size(); ++i)
+        {
+          if (p_buffer[i] == c)
+          {
+            return i;
+          }
+        }
+      }
+
+      return npos;
+    }
+
+    //*********************************************************************
+    /// Find last of any of content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_last_of(const ibasic_string<T>& str, size_t position = npos) const
+    {
+      return find_last_of(str.c_str(), position, str.size());
+    }
+
+    //*********************************************************************
+    /// Find last of any of content within the string
+    ///\param s   Pointer to the content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_last_of(const_pointer s, size_t position = npos) const
+    {
+      return find_last_of(s, position, etl::strlen(s));
+    }
+
+    //*********************************************************************
+    /// Find last of any of content within the string
+    ///\param s   Pointer to the content to find
+    ///\param pos The position to start searching from.
+    ///\param n   The number of characters to search for.
+    //*********************************************************************
+    size_t find_last_of(const_pointer s, size_t position, size_t n) const
+    {
+      if (empty())
+      {
+        return npos;
+      }
+
+      position = std::min(position, size() - 1);
+
+      const_reverse_iterator it = rbegin() + size() - position - 1;
+
+      while (it != rend())
+      {
+        for (size_t j = 0; j < n; ++j)
+        {
+          if (p_buffer[position] == s[j])
+          {
+            return position;
+          }
+        }
+
+        ++it;
+        --position;
+      }
+
+      return npos;
+    }
+
+    //*********************************************************************
+    /// Find last of character within the string
+    ///\param c   The character to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_last_of(value_type c, size_t position = npos) const
+    {
+      if (empty())
+      {
+        return npos;
+      }
+
+      position = std::min(position, size() - 1);
+
+      const_reverse_iterator it = rbegin() + size() - position - 1;
+
+      while (it != rend())
+      {
+        if (p_buffer[position] == c)
+        {
+          return position;
+        }
+
+        ++it;
+        --position;
+      }
+
+      return npos;
+    }
+
+    //*********************************************************************
+    /// Find first not of any of content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_first_not_of(const ibasic_string<T>& str, size_t position = 0) const
+    {
+      return find_first_not_of(str.c_str(), position, str.size());
+    }
+
+    //*********************************************************************
+    /// Find first not of any of content within the string
+    ///\param s   Pointer to the content to not find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_first_not_of(const_pointer s, size_t position = 0) const
+    {
+      return find_first_not_of(s, position, etl::strlen(s));
+    }
+
+    //*********************************************************************
+    /// Find first not of any of content within the string
+    ///\param s   Pointer to the content to not find
+    ///\param pos The position to start searching from.
+    ///\param n   The number of characters to search for.
+    //*********************************************************************
+    size_t find_first_not_of(const_pointer s, size_t position, size_t n) const
+    {
+      if (position < size())
+      {
+        for (size_t i = position; i < size(); ++i)
+        {
+          bool found = false;
+
+          for (size_t j = 0; j < n; ++j)
+          {
+            if (p_buffer[i] == s[j])
+            {
+              found = true;
+            }
+          }
+
+          if (!found)
+          {
+            return i;
+          }
+        }
+      }
+
+      return npos;
+    }
+
+    //*********************************************************************
+    /// Find first not of character within the string
+    ///\param c   The character to not find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_first_not_of(value_type c, size_t position = 0) const
+    {
+      if (position < size())
+      {
+        for (size_t i = position; i < size(); ++i)
+        {
+          if (p_buffer[i] != c)
+          {
+            return i;
+          }
+        }
+      }
+
+      return npos;
+    }
+
+    //*********************************************************************
+    /// Find last not of any of content within the string
+    ///\param str The content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_last_not_of(const ibasic_string<T>& str, size_t position = npos) const
+    {
+      return find_last_not_of(str.c_str(), position, str.size());
+    }
+
+    //*********************************************************************
+    /// Find last not of any of content within the string
+    ///\param s   The pointer to the content to find
+    ///\param pos The position to start searching from.
+    //*********************************************************************
+    size_t find_last_not_of(const_pointer s, size_t position = npos) const
+    {
+      return find_last_not_of(s, position, etl::strlen(s));
+    }
+
+    //*********************************************************************
+    /// Find last not of any of content within the string
+    ///\param s   The pointer to the content to find
+    ///\param pos The position to start searching from.
+    ///\param n   The number of characters to use.
+    //*********************************************************************
+    size_t find_last_not_of(const_pointer s, size_t position, size_t n) const
+    {
+      if (empty())
+      {
+        return npos;
+      }
+
+      position = std::min(position, size() - 1);
+
+      const_reverse_iterator it = rbegin() + size() - position - 1;
+
+      while (it != rend())
+      {
+        bool found = false;
+
+        for (size_t j = 0; j < n; ++j)
+        {
+          if (p_buffer[position] == s[j])
+          {
+            found = true;
+          }
+        }
+
+        if (!found)
+        {
+          return position;
+        }
+
+        ++it;
+        --position;
+      }
+
+      return npos;
+    }
+
+    //*********************************************************************
+    //
+    //*********************************************************************
+    size_t find_last_not_of(value_type c, size_t position = npos) const
+    {
+      if (empty())
+      {
+        return npos;
+      }
+
+      position = std::min(position, size() - 1);
+
+      const_reverse_iterator it = rbegin() + size() - position - 1;
+
+      while (it != rend())
+      {
+        if (p_buffer[position] != c)
+        {
+          return position;
+        }
+
+        ++it;
+        --position;
+      }
+
+      return npos;
+    }
+
+    //*************************************************************************
+    /// Assignment operator.
+    //*************************************************************************
+    ibasic_string& operator = (const ibasic_string& rhs)
+    {
+      if (&rhs != this)
+      {
+        assign(rhs.cbegin(), rhs.cend());
+      }
+
+      return *this;
+    }
+
+    //*************************************************************************
+    /// += operator.
+    //*************************************************************************
+    ibasic_string& operator += (const ibasic_string& rhs)
+    {
+      if (&rhs != this)
+      {
+        append(rhs);
+      }
+
+      return *this;
+    }
+
+    //*************************************************************************
+    /// += operator.
+    //*************************************************************************
+    ibasic_string& operator += (const T* rhs)
+    {
+      append(rhs);
+
+      return *this;
+    }
+
+    //*************************************************************************
+    /// += operator.
+    //*************************************************************************
+    ibasic_string& operator += (T rhs)
+    {
+      append(size_t(1), rhs);
+
+      return *this;
+    }
+
+#ifdef ETL_ISTRING_REPAIR_ENABLE
+    //*************************************************************************
+    /// Fix the internal pointers after a low level memory copy.
+    //*************************************************************************
+    virtual void repair() = 0;
+#endif
+
+  protected:
+
+    //*********************************************************************
+    /// Constructor.
+    //*********************************************************************
+    ibasic_string(T* p_buffer_, size_t MAX_SIZE_)
+      : string_base(MAX_SIZE_),
+        p_buffer(p_buffer_)
+    {
+    }
+
+    //*********************************************************************
+    /// Initialise the string.
+    //*********************************************************************
+    void initialise()
+    {
+      current_size = 0;
+      p_buffer[0] = 0;
+    }
+
+    //*************************************************************************
+    /// Fix the internal pointers after a low level memory copy.
+    //*************************************************************************
+    void repair(T* p_buffer_)
+    {
+      p_buffer = p_buffer_;
+    }
+
+  private:
+
+    //*************************************************************************
+    /// Compare helper function
+    //*************************************************************************
+    int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2) const
+    {
+      while ((first1 != last1) && (first2 != last2))
+      {
+        if (*first1 < *first2)
+        {
+          // Compared character is lower.
+          return -1;
+        }
+        else if (*first1 > *first2)
+        {
+          // Compared character is higher.
+          return 1;
+        }
+
+        ++first1;
+        ++first2;
+      }
+
+      // We reached the end of one or both of the strings.
+      if ((first1 == last1) && (first2 == last2))
+      {
+        // Same length.
+        return 0;
+      }
+      else if (first1 == last1)
+      {
+        // Compared string is shorter.
+        return -1;
+      }
+      else
+      {
+        // Compared string is longer.
+        return 1;
+      }
+    }
+
+    // Disable copy construction.
+    ibasic_string(const ibasic_string&);
+
+    T* p_buffer;
+  };
+
+  //***************************************************************************
+  /// Equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator ==(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin());
+  }
+
+  //***************************************************************************
+  /// Equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator ==(const etl::ibasic_string<T>& lhs, const T* rhs)
+  {
+    return (lhs.size() == etl::strlen(rhs)) && std::equal(lhs.begin(), lhs.end(), rhs);
+  }
+
+  //***************************************************************************
+  /// Equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator ==(const T* lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return (rhs.size() == etl::strlen(lhs)) && std::equal(rhs.begin(), rhs.end(), lhs);
+  }
+
+
+  //***************************************************************************
+  /// Not equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator !=(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return !(lhs == rhs);
+  }
+
+  //***************************************************************************
+  /// Not equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator !=(const etl::ibasic_string<T>& lhs, const T* rhs)
+  {
+    return !(lhs == rhs);
+  }
+
+  //***************************************************************************
+  /// Not equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator !=(const T* lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return !(lhs == rhs);
+  }
+
+
+  //***************************************************************************
+  /// Less than operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically less than the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator <(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+  }
+
+  //***************************************************************************
+  /// Less than operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically less than the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator <(const etl::ibasic_string<T>& lhs, const T* rhs)
+  {
+    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs));
+  }
+
+  //***************************************************************************
+  /// Less than operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically less than the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator <(const T* lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return std::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end());
+  }
+
+
+  //***************************************************************************
+  /// Greater than operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically greater than the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator >(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return (rhs < lhs);
+  }
+
+  //***************************************************************************
+  /// Greater than operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically greater than the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator >(const etl::ibasic_string<T>& lhs, const T* rhs)
+  {
+    return (rhs < lhs);
+  }
+
+  //***************************************************************************
+  /// Greater than operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically greater than the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator >(const T* lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return (rhs < lhs);
+  }
+
+
+  //***************************************************************************
+  /// Less than or equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically less than or equal to the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator <=(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return !(lhs > rhs);
+  }
+
+  //***************************************************************************
+  /// Less than or equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically less than or equal to the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator <=(const etl::ibasic_string<T>& lhs, const T* rhs)
+  {
+    return !(lhs > rhs);
+  }
+
+  //***************************************************************************
+  /// Less than or equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically less than or equal to the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator <=(const T* lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return !(lhs > rhs);
+  }
+
+
+  //***************************************************************************
+  /// Greater than or equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically greater than or equal to the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator >=(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return !(lhs < rhs);
+  }
+
+  //***************************************************************************
+  /// Greater than or equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically greater than or equal to the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator >=(const etl::ibasic_string<T>& lhs, const T* rhs)
+  {
+    return !(lhs < rhs);
+  }
+
+  //***************************************************************************
+  /// Greater than or equal operator.
+  ///\param lhs Reference to the first string.
+  ///\param rhs Reference to the second string.
+  ///\return <b>true</b> if the first string is lexicographically greater than or equal to the second, otherwise <b>false</b>
+  ///\ingroup string
+  //***************************************************************************
+  template <typename T>
+  bool operator >=(const T* lhs, const etl::ibasic_string<T>& rhs)
+  {
+    return !(lhs < rhs);
+  }
+}
+
+#ifdef ETL_COMPILER_MICROSOFT
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifdef ETL_COMPILER_MICROSOFT
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#undef ETL_FILE
+
+#endif
+