1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // Permission to use, copy, modify, distribute and sell this software for any
5 // purpose is hereby granted without fee, provided that the above copyright
6 // notice appear in all copies and that both that copyright notice and this
7 // permission notice appear in supporting documentation.
8 // The author makes no representations about the
9 // suitability of this software for any purpose. It is provided "as is"
10 // without express or implied warranty.
11 ////////////////////////////////////////////////////////////////////////////////
13 #ifndef FLEX_STRING_SHELL_INC_
14 #define FLEX_STRING_SHELL_INC_
16 // $Id: flex_string_shell.h 948 2009-01-26 01:55:50Z rich_sposato $
19 ///////////////////////////////////////////////////////////////////////////////
20 // class template flex_string
21 // This file does not include any storage policy headers
22 ///////////////////////////////////////////////////////////////////////////////
30 #include "flex_string_details.h"
33 // Forward declaration for default storage policy
34 template <typename E, class A> class AllocatorStringStorage;
37 template <class T> class mallocator
41 typedef value_type *pointer;
42 typedef const value_type *const_pointer;
43 typedef value_type &reference;
44 typedef const value_type &const_reference;
45 typedef std::size_t size_type;
46 //typedef unsigned int size_type;
47 //typedef std::ptrdiff_t difference_type;
48 typedef int difference_type;
53 typedef mallocator<U> other;
57 mallocator(const mallocator &) {}
59 //mallocator(const mallocator<U>&) {}
62 pointer address(reference x) const
66 const_pointer address(const_reference x) const
71 pointer allocate(size_type n, const_pointer = 0)
74 void *p = malloc(n * sizeof(T));
75 if (!p) throw bad_alloc();
76 return static_cast<pointer>(p);
79 void deallocate(pointer p, size_type)
85 size_type max_size() const
87 return static_cast<size_type>(-1) / sizeof(T);
90 void construct(pointer p, const value_type &x)
95 void destroy(pointer p)
101 void operator=(const mallocator &);
104 template<> class mallocator<void>
106 typedef void value_type;
107 typedef void *pointer;
108 typedef const void *const_pointer;
113 typedef mallocator<U> other;
118 inline bool operator==(const mallocator<T>&,
119 const mallocator<T>&)
125 inline bool operator!=(const mallocator<T>&,
126 const mallocator<T>&)
131 template <class Allocator>
132 typename Allocator::pointer Reallocate(
134 typename Allocator::pointer p,
135 typename Allocator::size_type oldObjCount,
136 typename Allocator::size_type newObjCount,
139 // @@@ not implemented
142 template <class Allocator>
143 typename Allocator::pointer Reallocate(
145 typename Allocator::pointer p,
146 typename Allocator::size_type oldObjCount,
147 typename Allocator::size_type newObjCount,
150 // @@@ not implemented
154 ////////////////////////////////////////////////////////////////////////////////
155 // class template flex_string
156 // a std::basic_string compatible implementation
157 // Uses a Storage policy
158 ////////////////////////////////////////////////////////////////////////////////
160 template <typename E,
161 class T = std::char_traits<E>,
162 class A = std::allocator<E>,
163 class Storage = AllocatorStringStorage<E, A> >
164 class flex_string : private Storage
167 template <typename Exception>
168 static void Enforce(bool condition, Exception *, const char *msg)
170 if (!condition) throw Exception(msg);
177 empty() == (size() == 0) &&
178 empty() == (begin() == end()) &&
179 size() <= max_size() &&
180 capacity() <= max_size() &&
181 size() <= capacity();
185 friend struct Invariant;
189 Invariant(const flex_string &s) : s_(s)
198 const flex_string &s_;
200 Invariant(const flex_string &) {}
202 Invariant &operator=(const Invariant &);
207 typedef T traits_type;
208 typedef typename traits_type::char_type value_type;
209 typedef A allocator_type;
210 typedef typename A::size_type size_type;
211 typedef typename A::difference_type difference_type;
213 typedef typename Storage::reference reference;
214 typedef typename A::const_reference const_reference;
215 typedef typename A::pointer pointer;
216 typedef typename A::const_pointer const_pointer;
218 typedef typename Storage::iterator iterator;
219 typedef typename Storage::const_iterator const_iterator;
220 typedef std::reverse_iterator<iterator
221 #ifdef NO_ITERATOR_TRAITS
225 typedef std::reverse_iterator<const_iterator
226 #ifdef NO_ITERATOR_TRAITS
229 > const_reverse_iterator;
231 static const size_type npos; // = size_type(-1)
234 static size_type Min(size_type lhs, size_type rhs)
236 return lhs < rhs ? lhs : rhs;
238 static size_type Max(size_type lhs, size_type rhs)
240 return lhs > rhs ? lhs : rhs;
242 static void Procust(size_type &n, size_type nmax)
244 if (n > nmax) n = nmax;
248 // 21.3.1 construct/copy/destroy
249 explicit flex_string(const A &a = A())
253 flex_string(const flex_string &str)
257 flex_string(const flex_string &str, size_type pos,
258 size_type n = npos, const A &a = A())
264 flex_string(const value_type *s, const A &a = A())
265 : Storage(s, traits_type::length(s), a)
268 flex_string(const value_type *s, size_type n, const A &a = A())
272 flex_string(size_type n, value_type c, const A &a = A())
276 template <class InputIterator>
277 flex_string(InputIterator begin, InputIterator end, const A &a = A())
286 flex_string &operator=(const flex_string &str)
293 flex_string &operator=(const value_type *s)
299 flex_string &operator=(value_type c)
308 return Storage::begin();
311 const_iterator begin() const
313 return Storage::begin();
318 return Storage::end();
321 const_iterator end() const
323 return Storage::end();
326 reverse_iterator rbegin()
328 return reverse_iterator(end());
331 const_reverse_iterator rbegin() const
333 return const_reverse_iterator(end());
336 reverse_iterator rend()
338 return reverse_iterator(begin());
341 const_reverse_iterator rend() const
343 return const_reverse_iterator(begin());
347 size_type size() const
349 return Storage::size();
352 size_type length() const
357 size_type max_size() const
359 return Storage::max_size();
362 void resize(size_type n, value_type c)
364 Storage::resize(n, c);
367 void resize(size_type n)
369 resize(n, value_type());
372 size_type capacity() const
374 return Storage::capacity();
377 void reserve(size_type res_arg = 0)
379 Enforce(res_arg <= max_size(), static_cast<std::length_error *>(0), "");
380 Storage::reserve(res_arg);
393 // 21.3.4 element access:
394 const_reference operator[](size_type pos) const
396 return *(c_str() + pos);
399 reference operator[](size_type pos)
401 return *(begin() + pos);
404 const_reference at(size_type n) const
406 Enforce(n <= size(), static_cast<std::out_of_range *>(0), "");
410 reference at(size_type n)
412 Enforce(n < size(), static_cast<std::out_of_range *>(0), "");
417 flex_string &operator+=(const flex_string &str)
422 flex_string &operator+=(const value_type *s)
427 flex_string &operator+=(const value_type c)
433 flex_string &append(const flex_string &str)
435 return append(str.data(), str.length());
438 flex_string &append(const flex_string &str, const size_type pos,
441 const size_type sz = str.size();
442 Enforce(pos <= sz, static_cast<std::out_of_range *>(0), "");
443 Procust(n, sz - pos);
444 return append(str.data() + pos, n);
447 flex_string &append(const value_type *s, const size_type n)
449 Invariant checker(*this);
451 static std::less_equal<const value_type *> le;
452 if (le(&*begin(), s) && le(s, &*end())) // aliasing
454 const size_type offset = s - &*begin();
455 Storage::reserve(size() + n);
456 s = &*begin() + offset;
458 Storage::append(s, s + n);
462 flex_string &append(const value_type *s)
464 return append(s, traits_type::length(s));
467 flex_string &append(size_type n, value_type c)
469 resize(size() + n, c);
473 template<class InputIterator>
474 flex_string &append(InputIterator first, InputIterator last)
476 insert(end(), first, last);
480 void push_back(const value_type c) // primitive
482 const size_type cap = capacity();
487 Storage::append(&c, &c + 1);
490 flex_string &assign(const flex_string &str)
492 if (&str == this) return *this;
493 return assign(str.data(), str.size());
496 flex_string &assign(const flex_string &str, const size_type pos,
499 const size_type sz = str.size();
500 Enforce(pos <= sz, static_cast<std::out_of_range *>(0), "");
501 Procust(n, sz - pos);
502 return assign(str.data() + pos, n);
505 flex_string &assign(const value_type *s, const size_type n)
507 Invariant checker(*this);
511 std::copy(s, s + n, begin());
516 const value_type *const s2 = s + size();
517 std::copy(s, s2, begin());
518 append(s2, n - size());
523 flex_string &assign(const value_type *s)
525 return assign(s, traits_type::length(s));
528 template <class ItOrLength, class ItOrChar>
529 flex_string &assign(ItOrLength first_or_n, ItOrChar last_or_c)
531 return replace(begin(), end(), first_or_n, last_or_c);
534 flex_string &insert(size_type pos1, const flex_string &str)
536 return insert(pos1, str.data(), str.size());
539 flex_string &insert(size_type pos1, const flex_string &str,
540 size_type pos2, size_type n)
542 Enforce(pos2 <= str.length(), static_cast<std::out_of_range *>(0), "");
543 Procust(n, str.length() - pos2);
544 return insert(pos1, str.data() + pos2, n);
547 flex_string &insert(size_type pos, const value_type *s, size_type n)
549 Enforce(pos <= length(), static_cast<std::out_of_range *>(0), "");
550 insert(begin() + pos, s, s + n);
554 flex_string &insert(size_type pos, const value_type *s)
556 return insert(pos, s, traits_type::length(s));
559 flex_string &insert(size_type pos, size_type n, value_type c)
561 Enforce(pos <= length(), static_cast<std::out_of_range *>(0), "");
562 insert(begin() + pos, n, c);
566 iterator insert(const iterator p, const value_type c)
568 const size_type pos = p - begin();
570 return begin() + pos;
574 template <int i> class Selector {};
576 flex_string &InsertImplDiscr(iterator p,
577 size_type n, value_type c, Selector<1>)
579 Invariant checker(*this);
581 assert(p >= begin() && p <= end());
582 if (capacity() - size() < n)
584 const size_type sz = p - begin();
588 const iterator oldEnd = end();
589 //if (p + n < oldEnd) // replaced because of crash (pk)
590 if( n < size_type(oldEnd - p))
592 append(oldEnd - n, oldEnd);
594 // reverse_iterator(oldEnd - n),
595 // reverse_iterator(p),
596 // reverse_iterator(oldEnd));
597 flex_string_details::pod_move(&*p, &*oldEnd - n, &*p + n);
598 std::fill(p, p + n, c);
602 append(n - (end() - p), c);
604 std::fill(p, oldEnd, c);
609 template<class InputIterator>
610 flex_string &InsertImplDiscr(iterator i,
611 InputIterator b, InputIterator e, Selector<0>)
614 typename std::iterator_traits<InputIterator>::iterator_category());
618 template <class FwdIterator>
619 void InsertImpl(iterator i,
620 FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
622 Invariant checker(*this);
624 const size_type pos = i - begin();
625 const typename std::iterator_traits<FwdIterator>::difference_type n2 =
626 std::distance(s1, s2);
628 using namespace flex_string_details;
629 assert(pos <= size());
631 const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
635 // realloc the string
636 static const std::less_equal<const value_type *> le =
637 std::less_equal<const value_type *>();
638 assert(!(le(&*begin(), &*s1) && le(&*s1, &*end())));
639 reserve(size() + n2);
642 if (pos + n2 <= size())
644 //const iterator oldEnd = end();
645 //Storage::append(oldEnd - n2, n2);
646 //std::copy(i, oldEnd - n2, i + n2);
647 const iterator tailBegin = end() - n2;
648 Storage::append(tailBegin, tailBegin + n2);
649 //std::copy(i, tailBegin, i + n2);
650 std::copy(reverse_iterator(tailBegin), reverse_iterator(i),
651 reverse_iterator(tailBegin + n2));
652 std::copy(s1, s2, i);
657 const size_type old_size = size();
658 std::advance(t, old_size - pos);
659 assert(std::distance(t, s2) >= 0);
660 Storage::append(t, s2);
661 Storage::append(data() + pos, data() + old_size);
666 template <class InputIterator>
667 void InsertImpl(iterator i1, iterator i2,
668 InputIterator b, InputIterator e, std::input_iterator_tag)
670 flex_string temp(begin(), i1);
675 temp.append(i2, end());
680 template <class ItOrLength, class ItOrChar>
681 void insert(iterator p, ItOrLength first_or_n, ItOrChar last_or_c)
683 Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
684 InsertImplDiscr(p, first_or_n, last_or_c, sel);
687 flex_string &erase(size_type pos = 0, size_type n = npos)
689 Invariant checker(*this);
691 Enforce(pos <= length(), static_cast<std::out_of_range *>(0), "");
692 Procust(n, length() - pos);
693 std::copy(begin() + pos + n, end(), begin() + pos);
694 resize(length() - n);
698 iterator erase(iterator position)
700 const size_type pos(position - begin());
702 return begin() + pos;
705 iterator erase(iterator first, iterator last)
707 const size_type pos(first - begin());
708 erase(pos, last - first);
709 return begin() + pos;
712 // Replaces at most n1 chars of *this, starting with pos1 with the content of str
713 flex_string &replace(size_type pos1, size_type n1, const flex_string &str)
715 return replace(pos1, n1, str.data(), str.size());
718 // Replaces at most n1 chars of *this, starting with pos1,
719 // with at most n2 chars of str starting with pos2
720 flex_string &replace(size_type pos1, size_type n1, const flex_string &str,
721 size_type pos2, size_type n2)
723 Enforce(pos2 <= str.length(), static_cast<std::out_of_range *>(0), "");
724 return replace(pos1, n1, str.data() + pos2,
725 Min(n2, str.size() - pos2));
729 // Replaces at most n1 chars of *this, starting with pos,
730 // with at most n2 chars of str.
731 // str must have at least n2 chars.
732 flex_string& replace(const size_type pos, size_type n1,
733 const value_type* s1, const size_type n2)
735 Invariant checker(*this);
737 Enforce(pos <= size(), (std::out_of_range*)0, "");
738 Procust(n1, size() - pos);
739 const iterator b = begin() + pos;
740 return replace(b, b + n1, s1, s1 + n2);
741 using namespace flex_string_details;
742 const int delta = int(n2 - n1);
743 static const std::less_equal<const value_type*> le;
744 const bool aliased = le(&*begin(), s1) && le(s1, &*end());
746 // From here on we're dealing with an aliased replace
749 // simple case, we're shrinking
750 pod_move(s1, s1 + n2, &*begin() + pos);
751 pod_move(&*begin() + pos + n1, &*end(), &*begin() + pos + n1 + delta);
752 resize(size() + delta);
756 // From here on we deal with aliased growth
757 if (capacity() < size() + delta)
759 // realloc the string
760 const size_type offset = s1 - data();
761 reserve(size() + delta);
762 s1 = data() + offset;
765 const value_type* s2 = s1 + n2;
766 value_type* d1 = &*begin() + pos;
767 value_type* d2 = d1 + n1;
769 const int tailLen = int(&*end() - d2);
771 if (delta <= tailLen)
773 value_type* oldEnd = &*end();
775 Storage::append(oldEnd - delta, delta);
777 pod_move(d2, d2 + (tailLen - delta), d2 + delta);
780 pod_copy(s1 + delta, s2 + delta, d1);
787 pod_move(s1, d2, d1);
788 pod_move(d2 + delta, s2 + delta, d1 + (d2 - s1));
792 pod_move(s1, s2, d1);
798 const size_type sz = delta - tailLen;
799 Storage::append(s2 - sz, sz);
800 Storage::append(d2, tailLen);
801 pod_move(s1, s2 - (delta - tailLen), d1);
807 // Replaces at most n1 chars of *this, starting with pos, with chars from s
808 flex_string &replace(size_type pos, size_type n1, const value_type *s)
810 return replace(pos, n1, s, traits_type::length(s));
813 // Replaces at most n1 chars of *this, starting with pos, with n2 occurences of c
815 // Replaces at most n1 chars of *this, starting with pos,
816 // with at most n2 chars of str.
817 // str must have at least n2 chars.
818 template <class StrOrLength, class NumOrChar>
819 flex_string &replace(size_type pos, size_type n1,
820 StrOrLength s_or_n2, NumOrChar n_or_c)
822 Invariant checker(*this);
824 Enforce(pos <= size(), static_cast<std::out_of_range *>(0), "");
825 Procust(n1, length() - pos);
826 const iterator b = begin() + pos;
827 return replace(b, b + n1, s_or_n2, n_or_c);
830 flex_string &replace(iterator i1, iterator i2, const flex_string &str)
832 return replace(i1, i2, str.data(), str.length());
835 flex_string &replace(iterator i1, iterator i2, const value_type *s)
837 return replace(i1, i2, s, traits_type::length(s));
841 flex_string &ReplaceImplDiscr(iterator i1, iterator i2,
842 const value_type *s, size_type n, Selector<2>)
845 assert(begin() <= i1 && i1 <= end());
846 assert(begin() <= i2 && i2 <= end());
847 return replace(i1, i2, s, s + n);
850 flex_string &ReplaceImplDiscr(iterator i1, iterator i2,
851 size_type n2, value_type c, Selector<1>)
853 const size_type n1 = i2 - i1;
856 std::fill(i1, i1 + n2, c);
861 std::fill(i1, i2, c);
862 insert(i2, n2 - n1, c);
867 template <class InputIterator>
868 flex_string &ReplaceImplDiscr(iterator i1, iterator i2,
869 InputIterator b, InputIterator e, Selector<0>)
871 ReplaceImpl(i1, i2, b, e,
872 typename std::iterator_traits<InputIterator>::iterator_category());
876 template <class FwdIterator>
877 void ReplaceImpl(iterator i1, iterator i2,
878 FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
880 Invariant checker(*this);
882 const typename std::iterator_traits<iterator>::difference_type n1 =
885 const typename std::iterator_traits<FwdIterator>::difference_type n2 =
886 std::distance(s1, s2);
889 // Handle aliased replace
890 static const std::less_equal<const value_type *> le =
891 std::less_equal<const value_type *>();
892 const bool aliased = le(&*begin(), &*s1) && le(&*s1, &*end());
893 if (aliased /* && capacity() < size() - n1 + n2 */)
895 // Aliased replace, copy to new string
897 temp.reserve(size() - n1 + n2);
898 temp.append(begin(), i1).append(s1, s2).append(i2, end());
906 std::copy(s1, s2, i1);
912 flex_string_details::copy_n(s1, n1, i1);
913 std::advance(s1, n1);
918 template <class InputIterator>
919 void ReplaceImpl(iterator i1, iterator i2,
920 InputIterator b, InputIterator e, std::input_iterator_tag)
922 flex_string temp(begin(), i1);
923 temp.append(b, e).append(i2, end());
928 template <class T1, class T2>
929 flex_string &replace(iterator i1, iterator i2,
930 T1 first_or_n_or_s, T2 last_or_c_or_n)
933 num1 = std::numeric_limits<T1>::is_specialized,
934 num2 = std::numeric_limits<T2>::is_specialized;
935 return ReplaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n,
936 Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
939 size_type copy(value_type *s, size_type n, size_type pos = 0) const
941 Enforce(pos <= size(), static_cast<std::out_of_range *>(0), "");
942 Procust(n, size() - pos);
944 flex_string_details::pod_copy(
951 void swap(flex_string &rhs)
954 this->Storage::swap(srhs);
957 // 21.3.6 string operations:
958 const value_type *c_str() const
960 return Storage::c_str();
963 const value_type *data() const
965 return Storage::data();
968 allocator_type get_allocator() const
970 return Storage::get_allocator();
973 size_type find(const flex_string &str, size_type pos = 0) const
975 return find(str.data(), pos, str.length());
978 size_type find (const value_type *s, size_type pos, size_type n) const
980 if (n + pos > size())
982 for (; pos + n <= size(); ++pos)
984 if (traits_type::compare(data() + pos, s, n) == 0)
992 size_type find (const value_type *s, size_type pos = 0) const
994 return find(s, pos, traits_type::length(s));
997 size_type find (value_type c, size_type pos = 0) const
999 return find(&c, pos, 1);
1002 size_type rfind(const flex_string &str, size_type pos = npos) const
1004 return rfind(str.data(), pos, str.length());
1007 size_type rfind(const value_type *s, size_type pos, size_type n) const
1009 if (n > length()) return npos;
1010 pos = Min(pos, length() - n);
1011 if (n == 0) return pos;
1013 const_iterator i(begin() + pos);
1016 if (traits_type::eq(*i, *s)
1017 && traits_type::compare(&*i, s, n) == 0)
1021 if (i == begin()) break;
1026 size_type rfind(const value_type *s, size_type pos = npos) const
1028 return rfind(s, pos, traits_type::length(s));
1031 size_type rfind(value_type c, size_type pos = npos) const
1033 return rfind(&c, pos, 1);
1036 size_type find_first_of(const flex_string &str, size_type pos = 0) const
1038 return find_first_of(str.data(), pos, str.length());
1041 size_type find_first_of(const value_type *s,
1042 size_type pos, size_type n) const
1044 if (pos > length() || n == 0) return npos;
1045 const_iterator i(begin() + pos),
1047 for (; i != finish; ++i)
1049 if (traits_type::find(s, n, *i) != 0)
1057 size_type find_first_of(const value_type *s, size_type pos = 0) const
1059 return find_first_of(s, pos, traits_type::length(s));
1062 size_type find_first_of(value_type c, size_type pos = 0) const
1064 return find_first_of(&c, pos, 1);
1067 size_type find_last_of (const flex_string &str,
1068 size_type pos = npos) const
1070 return find_last_of(str.data(), pos, str.length());
1073 size_type find_last_of (const value_type *s, size_type pos,
1076 if (!empty() && n > 0)
1078 pos = Min(pos, length() - 1);
1079 const_iterator i(begin() + pos);
1082 if (traits_type::find(s, n, *i) != 0)
1086 if (i == begin()) break;
1092 size_type find_last_of (const value_type *s,
1093 size_type pos = npos) const
1095 return find_last_of(s, pos, traits_type::length(s));
1098 size_type find_last_of (value_type c, size_type pos = npos) const
1100 return find_last_of(&c, pos, 1);
1103 size_type find_first_not_of(const flex_string &str,
1104 size_type pos = 0) const
1106 return find_first_not_of(str.data(), pos, str.size());
1109 size_type find_first_not_of(const value_type *s, size_type pos,
1117 for (; i != finish; ++i)
1119 if (traits_type::find(s, n, *i) == 0)
1128 size_type find_first_not_of(const value_type *s,
1129 size_type pos = 0) const
1131 return find_first_not_of(s, pos, traits_type::length(s));
1134 size_type find_first_not_of(value_type c, size_type pos = 0) const
1136 return find_first_not_of(&c, pos, 1);
1139 size_type find_last_not_of(const flex_string &str,
1140 size_type pos = npos) const
1142 return find_last_not_of(str.data(), pos, str.length());
1145 size_type find_last_not_of(const value_type *s, size_type pos,
1150 pos = Min(pos, size() - 1);
1151 const_iterator i(begin() + pos);
1154 if (traits_type::find(s, n, *i) == 0)
1158 if (i == begin()) break;
1164 size_type find_last_not_of(const value_type *s,
1165 size_type pos = npos) const
1167 return find_last_not_of(s, pos, traits_type::length(s));
1170 size_type find_last_not_of (value_type c, size_type pos = npos) const
1172 return find_last_not_of(&c, pos, 1);
1175 flex_string substr(size_type pos = 0, size_type n = npos) const
1177 Enforce(pos <= size(), static_cast<std::out_of_range *>(0), "");
1178 return flex_string(data() + pos, Min(n, size() - pos));
1181 int compare(const flex_string &str) const
1183 // FIX due to Goncalo N M de Carvalho July 18, 2005
1184 return compare(0, size(), str);
1187 int compare(size_type pos1, size_type n1,
1188 const flex_string &str) const
1190 return compare(pos1, n1, str.data(), str.size());
1193 // FIX to compare: added the TC
1194 // (http://www.comeaucomputing.com/iso/lwg-defects.html number 5)
1195 // Thanks to Caleb Epstein for the fix
1197 int compare(size_type pos1, size_type n1,
1198 const value_type *s) const
1200 return compare(pos1, n1, s, traits_type::length(s));
1203 int compare(size_type pos1, size_type n1,
1204 const value_type *s, size_type n2) const
1206 Enforce(pos1 <= size(), static_cast<std::out_of_range *>(0), "");
1207 Procust(n1, size() - pos1);
1208 // The line below fixed by Jean-Francois Bastien, 04-23-2007. Thanks!
1209 const int r = traits_type::compare(pos1 + data(), s, Min(n1, n2));
1210 return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
1213 int compare(size_type pos1, size_type n1,
1214 const flex_string &str,
1215 size_type pos2, size_type n2) const
1217 Enforce(pos2 <= str.size(), static_cast<std::out_of_range *>(0), "");
1218 return compare(pos1, n1, str.data() + pos2, Min(n2, str.size() - pos2));
1221 // Code from Jean-Francois Bastien (03/26/2007)
1222 int compare(const value_type *s) const
1224 // Could forward to compare(0, size(), s, traits_type::length(s))
1225 // but that does two extra checks
1226 const size_type n1(size()), n2(traits_type::length(s));
1227 const int r = traits_type::compare(data(), s, Min(n1, n2));
1228 return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
1232 // non-member functions
1233 template <typename E, class T, class A, class S>
1234 flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
1235 const flex_string<E, T, A, S>& rhs)
1237 flex_string<E, T, A, S> result;
1238 result.reserve(lhs.size() + rhs.size());
1239 result.append(lhs).append(rhs);
1243 template <typename E, class T, class A, class S>
1244 flex_string<E, T, A, S> operator+(const typename flex_string<E, T, A, S>::value_type *lhs,
1245 const flex_string<E, T, A, S>& rhs)
1247 flex_string<E, T, A, S> result;
1248 const typename flex_string<E, T, A, S>::size_type len =
1249 flex_string<E, T, A, S>::traits_type::length(lhs);
1250 result.reserve(len + rhs.size());
1251 result.append(lhs, len).append(rhs);
1255 template <typename E, class T, class A, class S>
1256 flex_string<E, T, A, S> operator+(
1257 typename flex_string<E, T, A, S>::value_type lhs,
1258 const flex_string<E, T, A, S>& rhs)
1260 flex_string<E, T, A, S> result;
1261 result.reserve(1 + rhs.size());
1262 result.push_back(lhs);
1267 template <typename E, class T, class A, class S>
1268 flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
1269 const typename flex_string<E, T, A, S>::value_type *rhs)
1271 typedef typename flex_string<E, T, A, S>::size_type size_type;
1272 typedef typename flex_string<E, T, A, S>::traits_type traits_type;
1274 flex_string<E, T, A, S> result;
1275 const size_type len = traits_type::length(rhs);
1276 result.reserve(lhs.size() + len);
1277 result.append(lhs).append(rhs, len);
1281 template <typename E, class T, class A, class S>
1282 flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
1283 typename flex_string<E, T, A, S>::value_type rhs)
1285 flex_string<E, T, A, S> result;
1286 result.reserve(lhs.size() + 1);
1288 result.push_back(rhs);
1292 template <typename E, class T, class A, class S>
1293 bool operator==(const flex_string<E, T, A, S>& lhs,
1294 const flex_string<E, T, A, S>& rhs)
1296 return lhs.compare(rhs) == 0;
1299 template <typename E, class T, class A, class S>
1300 bool operator==(const typename flex_string<E, T, A, S>::value_type *lhs,
1301 const flex_string<E, T, A, S>& rhs)
1306 template <typename E, class T, class A, class S>
1307 bool operator==(const flex_string<E, T, A, S>& lhs,
1308 const typename flex_string<E, T, A, S>::value_type *rhs)
1310 return lhs.compare(rhs) == 0;
1313 template <typename E, class T, class A, class S>
1314 bool operator!=(const flex_string<E, T, A, S>& lhs,
1315 const flex_string<E, T, A, S>& rhs)
1317 return !(lhs == rhs);
1320 template <typename E, class T, class A, class S>
1321 bool operator!=(const typename flex_string<E, T, A, S>::value_type *lhs,
1322 const flex_string<E, T, A, S>& rhs)
1324 return !(lhs == rhs);
1327 template <typename E, class T, class A, class S>
1328 bool operator!=(const flex_string<E, T, A, S>& lhs,
1329 const typename flex_string<E, T, A, S>::value_type *rhs)
1331 return !(lhs == rhs);
1334 template <typename E, class T, class A, class S>
1335 bool operator<(const flex_string<E, T, A, S>& lhs,
1336 const flex_string<E, T, A, S>& rhs)
1338 return lhs.compare(rhs) < 0;
1341 template <typename E, class T, class A, class S>
1342 bool operator<(const flex_string<E, T, A, S>& lhs,
1343 const typename flex_string<E, T, A, S>::value_type *rhs)
1345 return lhs.compare(rhs) < 0;
1348 template <typename E, class T, class A, class S>
1349 bool operator<(const typename flex_string<E, T, A, S>::value_type *lhs,
1350 const flex_string<E, T, A, S>& rhs)
1352 return rhs.compare(lhs) > 0;
1355 template <typename E, class T, class A, class S>
1356 bool operator>(const flex_string<E, T, A, S>& lhs,
1357 const flex_string<E, T, A, S>& rhs)
1362 template <typename E, class T, class A, class S>
1363 bool operator>(const flex_string<E, T, A, S>& lhs,
1364 const typename flex_string<E, T, A, S>::value_type *rhs)
1369 template <typename E, class T, class A, class S>
1370 bool operator>(const typename flex_string<E, T, A, S>::value_type *lhs,
1371 const flex_string<E, T, A, S>& rhs)
1376 template <typename E, class T, class A, class S>
1377 bool operator<=(const flex_string<E, T, A, S>& lhs,
1378 const flex_string<E, T, A, S>& rhs)
1380 return !(rhs < lhs);
1383 template <typename E, class T, class A, class S>
1384 bool operator<=(const flex_string<E, T, A, S>& lhs,
1385 const typename flex_string<E, T, A, S>::value_type *rhs)
1387 return !(rhs < lhs);
1390 template <typename E, class T, class A, class S>
1391 bool operator<=(const typename flex_string<E, T, A, S>::value_type *lhs,
1392 const flex_string<E, T, A, S>& rhs)
1394 return !(rhs < lhs);
1397 template <typename E, class T, class A, class S>
1398 bool operator>=(const flex_string<E, T, A, S>& lhs,
1399 const flex_string<E, T, A, S>& rhs)
1401 return !(lhs < rhs);
1404 template <typename E, class T, class A, class S>
1405 bool operator>=(const flex_string<E, T, A, S>& lhs,
1406 const typename flex_string<E, T, A, S>::value_type *rhs)
1408 return !(lhs < rhs);
1411 template <typename E, class T, class A, class S>
1412 bool operator>=(const typename flex_string<E, T, A, S>::value_type *lhs,
1413 const flex_string<E, T, A, S>& rhs)
1415 return !(lhs < rhs);
1418 // subclause 21.3.7.8:
1419 //void swap(flex_string<E, T, A, S>& lhs, flex_string<E, T, A, S>& rhs); // to do
1421 template <typename E, class T, class A, class S>
1422 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
1423 typename flex_string<E, T, A, S>::traits_type>&
1425 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
1426 typename flex_string<E, T, A, S>::traits_type>& is,
1427 flex_string<E, T, A, S>& str);
1429 template <typename E, class T, class A, class S>
1430 std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
1431 typename flex_string<E, T, A, S>::traits_type>&
1433 std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
1434 typename flex_string<E, T, A, S>::traits_type>& os,
1435 const flex_string<E, T, A, S>& str)
1437 return os << str.c_str();
1440 template <typename E, class T, class A, class S>
1441 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
1442 typename flex_string<E, T, A, S>::traits_type>&
1444 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
1445 typename flex_string<E, T, A, S>::traits_type>& is,
1446 flex_string<E, T, A, S>& str,
1447 typename flex_string<E, T, A, S>::value_type delim);
1449 template <typename E, class T, class A, class S>
1450 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
1451 typename flex_string<E, T, A, S>::traits_type>&
1453 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
1454 typename flex_string<E, T, A, S>::traits_type>& is,
1455 flex_string<E, T, A, S>& str);
1457 template <typename E1, class T, class A, class S>
1458 const typename flex_string<E1, T, A, S>::size_type
1459 flex_string<E1, T, A, S>::npos = static_cast<typename flex_string<E1, T, A, S>::size_type>(-1);
1461 #endif // FLEX_STRING_SHELL_INC_