Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
basic_string.h
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
Generated on Tue Jul 12 2022 14:05:39 by
