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