Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers basic_string.h Source File

basic_string.h

Go to the documentation of this file.
00001 ///\file
00002 
00003 /******************************************************************************
00004 The MIT License(MIT)
00005 
00006 Embedded Template Library.
00007 https://github.com/ETLCPP/etl
00008 http://www.etlcpp.com
00009 
00010 Copyright(c) 2016 jwellbelove
00011 
00012 Permission is hereby granted, free of charge, to any person obtaining a copy
00013 of this software and associated documentation files(the "Software"), to deal
00014 in the Software without restriction, including without limitation the rights
00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00016 copies of the Software, and to permit persons to whom the Software is
00017 furnished to do so, subject to the following conditions :
00018 
00019 The above copyright notice and this permission notice shall be included in all
00020 copies or substantial portions of the Software.
00021 
00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00028 SOFTWARE.
00029 ******************************************************************************/
00030 
00031 #ifndef __ETL_BASIC_STRING__
00032 #define __ETL_BASIC_STRING__
00033 
00034 #include <stddef.h>
00035 #include <stdint.h>
00036 #include <iterator>
00037 #include <algorithm>
00038 #include <functional>
00039 #include <string.h>
00040 
00041 #include "platform.h "
00042 #include "char_traits.h "
00043 #include "container.h "
00044 #include "alignment.h "
00045 #include "array.h "
00046 #include "algorithm.h "
00047 #include "type_traits.h "
00048 #include "error_handler.h "
00049 #include "integral_limits.h "
00050 #include "exception.h "
00051 
00052 #define ETL_FILE "27"
00053 
00054 #ifdef ETL_COMPILER_GCC
00055 #pragma GCC diagnostic ignored "-Wunused-variable"
00056 #endif
00057 
00058 #ifdef ETL_COMPILER_MICROSOFT
00059 #undef min
00060 #endif
00061 
00062 #ifdef ETL_COMPILER_MICROSOFT
00063 #undef max
00064 #endif
00065 
00066 //*****************************************************************************
00067 ///\defgroup basic_string basic_string
00068 /// A basic_string with the capacity defined at compile time.
00069 ///\ingroup containers
00070 //*****************************************************************************
00071 
00072 namespace etl
00073 {
00074   //***************************************************************************
00075   /// Alternative strlen for all character types.
00076   //***************************************************************************
00077   template <typename T>
00078   size_t strlen(const T* t)
00079   {
00080     return etl::char_traits<T>::length(t);
00081   }
00082 
00083   //***************************************************************************
00084   ///\ingroup string
00085   /// Exception base for strings
00086   //***************************************************************************
00087   class string_exception : public etl::exception
00088   {
00089   public:
00090 
00091     string_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
00092       : exception(reason_, file_name_, line_number_)
00093     {
00094     }
00095   };
00096 
00097   //***************************************************************************
00098   ///\ingroup string
00099   /// String empty exception.
00100   //***************************************************************************
00101   class string_empty : public etl::string_exception
00102   {
00103   public:
00104 
00105     string_empty(string_type file_name_, numeric_type line_number_)
00106       : string_exception(ETL_ERROR_TEXT("string:empty", ETL_FILE"A"), file_name_, line_number_)
00107     {
00108     }
00109   };
00110 
00111   //***************************************************************************
00112   ///\ingroup string
00113   /// String out of bounds exception.
00114   //***************************************************************************
00115   class string_out_of_bounds : public etl::string_exception
00116   {
00117   public:
00118 
00119     string_out_of_bounds(string_type file_name_, numeric_type line_number_)
00120       : string_exception(ETL_ERROR_TEXT("string:bounds", ETL_FILE"B"), file_name_, line_number_)
00121     {
00122     }
00123   };
00124 
00125   //***************************************************************************
00126   ///\ingroup string
00127   /// String iterator exception.
00128   //***************************************************************************
00129   class string_iterator : public etl::string_exception
00130   {
00131   public:
00132 
00133     string_iterator(string_type file_name_, numeric_type line_number_)
00134       : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_FILE"C"), file_name_, line_number_)
00135     {
00136     }
00137   };
00138 
00139   //***************************************************************************
00140   ///\ingroup string
00141   /// The base class for all templated string types.
00142   //***************************************************************************
00143   class string_base
00144   {
00145   public:
00146 
00147     typedef size_t size_type;
00148 
00149     enum
00150     {
00151       npos = etl::integral_limits<size_t>::max
00152     };
00153 
00154     //*************************************************************************
00155     /// Gets the current size of the string.
00156     ///\return The current size of the string.
00157     //*************************************************************************
00158     size_type size() const
00159     {
00160       return current_size;
00161     }
00162 
00163     //*************************************************************************
00164     /// Gets the current size of the string.
00165     ///\return The current size of the string.
00166     //*************************************************************************
00167     size_type length() const
00168     {
00169       return current_size;
00170     }
00171 
00172     //*************************************************************************
00173     /// Checks the 'empty' state of the string.
00174     ///\return <b>true</b> if empty.
00175     //*************************************************************************
00176     bool empty() const
00177     {
00178       return (current_size == 0);
00179     }
00180 
00181     //*************************************************************************
00182     /// Checks the 'full' state of the string.
00183     ///\return <b>true</b> if full.
00184     //*************************************************************************
00185     bool full() const
00186     {
00187       return current_size == CAPACITY;
00188     }
00189 
00190     //*************************************************************************
00191     /// Returns the capacity of the string.
00192     ///\return The capacity of the string.
00193     //*************************************************************************
00194     size_type capacity() const
00195     {
00196       return CAPACITY;
00197     }
00198 
00199     //*************************************************************************
00200     /// Returns the maximum possible size of the string.
00201     ///\return The maximum size of the string.
00202     //*************************************************************************
00203     size_type max_size() const
00204     {
00205       return CAPACITY;
00206     }
00207 
00208     //*************************************************************************
00209     /// Returns the remaining capacity.
00210     ///\return The remaining capacity.
00211     //*************************************************************************
00212     size_t available() const
00213     {
00214       return max_size() - size();
00215     }
00216 
00217     //*************************************************************************
00218     /// Returns whether the string was truncated by the last operation.
00219     ///\return Whether the string was truncated by the last operation.
00220     //*************************************************************************
00221     size_t truncated() const
00222     {
00223       return is_truncated;
00224     }
00225 
00226   protected:
00227 
00228     //*************************************************************************
00229     /// Constructor.
00230     //*************************************************************************
00231     string_base(size_type max_size_)
00232       : is_truncated(false),
00233         current_size(0),
00234         CAPACITY(max_size_)
00235     {
00236     }
00237 
00238     bool            is_truncated; ///< Set to true if the operation truncated the string.
00239     size_type       current_size; ///< The current number of elements in the string.
00240     const size_type CAPACITY;     ///< The maximum number of elements in the string.
00241   };
00242 
00243   //***************************************************************************
00244   /// The base class for specifically sized strings.
00245   /// Can be used as a reference type for all strings containing a specific type.
00246   ///\ingroup string
00247   //***************************************************************************
00248   template <typename T>
00249   class ibasic_string : public etl::string_base
00250   {
00251   public:
00252 
00253     typedef T                                     value_type;
00254     typedef T&                                    reference;
00255     typedef const T&                              const_reference;
00256     typedef T*                                    pointer;
00257     typedef const T*                              const_pointer;
00258     typedef T*                                    iterator;
00259     typedef const T*                              const_iterator;
00260     typedef std::reverse_iterator<iterator>       reverse_iterator;
00261     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00262     typedef size_t                                size_type;
00263 
00264     typedef typename std::iterator_traits<iterator>::difference_type difference_type;
00265 
00266     //*********************************************************************
00267     /// Returns an iterator to the beginning of the string.
00268     ///\return An iterator to the beginning of the string.
00269     //*********************************************************************
00270     iterator begin()
00271     {
00272       return &p_buffer[0];
00273     }
00274 
00275     //*********************************************************************
00276     /// Returns a const_iterator to the beginning of the string.
00277     ///\return A const iterator to the beginning of the string.
00278     //*********************************************************************
00279     const_iterator begin() const
00280     {
00281       return &p_buffer[0];
00282     }
00283 
00284     //*********************************************************************
00285     /// Returns an iterator to the end of the string.
00286     ///\return An iterator to the end of the string.
00287     //*********************************************************************
00288     iterator end()
00289     {
00290       return &p_buffer[current_size];
00291     }
00292 
00293     //*********************************************************************
00294     /// Returns a const_iterator to the end of the string.
00295     ///\return A const iterator to the end of the string.
00296     //*********************************************************************
00297     const_iterator end() const
00298     {
00299       return &p_buffer[current_size];
00300     }
00301 
00302     //*********************************************************************
00303     /// Returns a const_iterator to the beginning of the string.
00304     ///\return A const iterator to the beginning of the string.
00305     //*********************************************************************
00306     const_iterator cbegin() const
00307     {
00308       return &p_buffer[0];
00309     }
00310 
00311     //*********************************************************************
00312     /// Returns a const_iterator to the end of the string.
00313     ///\return A const iterator to the end of the string.
00314     //*********************************************************************
00315     const_iterator cend() const
00316     {
00317       return &p_buffer[current_size];
00318     }
00319 
00320     //*********************************************************************
00321     /// Returns an reverse iterator to the reverse beginning of the string.
00322     ///\return Iterator to the reverse beginning of the string.
00323     //*********************************************************************
00324     reverse_iterator rbegin()
00325     {
00326       return reverse_iterator(end());
00327     }
00328 
00329     //*********************************************************************
00330     /// Returns a const reverse iterator to the reverse beginning of the string.
00331     ///\return Const iterator to the reverse beginning of the string.
00332     //*********************************************************************
00333     const_reverse_iterator rbegin() const
00334     {
00335       return const_reverse_iterator(end());
00336     }
00337 
00338     //*********************************************************************
00339     /// Returns a reverse iterator to the end + 1 of the string.
00340     ///\return Reverse iterator to the end + 1 of the string.
00341     //*********************************************************************
00342     reverse_iterator rend()
00343     {
00344       return reverse_iterator(begin());
00345     }
00346 
00347     //*********************************************************************
00348     /// Returns a const reverse iterator to the end + 1 of the string.
00349     ///\return Const reverse iterator to the end + 1 of the string.
00350     //*********************************************************************
00351     const_reverse_iterator rend() const
00352     {
00353       return const_reverse_iterator(begin());
00354     }
00355 
00356     //*********************************************************************
00357     /// Returns a const reverse iterator to the reverse beginning of the string.
00358     ///\return Const reverse iterator to the reverse beginning of the string.
00359     //*********************************************************************
00360     const_reverse_iterator crbegin() const
00361     {
00362       return const_reverse_iterator(cend());
00363     }
00364 
00365     //*********************************************************************
00366     /// Returns a const reverse iterator to the end + 1 of the string.
00367     ///\return Const reverse iterator to the end + 1 of the string.
00368     //*********************************************************************
00369     const_reverse_iterator crend() const
00370     {
00371       return const_reverse_iterator(cbegin());
00372     }
00373 
00374     //*********************************************************************
00375     /// Resizes the string.
00376     /// If asserts or exceptions are enabled and the new size is larger than the
00377     ///\param new_size The new size.
00378     //*********************************************************************
00379     void resize(size_t new_size)
00380     {
00381       resize(new_size, 0);
00382     }
00383 
00384     //*********************************************************************
00385     /// Resizes the string.
00386     ///\param new_size The new size.
00387     ///\param value    The value to fill new elements with. Default = default constructed value.
00388     //*********************************************************************
00389     void resize(size_t new_size, T value)
00390     {
00391       new_size = std::min(new_size, CAPACITY);
00392 
00393       // Size up?
00394       if (new_size > current_size)
00395       {
00396         std::fill(p_buffer + current_size, p_buffer + new_size, value);
00397       }
00398 
00399       current_size = new_size;
00400       p_buffer[new_size] = 0;
00401     }
00402 
00403     //*********************************************************************
00404     /// Returns a reference to the value at index 'i'
00405     ///\param i The index.
00406     ///\return A reference to the value at index 'i'
00407     //*********************************************************************
00408     reference operator [](size_t i)
00409     {
00410       return p_buffer[i];
00411     }
00412 
00413     //*********************************************************************
00414     /// Returns a const reference to the value at index 'i'
00415     ///\param i The index.
00416     ///\return A const reference to the value at index 'i'
00417     //*********************************************************************
00418     const_reference operator [](size_t i) const
00419     {
00420       return p_buffer[i];
00421     }
00422 
00423     //*********************************************************************
00424     /// Returns a reference to the value at index 'i'
00425     /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range.
00426     ///\param i The index.
00427     ///\return A reference to the value at index 'i'
00428     //*********************************************************************
00429     reference at(size_t i)
00430     {
00431       ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
00432       return p_buffer[i];
00433     }
00434 
00435     //*********************************************************************
00436     /// Returns a const reference to the value at index 'i'
00437     /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range.
00438     ///\param i The index.
00439     ///\return A const reference to the value at index 'i'
00440     //*********************************************************************
00441     const_reference at(size_t i) const
00442     {
00443       ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds));
00444       return p_buffer[i];
00445     }
00446 
00447     //*********************************************************************
00448     /// Returns a reference to the first element.
00449     ///\return A reference to the first element.
00450     //*********************************************************************
00451     reference front()
00452     {
00453       return p_buffer[0];
00454     }
00455 
00456     //*********************************************************************
00457     /// Returns a const reference to the first element.
00458     ///\return A const reference to the first element.
00459     //*********************************************************************
00460     const_reference front() const
00461     {
00462       return p_buffer[0];
00463     }
00464 
00465     //*********************************************************************
00466     /// Returns a reference to the last element.
00467     ///\return A reference to the last element.
00468     //*********************************************************************
00469     reference back()
00470     {
00471       return p_buffer[current_size - 1];
00472     }
00473 
00474     //*********************************************************************
00475     /// Returns a const reference to the last element.
00476     ///\return A const reference to the last element.
00477     //*********************************************************************
00478     const_reference back() const
00479     {
00480       return p_buffer[current_size - 1];
00481     }
00482 
00483     //*********************************************************************
00484     /// Returns a pointer to the beginning of the string data.
00485     ///\return A pointer to the beginning of the string data.
00486     //*********************************************************************
00487     pointer data()
00488     {
00489       return p_buffer;
00490     }
00491 
00492     //*********************************************************************
00493     /// Returns a const pointer to the beginning of the string data.
00494     ///\return A const pointer to the beginning of the string data.
00495     //*********************************************************************
00496     const_pointer data() const
00497     {
00498       return p_buffer;
00499     }
00500 
00501     //*********************************************************************
00502     /// Assigns values to the string.
00503     /// Truncates if the string does not have enough free space.
00504     ///\param other The other string.
00505     //*********************************************************************
00506     void assign(const etl::ibasic_string<T>& other)
00507     {
00508       size_t len = std::min(CAPACITY, other.size());
00509       assign(other.begin(), other.begin() + len);
00510     }
00511 
00512     //*********************************************************************
00513     /// Assigns values to the string.
00514     /// Truncates if the string does not have enough free space.
00515     ///\param other The other string.
00516     ///\param subposition The position to start from.
00517     ///\param sublength   The length to copy.
00518     //*********************************************************************
00519     void assign(const etl::ibasic_string<T>& other, size_t subposition, size_t sublength)
00520     {
00521       if (sublength == npos)
00522       {
00523         sublength = other.size() - subposition;
00524       }
00525 
00526       ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds));
00527 
00528       assign(other.begin() + subposition, sublength);
00529     }
00530 
00531     //*********************************************************************
00532     /// Assigns values to the string.
00533     /// Truncates if the string does not have enough free space.
00534     ///\param other The other string.
00535     //*********************************************************************
00536     void assign(const_pointer other)
00537     {
00538       initialise();
00539 
00540       while ((*other != 0) && (current_size < CAPACITY))
00541       {
00542         p_buffer[current_size++] = *other++;
00543       }
00544 
00545       is_truncated = (*other != 0);
00546 
00547       p_buffer[current_size] = 0;
00548     }
00549 
00550     //*********************************************************************
00551     /// Assigns values to the string.
00552     /// Truncates if the string does not have enough free space.
00553     ///\param other The other string.
00554     ///\param length The length to copy.
00555     //*********************************************************************
00556     void assign(const_pointer other, size_t length_)
00557     {
00558       length_ = std::min(length_, CAPACITY);
00559 
00560       initialise();
00561 
00562       etl::copy_n(other, length_, begin());
00563 
00564       current_size = length_;
00565       p_buffer[current_size] = 0;
00566     }
00567 
00568     //*********************************************************************
00569     /// Assigns values to the string.
00570     /// If asserts or exceptions are enabled, emits string_iterator if the iterators are reversed.
00571     /// Truncates if the string does not have enough free space.
00572     ///\param first The iterator to the first element.
00573     ///\param last  The iterator to the last element + 1.
00574     //*********************************************************************
00575     template <typename TIterator>
00576     void assign(TIterator first, TIterator last)
00577     {
00578 #if defined(ETL_DEBUG)
00579       difference_type d = std::distance(first, last);
00580       ETL_ASSERT(d >= 0, ETL_ERROR(string_iterator));
00581 #endif
00582 
00583       initialise();
00584 
00585       while ((first != last) && (current_size != CAPACITY))
00586       {
00587         p_buffer[current_size++] = *first++;
00588       }
00589 
00590       p_buffer[current_size] = 0;
00591     }
00592 
00593     //*********************************************************************
00594     /// Assigns values to the string.
00595     /// Truncates if the string does not have enough free space.
00596     ///\param n     The number of elements to add.
00597     ///\param value The value to insert for each element.
00598     //*********************************************************************
00599     void assign(size_t n, T value)
00600     {
00601       initialise();
00602 
00603       n = std::min(n, CAPACITY);
00604 
00605       std::fill_n(begin(), n, value);
00606       current_size = n;
00607       p_buffer[current_size] = 0;
00608     }
00609 
00610     //*************************************************************************
00611     /// Clears the string.
00612     //*************************************************************************
00613     void clear()
00614     {
00615       initialise();
00616     }
00617 
00618     //*********************************************************************
00619     /// Inserts a value at the end of the string.
00620     /// Sets 'truncated' if the string is already full.
00621     ///\param value The value to add.
00622     //*********************************************************************
00623     void push_back(T value)
00624     {
00625       if (current_size != CAPACITY)
00626       {
00627         p_buffer[current_size++] = value;
00628         is_truncated = false;
00629       }
00630       else
00631       {
00632         is_truncated = true;
00633       }
00634     }
00635 
00636     //*************************************************************************
00637     /// Removes an element from the end of the string.
00638     /// Does nothing if the string is empty.
00639     //*************************************************************************
00640     void pop_back()
00641     {
00642       if (current_size != 0)
00643       {
00644         p_buffer[--current_size] = 0;
00645       }
00646     }
00647 
00648     //*********************************************************************
00649     /// Appends to the string.
00650     ///\param str The string to append.
00651     //*********************************************************************
00652     ibasic_string& append(const ibasic_string& str)
00653     {
00654       insert(end(), str.begin(), str.end());
00655       return *this;
00656     }
00657 
00658     //*********************************************************************
00659     /// Appends to the string.
00660     ///\param str The string to append.
00661     ///\param subposition The position in str.
00662     ///\param sublength The number of characters.
00663     //*********************************************************************
00664     ibasic_string& append(const ibasic_string& str, size_t subposition, size_t sublength = npos)
00665     {
00666       ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
00667 
00668       insert(size(), str, subposition, sublength);
00669       return *this;
00670     }
00671 
00672     //*********************************************************************
00673     /// Appends to the string.
00674     ///\param str The string to append.
00675     //*********************************************************************
00676     ibasic_string& append(const T* str)
00677     {
00678       insert(size(), str);
00679       return *this;
00680     }
00681 
00682     //*********************************************************************
00683     /// Appends to the string.
00684     ///\param str The string to append.
00685     ///\param n   The number of characters.
00686     //*********************************************************************
00687     ibasic_string& append(const T* str, size_t n)
00688     {
00689       insert(size(), str, n);
00690       return *this;
00691     }
00692 
00693     //*********************************************************************
00694     /// Appends to the string.
00695     ///\param n The number of characters.
00696     ///\param c The character.
00697     //*********************************************************************
00698     ibasic_string& append(size_t n, T c)
00699     {
00700       insert(size(), n, c);
00701       return *this;
00702     }
00703 
00704     //*********************************************************************
00705     /// Appends to the string.
00706     ///\param first The first of the characters to append.
00707     ///\param last  The last + 1 character to add.
00708     //*********************************************************************
00709     template <class TIterator>
00710     ibasic_string& append(TIterator first, TIterator last)
00711     {
00712       insert(end(), first, last);
00713       return *this;
00714     }
00715 
00716     //*********************************************************************
00717     /// Inserts a value to the string.
00718     ///\param position The position to insert before.
00719     ///\param value    The value to insert.
00720     //*********************************************************************
00721     iterator insert(const_iterator position, T value)
00722     {
00723       is_truncated = false;
00724 
00725       // Quick hack, as iterators are pointers.
00726       iterator insert_position = const_cast<iterator>(position);
00727 
00728       if (current_size < CAPACITY)
00729       {
00730         // Not full yet.
00731         if (position != end())
00732         {
00733           // Insert in the middle.
00734           ++current_size;
00735           std::copy_backward(insert_position, end() - 1, end());
00736           *insert_position = value;
00737         }
00738         else
00739         {
00740           // Insert at the end.
00741           *insert_position = value;
00742           ++current_size;
00743         }
00744       }
00745       else
00746       {
00747         // Already full.
00748         if (position != end())
00749         {
00750           // Insert in the middle.
00751           std::copy_backward(insert_position, end() - 1, end());
00752           *insert_position = value;
00753         }
00754 
00755         is_truncated = true;
00756       }
00757 
00758       p_buffer[current_size] = 0;
00759 
00760       return insert_position;
00761     }
00762 
00763     //*********************************************************************
00764     /// Inserts 'n' values to the string.
00765     ///\param position The position to insert before.
00766     ///\param n        The number of elements to add.
00767     ///\param value    The value to insert.
00768     //*********************************************************************
00769     void insert(const_iterator position, size_t n, T value)
00770     {
00771       is_truncated = false;
00772 
00773       if (n == 0)
00774       {
00775         return;
00776       }
00777 
00778       // Quick hack, as iterators are pointers.
00779       iterator insert_position = const_cast<iterator>(position);
00780       const size_t start = std::distance(cbegin(), position);
00781 
00782       // No effect.
00783       if (start == CAPACITY)
00784       {
00785         return;
00786       }
00787 
00788       // Fills the string to the end?
00789       if ((start + n) >= CAPACITY)
00790       {
00791         is_truncated = ((current_size + n) > CAPACITY);
00792         current_size = CAPACITY;
00793         std::fill(insert_position, end(), value);
00794       }
00795       else
00796       {
00797         // Lets do some shifting.
00798         const size_t shift_amount = n;
00799         const size_t to_position = start + shift_amount;
00800         const size_t remaining_characters = current_size - start;
00801         const size_t max_shift_characters = CAPACITY - start - shift_amount;
00802         const size_t characters_to_shift = std::min(max_shift_characters, remaining_characters);
00803 
00804         // Will the string truncate?
00805         if ((start + shift_amount + remaining_characters) > CAPACITY)
00806         {
00807           current_size = CAPACITY;
00808           is_truncated = true;
00809         }
00810         else
00811         {
00812           current_size += shift_amount;
00813         }
00814 
00815         std::copy_backward(insert_position, insert_position + characters_to_shift, begin() + to_position + characters_to_shift);
00816         std::fill(insert_position, insert_position + shift_amount, value);
00817       }
00818 
00819       p_buffer[current_size] = 0;
00820     }
00821 
00822     //*********************************************************************
00823     /// Inserts a range of values to the string.
00824     /// If asserts or exceptions are enabled, emits string_full if the string does not have enough free space.
00825     ///\param position The position to insert before.
00826     ///\param first    The first element to add.
00827     ///\param last     The last + 1 element to add.
00828     //*********************************************************************
00829     template <class TIterator>
00830     void insert(iterator position, TIterator first, TIterator last)
00831     {
00832       is_truncated = false;
00833 
00834       if (first == last)
00835       {
00836         return;
00837       }
00838 
00839       const size_t start = std::distance(begin(), position);
00840       const size_t n = std::distance(first, last);
00841 
00842       // No effect.
00843       if (start == CAPACITY)
00844       {
00845         return;
00846       }
00847 
00848       // Fills the string to the end?
00849       if ((start + n) >= CAPACITY)
00850       {
00851         is_truncated = ((current_size + n) > CAPACITY);
00852         current_size = CAPACITY;
00853 
00854         while (position != end())
00855         {
00856           *position++ = *first++;
00857         }
00858       }
00859       else
00860       {
00861         // Lets do some shifting.
00862         const size_t shift_amount = n;
00863         const size_t to_position = start + shift_amount;
00864         const size_t remaining_characters = current_size - start;
00865         const size_t max_shift_characters = CAPACITY - start - shift_amount;
00866         const size_t characters_to_shift = std::min(max_shift_characters, remaining_characters);
00867 
00868         // Will the string truncate?
00869         if ((start + shift_amount + remaining_characters) > CAPACITY)
00870         {
00871           current_size = CAPACITY;
00872           is_truncated = true;
00873         }
00874         else
00875         {
00876           current_size += shift_amount;
00877         }
00878 
00879         std::copy_backward(position, position + characters_to_shift, begin() + to_position + characters_to_shift);
00880 
00881         while (first != last)
00882         {
00883           *position++ = *first++;
00884         }
00885       }
00886 
00887       p_buffer[current_size] = 0;
00888     }
00889 
00890     //*********************************************************************
00891     /// Inserts a string at the specified position.
00892     ///\param position The position to insert before.
00893     ///\param str      The string to insert.
00894     //*********************************************************************
00895     etl::ibasic_string<T>& insert(size_t position, const etl::ibasic_string<T>& str)
00896     {
00897       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
00898 
00899       insert(begin() + position, str.cbegin(), str.cend());
00900       return *this;
00901     }
00902 
00903     //*********************************************************************
00904     /// Inserts a string at the specified position from subposition for sublength.
00905     ///\param position    The position to insert before.
00906     ///\param str         The string to insert.
00907     ///\param subposition The subposition to start from.
00908     ///\param sublength   The number of characters to insert.
00909     //*********************************************************************
00910     etl::ibasic_string<T>& insert(size_t position, const etl::ibasic_string<T>& str, size_t subposition, size_t sublength)
00911     {
00912       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
00913       ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
00914 
00915       if ((sublength == npos) || (subposition + sublength > str.size()))
00916       {
00917         sublength = str.size() - subposition;
00918       }
00919 
00920       insert(begin() + position, str.cbegin() + subposition, str.cbegin() + subposition + sublength);
00921       return *this;
00922     }
00923 
00924     //*********************************************************************
00925     /// Inserts a string at the specified position from pointer.
00926     ///\param position The position to insert before.
00927     ///\param s        The string to insert.
00928     //*********************************************************************
00929     etl::ibasic_string<T>& insert(size_t position, const_pointer s)
00930     {
00931       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
00932 
00933       insert(begin() + position, s, s + strlen(s));
00934       return *this;
00935     }
00936 
00937     //*********************************************************************
00938     /// Inserts a string at the specified position from pointer for n characters.
00939     ///\param position The position to insert before.
00940     ///\param s        The string to insert.
00941     ///\param n        The number of characters to insert.
00942     //*********************************************************************
00943     etl::ibasic_string<T>& insert(size_t position, const_pointer s, size_t n)
00944     {
00945       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
00946 
00947       insert(begin() + position, s, s + n);
00948       return *this;
00949     }
00950 
00951     //*********************************************************************
00952     /// Insert n characters of c at position.
00953     ///\param position The position to insert before.
00954     ///\param n        The number of characters to insert.
00955     ///\param c        The character to insert.
00956     //*********************************************************************
00957     etl::ibasic_string<T>& insert(size_t position, size_t n, value_type c)
00958     {
00959       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
00960 
00961       insert(begin() + position, n, c);
00962       return *this;
00963     }
00964 
00965     //*********************************************************************
00966     /// Erases a sequence.
00967     ///\param position Position to start from.
00968     ///\param length   Number of characters.
00969     ///\return A refernce to this string.
00970     //*********************************************************************
00971     etl::ibasic_string<T>& erase(size_t position, size_t length_ = npos)
00972     {
00973       // Limit the length.
00974       length_ = std::min(length_, size() - position);
00975 
00976       erase(begin() + position, begin() + position + length_);
00977 
00978       return *this;
00979     }
00980 
00981     //*********************************************************************
00982     /// Erases an element.
00983     ///\param i_element Iterator to the element.
00984     ///\return An iterator pointing to the element that followed the erased element.
00985     //*********************************************************************
00986     iterator erase(iterator i_element)
00987     {
00988       std::copy(i_element + 1, end(), i_element);
00989       p_buffer[--current_size] = 0;
00990 
00991       return i_element;
00992     }
00993 
00994     //*********************************************************************
00995     /// Erases a range of elements.
00996     /// The range includes all the elements between first and last, including the
00997     /// element pointed by first, but not the one pointed by last.
00998     ///\param first Iterator to the first element.
00999     ///\param last  Iterator to the last element.
01000     ///\return An iterator pointing to the element that followed the erased element.
01001     //*********************************************************************
01002     iterator erase(iterator first, iterator last)
01003     {
01004       std::copy(last, end(), first);
01005       size_t n_delete = std::distance(first, last);
01006 
01007       current_size -= n_delete;
01008       p_buffer[current_size] = 0;
01009 
01010       return first;
01011     }
01012 
01013     //*********************************************************************
01014     /// Return a pointer to a C string.
01015     //*********************************************************************
01016     const_pointer c_str() const
01017     {
01018       return p_buffer;
01019     }
01020 
01021     //*********************************************************************
01022     /// Copies a portion of a string.
01023     ///\param s   Pointer to the string to copy.
01024     ///\param len The number of characters to copy.
01025     ///\param pos The position to start copying from.
01026     //*********************************************************************
01027     size_t copy(pointer s, size_t len, size_t pos = 0)
01028     {
01029       size_t endpos = std::min(pos + len, size());
01030 
01031       for (size_t i = pos; i < endpos; ++i)
01032       {
01033         *s++ = p_buffer[i];
01034       }
01035 
01036       return endpos - pos;
01037     }
01038 
01039     //*********************************************************************
01040     /// Find content within the string
01041     ///\param str The content to find
01042     ///\param pos The position to start searching from.
01043     //*********************************************************************
01044     size_t find(const ibasic_string<T>& str, size_t pos = 0) const
01045     {
01046       if ((pos + str.size()) > size())
01047       {
01048         return npos;
01049       }
01050 
01051       const_iterator iposition = std::search(begin() + pos, end(), str.begin(), str.end());
01052 
01053       if (iposition == end())
01054       {
01055         return npos;
01056       }
01057       else
01058       {
01059         return std::distance(begin(), iposition);
01060       }
01061     }
01062 
01063     //*********************************************************************
01064     /// Find content within the string
01065     ///\param s   Pointer to the content to find
01066     ///\param pos The position to start searching from.
01067     //*********************************************************************
01068     size_t find(const_pointer s, size_t pos = 0) const
01069     {
01070 #if defined(ETL_DEBUG)
01071       if ((pos + etl::strlen(s)) > size())
01072       {
01073         return npos;
01074       }
01075 #endif
01076 
01077       const_iterator iposition = std::search(begin() + pos, end(), s, s + etl::strlen(s));
01078 
01079       if (iposition == end())
01080       {
01081         return npos;
01082       }
01083       else
01084       {
01085         return std::distance(begin(), iposition);
01086       }
01087     }
01088 
01089     //*********************************************************************
01090     /// Find content within the string
01091     ///\param s   Pointer to the content to find
01092     ///\param pos The position to start searching from.
01093     ///\param n   The number of characters to search for.
01094     //*********************************************************************
01095     size_t find(const_pointer s, size_t pos, size_t n) const
01096     {
01097 #if defined(ETL_DEBUG)
01098       if ((pos + etl::strlen(s) - n) > size())
01099       {
01100         return npos;
01101       }
01102 #endif
01103 
01104       const_iterator iposition = std::search(begin() + pos, end(), s, s + n);
01105 
01106       if (iposition == end())
01107       {
01108         return npos;
01109       }
01110       else
01111       {
01112         return std::distance(begin(), iposition);
01113       }
01114     }
01115 
01116     //*********************************************************************
01117     /// Find character within the string
01118     ///\param c        The character to find.
01119     ///\param position The position to start searching from.
01120     //*********************************************************************
01121     size_t find(T c, size_t position = 0) const
01122     {
01123       const_iterator i = std::find(begin() + position, end(), c);
01124 
01125       if (i != end())
01126       {
01127         return std::distance(begin(), i);
01128       }
01129       else
01130       {
01131         return npos;
01132       }
01133     }
01134 
01135     //*********************************************************************
01136     /// Find content within the string
01137     ///\param str The content to find
01138     ///\param pos The position to start searching from.
01139     //*********************************************************************
01140     size_t rfind(const ibasic_string<T>& str, size_t position = npos) const
01141     {
01142       if ((str.size()) > size())
01143       {
01144         return npos;
01145       }
01146 
01147       if (position >= size())
01148       {
01149         position = size();
01150       }
01151 
01152       position = size() - position;
01153 
01154       const_reverse_iterator iposition = std::search(rbegin() + position, rend(), str.rbegin(), str.rend());
01155 
01156       if (iposition == rend())
01157       {
01158         return npos;
01159       }
01160       else
01161       {
01162         return size() - str.size() - std::distance(rbegin(), iposition);
01163       }
01164     }
01165 
01166     //*********************************************************************
01167     /// Find content within the string
01168     ///\param str The content to find
01169     ///\param pos The position to start searching from.
01170     //*********************************************************************
01171     size_t rfind(const_pointer s, size_t position = npos) const
01172     {
01173       size_t len = etl::strlen(s);
01174 
01175       if (len > size())
01176       {
01177         return npos;
01178       }
01179 
01180       if (position >= size())
01181       {
01182         position = size();
01183       }
01184 
01185       position = size() - position;
01186 
01187       const_reverse_iterator srbegin(s + len);
01188       const_reverse_iterator srend(s);
01189 
01190       const_reverse_iterator iposition = std::search(rbegin() + position, rend(), srbegin, srend);
01191 
01192       if (iposition == rend())
01193       {
01194         return npos;
01195       }
01196       else
01197       {
01198         return size() - len - std::distance(rbegin(), iposition);
01199       }
01200     }
01201 
01202     //*********************************************************************
01203     /// Find content within the string
01204     ///\param str The content to find
01205     ///\param pos The position to start searching from.
01206     //*********************************************************************
01207     size_t rfind(const_pointer s, size_t position, size_t length_) const
01208     {
01209       if (length_ > size())
01210       {
01211         return npos;
01212       }
01213 
01214       if (position >= size())
01215       {
01216         position = size();
01217       }
01218 
01219       position = size() - position;
01220 
01221       const_reverse_iterator srbegin(s + length_);
01222       const_reverse_iterator srend(s);
01223 
01224       const_reverse_iterator iposition = std::search(rbegin() + position, rend(), srbegin, srend);
01225 
01226       if (iposition == rend())
01227       {
01228         return npos;
01229       }
01230       else
01231       {
01232         return size() - length_ - std::distance(rbegin(), iposition);
01233       }
01234     }
01235 
01236     //*********************************************************************
01237     /// Find character within the string
01238     ///\param c   The character to find
01239     ///\param pos The position to start searching from.
01240     //*********************************************************************
01241     size_t rfind(T c, size_t position = npos) const
01242     {
01243       if (position >= size())
01244       {
01245         position = size();
01246       }
01247 
01248       position = size() - position;
01249 
01250       const_reverse_iterator i = std::find(rbegin() + position, rend(), c);
01251 
01252       if (i != rend())
01253       {
01254         return size() - std::distance(rbegin(), i) - 1;
01255       }
01256       else
01257       {
01258         return npos;
01259       }
01260     }
01261 
01262     //*********************************************************************
01263     /// Replace 'length' characters from 'position' with 'str'.
01264     ///\param position The position to start from.
01265     ///\param length   The number of characters to replace.
01266     ///\param str      The string to replace it with.
01267     //*********************************************************************
01268     ibasic_string& replace(size_t position, size_t length_, const ibasic_string& str)
01269     {
01270       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
01271 
01272       // Limit the length.
01273       length_ = std::min(length_, size() - position);
01274 
01275       // Erase the bit we want to replace.
01276       erase(position, length_);
01277 
01278       // Insert the new stuff.
01279       insert(position, str);
01280 
01281       return *this;
01282     }
01283 
01284     //*********************************************************************
01285     /// Replace characters from 'first' to one before 'last' with 'str'.
01286     ///\param first The position to start from.
01287     ///\param last  The one after the position to end at.
01288     ///\param str   The string to replace it with.
01289     //*********************************************************************
01290     ibasic_string& replace(const_iterator first, const_iterator last, const ibasic_string& str)
01291     {
01292       // Quick hack, as iterators are pointers.
01293       iterator first_ = const_cast<iterator>(first);
01294       iterator last_ = const_cast<iterator>(last);
01295 
01296       // Erase the bit we want to replace.
01297       erase(first_, last_);
01298 
01299       // Insert the new stuff.
01300       insert(first_, str.begin(), str.end());
01301 
01302       return *this;
01303     }
01304 
01305     //*********************************************************************
01306     /// Replace characters from 'position' of 'length' with 'str' from 'subpsotion' of 'sublength'.
01307     //*********************************************************************
01308     ibasic_string& replace(size_t position, size_t length_, const ibasic_string& str, size_t subposition, size_t sublength)
01309     {
01310       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
01311       ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
01312 
01313       // Limit the lengths.
01314       length_ = std::min(length_, size() - position);
01315       sublength = std::min(sublength, str.size() - subposition);
01316 
01317       // Erase the bit we want to replace.
01318       erase(position, length_);
01319 
01320       // Insert the new stuff.
01321       insert(position, str, subposition, sublength);
01322 
01323       return *this;
01324     }
01325 
01326     //*********************************************************************
01327     /// Replace characters from 'position' of 'length' with pointed to string.
01328     //*********************************************************************
01329     ibasic_string& replace(size_t position, size_t length_, const_pointer s)
01330     {
01331       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
01332 
01333       // Limit the length.
01334       length_ = std::min(length_, size() - position);
01335 
01336       // Erase the bit we want to replace.
01337       erase(position, length_);
01338 
01339       // Insert the new stuff.
01340       insert(position, s, etl::strlen(s));
01341 
01342       return *this;
01343     }
01344 
01345     //*********************************************************************
01346     /// Replace characters from 'first'  'last' with pointed to string.
01347     //*********************************************************************
01348     ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s)
01349     {
01350       // Quick hack, as iterators are pointers.
01351       iterator first_ = const_cast<iterator>(first);
01352       iterator last_ = const_cast<iterator>(last);
01353 
01354       // Erase the bit we want to replace.
01355       erase(first_, last_);
01356 
01357       // Insert the new stuff.
01358       insert(first_, s, s + etl::strlen(s));
01359 
01360       return *this;
01361     }
01362 
01363     //*********************************************************************
01364     /// Replace characters from 'position' of 'length' with 'n' characters from pointed to string.
01365     //*********************************************************************
01366     ibasic_string& replace(size_t position, size_t length_, const_pointer s, size_t n)
01367     {
01368       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
01369 
01370       // Limit the length.
01371       length_ = std::min(length_, size() - position);
01372 
01373       // Erase the bit we want to replace.
01374       erase(position, length_);
01375 
01376       // Insert the new stuff.
01377       insert(position, s, n);
01378 
01379       return *this;
01380     }
01381 
01382     //*********************************************************************
01383     /// Replace characters from 'first' to 'last' with 'n' characters from pointed to string.
01384     //*********************************************************************
01385     ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s, size_t n)
01386     {
01387       // Quick hack, as iterators are pointers.
01388       iterator first_ = const_cast<iterator>(first);
01389       iterator last_ = const_cast<iterator>(last);
01390 
01391       // Erase the bit we want to replace.
01392       erase(first_, last_);
01393 
01394       // Insert the new stuff.
01395       insert(first_, s, s + n);
01396 
01397       return *this;
01398     }
01399 
01400     //*********************************************************************
01401     /// Replace characters from 'position' of 'length' with 'n' copies of 'c'.
01402     //*********************************************************************
01403     ibasic_string& replace(size_t position, size_t length_, size_t n, value_type c)
01404     {
01405       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
01406 
01407       // Limit the length.
01408       length_ = std::min(length_, size() - position);
01409 
01410       // Erase the bit we want to replace.
01411       erase(position, length_);
01412 
01413       // Insert the new stuff.
01414       insert(position, n, c);
01415 
01416       return *this;
01417     }
01418 
01419     //*********************************************************************
01420     /// Replace characters from 'first' of 'last' with 'n' copies of 'c'.
01421     //*********************************************************************
01422     ibasic_string& replace(const_iterator first, const_iterator last, size_t n, value_type c)
01423     {
01424       // Quick hack, as iterators are pointers.
01425       iterator first_ = const_cast<iterator>(first);
01426       iterator last_ = const_cast<iterator>(last);
01427 
01428       // Erase the bit we want to replace.
01429       erase(first_, last_);
01430 
01431       // Insert the new stuff.
01432       insert(first_, n, c);
01433 
01434       return *this;
01435     }
01436 
01437     //*********************************************************************
01438     /// Replace characters from 'first' of 'last' with characters from 'first_replace' to 'last_replace'.
01439     //*********************************************************************
01440     template <typename TIterator>
01441     ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace)
01442     {
01443       // Quick hack, as iterators are pointers.
01444       iterator first_ = const_cast<iterator>(first);
01445       iterator last_ = const_cast<iterator>(last);
01446 
01447       // Erase the bit we want to replace.
01448       erase(first_, last_);
01449 
01450       // Insert the new stuff.
01451       insert(first_, first_replace, last_replace);
01452 
01453       return *this;
01454     }
01455 
01456     //*************************************************************************
01457     /// Compare with string.
01458     //*************************************************************************
01459     int compare(const ibasic_string& str) const
01460     {
01461       return compare(p_buffer,
01462         p_buffer + size(),
01463         str.p_buffer,
01464         str.p_buffer + str.size());
01465     }
01466 
01467     //*************************************************************************
01468     /// Compare position / length with string.
01469     //*************************************************************************
01470     int compare(size_t position, size_t length_, const ibasic_string& str) const
01471     {
01472       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
01473 
01474       // Limit the length.
01475       length_ = std::min(length_, size() - position);
01476 
01477       return compare(p_buffer + position,
01478         p_buffer + position + length_,
01479         str.p_buffer,
01480         str.p_buffer + str.size());
01481     }
01482 
01483     //*************************************************************************
01484     /// Compare position / length with string / subposition / sublength.
01485     //*************************************************************************
01486     int compare(size_t position, size_t length_, const ibasic_string& str, size_t subposition, size_t sublength) const
01487     {
01488       ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds));
01489       ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
01490 
01491       // Limit the lengths.
01492       length_ = std::min(length_, size() - position);
01493       sublength = std::min(sublength, str.size() - subposition);
01494 
01495       return compare(p_buffer + position,
01496         p_buffer + position + length_,
01497         str.p_buffer + subposition,
01498         str.p_buffer + subposition + sublength);
01499     }
01500 
01501     //*************************************************************************
01502     ///  Compare with C string
01503     //*************************************************************************
01504     int compare(const value_type* s) const
01505     {
01506       return compare(p_buffer,
01507         p_buffer + size(),
01508         s,
01509         s + etl::strlen(s));
01510     }
01511 
01512     //*************************************************************************
01513     /// Compare position / length with C string.
01514     //*************************************************************************
01515     int compare(size_t position, size_t length_, const_pointer s) const
01516     {
01517       return compare(p_buffer + position,
01518         p_buffer + position + length_,
01519         s,
01520         s + etl::strlen(s));
01521     }
01522 
01523     //*************************************************************************
01524     /// Compare position / length with C string / n.
01525     //*************************************************************************
01526     int compare(size_t position, size_t length_, const_pointer s, size_t n) const
01527     {
01528       return compare(p_buffer + position,
01529         p_buffer + position + length_,
01530         s,
01531         s + n);;
01532     }
01533 
01534     //*********************************************************************
01535     /// Find first of any of content within the string
01536     ///\param str The content to find
01537     ///\param pos The position to start searching from.
01538     //*********************************************************************
01539     size_t find_first_of(const ibasic_string<T>& str, size_t position = 0) const
01540     {
01541       return find_first_of(str.c_str(), position, str.size());
01542     }
01543 
01544     //*********************************************************************
01545     /// Find first of any of content within the string
01546     ///\param s   Pointer to the content to find
01547     ///\param pos The position to start searching from.
01548     //*********************************************************************
01549     size_t find_first_of(const_pointer s, size_t position = 0) const
01550     {
01551       return find_first_of(s, position, etl::strlen(s));
01552     }
01553 
01554     //*********************************************************************
01555     /// Find first of any of content within the string
01556     ///\param s   Pointer to the content to find
01557     ///\param pos The position to start searching from.
01558     ///\param n   The number of characters to search for.
01559     //*********************************************************************
01560     size_t find_first_of(const_pointer s, size_t position, size_t n) const
01561     {
01562       if (position < size())
01563       {
01564         for (size_t i = position; i < size(); ++i)
01565         {
01566           for (size_t j = 0; j < n; ++j)
01567           {
01568             if (p_buffer[i] == s[j])
01569             {
01570               return i;
01571             }
01572           }
01573         }
01574       }
01575 
01576       return npos;
01577     }
01578 
01579     //*********************************************************************
01580     /// Find first of character within the string
01581     ///\param c   The character to find
01582     ///\param pos The position to start searching from.
01583     //*********************************************************************
01584     size_t find_first_of(value_type c, size_t position = 0) const
01585     {
01586       if (position < size())
01587       {
01588         for (size_t i = position; i < size(); ++i)
01589         {
01590           if (p_buffer[i] == c)
01591           {
01592             return i;
01593           }
01594         }
01595       }
01596 
01597       return npos;
01598     }
01599 
01600     //*********************************************************************
01601     /// Find last of any of content within the string
01602     ///\param str The content to find
01603     ///\param pos The position to start searching from.
01604     //*********************************************************************
01605     size_t find_last_of(const ibasic_string<T>& str, size_t position = npos) const
01606     {
01607       return find_last_of(str.c_str(), position, str.size());
01608     }
01609 
01610     //*********************************************************************
01611     /// Find last of any of content within the string
01612     ///\param s   Pointer to the content to find
01613     ///\param pos The position to start searching from.
01614     //*********************************************************************
01615     size_t find_last_of(const_pointer s, size_t position = npos) const
01616     {
01617       return find_last_of(s, position, etl::strlen(s));
01618     }
01619 
01620     //*********************************************************************
01621     /// Find last of any of content within the string
01622     ///\param s   Pointer to the content to find
01623     ///\param pos The position to start searching from.
01624     ///\param n   The number of characters to search for.
01625     //*********************************************************************
01626     size_t find_last_of(const_pointer s, size_t position, size_t n) const
01627     {
01628       if (empty())
01629       {
01630         return npos;
01631       }
01632 
01633       position = std::min(position, size() - 1);
01634 
01635       const_reverse_iterator it = rbegin() + size() - position - 1;
01636 
01637       while (it != rend())
01638       {
01639         for (size_t j = 0; j < n; ++j)
01640         {
01641           if (p_buffer[position] == s[j])
01642           {
01643             return position;
01644           }
01645         }
01646 
01647         ++it;
01648         --position;
01649       }
01650 
01651       return npos;
01652     }
01653 
01654     //*********************************************************************
01655     /// Find last of character within the string
01656     ///\param c   The character to find
01657     ///\param pos The position to start searching from.
01658     //*********************************************************************
01659     size_t find_last_of(value_type c, size_t position = npos) const
01660     {
01661       if (empty())
01662       {
01663         return npos;
01664       }
01665 
01666       position = std::min(position, size() - 1);
01667 
01668       const_reverse_iterator it = rbegin() + size() - position - 1;
01669 
01670       while (it != rend())
01671       {
01672         if (p_buffer[position] == c)
01673         {
01674           return position;
01675         }
01676 
01677         ++it;
01678         --position;
01679       }
01680 
01681       return npos;
01682     }
01683 
01684     //*********************************************************************
01685     /// Find first not of any of content within the string
01686     ///\param str The content to find
01687     ///\param pos The position to start searching from.
01688     //*********************************************************************
01689     size_t find_first_not_of(const ibasic_string<T>& str, size_t position = 0) const
01690     {
01691       return find_first_not_of(str.c_str(), position, str.size());
01692     }
01693 
01694     //*********************************************************************
01695     /// Find first not of any of content within the string
01696     ///\param s   Pointer to the content to not find
01697     ///\param pos The position to start searching from.
01698     //*********************************************************************
01699     size_t find_first_not_of(const_pointer s, size_t position = 0) const
01700     {
01701       return find_first_not_of(s, position, etl::strlen(s));
01702     }
01703 
01704     //*********************************************************************
01705     /// Find first not of any of content within the string
01706     ///\param s   Pointer to the content to not find
01707     ///\param pos The position to start searching from.
01708     ///\param n   The number of characters to search for.
01709     //*********************************************************************
01710     size_t find_first_not_of(const_pointer s, size_t position, size_t n) const
01711     {
01712       if (position < size())
01713       {
01714         for (size_t i = position; i < size(); ++i)
01715         {
01716           bool found = false;
01717 
01718           for (size_t j = 0; j < n; ++j)
01719           {
01720             if (p_buffer[i] == s[j])
01721             {
01722               found = true;
01723             }
01724           }
01725 
01726           if (!found)
01727           {
01728             return i;
01729           }
01730         }
01731       }
01732 
01733       return npos;
01734     }
01735 
01736     //*********************************************************************
01737     /// Find first not of character within the string
01738     ///\param c   The character to not find
01739     ///\param pos The position to start searching from.
01740     //*********************************************************************
01741     size_t find_first_not_of(value_type c, size_t position = 0) const
01742     {
01743       if (position < size())
01744       {
01745         for (size_t i = position; i < size(); ++i)
01746         {
01747           if (p_buffer[i] != c)
01748           {
01749             return i;
01750           }
01751         }
01752       }
01753 
01754       return npos;
01755     }
01756 
01757     //*********************************************************************
01758     /// Find last not of any of content within the string
01759     ///\param str The content to find
01760     ///\param pos The position to start searching from.
01761     //*********************************************************************
01762     size_t find_last_not_of(const ibasic_string<T>& str, size_t position = npos) const
01763     {
01764       return find_last_not_of(str.c_str(), position, str.size());
01765     }
01766 
01767     //*********************************************************************
01768     /// Find last not of any of content within the string
01769     ///\param s   The pointer to the content to find
01770     ///\param pos The position to start searching from.
01771     //*********************************************************************
01772     size_t find_last_not_of(const_pointer s, size_t position = npos) const
01773     {
01774       return find_last_not_of(s, position, etl::strlen(s));
01775     }
01776 
01777     //*********************************************************************
01778     /// Find last not of any of content within the string
01779     ///\param s   The pointer to the content to find
01780     ///\param pos The position to start searching from.
01781     ///\param n   The number of characters to use.
01782     //*********************************************************************
01783     size_t find_last_not_of(const_pointer s, size_t position, size_t n) const
01784     {
01785       if (empty())
01786       {
01787         return npos;
01788       }
01789 
01790       position = std::min(position, size() - 1);
01791 
01792       const_reverse_iterator it = rbegin() + size() - position - 1;
01793 
01794       while (it != rend())
01795       {
01796         bool found = false;
01797 
01798         for (size_t j = 0; j < n; ++j)
01799         {
01800           if (p_buffer[position] == s[j])
01801           {
01802             found = true;
01803           }
01804         }
01805 
01806         if (!found)
01807         {
01808           return position;
01809         }
01810 
01811         ++it;
01812         --position;
01813       }
01814 
01815       return npos;
01816     }
01817 
01818     //*********************************************************************
01819     //
01820     //*********************************************************************
01821     size_t find_last_not_of(value_type c, size_t position = npos) const
01822     {
01823       if (empty())
01824       {
01825         return npos;
01826       }
01827 
01828       position = std::min(position, size() - 1);
01829 
01830       const_reverse_iterator it = rbegin() + size() - position - 1;
01831 
01832       while (it != rend())
01833       {
01834         if (p_buffer[position] != c)
01835         {
01836           return position;
01837         }
01838 
01839         ++it;
01840         --position;
01841       }
01842 
01843       return npos;
01844     }
01845 
01846     //*************************************************************************
01847     /// Assignment operator.
01848     //*************************************************************************
01849     ibasic_string& operator = (const ibasic_string& rhs)
01850     {
01851       if (&rhs != this)
01852       {
01853         assign(rhs.cbegin(), rhs.cend());
01854       }
01855 
01856       return *this;
01857     }
01858 
01859     //*************************************************************************
01860     /// += operator.
01861     //*************************************************************************
01862     ibasic_string& operator += (const ibasic_string& rhs)
01863     {
01864       if (&rhs != this)
01865       {
01866         append(rhs);
01867       }
01868 
01869       return *this;
01870     }
01871 
01872     //*************************************************************************
01873     /// += operator.
01874     //*************************************************************************
01875     ibasic_string& operator += (const T* rhs)
01876     {
01877       append(rhs);
01878 
01879       return *this;
01880     }
01881 
01882     //*************************************************************************
01883     /// += operator.
01884     //*************************************************************************
01885     ibasic_string& operator += (T rhs)
01886     {
01887       append(size_t(1), rhs);
01888 
01889       return *this;
01890     }
01891 
01892 #ifdef ETL_ISTRING_REPAIR_ENABLE
01893     //*************************************************************************
01894     /// Fix the internal pointers after a low level memory copy.
01895     //*************************************************************************
01896     virtual void repair() = 0;
01897 #endif
01898 
01899   protected:
01900 
01901     //*********************************************************************
01902     /// Constructor.
01903     //*********************************************************************
01904     ibasic_string(T* p_buffer_, size_t MAX_SIZE_)
01905       : string_base(MAX_SIZE_),
01906         p_buffer(p_buffer_)
01907     {
01908     }
01909 
01910     //*********************************************************************
01911     /// Initialise the string.
01912     //*********************************************************************
01913     void initialise()
01914     {
01915       current_size = 0;
01916       p_buffer[0] = 0;
01917     }
01918 
01919     //*************************************************************************
01920     /// Fix the internal pointers after a low level memory copy.
01921     //*************************************************************************
01922     void repair(T* p_buffer_)
01923     {
01924       p_buffer = p_buffer_;
01925     }
01926 
01927   private:
01928 
01929     //*************************************************************************
01930     /// Compare helper function
01931     //*************************************************************************
01932     int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2) const
01933     {
01934       while ((first1 != last1) && (first2 != last2))
01935       {
01936         if (*first1 < *first2)
01937         {
01938           // Compared character is lower.
01939           return -1;
01940         }
01941         else if (*first1 > *first2)
01942         {
01943           // Compared character is higher.
01944           return 1;
01945         }
01946 
01947         ++first1;
01948         ++first2;
01949       }
01950 
01951       // We reached the end of one or both of the strings.
01952       if ((first1 == last1) && (first2 == last2))
01953       {
01954         // Same length.
01955         return 0;
01956       }
01957       else if (first1 == last1)
01958       {
01959         // Compared string is shorter.
01960         return -1;
01961       }
01962       else
01963       {
01964         // Compared string is longer.
01965         return 1;
01966       }
01967     }
01968 
01969     // Disable copy construction.
01970     ibasic_string(const ibasic_string&);
01971 
01972     T* p_buffer;
01973   };
01974 
01975   //***************************************************************************
01976   /// Equal operator.
01977   ///\param lhs Reference to the first string.
01978   ///\param rhs Reference to the second string.
01979   ///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
01980   ///\ingroup string
01981   //***************************************************************************
01982   template <typename T>
01983   bool operator ==(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
01984   {
01985     return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin());
01986   }
01987 
01988   //***************************************************************************
01989   /// Equal operator.
01990   ///\param lhs Reference to the first string.
01991   ///\param rhs Reference to the second string.
01992   ///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
01993   ///\ingroup string
01994   //***************************************************************************
01995   template <typename T>
01996   bool operator ==(const etl::ibasic_string<T>& lhs, const T* rhs)
01997   {
01998     return (lhs.size() == etl::strlen(rhs)) && std::equal(lhs.begin(), lhs.end(), rhs);
01999   }
02000 
02001   //***************************************************************************
02002   /// Equal operator.
02003   ///\param lhs Reference to the first string.
02004   ///\param rhs Reference to the second string.
02005   ///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
02006   ///\ingroup string
02007   //***************************************************************************
02008   template <typename T>
02009   bool operator ==(const T* lhs, const etl::ibasic_string<T>& rhs)
02010   {
02011     return (rhs.size() == etl::strlen(lhs)) && std::equal(rhs.begin(), rhs.end(), lhs);
02012   }
02013 
02014 
02015   //***************************************************************************
02016   /// Not equal operator.
02017   ///\param lhs Reference to the first string.
02018   ///\param rhs Reference to the second string.
02019   ///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
02020   ///\ingroup string
02021   //***************************************************************************
02022   template <typename T>
02023   bool operator !=(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
02024   {
02025     return !(lhs == rhs);
02026   }
02027 
02028   //***************************************************************************
02029   /// Not equal operator.
02030   ///\param lhs Reference to the first string.
02031   ///\param rhs Reference to the second string.
02032   ///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
02033   ///\ingroup string
02034   //***************************************************************************
02035   template <typename T>
02036   bool operator !=(const etl::ibasic_string<T>& lhs, const T* rhs)
02037   {
02038     return !(lhs == rhs);
02039   }
02040 
02041   //***************************************************************************
02042   /// Not equal operator.
02043   ///\param lhs Reference to the first string.
02044   ///\param rhs Reference to the second string.
02045   ///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
02046   ///\ingroup string
02047   //***************************************************************************
02048   template <typename T>
02049   bool operator !=(const T* lhs, const etl::ibasic_string<T>& rhs)
02050   {
02051     return !(lhs == rhs);
02052   }
02053 
02054 
02055   //***************************************************************************
02056   /// Less than operator.
02057   ///\param lhs Reference to the first string.
02058   ///\param rhs Reference to the second string.
02059   ///\return <b>true</b> if the first string is lexicographically less than the second, otherwise <b>false</b>
02060   ///\ingroup string
02061   //***************************************************************************
02062   template <typename T>
02063   bool operator <(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
02064   {
02065     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
02066   }
02067 
02068   //***************************************************************************
02069   /// Less than operator.
02070   ///\param lhs Reference to the first string.
02071   ///\param rhs Reference to the second string.
02072   ///\return <b>true</b> if the first string is lexicographically less than the second, otherwise <b>false</b>
02073   ///\ingroup string
02074   //***************************************************************************
02075   template <typename T>
02076   bool operator <(const etl::ibasic_string<T>& lhs, const T* rhs)
02077   {
02078     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs));
02079   }
02080 
02081   //***************************************************************************
02082   /// Less than operator.
02083   ///\param lhs Reference to the first string.
02084   ///\param rhs Reference to the second string.
02085   ///\return <b>true</b> if the first string is lexicographically less than the second, otherwise <b>false</b>
02086   ///\ingroup string
02087   //***************************************************************************
02088   template <typename T>
02089   bool operator <(const T* lhs, const etl::ibasic_string<T>& rhs)
02090   {
02091     return std::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end());
02092   }
02093 
02094 
02095   //***************************************************************************
02096   /// Greater than operator.
02097   ///\param lhs Reference to the first string.
02098   ///\param rhs Reference to the second string.
02099   ///\return <b>true</b> if the first string is lexicographically greater than the second, otherwise <b>false</b>
02100   ///\ingroup string
02101   //***************************************************************************
02102   template <typename T>
02103   bool operator >(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
02104   {
02105     return (rhs < lhs);
02106   }
02107 
02108   //***************************************************************************
02109   /// Greater than operator.
02110   ///\param lhs Reference to the first string.
02111   ///\param rhs Reference to the second string.
02112   ///\return <b>true</b> if the first string is lexicographically greater than the second, otherwise <b>false</b>
02113   ///\ingroup string
02114   //***************************************************************************
02115   template <typename T>
02116   bool operator >(const etl::ibasic_string<T>& lhs, const T* rhs)
02117   {
02118     return (rhs < lhs);
02119   }
02120 
02121   //***************************************************************************
02122   /// Greater than operator.
02123   ///\param lhs Reference to the first string.
02124   ///\param rhs Reference to the second string.
02125   ///\return <b>true</b> if the first string is lexicographically greater than the second, otherwise <b>false</b>
02126   ///\ingroup string
02127   //***************************************************************************
02128   template <typename T>
02129   bool operator >(const T* lhs, const etl::ibasic_string<T>& rhs)
02130   {
02131     return (rhs < lhs);
02132   }
02133 
02134 
02135   //***************************************************************************
02136   /// Less than or equal operator.
02137   ///\param lhs Reference to the first string.
02138   ///\param rhs Reference to the second string.
02139   ///\return <b>true</b> if the first string is lexicographically less than or equal to the second, otherwise <b>false</b>
02140   ///\ingroup string
02141   //***************************************************************************
02142   template <typename T>
02143   bool operator <=(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
02144   {
02145     return !(lhs > rhs);
02146   }
02147 
02148   //***************************************************************************
02149   /// Less than or equal operator.
02150   ///\param lhs Reference to the first string.
02151   ///\param rhs Reference to the second string.
02152   ///\return <b>true</b> if the first string is lexicographically less than or equal to the second, otherwise <b>false</b>
02153   ///\ingroup string
02154   //***************************************************************************
02155   template <typename T>
02156   bool operator <=(const etl::ibasic_string<T>& lhs, const T* rhs)
02157   {
02158     return !(lhs > rhs);
02159   }
02160 
02161   //***************************************************************************
02162   /// Less than or equal operator.
02163   ///\param lhs Reference to the first string.
02164   ///\param rhs Reference to the second string.
02165   ///\return <b>true</b> if the first string is lexicographically less than or equal to the second, otherwise <b>false</b>
02166   ///\ingroup string
02167   //***************************************************************************
02168   template <typename T>
02169   bool operator <=(const T* lhs, const etl::ibasic_string<T>& rhs)
02170   {
02171     return !(lhs > rhs);
02172   }
02173 
02174 
02175   //***************************************************************************
02176   /// Greater than or equal operator.
02177   ///\param lhs Reference to the first string.
02178   ///\param rhs Reference to the second string.
02179   ///\return <b>true</b> if the first string is lexicographically greater than or equal to the second, otherwise <b>false</b>
02180   ///\ingroup string
02181   //***************************************************************************
02182   template <typename T>
02183   bool operator >=(const etl::ibasic_string<T>& lhs, const etl::ibasic_string<T>& rhs)
02184   {
02185     return !(lhs < rhs);
02186   }
02187 
02188   //***************************************************************************
02189   /// Greater than or equal operator.
02190   ///\param lhs Reference to the first string.
02191   ///\param rhs Reference to the second string.
02192   ///\return <b>true</b> if the first string is lexicographically greater than or equal to the second, otherwise <b>false</b>
02193   ///\ingroup string
02194   //***************************************************************************
02195   template <typename T>
02196   bool operator >=(const etl::ibasic_string<T>& lhs, const T* rhs)
02197   {
02198     return !(lhs < rhs);
02199   }
02200 
02201   //***************************************************************************
02202   /// Greater than or equal operator.
02203   ///\param lhs Reference to the first string.
02204   ///\param rhs Reference to the second string.
02205   ///\return <b>true</b> if the first string is lexicographically greater than or equal to the second, otherwise <b>false</b>
02206   ///\ingroup string
02207   //***************************************************************************
02208   template <typename T>
02209   bool operator >=(const T* lhs, const etl::ibasic_string<T>& rhs)
02210   {
02211     return !(lhs < rhs);
02212   }
02213 }
02214 
02215 #ifdef ETL_COMPILER_MICROSOFT
02216 #define min(a,b) (((a) < (b)) ? (a) : (b))
02217 #endif
02218 
02219 #ifdef ETL_COMPILER_MICROSOFT
02220 #define max(a,b) (((a) > (b)) ? (a) : (b))
02221 #endif
02222 
02223 #undef ETL_FILE
02224 
02225 #endif
02226