LCOV - code coverage report
Current view: top level - usr/include/boost/wave/util - flex_string.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 381 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 41 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*=============================================================================
       2             :     Boost.Wave: A Standard compliant C++ preprocessor library
       3             :     http://www.boost.org/
       4             : 
       5             :     Copyright (c) 2001 by Andrei Alexandrescu. Distributed under the Boost
       6             :     Software License, Version 1.0. (See accompanying file
       7             :     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       8             : =============================================================================*/
       9             : 
      10             : // This code is taken from:
      11             : // Andrei Alexandrescu, Generic<Programming>: A Policy-Based basic_string
      12             : // Implementation. http://www.cuj.com/documents/s=7994/cujcexp1906alexandr/
      13             : //
      14             : // #HK030306:
      15             : //      - Moved into the namespace boost::wave::util
      16             : //      - Added a bunch of missing typename(s)
      17             : //      - Integrated with boost config
      18             : //      - Added a missing header include
      19             : //      - Added special constructors and operator= to allow CowString to be
      20             : //        a real COW-string (removed unnecessary data copying)
      21             : //      - Fixed a string terminating bug in append
      22             : //
      23             : // #HK040109:
      24             : //      - Incorporated the changes from Andrei's latest version of this class
      25             : //
      26             : // #HK070307:
      27             : //      - Once again incorporated the changes from Andrei's latest version of
      28             : //        this class
      29             : //
      30             : // #HK090523:
      31             : //      - Incorporated the changes from latest version of flex_string as
      32             : //        maintained in Loki
      33             : //
      34             : // #HK130910:
      35             : //      - Removed the getline implementation which was borrowed from the SGI
      36             : //        STL as the license for this code is not compatible with Boost.
      37             : 
      38             : #ifndef FLEX_STRING_INC_
      39             : #define FLEX_STRING_INC_
      40             : 
      41             : /*
      42             : ////////////////////////////////////////////////////////////////////////////////
      43             : template <typename E, class A = @>
      44             : class StoragePolicy
      45             : {
      46             :     typedef E value_type;
      47             :     typedef @ iterator;
      48             :     typedef @ const_iterator;
      49             :     typedef A allocator_type;
      50             :     typedef @ size_type;
      51             : 
      52             :     StoragePolicy(const StoragePolicy& s);
      53             :     StoragePolicy(const A&);
      54             :     StoragePolicy(const E* s, size_type len, const A&);
      55             :     StoragePolicy(size_type len, E c, const A&);
      56             :     ~StoragePolicy();
      57             : 
      58             :     iterator begin();
      59             :     const_iterator begin() const;
      60             :     iterator end();
      61             :     const_iterator end() const;
      62             : 
      63             :     size_type size() const;
      64             :     size_type max_size() const;
      65             :     size_type capacity() const;
      66             : 
      67             :     void reserve(size_type res_arg);
      68             : 
      69             :     void append(const E* s, size_type sz);
      70             : 
      71             :     template <class InputIterator>
      72             :     void append(InputIterator b, InputIterator e);
      73             : 
      74             :     void resize(size_type newSize, E fill);
      75             : 
      76             :     void swap(StoragePolicy& rhs);
      77             : 
      78             :     const E* c_str() const;
      79             :     const E* data() const;
      80             : 
      81             :     A get_allocator() const;
      82             : };
      83             : ////////////////////////////////////////////////////////////////////////////////
      84             : */
      85             : 
      86             : #include <boost/config.hpp>
      87             : #include <boost/assert.hpp>
      88             : #include <boost/throw_exception.hpp>
      89             : 
      90             : #include <boost/iterator/reverse_iterator.hpp>
      91             : 
      92             : #include <boost/wave/wave_config.hpp>
      93             : #if BOOST_WAVE_SERIALIZATION != 0
      94             : #include <boost/serialization/serialization.hpp>
      95             : #include <boost/serialization/split_free.hpp>
      96             : #include <boost/serialization/collections_save_imp.hpp>
      97             : #include <boost/serialization/collections_load_imp.hpp>
      98             : #define BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK 1
      99             : #endif
     100             : 
     101             : #include <memory>
     102             : #include <new>
     103             : #include <string>
     104             : #include <vector>
     105             : #include <algorithm>
     106             : #include <functional>
     107             : #include <limits>
     108             : #include <stdexcept>
     109             : #include <ios>
     110             : 
     111             : #include <cstddef>
     112             : #include <cstring>
     113             : #include <cstdlib>
     114             : 
     115             : // this must occur after all of the includes and before any code appears
     116             : #ifdef BOOST_HAS_ABI_HEADERS
     117             : #include BOOST_ABI_PREFIX
     118             : #endif
     119             : 
     120             : ///////////////////////////////////////////////////////////////////////////////
     121             : namespace boost {
     122             : namespace wave {
     123             : namespace util {
     124             : 
     125             : namespace flex_string_details
     126             : {
     127             :     template <class InIt, class OutIt>
     128             :     OutIt copy_n(InIt b,
     129             :         typename std::iterator_traits<InIt>::difference_type n, OutIt d)
     130             :     {
     131             :         for (/**/; n != 0; --n, ++b, ++d)
     132             :         {
     133             :             *d = *b;
     134             :         }
     135             :         return d;
     136             :     }
     137             : 
     138             :     template <class Pod, class T>
     139           0 :     inline void pod_fill(Pod* b, Pod* e, T c)
     140             :     {
     141           0 :         switch ((e - b) & 7)
     142             :         {
     143           0 :         case 0:
     144           0 :             while (b != e)
     145             :             {
     146           0 :                 *b = c; ++b; BOOST_FALLTHROUGH;
     147           0 :         case 7: *b = c; ++b; BOOST_FALLTHROUGH;
     148           0 :         case 6: *b = c; ++b; BOOST_FALLTHROUGH;
     149           0 :         case 5: *b = c; ++b; BOOST_FALLTHROUGH;
     150           0 :         case 4: *b = c; ++b; BOOST_FALLTHROUGH;
     151           0 :         case 3: *b = c; ++b; BOOST_FALLTHROUGH;
     152           0 :         case 2: *b = c; ++b; BOOST_FALLTHROUGH;
     153           0 :         case 1: *b = c; ++b;
     154             :             }
     155             :         }
     156           0 :     }
     157             : 
     158             :     template <class Pod>
     159             :     inline void pod_move(const Pod* b, const Pod* e, Pod* d)
     160             :     {
     161             :         using namespace std;
     162             :         memmove(d, b, (e - b) * sizeof(*b));
     163             :     }
     164             : 
     165             :     template <class Pod>
     166           0 :     inline Pod* pod_copy(const Pod* b, const Pod* e, Pod* d)
     167             :     {
     168           0 :         const std::size_t s = e - b;
     169             :         using namespace std;
     170           0 :         memcpy(d, b, s * sizeof(*b));
     171           0 :         return d + s;
     172             :     }
     173             : 
     174             :     template <typename T> struct get_unsigned
     175             :     {
     176             :         typedef T result;
     177             :     };
     178             : 
     179             :     template <> struct get_unsigned<char>
     180             :     {
     181             :         typedef unsigned char result;
     182             :     };
     183             : 
     184             :     template <> struct get_unsigned<signed char>
     185             :     {
     186             :         typedef unsigned char result;
     187             :     };
     188             : 
     189             :     template <> struct get_unsigned<short int>
     190             :     {
     191             :         typedef unsigned short int result;
     192             :     };
     193             : 
     194             :     template <> struct get_unsigned<int>
     195             :     {
     196             :         typedef unsigned int result;
     197             :     };
     198             : 
     199             :     template <> struct get_unsigned<long int>
     200             :     {
     201             :         typedef unsigned long int result;
     202             :     };
     203             : 
     204             :     enum Shallow {};
     205             : }
     206             : 
     207             : template <class T> class mallocator
     208             : {
     209             : public:
     210             :     typedef T                 value_type;
     211             :     typedef value_type*       pointer;
     212             :     typedef const value_type* const_pointer;
     213             :     typedef value_type&       reference;
     214             :     typedef const value_type& const_reference;
     215             :     typedef std::size_t       size_type;
     216             :     //typedef unsigned int      size_type;
     217             :     //typedef std::ptrdiff_t    difference_type;
     218             :     typedef int               difference_type;
     219             : 
     220             :     template <class U>
     221             :     struct rebind { typedef mallocator<U> other; };
     222             : 
     223             :     mallocator() {}
     224             :     mallocator(const mallocator&) {}
     225             :     //template <class U>
     226             :     //mallocator(const mallocator<U>&) {}
     227             :     ~mallocator() {}
     228             : 
     229             :     pointer address(reference x) const { return &x; }
     230             :     const_pointer address(const_reference x) const
     231             :     {
     232             :         return x;
     233             :     }
     234             : 
     235             :     pointer allocate(size_type n, const_pointer = 0)
     236             :     {
     237             :         using namespace std;
     238             :         void* p = malloc(n * sizeof(T));
     239             :         if (!p) boost::throw_exception(std::bad_alloc());
     240             :         return static_cast<pointer>(p);
     241             :     }
     242             : 
     243             :     void deallocate(pointer p, size_type)
     244             :     {
     245             :         using namespace std;
     246             :         free(p);
     247             :     }
     248             : 
     249             :     size_type max_size() const
     250             :     {
     251             :         return static_cast<size_type>(-1) / sizeof(T);
     252             :     }
     253             : 
     254             :     void construct(pointer p, const value_type& x)
     255             :     {
     256             :         new(p) value_type(x);
     257             :     }
     258             : 
     259             :     void destroy(pointer p)
     260             :     {
     261             :         p->~value_type();
     262             :     }
     263             : 
     264             : private:
     265             :     void operator=(const mallocator&);
     266             : };
     267             : 
     268             : template<> class mallocator<void>
     269             : {
     270             :   typedef void        value_type;
     271             :   typedef void*       pointer;
     272             :   typedef const void* const_pointer;
     273             : 
     274             :   template <class U>
     275             :   struct rebind { typedef mallocator<U> other; };
     276             : };
     277             : 
     278             : template <class T>
     279             : inline bool operator==(const mallocator<T>&,
     280             :                        const mallocator<T>&) {
     281             :   return true;
     282             : }
     283             : 
     284             : template <class T>
     285             : inline bool operator!=(const mallocator<T>&,
     286             :                        const mallocator<T>&) {
     287             :   return false;
     288             : }
     289             : 
     290             : template <class Allocator>
     291             : typename Allocator::pointer Reallocate(
     292             :     Allocator& alloc,
     293             :     typename Allocator::pointer p,
     294             :     typename Allocator::size_type oldObjCount,
     295             :     typename Allocator::size_type newObjCount,
     296             :     void*)
     297             : {
     298             :     // @@@ not implemented
     299             :     return NULL;
     300             : }
     301             : 
     302             : template <class Allocator>
     303             : typename Allocator::pointer Reallocate(
     304             :     Allocator& alloc,
     305             :     typename Allocator::pointer p,
     306             :     typename Allocator::size_type oldObjCount,
     307             :     typename Allocator::size_type newObjCount,
     308             :     mallocator<void>*)
     309             : {
     310             :     // @@@ not implemented
     311             :     return NULL;
     312             : }
     313             : 
     314             : ////////////////////////////////////////////////////////////////////////////////
     315             : // class template SimpleStringStorage
     316             : // Allocates memory with malloc
     317             : ////////////////////////////////////////////////////////////////////////////////
     318             : 
     319             : template <typename E, class A = std::allocator<E> >
     320             : class SimpleStringStorage
     321             : {
     322             :     // The "public" below exists because MSVC can't do template typedefs
     323             : public:
     324             :     struct Data
     325             :     {
     326             :         Data() : pEnd_(buffer_), pEndOfMem_(buffer_) { buffer_[0] = E(0); }
     327             : 
     328             :         E* pEnd_;
     329             :         E* pEndOfMem_;
     330             :         E buffer_[1];
     331             :     };
     332             :     static const Data emptyString_;
     333             : 
     334             :     typedef typename A::size_type size_type;
     335             : 
     336             : private:
     337             :     Data* pData_;
     338             : 
     339             :     void Init(size_type size, size_type capacity)
     340             :     {
     341             :         BOOST_ASSERT(size <= capacity);
     342             :         if (capacity == 0)
     343             :         {
     344             :             pData_ = const_cast<Data*>(&emptyString_);
     345             :         }
     346             :         else
     347             :         {
     348             :             // 11-17-2000: comment added:
     349             :             //     No need to allocate (capacity + 1) to
     350             :             //     accommodate the terminating 0, because Data already
     351             :             //     has one character in there
     352             :             pData_ = static_cast<Data*>(
     353             :                 malloc(sizeof(Data) + capacity * sizeof(E)));
     354             :             if (!pData_) boost::throw_exception(std::bad_alloc());
     355             :             pData_->pEnd_ = pData_->buffer_ + size;
     356             :             pData_->pEndOfMem_ = pData_->buffer_ + capacity;
     357             :         }
     358             :     }
     359             : 
     360             : private:
     361             :     // Warning - this doesn't initialize pData_. Used in reserve()
     362             :     SimpleStringStorage()
     363             :     { }
     364             : 
     365             : public:
     366             :     typedef E value_type;
     367             :     typedef E* iterator;
     368             :     typedef const E* const_iterator;
     369             :     typedef A allocator_type;
     370             : 
     371             :     SimpleStringStorage(const SimpleStringStorage& rhs)
     372             :     {
     373             :         const size_type sz = rhs.size();
     374             :         Init(sz, sz);
     375             :         if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
     376             :     }
     377             : 
     378             :     SimpleStringStorage(const SimpleStringStorage& s,
     379             :         flex_string_details::Shallow)
     380             :         : pData_(s.pData_)
     381             :     {
     382             :     }
     383             : 
     384             :     SimpleStringStorage(const A&)
     385             :     { pData_ = const_cast<Data*>(&emptyString_); }
     386             : 
     387             :     SimpleStringStorage(const E* s, size_type len, const A&)
     388             :     {
     389             :         Init(len, len);
     390             :         flex_string_details::pod_copy(s, s + len, begin());
     391             :     }
     392             : 
     393             :     SimpleStringStorage(size_type len, E c, const A&)
     394             :     {
     395             :         Init(len, len);
     396             :         flex_string_details::pod_fill(begin(), end(), c);
     397             :     }
     398             : 
     399             :     SimpleStringStorage& operator=(const SimpleStringStorage& rhs)
     400             :     {
     401             :         const size_type sz = rhs.size();
     402             :         reserve(sz);
     403             :         flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
     404             :         pData_->pEnd_ = &*begin() + sz;
     405             :         return *this;
     406             :     }
     407             : 
     408             :     ~SimpleStringStorage()
     409             :     {
     410             :         BOOST_ASSERT(begin() <= end());
     411             :         if (pData_ != &emptyString_) free(pData_);
     412             :     }
     413             : 
     414             :     iterator begin()
     415             :     { return pData_->buffer_; }
     416             : 
     417             :     const_iterator begin() const
     418             :     { return pData_->buffer_; }
     419             : 
     420             :     iterator end()
     421             :     { return pData_->pEnd_; }
     422             : 
     423             :     const_iterator end() const
     424             :     { return pData_->pEnd_; }
     425             : 
     426             :     size_type size() const
     427             :     { return pData_->pEnd_ - pData_->buffer_; }
     428             : 
     429             :     size_type max_size() const
     430             :     { return std::size_t(-1) / sizeof(E) - sizeof(Data) - 1; }
     431             : 
     432             :     size_type capacity() const
     433             :     { return pData_->pEndOfMem_ - pData_->buffer_; }
     434             : 
     435             :     void reserve(size_type res_arg)
     436             :     {
     437             :         if (res_arg <= capacity())
     438             :         {
     439             :             // @@@ insert shrinkage here if you wish
     440             :             return;
     441             :         }
     442             : 
     443             :         if (pData_ == &emptyString_)
     444             :         {
     445             :             Init(0, res_arg);
     446             :         }
     447             :         else
     448             :         {
     449             :             const size_type sz = size();
     450             : 
     451             :             void* p = realloc(pData_,
     452             :                 sizeof(Data) + res_arg * sizeof(E));
     453             :             if (!p) boost::throw_exception(std::bad_alloc());
     454             : 
     455             :             if (p != pData_)
     456             :             {
     457             :                 pData_ = static_cast<Data*>(p);
     458             :                 pData_->pEnd_ = pData_->buffer_ + sz;
     459             :             }
     460             :             pData_->pEndOfMem_ = pData_->buffer_ + res_arg;
     461             :         }
     462             :     }
     463             : 
     464             :     void append(const E* s, size_type sz)
     465             :     {
     466             :         const size_type neededCapacity = size() + sz;
     467             : 
     468             :         if (capacity() < neededCapacity)
     469             :         {
     470             :             const iterator b = begin();
     471             :             static std::less_equal<const E*> le;
     472             :             if (le(b, s) && le(s, end()))
     473             :             {
     474             :                // aliased
     475             :                 const size_type offset = s - b;
     476             :                 reserve(neededCapacity);
     477             :                 s = begin() + offset;
     478             :             }
     479             :             else
     480             :             {
     481             :                 reserve(neededCapacity);
     482             :             }
     483             :         }
     484             :         flex_string_details::pod_copy(s, s + sz, end());
     485             :         pData_->pEnd_ += sz;
     486             :     }
     487             : 
     488             :     template <class InputIterator>
     489             :     void append(InputIterator b, InputIterator e)
     490             :     {
     491             :         // @@@ todo: optimize this depending on iterator type
     492             :         for (; b != e; ++b)
     493             :         {
     494             :             *this += *b;
     495             :         }
     496             :     }
     497             : 
     498             :     void resize(size_type newSize, E fill)
     499             :     {
     500             :         const int delta = int(newSize - size());
     501             :         if (delta == 0) return;
     502             : 
     503             :         if (delta > 0)
     504             :         {
     505             :             if (newSize > capacity())
     506             :             {
     507             :                 reserve(newSize);
     508             :             }
     509             :             E* e = &*end();
     510             :             flex_string_details::pod_fill(e, e + delta, fill);
     511             :         }
     512             :         pData_->pEnd_ = pData_->buffer_ + newSize;
     513             :     }
     514             : 
     515             :     void swap(SimpleStringStorage& rhs)
     516             :     {
     517             :         std::swap(pData_, rhs.pData_);
     518             :     }
     519             : 
     520             :     const E* c_str() const
     521             :     {
     522             :         if (pData_ != &emptyString_) *pData_->pEnd_ = E();
     523             :         return pData_->buffer_;
     524             :     }
     525             : 
     526             :     const E* data() const
     527             :     { return pData_->buffer_; }
     528             : 
     529             :     A get_allocator() const
     530             :     { return A(); }
     531             : };
     532             : 
     533             : template <typename E, class A>
     534             : const typename SimpleStringStorage<E, A>::Data
     535             : SimpleStringStorage<E, A>::emptyString_ =
     536             :     typename SimpleStringStorage<E, A>::Data();
     537             : 
     538             : ////////////////////////////////////////////////////////////////////////////////
     539             : // class template AllocatorStringStorage
     540             : // Allocates with your allocator
     541             : // Takes advantage of the Empty Base Optimization if available
     542             : ////////////////////////////////////////////////////////////////////////////////
     543             : 
     544             : template <typename E, class A = std::allocator<E> >
     545             : class AllocatorStringStorage : public A
     546             : {
     547             :     typedef typename A::size_type size_type;
     548             :     typedef typename SimpleStringStorage<E, A>::Data Data;
     549             : 
     550             :     void* Alloc(size_type sz, const void* p = 0)
     551             :     {
     552             :         return A::allocate(1 + (sz - 1) / sizeof(E),
     553             :             static_cast<const char*>(p));
     554             :     }
     555             : 
     556             :     void* Realloc(void* p, size_type oldSz, size_type newSz)
     557             :     {
     558             :         void* r = Alloc(newSz);
     559             :         flex_string_details::pod_copy(p, p + Min(oldSz, newSz), r);
     560             :         Free(p, oldSz);
     561             :         return r;
     562             :     }
     563             : 
     564           0 :     void Free(void* p, size_type sz)
     565             :     {
     566           0 :         A::deallocate(static_cast<E*>(p), sz);
     567           0 :     }
     568             : 
     569             :     Data* pData_;
     570             : 
     571             :     void Init(size_type size, size_type cap)
     572             :     {
     573             :         BOOST_ASSERT(size <= cap);
     574             : 
     575             :         if (cap == 0)
     576             :         {
     577             :             pData_ = const_cast<Data*>(
     578             :                 &SimpleStringStorage<E, A>::emptyString_);
     579             :         }
     580             :         else
     581             :         {
     582             :             pData_ = static_cast<Data*>(Alloc(
     583             :                 cap * sizeof(E) + sizeof(Data)));
     584             :             pData_->pEnd_ = pData_->buffer_ + size;
     585             :             pData_->pEndOfMem_ = pData_->buffer_ + cap;
     586             :         }
     587             :     }
     588             : 
     589             : public:
     590             :     typedef E value_type;
     591             :     typedef E* iterator;
     592             :     typedef const E* const_iterator;
     593             :     typedef A allocator_type;
     594             : 
     595             :     AllocatorStringStorage()
     596             :     : A(), pData_(0)
     597             :     {
     598             :     }
     599             : 
     600           0 :     AllocatorStringStorage(const AllocatorStringStorage& rhs)
     601           0 :     : A(rhs.get_allocator())
     602             :     {
     603           0 :         const size_type sz = rhs.size();
     604           0 :         Init(sz, sz);
     605           0 :         if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
     606           0 :     }
     607             : 
     608           0 :     AllocatorStringStorage(const AllocatorStringStorage& s,
     609             :         flex_string_details::Shallow)
     610           0 :     : A(s.get_allocator())
     611             :     {
     612           0 :         pData_ = s.pData_;
     613             :     }
     614             : 
     615           0 :     AllocatorStringStorage(const A& a) : A(a)
     616             :     {
     617           0 :         pData_ = const_cast<Data*>(
     618             :             &SimpleStringStorage<E, A>::emptyString_);
     619             :     }
     620             : 
     621             :     AllocatorStringStorage(const E* s, size_type len, const A& a)
     622             :     : A(a)
     623             :     {
     624             :         Init(len, len);
     625             :         flex_string_details::pod_copy(s, s + len, begin());
     626             :     }
     627             : 
     628           0 :     AllocatorStringStorage(size_type len, E c, const A& a)
     629           0 :     : A(a)
     630             :     {
     631           0 :         Init(len, len);
     632           0 :         flex_string_details::pod_fill(&*begin(), &*end(), c);
     633           0 :     }
     634             : 
     635             :     AllocatorStringStorage& operator=(const AllocatorStringStorage& rhs)
     636             :     {
     637             :         const size_type sz = rhs.size();
     638             :         reserve(sz);
     639             :         flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
     640             :         pData_->pEnd_ = &*begin() + rhs.size();
     641             :         return *this;
     642             :     }
     643             : 
     644           0 :     ~AllocatorStringStorage()
     645             :     {
     646           0 :         if (capacity())
     647             :         {
     648           0 :             Free(pData_,
     649           0 :                 sizeof(Data) + capacity() * sizeof(E));
     650             :         }
     651           0 :     }
     652             : 
     653           0 :     iterator begin()
     654           0 :     { return pData_->buffer_; }
     655             : 
     656           0 :     const_iterator begin() const
     657           0 :     { return pData_->buffer_; }
     658             : 
     659           0 :     iterator end()
     660           0 :     { return pData_->pEnd_; }
     661             : 
     662           0 :     const_iterator end() const
     663           0 :     { return pData_->pEnd_; }
     664             : 
     665           0 :     size_type size() const
     666           0 :     { return size_type(end() - begin()); }
     667             : 
     668           0 :     size_type max_size() const
     669           0 :     { return A::max_size(); }
     670             : 
     671           0 :     size_type capacity() const
     672           0 :     { return size_type(pData_->pEndOfMem_ - pData_->buffer_); }
     673             : 
     674           0 :     void resize(size_type n, E c)
     675             :     {
     676           0 :         reserve(n);
     677           0 :         iterator newEnd = begin() + n;
     678           0 :         iterator oldEnd = end();
     679           0 :         if (newEnd > oldEnd)
     680             :         {
     681             :             // Copy the characters
     682           0 :             flex_string_details::pod_fill(oldEnd, newEnd, c);
     683             :         }
     684           0 :         if (capacity()) pData_->pEnd_ = newEnd;
     685           0 :     }
     686             : 
     687           0 :     void reserve(size_type res_arg)
     688             :     {
     689           0 :         if (res_arg <= capacity())
     690             :         {
     691             :             // @@@ shrink to fit here
     692           0 :             return;
     693             :         }
     694             : 
     695           0 :         A& myAlloc = *this;
     696           0 :         AllocatorStringStorage newStr(myAlloc);
     697           0 :         newStr.Init(size(), res_arg);
     698             : 
     699           0 :         flex_string_details::pod_copy(begin(), end(), newStr.begin());
     700             : 
     701           0 :         swap(newStr);
     702             :     }
     703             : 
     704             :     template <class ForwardIterator>
     705           0 :     void append(ForwardIterator b, ForwardIterator e)
     706             :     {
     707             :         const size_type
     708           0 :             sz = std::distance(b, e),
     709           0 :             neededCapacity = size() + sz;
     710             : 
     711           0 :         if (capacity() < neededCapacity)
     712             :         {
     713             : //             typedef std::less_equal<const E*> le_type;
     714             : //             BOOST_ASSERT(!(le_type()(begin(), &*b) && le_type()(&*b, end())));
     715           0 :             reserve(neededCapacity);
     716             :         }
     717           0 :         std::copy(b, e, end());
     718           0 :         pData_->pEnd_ += sz;
     719           0 :     }
     720             : 
     721           0 :     void swap(AllocatorStringStorage& rhs)
     722             :     {
     723             :         // @@@ The following line is commented due to a bug in MSVC
     724             :         //std::swap(lhsAlloc, rhsAlloc);
     725           0 :         std::swap(pData_, rhs.pData_);
     726             :     }
     727             : 
     728           0 :     const E* c_str() const
     729             :     {
     730           0 :         if (pData_ != &SimpleStringStorage<E, A>::emptyString_)
     731             :         {
     732           0 :             *pData_->pEnd_ = E();
     733             :         }
     734           0 :         return &*begin();
     735             :     }
     736             : 
     737           0 :     const E* data() const
     738           0 :     { return &*begin(); }
     739             : 
     740           0 :     A get_allocator() const
     741           0 :     { return *this; }
     742             : };
     743             : 
     744             : ////////////////////////////////////////////////////////////////////////////////
     745             : // class template VectorStringStorage
     746             : // Uses std::vector
     747             : // Takes advantage of the Empty Base Optimization if available
     748             : ////////////////////////////////////////////////////////////////////////////////
     749             : 
     750             : template <typename E, class A = std::allocator<E> >
     751             : class VectorStringStorage : protected std::vector<E, A>
     752             : {
     753             :     typedef std::vector<E, A> base;
     754             : 
     755             : public: // protected:
     756             :     typedef E value_type;
     757             :     typedef typename base::iterator iterator;
     758             :     typedef typename base::const_iterator const_iterator;
     759             :     typedef A allocator_type;
     760             :     typedef typename A::size_type size_type;
     761             : 
     762             :     VectorStringStorage(const VectorStringStorage& s) : base(s)
     763             :     { }
     764             : 
     765             :     VectorStringStorage(const A& a) : base(1, E(), a)
     766             :     { }
     767             : 
     768             :     VectorStringStorage(const E* s, size_type len, const A& a)
     769             :     : base(a)
     770             :     {
     771             :         base::reserve(len + 1);
     772             :         base::insert(base::end(), s, s + len);
     773             :         // Terminating zero
     774             :         base::insert(base::end(), E());
     775             :     }
     776             : 
     777             :     VectorStringStorage(size_type len, E c, const A& a)
     778             :     : base(len + 1, c, a)
     779             :     {
     780             :         // Terminating zero
     781             :         base::back() = E();
     782             :     }
     783             : 
     784             :     VectorStringStorage& operator=(const VectorStringStorage& rhs)
     785             :     {
     786             :         base& v = *this;
     787             :         v = rhs;
     788             :         return *this;
     789             :     }
     790             : 
     791             :     iterator begin()
     792             :     { return base::begin(); }
     793             : 
     794             :     const_iterator begin() const
     795             :     { return base::begin(); }
     796             : 
     797             :     iterator end()
     798             :     { return base::end() - 1; }
     799             : 
     800             :     const_iterator end() const
     801             :     { return base::end() - 1; }
     802             : 
     803             :     size_type size() const
     804             :     { return base::size() - 1; }
     805             : 
     806             :     size_type max_size() const
     807             :     { return base::max_size() - 1; }
     808             : 
     809             :     size_type capacity() const
     810             :     { return base::capacity() - 1; }
     811             : 
     812             :     void reserve(size_type res_arg)
     813             :     {
     814             :         BOOST_ASSERT(res_arg < max_size());
     815             :         base::reserve(res_arg + 1);
     816             :     }
     817             : 
     818             :     void append(const E* s, size_type sz)
     819             :     {
     820             :         // Check for aliasing because std::vector doesn't do it.
     821             :         static std::less_equal<const E*> le;
     822             :         if (!base::empty())
     823             :         {
     824             :             const E* start = &base::front();
     825             :             if (le(start, s) && le(s, start + size()))
     826             :             {
     827             :                 // aliased
     828             :                 const size_type offset = s - start;
     829             :                 reserve(size() + sz);
     830             :                 s = &base::front() + offset;
     831             :             }
     832             :         }
     833             :         base::insert(end(), s, s + sz);
     834             :     }
     835             : 
     836             :     template <class InputIterator>
     837             :     void append(InputIterator b, InputIterator e)
     838             :     {
     839             :         base::insert(end(), b, e);
     840             :     }
     841             : 
     842             :     void resize(size_type n, E c)
     843             :     {
     844             :         base::reserve(n + 1);
     845             :         base::back() = c;
     846             :         base::resize(n + 1, c);
     847             :         base::back() = E();
     848             :     }
     849             : 
     850             :     void swap(VectorStringStorage& rhs)
     851             :     { base::swap(rhs); }
     852             : 
     853             :     const E* c_str() const
     854             :     { return &*begin(); }
     855             : 
     856             :     const E* data() const
     857             :     { return &*begin(); }
     858             : 
     859             :     A get_allocator() const
     860             :     { return base::get_allocator(); }
     861             : };
     862             : 
     863             : ////////////////////////////////////////////////////////////////////////////////
     864             : // class template SmallStringOpt
     865             : // Builds the small string optimization over any other storage
     866             : ////////////////////////////////////////////////////////////////////////////////
     867             : 
     868             : template <class Storage, unsigned int threshold,
     869             :     typename Align = typename Storage::value_type*>
     870             : class SmallStringOpt
     871             : {
     872             : public:
     873             :     typedef typename Storage::value_type value_type;
     874             :     typedef value_type* iterator;
     875             :     typedef const value_type* const_iterator;
     876             :     typedef typename Storage::allocator_type allocator_type;
     877             :     typedef typename allocator_type::size_type size_type;
     878             : 
     879             : private:
     880             :   enum { temp1 = threshold * sizeof(value_type) > sizeof(Storage)
     881             :         ? threshold  * sizeof(value_type)
     882             :         : sizeof(Storage) };
     883             : 
     884             :     enum { temp2 = temp1 > sizeof(Align) ? temp1 : sizeof(Align) };
     885             : 
     886             : public:
     887             :     enum { maxSmallString =
     888             :     (temp2 + sizeof(value_type) - 1) / sizeof(value_type) };
     889             : 
     890             : private:
     891             :     enum { magic = maxSmallString + 1 };
     892             : 
     893             :     union
     894             :     {
     895             :         mutable value_type buf_[maxSmallString + 1];
     896             :         Align align_;
     897             :     };
     898             : 
     899             :     Storage& GetStorage()
     900             :     {
     901             :         BOOST_ASSERT(buf_[maxSmallString] == magic);
     902             :         Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
     903             :         return *p;
     904             :     }
     905             : 
     906             :     const Storage& GetStorage() const
     907             :     {
     908             :         BOOST_ASSERT(buf_[maxSmallString] == magic);
     909             :         const Storage *p = reinterpret_cast<const Storage*>(&buf_[0]);
     910             :         return *p;
     911             :     }
     912             : 
     913             :     bool Small() const
     914             :     {
     915             :         return buf_[maxSmallString] != magic;
     916             :     }
     917             : 
     918             : public:
     919             :   SmallStringOpt(const SmallStringOpt& s)
     920             :     {
     921             :         if (s.Small())
     922             :         {
     923             :             flex_string_details::pod_copy(
     924             :                 s.buf_,
     925             :                 s.buf_ + s.size(),
     926             :                 buf_);
     927             :         }
     928             :         else
     929             :         {
     930             :             new(buf_) Storage(s.GetStorage());
     931             :         }
     932             :         buf_[maxSmallString] = s.buf_[maxSmallString];
     933             :     }
     934             : 
     935             :     SmallStringOpt(const allocator_type&)
     936             :     {
     937             :         buf_[maxSmallString] = maxSmallString;
     938             :     }
     939             : 
     940             :     SmallStringOpt(const value_type* s, size_type len, const allocator_type& a)
     941             :     {
     942             :         if (len <= maxSmallString)
     943             :         {
     944             :             flex_string_details::pod_copy(s, s + len, buf_);
     945             :             buf_[maxSmallString] = value_type(maxSmallString - len);
     946             :         }
     947             :         else
     948             :         {
     949             :             new(buf_) Storage(s, len, a);
     950             :             buf_[maxSmallString] = magic;
     951             :         }
     952             :     }
     953             : 
     954             :     SmallStringOpt(size_type len, value_type c, const allocator_type& a)
     955             :     {
     956             :         if (len <= maxSmallString)
     957             :         {
     958             :             flex_string_details::pod_fill(buf_, buf_ + len, c);
     959             :             buf_[maxSmallString] = value_type(maxSmallString - len);
     960             :         }
     961             :         else
     962             :         {
     963             :             new(buf_) Storage(len, c, a);
     964             :             buf_[maxSmallString] = magic;
     965             :         }
     966             :     }
     967             : 
     968             :     SmallStringOpt& operator=(const SmallStringOpt& rhs)
     969             :     {
     970             :         reserve(rhs.size());
     971             :         resize(0, 0);
     972             :         append(rhs.data(), rhs.size());
     973             :         return *this;
     974             :     }
     975             : 
     976             :     ~SmallStringOpt()
     977             :     {
     978             :         if (!Small()) GetStorage().~Storage();
     979             :     }
     980             : 
     981             :     iterator begin()
     982             :     {
     983             :         if (Small()) return buf_;
     984             :         return &*GetStorage().begin();
     985             :     }
     986             : 
     987             :     const_iterator begin() const
     988             :     {
     989             :         if (Small()) return buf_;
     990             :         return &*GetStorage().begin();
     991             :     }
     992             : 
     993             :     iterator end()
     994             :     {
     995             :         if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
     996             :         return &*GetStorage().end();
     997             :     }
     998             : 
     999             :     const_iterator end() const
    1000             :     {
    1001             :         if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
    1002             :         return &*GetStorage().end();
    1003             :     }
    1004             : 
    1005             :     size_type size() const
    1006             :     {
    1007             :         BOOST_ASSERT(!Small() || maxSmallString >= buf_[maxSmallString]);
    1008             :         return Small()
    1009             :             ? maxSmallString - buf_[maxSmallString]
    1010             :             : GetStorage().size();
    1011             :     }
    1012             : 
    1013             :     size_type max_size() const
    1014             :     { return get_allocator().max_size(); }
    1015             : 
    1016             :     size_type capacity() const
    1017             :     { return Small() ? maxSmallString : GetStorage().capacity(); }
    1018             : 
    1019             :     void reserve(size_type res_arg)
    1020             :     {
    1021             :         if (Small())
    1022             :         {
    1023             :             if (res_arg <= maxSmallString) return;
    1024             :             SmallStringOpt temp(*this);
    1025             :             this->~SmallStringOpt();
    1026             :             new(buf_) Storage(temp.data(), temp.size(),
    1027             :                 temp.get_allocator());
    1028             :             buf_[maxSmallString] = magic;
    1029             :             GetStorage().reserve(res_arg);
    1030             :         }
    1031             :         else
    1032             :         {
    1033             :             GetStorage().reserve(res_arg);
    1034             :         }
    1035             :         BOOST_ASSERT(capacity() >= res_arg);
    1036             :     }
    1037             : 
    1038             :     void append(const value_type* s, size_type sz)
    1039             :     {
    1040             :         if (!Small())
    1041             :         {
    1042             :             GetStorage().append(s, sz);
    1043             :         }
    1044             :         else
    1045             :         {
    1046             :             // append to a small string
    1047             :             const size_type neededCapacity =
    1048             :                 maxSmallString - buf_[maxSmallString] + sz;
    1049             : 
    1050             :             if (maxSmallString < neededCapacity)
    1051             :             {
    1052             :                 // need to change storage strategy
    1053             :                 allocator_type alloc;
    1054             :                 Storage temp(alloc);
    1055             :                 temp.reserve(neededCapacity);
    1056             :                 temp.append(buf_, maxSmallString - buf_[maxSmallString]);
    1057             :                 temp.append(s, sz);
    1058             :                 buf_[maxSmallString] = magic;
    1059             :                 new(buf_) Storage(temp.get_allocator());
    1060             :                 GetStorage().swap(temp);
    1061             :             }
    1062             :             else
    1063             :             {
    1064             :                 flex_string_details::pod_move(s, s + sz,
    1065             :                     buf_ + maxSmallString - buf_[maxSmallString]);
    1066             :                 buf_[maxSmallString] -= value_type(sz);
    1067             :             }
    1068             :         }
    1069             :     }
    1070             : 
    1071             :     template <class InputIterator>
    1072             :     void append(InputIterator b, InputIterator e)
    1073             :     {
    1074             :         // @@@ todo: optimize this depending on iterator type
    1075             :         for (; b != e; ++b)
    1076             :         {
    1077             :             *this += *b;
    1078             :         }
    1079             :     }
    1080             : 
    1081             :     void resize(size_type n, value_type c)
    1082             :     {
    1083             :         if (Small())
    1084             :         {
    1085             :             if (n > maxSmallString)
    1086             :             {
    1087             :                 // Small string resized to big string
    1088             :                 SmallStringOpt temp(*this); // can't throw
    1089             :                 // 11-17-2001: correct exception safety bug
    1090             :                 Storage newString(temp.data(), temp.size(),
    1091             :                     temp.get_allocator());
    1092             :                 newString.resize(n, c);
    1093             :                 // We make the reasonable assumption that an empty Storage
    1094             :                 //     constructor won't throw
    1095             :                 this->~SmallStringOpt();
    1096             :                 new(&buf_[0]) Storage(temp.get_allocator());
    1097             :                 buf_[maxSmallString] = value_type(magic);
    1098             :                 GetStorage().swap(newString);
    1099             :             }
    1100             :             else
    1101             :             {
    1102             :                 // Small string resized to small string
    1103             :                 // 11-17-2001: bug fix: terminating zero not copied
    1104             :                 size_type toFill = n > size() ? n - size() : 0;
    1105             :                 flex_string_details::pod_fill(end(), end() + toFill, c);
    1106             :                 buf_[maxSmallString] = value_type(maxSmallString - n);
    1107             :             }
    1108             :         }
    1109             :         else
    1110             :         {
    1111             :             if (n > maxSmallString)
    1112             :             {
    1113             :                 // Big string resized to big string
    1114             :                 GetStorage().resize(n, c);
    1115             :             }
    1116             :             else
    1117             :             {
    1118             :                 // Big string resized to small string
    1119             :                 // 11-17=2001: bug fix in the BOOST_ASSERTion below
    1120             :                 BOOST_ASSERT(capacity() > n);
    1121             :                 SmallStringOpt newObj(data(), n, get_allocator());
    1122             :                 newObj.swap(*this);
    1123             :             }
    1124             :         }
    1125             :     }
    1126             : 
    1127             :     void swap(SmallStringOpt& rhs)
    1128             :     {
    1129             :         if (Small())
    1130             :         {
    1131             :             if (rhs.Small())
    1132             :             {
    1133             :                 // Small swapped with small
    1134             :                 std::swap_ranges(buf_, buf_ + maxSmallString + 1,
    1135             :                     rhs.buf_);
    1136             :             }
    1137             :             else
    1138             :             {
    1139             :                 // Small swapped with big
    1140             :                 // Make a copy of myself - can't throw
    1141             :                 SmallStringOpt temp(*this);
    1142             :                 // Nuke myself
    1143             :                 this->~SmallStringOpt();
    1144             :                 // Make an empty storage for myself (likely won't throw)
    1145             :                 new(buf_) Storage(0, value_type(), rhs.get_allocator());
    1146             :                 buf_[maxSmallString] = magic;
    1147             :                 // Recurse to this same function
    1148             :                 swap(rhs);
    1149             :                 // Nuke rhs
    1150             :                 rhs.~SmallStringOpt();
    1151             :                 // Build the new small string into rhs
    1152             :                 new(&rhs) SmallStringOpt(temp);
    1153             :             }
    1154             :         }
    1155             :         else
    1156             :         {
    1157             :             if (rhs.Small())
    1158             :             {
    1159             :                 // Big swapped with small
    1160             :                 // Already implemented, recurse with reversed args
    1161             :                 rhs.swap(*this);
    1162             :             }
    1163             :             else
    1164             :             {
    1165             :                 // Big swapped with big
    1166             :                 GetStorage().swap(rhs.GetStorage());
    1167             :             }
    1168             :         }
    1169             :     }
    1170             : 
    1171             :     const value_type* c_str() const
    1172             :     {
    1173             :         if (!Small()) return GetStorage().c_str();
    1174             :         buf_[maxSmallString - buf_[maxSmallString]] = value_type();
    1175             :         return buf_;
    1176             :     }
    1177             : 
    1178             :     const value_type* data() const
    1179             :     { return Small() ? buf_ : GetStorage().data(); }
    1180             : 
    1181             :     allocator_type get_allocator() const
    1182             :     { return allocator_type(); }
    1183             : };
    1184             : 
    1185             : ////////////////////////////////////////////////////////////////////////////////
    1186             : // class template CowString
    1187             : // Implements Copy on Write over any storage
    1188             : ////////////////////////////////////////////////////////////////////////////////
    1189             : 
    1190             : template <
    1191             :     typename Storage,
    1192             :     typename Align = BOOST_DEDUCED_TYPENAME Storage::value_type*
    1193             : >
    1194             : class CowString
    1195             : {
    1196             :     typedef typename Storage::value_type E;
    1197             :     typedef typename flex_string_details::get_unsigned<E>::result RefCountType;
    1198             : 
    1199             : public:
    1200             :     typedef E value_type;
    1201             :     typedef typename Storage::iterator iterator;
    1202             :     typedef typename Storage::const_iterator const_iterator;
    1203             :     typedef typename Storage::allocator_type allocator_type;
    1204             :     typedef typename allocator_type::size_type size_type;
    1205             :     typedef typename Storage::reference reference;
    1206             : 
    1207             : private:
    1208             :     union
    1209             :     {
    1210             :         mutable char buf_[sizeof(Storage)];
    1211             :         Align align_;
    1212             :     };
    1213             : 
    1214           0 :     Storage& Data() const
    1215             :     {
    1216           0 :         Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
    1217             :         return *p;
    1218             :     }
    1219             : 
    1220           0 :     RefCountType GetRefs() const
    1221             :     {
    1222           0 :         const Storage& d = Data();
    1223           0 :         BOOST_ASSERT(d.size() > 0);
    1224           0 :         BOOST_ASSERT(static_cast<RefCountType>(*d.begin()) != 0);
    1225           0 :         return *d.begin();
    1226             :     }
    1227             : 
    1228           0 :     RefCountType& Refs()
    1229             :     {
    1230           0 :         Storage& d = Data();
    1231           0 :         BOOST_ASSERT(d.size() > 0);
    1232           0 :         return reinterpret_cast<RefCountType&>(*d.begin());
    1233             :     }
    1234             : 
    1235           0 :     void MakeUnique() const
    1236             :     {
    1237           0 :         BOOST_ASSERT(GetRefs() >= 1);
    1238           0 :         if (GetRefs() == 1) return;
    1239             : 
    1240             :         union
    1241             :         {
    1242             :             char buf_[sizeof(Storage)];
    1243             :             Align align_;
    1244             :         } temp;
    1245             : 
    1246           0 :         --(*Data().begin()); // decrement the use count of the remaining object
    1247             : 
    1248           0 :         Storage* p = reinterpret_cast<Storage*>(&temp.buf_[0]);
    1249           0 :         new(buf_) Storage(
    1250           0 :             *new(p) Storage(Data()),
    1251             :             flex_string_details::Shallow());
    1252           0 :         *Data().begin() = 1;
    1253             :     }
    1254             : 
    1255             : public:
    1256           0 :     CowString(const CowString& s)
    1257             :     {
    1258           0 :         if (s.GetRefs() == (std::numeric_limits<RefCountType>::max)())
    1259             :         {
    1260             :             // must make a brand new copy
    1261           0 :             new(buf_) Storage(s.Data()); // non shallow
    1262           0 :             Refs() = 1;
    1263             :         }
    1264             :         else
    1265             :         {
    1266           0 :             new(buf_) Storage(s.Data(), flex_string_details::Shallow());
    1267           0 :             ++Refs();
    1268             :         }
    1269           0 :         BOOST_ASSERT(Data().size() > 0);
    1270           0 :     }
    1271             : 
    1272           0 :     CowString(const allocator_type& a)
    1273             :     {
    1274           0 :         new(buf_) Storage(1, 1, a);
    1275             :     }
    1276             : 
    1277           0 :     CowString(const E* s, size_type len, const allocator_type& a)
    1278             :     {
    1279             :         // Warning - MSVC's debugger has trouble tracing through the code below.
    1280             :         // It seems to be a const-correctness issue
    1281             :         //
    1282           0 :         new(buf_) Storage(a);
    1283           0 :         Data().reserve(len + 1);
    1284           0 :         Data().resize(1, 1);
    1285           0 :         Data().append(s, s + len);
    1286           0 :     }
    1287             : 
    1288           0 :     CowString(size_type len, E c, const allocator_type& a)
    1289             :     {
    1290           0 :         new(buf_) Storage(len + 1, c, a);
    1291           0 :         Refs() = 1;
    1292           0 :     }
    1293             : 
    1294           0 :     CowString& operator=(const CowString& rhs)
    1295             :     {
    1296             : //        CowString(rhs).swap(*this);
    1297           0 :         if (--Refs() == 0)
    1298           0 :             Data().~Storage();
    1299           0 :         if (rhs.GetRefs() == (std::numeric_limits<RefCountType>::max)())
    1300             :         {
    1301             :             // must make a brand new copy
    1302           0 :             new(buf_) Storage(rhs.Data()); // non shallow
    1303           0 :             Refs() = 1;
    1304             :         }
    1305             :         else
    1306             :         {
    1307           0 :             new(buf_) Storage(rhs.Data(), flex_string_details::Shallow());
    1308           0 :             ++Refs();
    1309             :         }
    1310           0 :         BOOST_ASSERT(Data().size() > 0);
    1311           0 :         return *this;
    1312             :     }
    1313             : 
    1314           0 :     ~CowString()
    1315             :     {
    1316           0 :         BOOST_ASSERT(Data().size() > 0);
    1317           0 :         if (--Refs() == 0)
    1318           0 :             Data().~Storage();
    1319           0 :     }
    1320             : 
    1321           0 :     iterator begin()
    1322             :     {
    1323           0 :         BOOST_ASSERT(Data().size() > 0);
    1324           0 :         MakeUnique();
    1325           0 :         return Data().begin() + 1;
    1326             :     }
    1327             : 
    1328           0 :     const_iterator begin() const
    1329             :     {
    1330           0 :         BOOST_ASSERT(Data().size() > 0);
    1331           0 :         return Data().begin() + 1;
    1332             :     }
    1333             : 
    1334             :     iterator end()
    1335             :     {
    1336             :         MakeUnique();
    1337             :         return Data().end();
    1338             :     }
    1339             : 
    1340           0 :     const_iterator end() const
    1341             :     {
    1342           0 :         return Data().end();
    1343             :     }
    1344             : 
    1345           0 :     size_type size() const
    1346             :     {
    1347           0 :         BOOST_ASSERT(Data().size() > 0);
    1348           0 :         return Data().size() - 1;
    1349             :     }
    1350             : 
    1351           0 :     size_type max_size() const
    1352             :     {
    1353           0 :         BOOST_ASSERT(Data().max_size() > 0);
    1354           0 :         return Data().max_size() - 1;
    1355             :     }
    1356             : 
    1357           0 :     size_type capacity() const
    1358             :     {
    1359           0 :         BOOST_ASSERT(Data().capacity() > 0);
    1360           0 :         return Data().capacity() - 1;
    1361             :     }
    1362             : 
    1363           0 :     void resize(size_type n, E c)
    1364             :     {
    1365           0 :         BOOST_ASSERT(Data().size() > 0);
    1366           0 :         MakeUnique();
    1367           0 :         Data().resize(n + 1, c);
    1368           0 :     }
    1369             : 
    1370             :     template <class FwdIterator>
    1371           0 :     void append(FwdIterator b, FwdIterator e)
    1372             :     {
    1373           0 :         MakeUnique();
    1374           0 :         Data().append(b, e);
    1375           0 :     }
    1376             : 
    1377           0 :     void reserve(size_type res_arg)
    1378             :     {
    1379           0 :         if (capacity() > res_arg) return;
    1380           0 :         MakeUnique();
    1381           0 :         Data().reserve(res_arg + 1);
    1382             :     }
    1383             : 
    1384             :     void swap(CowString& rhs)
    1385             :     {
    1386             :         Data().swap(rhs.Data());
    1387             :     }
    1388             : 
    1389           0 :     const E* c_str() const
    1390             :     {
    1391           0 :         BOOST_ASSERT(Data().size() > 0);
    1392           0 :         return Data().c_str() + 1;
    1393             :     }
    1394             : 
    1395           0 :     const E* data() const
    1396             :     {
    1397           0 :         BOOST_ASSERT(Data().size() > 0);
    1398           0 :         return Data().data() + 1;
    1399             :     }
    1400             : 
    1401             :     allocator_type get_allocator() const
    1402             :     {
    1403             :         return Data().get_allocator();
    1404             :     }
    1405             : };
    1406             : 
    1407             : ////////////////////////////////////////////////////////////////////////////////
    1408             : // class template flex_string
    1409             : // a std::basic_string compatible implementation
    1410             : // Uses a Storage policy
    1411             : ////////////////////////////////////////////////////////////////////////////////
    1412             : 
    1413             : template <typename E,
    1414             :     class T = std::char_traits<E>,
    1415             :     class A = std::allocator<E>,
    1416             :     class Storage = AllocatorStringStorage<E, A> >
    1417             : class flex_string : private Storage
    1418             : {
    1419             : #if defined(BOOST_WAVE_FLEXSTRING_THROW_ON_ENFORCE)
    1420             :     template <typename Exception>
    1421             :     static void Enforce(bool condition, Exception*, const char* msg)
    1422             :     { if (!condition) boost::throw_exception(Exception(msg)); }
    1423             : #else
    1424             :     template <typename Exception>
    1425           0 :     static inline void Enforce(bool condition, Exception*, const char* msg)
    1426           0 :     { BOOST_ASSERT(condition && msg); }
    1427             : #endif // defined(BOOST_WAVE_FLEXSTRING_THROW_ON_ENFORCE)
    1428             : 
    1429             : #ifndef NDEBUG
    1430           0 :     bool Sane() const
    1431             :     {
    1432             :         return
    1433           0 :             begin() <= end() &&
    1434           0 :             empty() == (size() == 0) &&
    1435           0 :             empty() == (begin() == end()) &&
    1436           0 :             size() <= max_size() &&
    1437           0 :             capacity() <= max_size() &&
    1438           0 :             size() <= capacity();
    1439             :     }
    1440             : 
    1441             :     struct Invariant;
    1442             :     friend struct Invariant;
    1443             :     struct Invariant
    1444             :     {
    1445           0 :         Invariant(const flex_string& s) : s_(s)
    1446             :         {
    1447           0 :             BOOST_ASSERT(s_.Sane());
    1448           0 :         }
    1449           0 :         ~Invariant()
    1450             :         {
    1451           0 :             BOOST_ASSERT(s_.Sane());
    1452           0 :         }
    1453             :     private:
    1454             :         const flex_string& s_;
    1455             :         Invariant& operator=(const Invariant&);
    1456             :     };
    1457             : #endif
    1458             : 
    1459             : public:
    1460             :     // types
    1461             :     typedef T traits_type;
    1462             :     typedef typename traits_type::char_type value_type;
    1463             :     typedef A allocator_type;
    1464             :     typedef typename A::size_type size_type;
    1465             :     typedef typename A::difference_type difference_type;
    1466             : 
    1467             :     typedef typename A::reference reference;
    1468             :     typedef typename A::const_reference const_reference;
    1469             :     typedef typename A::pointer pointer;
    1470             :     typedef typename A::const_pointer const_pointer;
    1471             : 
    1472             :     typedef typename Storage::iterator iterator;
    1473             :     typedef typename Storage::const_iterator const_iterator;
    1474             : 
    1475             :     typedef boost::reverse_iterator<iterator> reverse_iterator;
    1476             :     typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
    1477             : 
    1478             :     static const size_type npos;    // = size_type(-1)
    1479             : 
    1480             : private:
    1481           0 :     static size_type Min(size_type lhs, size_type rhs)
    1482             :     { return lhs < rhs ? lhs : rhs; }
    1483           0 :     static void Procust(size_type& n, size_type nmax)
    1484             :     { if (n > nmax) n = nmax; }
    1485             : 
    1486             : public:
    1487             :     // 21.3.1 construct/copy/destroy
    1488           0 :     explicit flex_string(const A& a = A())
    1489           0 :     : Storage(a)
    1490           0 :     {}
    1491             : 
    1492           0 :     flex_string(const flex_string& str)
    1493           0 :     : Storage(str)
    1494             :     {
    1495           0 :     }
    1496             : 
    1497             :     flex_string(const flex_string& str, size_type pos,
    1498             :         size_type n = npos, const A& a = A())
    1499             :     : Storage(a)
    1500             :     {
    1501             :         Enforce(pos <= str.size(), (std::out_of_range*)0, "");
    1502             :         assign(str, pos, n);
    1503             :     }
    1504             : 
    1505           0 :     flex_string(const value_type* s, const A& a = A())
    1506           0 :     : Storage(s, traits_type::length(s), a)
    1507           0 :     {}
    1508             : 
    1509           0 :     flex_string(const value_type* s, size_type n, const A& a = A())
    1510           0 :     : Storage(s, n, a)
    1511             :     {}
    1512             : 
    1513           0 :     flex_string(size_type n, value_type c, const A& a = A())
    1514           0 :     : Storage(n, c, a)
    1515           0 :     {}
    1516             : 
    1517             :     template <class InputIterator>
    1518             :     flex_string(InputIterator begin, InputIterator end, const A& a = A())
    1519             :     : Storage(a)
    1520             :     {
    1521             :         assign(begin, end);
    1522             :     }
    1523             : 
    1524           0 :     ~flex_string()
    1525           0 :     {}
    1526             : 
    1527           0 :     flex_string& operator=(const flex_string& str)
    1528             :     {
    1529           0 :         if (this != &str) {
    1530           0 :             Storage& s = *this;
    1531           0 :             s = str;
    1532             :         }
    1533             :         return *this;
    1534             :     }
    1535             : 
    1536           0 :     flex_string& operator=(const value_type* s)
    1537             :     {
    1538           0 :         assign(s);
    1539             :         return *this;
    1540             :     }
    1541             : 
    1542             :     flex_string& operator=(value_type c)
    1543             :     {
    1544             :         assign(1, c);
    1545             :         return *this;
    1546             :     }
    1547             : 
    1548             :     // 21.3.2 iterators:
    1549           0 :     iterator begin()
    1550           0 :     { return Storage::begin(); }
    1551             : 
    1552           0 :     const_iterator begin() const
    1553           0 :     { return Storage::begin(); }
    1554             : 
    1555             :     iterator end()
    1556             :     { return Storage::end(); }
    1557             : 
    1558           0 :     const_iterator end() const
    1559           0 :     { return Storage::end(); }
    1560             : 
    1561             :     reverse_iterator rbegin()
    1562             :     { return reverse_iterator(end()); }
    1563             : 
    1564             :     const_reverse_iterator rbegin() const
    1565             :     { return const_reverse_iterator(end()); }
    1566             : 
    1567             :     reverse_iterator rend()
    1568             :     { return reverse_iterator(begin()); }
    1569             : 
    1570             :     const_reverse_iterator rend() const
    1571             :     { return const_reverse_iterator(begin()); }
    1572             : 
    1573             : #if BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK != 0
    1574             :     //  temporary hack to make it easier to serialize flex_string's using
    1575             :     //  the Boost.Serialization library
    1576             :     value_type & back() { return *(begin()+size()-1); }
    1577             :     value_type const& back() const { return *(begin()+size()-1); }
    1578             : #endif
    1579             : 
    1580             :     // 21.3.3 capacity:
    1581           0 :     size_type size() const
    1582           0 :     { return Storage::size(); }
    1583             : 
    1584           0 :     size_type length() const
    1585           0 :     { return size(); }
    1586             : 
    1587           0 :     size_type max_size() const
    1588           0 :     { return Storage::max_size(); }
    1589             : 
    1590           0 :     void resize(size_type n, value_type c)
    1591           0 :     { Storage::resize(n, c); }
    1592             : 
    1593           0 :     void resize(size_type n)
    1594           0 :     { resize(n, value_type()); }
    1595             : 
    1596           0 :     size_type capacity() const
    1597           0 :     { return Storage::capacity(); }
    1598             : 
    1599           0 :     void reserve(size_type res_arg = 0)
    1600             :     {
    1601           0 :         Enforce(res_arg <= max_size(), (std::length_error*)0, "");
    1602           0 :         Storage::reserve(res_arg);
    1603           0 :     }
    1604             : 
    1605             :     void clear()
    1606             :     { resize(0); }
    1607             : 
    1608           0 :     bool empty() const
    1609           0 :     { return size() == 0; }
    1610             : 
    1611             :     // 21.3.4 element access:
    1612           0 :     const_reference operator[](size_type pos) const
    1613           0 :     { return *(begin() + pos); }
    1614             : 
    1615           0 :     reference operator[](size_type pos)
    1616           0 :     { return *(begin() + pos); }
    1617             : 
    1618             :     const_reference at(size_type n) const
    1619             :     {
    1620             :         Enforce(n < size(), (std::out_of_range*)0, "");
    1621             :         return (*this)[n];
    1622             :     }
    1623             : 
    1624             :     reference at(size_type n)
    1625             :     {
    1626             :         Enforce(n < size(), (std::out_of_range*)0, "");
    1627             :         return (*this)[n];
    1628             :     }
    1629             : 
    1630             :     // 21.3.5 modifiers:
    1631           0 :     flex_string& operator+=(const flex_string& str)
    1632           0 :     { return append(str); }
    1633             : 
    1634           0 :     flex_string& operator+=(const value_type* s)
    1635           0 :     { return append(s); }
    1636             : 
    1637             :     flex_string& operator+=(value_type c)
    1638             :     {
    1639             :         push_back(c);
    1640             :         return *this;
    1641             :     }
    1642             : 
    1643           0 :     flex_string& append(const flex_string& str)
    1644           0 :     { return append(str, 0, npos); }
    1645             : 
    1646           0 :     flex_string& append(const flex_string& str, const size_type pos,
    1647             :         size_type n)
    1648             :     {
    1649           0 :         const size_type sz = str.size();
    1650           0 :         Enforce(pos <= sz, (std::out_of_range*)0, "");
    1651           0 :         Procust(n, sz - pos);
    1652           0 :         return append(str.c_str() + pos, n);
    1653             :     }
    1654             : 
    1655           0 :     flex_string& append(const value_type* s, const size_type n)
    1656             :     {
    1657             : #ifndef NDEBUG
    1658           0 :         Invariant checker(*this);
    1659             : #endif
    1660           0 :         if (IsAliasedRange(s, s + n))
    1661             :         {
    1662           0 :             const size_type offset = s - &*begin();
    1663           0 :             Storage::reserve(size() + n);
    1664           0 :             s = &*begin() + offset;
    1665             :         }
    1666           0 :         Storage::append(s, s+ n);
    1667           0 :         return *this;
    1668             :     }
    1669             : 
    1670           0 :     flex_string& append(const value_type* s)
    1671           0 :     { return append(s, traits_type::length(s)); }
    1672             : 
    1673             :     flex_string& append(size_type n, value_type c)
    1674             :     {
    1675             :         resize(size() + n, c);
    1676             :         return *this;
    1677             :     }
    1678             : 
    1679             :     template<class InputIterator>
    1680             :     flex_string& append(InputIterator first, InputIterator last)
    1681             :     {
    1682             :         insert(end(), first, last);
    1683             :         return *this;
    1684             :     }
    1685             : 
    1686             :     void push_back(value_type c)
    1687             :     {
    1688             :         const size_type cap = capacity();
    1689             :         if (size() == cap)
    1690             :         {
    1691             :             reserve(cap << 1u);
    1692             :         }
    1693             :         Storage::append(&c, &c + 1);
    1694             :     }
    1695             : 
    1696             :     flex_string& assign(const flex_string& str)
    1697             :     {
    1698             :         if (&str == this) return *this;
    1699             :         return assign(str.data(), str.size());
    1700             :     }
    1701             : 
    1702             :     flex_string& assign(const flex_string& str, size_type pos,
    1703             :         size_type n)
    1704             :     {
    1705             :         const size_type sz = str.size();
    1706             :         Enforce(pos <= str.size(), (std::out_of_range*)0, "");
    1707             :         Procust(n, sz - pos);
    1708             :         return assign(str.data() + pos, n);
    1709             :     }
    1710             : 
    1711           0 :     flex_string& assign(const value_type* s, size_type n)
    1712             :     {
    1713             : #ifndef NDEBUG
    1714           0 :         Invariant checker(*this);
    1715             : #endif
    1716           0 :         if (size() >= n)
    1717             :         {
    1718           0 :             std::copy(s, s + n, begin());
    1719           0 :             resize(n);
    1720             :         }
    1721             :         else
    1722             :         {
    1723           0 :             const value_type *const s2 = s + size();
    1724           0 :             std::copy(s, s2, begin());
    1725           0 :             append(s2, n - size());
    1726             :         }
    1727           0 :         return *this;
    1728             :     }
    1729             : 
    1730           0 :     flex_string& assign(const value_type* s)
    1731           0 :     { return assign(s, traits_type::length(s)); }
    1732             : 
    1733             :     template <class ItOrLength, class ItOrChar>
    1734             :     flex_string& assign(ItOrLength first_or_n, ItOrChar last_or_c)
    1735             :     { return replace(begin(), end(), first_or_n, last_or_c); }
    1736             : 
    1737             :     flex_string& insert(size_type pos1, const flex_string& str)
    1738             :     { return insert(pos1, str.data(), str.size()); }
    1739             : 
    1740             :     flex_string& insert(size_type pos1, const flex_string& str,
    1741             :         size_type pos2, size_type n)
    1742             :     {
    1743             :         Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
    1744             :         Procust(n, str.length() - pos2);
    1745             :         return insert(pos1, str.data() + pos2, n);
    1746             :     }
    1747             : 
    1748             :     flex_string& insert(size_type pos, const value_type* s, size_type n)
    1749             :     {
    1750             :         Enforce(pos <= length(), (std::out_of_range*)0, "");
    1751             :         insert(begin() + pos, s, s + n);
    1752             :         return *this;
    1753             :     }
    1754             : 
    1755             :     flex_string& insert(size_type pos, const value_type* s)
    1756             :     { return insert(pos, s, traits_type::length(s)); }
    1757             : 
    1758             :     flex_string& insert(size_type pos, size_type n, value_type c)
    1759             :     {
    1760             :         Enforce(pos <= length(), (std::out_of_range*)0, "");
    1761             :         insert(begin() + pos, n, c);
    1762             :         return *this;
    1763             :     }
    1764             : 
    1765             :     iterator insert(iterator p, value_type c = value_type())
    1766             :     {
    1767             :         const size_type pos = p - begin();
    1768             :         insert(pos, &c, 1);
    1769             :         return begin() + pos;
    1770             :     }
    1771             : 
    1772             : private:
    1773             :     // Care must be taken when dereferencing some iterator types.
    1774             :     //
    1775             :     // Users can implement this function in their namespace if their storage
    1776             :     // uses a special iterator type, the function will be found through ADL.
    1777             :     template<class Iterator>
    1778             :     const typename std::iterator_traits<Iterator>::value_type*
    1779           0 :     DereferenceValidIterator(Iterator it) const
    1780             :     {
    1781             :         return &*it;
    1782             :     }
    1783             : 
    1784             :     // Care must be taken when dereferencing a reverse iterators, hence this
    1785             :     // special case. This isn't in the std namespace so as not to pollute it or
    1786             :     // create name clashes.
    1787             :     template<typename Iterator>
    1788             :     const typename std::iterator_traits<Iterator>::value_type*
    1789             :     DereferenceValidIterator(std::reverse_iterator<Iterator> it) const
    1790             :     {
    1791             :         return &*--it;
    1792             :     }
    1793             : 
    1794             :     // Determine if the range aliases the current string.
    1795             :     //
    1796             :     // This method cannot be const because calling begin/end on copy-on-write
    1797             :     // implementations must have side effects.
    1798             :     // A const version wouldn't make the string unique through this call.
    1799             :     template<class Iterator>
    1800           0 :     bool IsAliasedRange(Iterator beginIterator, Iterator endIterator)
    1801             :     {
    1802           0 :         if(!empty() && beginIterator != endIterator)
    1803             :         {
    1804             :             typedef const typename std::iterator_traits<Iterator>::value_type *
    1805             :                 pointer;
    1806             : 
    1807           0 :             pointer myBegin(&*begin());
    1808           0 :             pointer myEnd(&*begin() + size());
    1809           0 :             pointer rangeBegin(DereferenceValidIterator(beginIterator));
    1810             : 
    1811             :             const std::less_equal<pointer> less_equal = std::less_equal<pointer>();
    1812           0 :             if(less_equal(myBegin, rangeBegin) && less_equal(rangeBegin, myEnd))
    1813             :                 return true;
    1814             :         }
    1815             :         return false;
    1816             :     }
    1817             : 
    1818             :     template <int i> class Selector {};
    1819             : 
    1820             :     flex_string& InsertImplDiscr(iterator p,
    1821             :         size_type n, value_type c, Selector<1>)
    1822             :     {
    1823             : #ifndef NDEBUG
    1824             :         Invariant checker(*this);
    1825             : #endif
    1826             :         BOOST_ASSERT(begin() <= p && p <= end());
    1827             :         const size_type insertOffset(p - begin());
    1828             :         const size_type originalSize(size());
    1829             :         if(n < originalSize - insertOffset)
    1830             :         {
    1831             :             // The new characters fit within the original string.
    1832             :             // The characters that are pushed back need to be moved because
    1833             :             // they're aliased.
    1834             :             // The appended characters will all be overwritten by the move.
    1835             :             append(n, value_type(0));
    1836             :             value_type* begin(&*begin());
    1837             :             flex_string_details::pod_move(begin + insertOffset,
    1838             :                 begin + originalSize, begin + insertOffset + n);
    1839             :             std::fill(begin + insertOffset, begin + insertOffset + n, c);
    1840             :         }
    1841             :         else
    1842             :         {
    1843             :             // The new characters exceed the original string.
    1844             :             // The characters that are pushed back can simply be copied since
    1845             :             // they aren't aliased.
    1846             :             // The appended characters will partly be overwritten by the copy.
    1847             :             append(n, c);
    1848             :             value_type* begin(&*begin());
    1849             :             flex_string_details::pod_copy(begin + insertOffset,
    1850             :                 begin + originalSize, begin + insertOffset + n);
    1851             :             std::fill(begin + insertOffset, begin + originalSize, c);
    1852             :         }
    1853             :         return *this;
    1854             :     }
    1855             : 
    1856             :     template<class InputIterator>
    1857             :     flex_string& InsertImplDiscr(iterator i,
    1858             :         InputIterator b, InputIterator e, Selector<0>)
    1859             :     {
    1860             :         InsertImpl(i, b, e,
    1861             :             typename std::iterator_traits<InputIterator>::iterator_category());
    1862             :         return *this;
    1863             :     }
    1864             : 
    1865             :     template <class FwdIterator>
    1866             :     void InsertImpl(iterator i,
    1867             :         FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
    1868             :     {
    1869             :         if(s1 == s2)
    1870             :         {
    1871             :             // Insert an empty range.
    1872             :             return;
    1873             :         }
    1874             : 
    1875             :         if(IsAliasedRange(s1, s2))
    1876             :         {
    1877             :             // The source range is contained in the current string, copy it
    1878             :             // and recurse.
    1879             :             const flex_string temporary(s1, s2);
    1880             :             InsertImpl(i, temporary.begin(), temporary.end(),
    1881             :                 typename std::iterator_traits<FwdIterator>::iterator_category());
    1882             :             return;
    1883             :         }
    1884             : 
    1885             : #ifndef NDEBUG
    1886             :         Invariant checker(*this);
    1887             : #endif
    1888             :         const size_type pos = i - begin();
    1889             :         const typename std::iterator_traits<FwdIterator>::difference_type n2 =
    1890             :             std::distance(s1, s2);
    1891             : 
    1892             :         BOOST_ASSERT(n2 >= 0);
    1893             :         using namespace flex_string_details;
    1894             :         BOOST_ASSERT(pos <= size());
    1895             : 
    1896             :         const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
    1897             :             capacity() - size();
    1898             :         if (maxn2 < n2)
    1899             :         {
    1900             :             // Reallocate the string.
    1901             :             BOOST_ASSERT(!IsAliasedRange(s1, s2));
    1902             :             reserve(size() + n2);
    1903             :             i = begin() + pos;
    1904             :         }
    1905             :         if (pos + n2 <= size())
    1906             :         {
    1907             :             const iterator tailBegin = end() - n2;
    1908             :             Storage::append(tailBegin, tailBegin + n2);
    1909             :             std::copy(reverse_iterator(tailBegin), reverse_iterator(i),
    1910             :                 reverse_iterator(tailBegin + n2));
    1911             :             std::copy(s1, s2, i);
    1912             :         }
    1913             :         else
    1914             :         {
    1915             :             FwdIterator t = s1;
    1916             :             const size_type old_size = size();
    1917             :             std::advance(t, old_size - pos);
    1918             :             BOOST_ASSERT(std::distance(t, s2) >= 0);
    1919             :             Storage::append(t, s2);
    1920             :             Storage::append(data() + pos, data() + old_size);
    1921             :             std::copy(s1, t, i);
    1922             :         }
    1923             :     }
    1924             : 
    1925             :     template <class InputIterator>
    1926             :     void InsertImpl(iterator insertPosition,
    1927             :         InputIterator inputBegin, InputIterator inputEnd,
    1928             :         std::input_iterator_tag)
    1929             :     {
    1930             :         flex_string temporary(begin(), insertPosition);
    1931             :         for (; inputBegin != inputEnd; ++inputBegin)
    1932             :         {
    1933             :             temporary.push_back(*inputBegin);
    1934             :         }
    1935             :         temporary.append(insertPosition, end());
    1936             :         swap(temporary);
    1937             :     }
    1938             : 
    1939             : public:
    1940             :     template <class ItOrLength, class ItOrChar>
    1941             :     void insert(iterator p, ItOrLength first_or_n, ItOrChar last_or_c)
    1942             :     {
    1943             :         Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
    1944             :         InsertImplDiscr(p, first_or_n, last_or_c, sel);
    1945             :     }
    1946             : 
    1947             :     flex_string& erase(size_type pos = 0, size_type n = npos)
    1948             :     {
    1949             : #ifndef NDEBUG
    1950             :         Invariant checker(*this);
    1951             : #endif
    1952             :         Enforce(pos <= length(), (std::out_of_range*)0, "");
    1953             :         Procust(n, length() - pos);
    1954             :         std::copy(begin() + pos + n, end(), begin() + pos);
    1955             :         resize(length() - n);
    1956             :         return *this;
    1957             :     }
    1958             : 
    1959             :     iterator erase(iterator position)
    1960             :     {
    1961             :         const size_type pos(position - begin());
    1962             :         erase(pos, 1);
    1963             :         return begin() + pos;
    1964             :     }
    1965             : 
    1966             :     iterator erase(iterator first, iterator last)
    1967             :     {
    1968             :         const size_type pos(first - begin());
    1969             :         erase(pos, last - first);
    1970             :         return begin() + pos;
    1971             :     }
    1972             : 
    1973             :     // Replaces at most n1 chars of *this, starting with pos1 with the content of str
    1974             :     flex_string& replace(size_type pos1, size_type n1, const flex_string& str)
    1975             :     { return replace(pos1, n1, str, 0, npos); }
    1976             : 
    1977             :     // Replaces at most n1 chars of *this, starting with pos1,
    1978             :     // with at most n2 chars of str starting with pos2
    1979             :     flex_string& replace(size_type pos1, size_type n1, const flex_string& str,
    1980             :         size_type pos2, size_type n2)
    1981             :     {
    1982             :         Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
    1983             :         return replace(pos1, n1, str.data() + pos2,
    1984             :             Min(n2, str.size() - pos2));
    1985             :     }
    1986             : 
    1987             :     // Replaces at most n1 chars of *this, starting with pos, with chars from s
    1988             :     flex_string& replace(size_type pos, size_type n1, const value_type* s)
    1989             :     { return replace(pos, n1, s, traits_type::length(s)); }
    1990             : 
    1991             :     // Replaces at most n1 chars of *this, starting with pos, with n2 occurrences of c
    1992             :     // consolidated with
    1993             :     // Replaces at most n1 chars of *this, starting with pos,
    1994             :     // with at most n2 chars of str.
    1995             :     // str must have at least n2 chars.
    1996             :     template <class StrOrLength, class NumOrChar>
    1997             :     flex_string& replace(size_type pos, size_type n1,
    1998             :         StrOrLength s_or_n2, NumOrChar n_or_c)
    1999             :     {
    2000             : #ifndef NDEBUG
    2001             :         Invariant checker(*this);
    2002             : #endif
    2003             :         Enforce(pos <= size(), (std::out_of_range*)0, "");
    2004             :         Procust(n1, length() - pos);
    2005             :         const iterator b = begin() + pos;
    2006             :         return replace(b, b + n1, s_or_n2, n_or_c);
    2007             :     }
    2008             : 
    2009             :     flex_string& replace(iterator i1, iterator i2, const flex_string& str)
    2010             :     { return replace(i1, i2, str.c_str(), str.length()); }
    2011             : 
    2012             :     flex_string& replace(iterator i1, iterator i2, const value_type* s)
    2013             :     { return replace(i1, i2, s, traits_type::length(s)); }
    2014             : 
    2015             : private:
    2016             :     flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
    2017             :         const value_type* s, size_type n, Selector<2>)
    2018             :     {
    2019             :         BOOST_ASSERT(i1 <= i2);
    2020             :         BOOST_ASSERT(begin() <= i1 && i1 <= end());
    2021             :         BOOST_ASSERT(begin() <= i2 && i2 <= end());
    2022             :         return replace(i1, i2, s, s + n);
    2023             :     }
    2024             : 
    2025             :     flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
    2026             :         size_type n2, value_type c, Selector<1>)
    2027             :     {
    2028             :         const size_type n1 = i2 - i1;
    2029             :         if (n1 > n2)
    2030             :         {
    2031             :             std::fill(i1, i1 + n2, c);
    2032             :             erase(i1 + n2, i2);
    2033             :         }
    2034             :         else
    2035             :         {
    2036             :             std::fill(i1, i2, c);
    2037             :             insert(i2, n2 - n1, c);
    2038             :         }
    2039             :         return *this;
    2040             :     }
    2041             : 
    2042             :     template <class InputIterator>
    2043             :     flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
    2044             :         InputIterator b, InputIterator e, Selector<0>)
    2045             :     {
    2046             :         ReplaceImpl(i1, i2, b, e,
    2047             :             typename std::iterator_traits<InputIterator>::iterator_category());
    2048             :         return *this;
    2049             :     }
    2050             : 
    2051             :     template <class FwdIterator>
    2052             :     void ReplaceImpl(iterator i1, iterator i2,
    2053             :         FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
    2054             :     {
    2055             : #ifndef NDEBUG
    2056             :         Invariant checker(*this);
    2057             : #endif
    2058             :         const typename std::iterator_traits<iterator>::difference_type n1 =
    2059             :             i2 - i1;
    2060             :         BOOST_ASSERT(n1 >= 0);
    2061             :         const typename std::iterator_traits<FwdIterator>::difference_type n2 =
    2062             :         std::distance(s1, s2);
    2063             :         BOOST_ASSERT(n2 >= 0);
    2064             : 
    2065             :         if (IsAliasedRange(s1, s2))
    2066             :         {
    2067             :             // Aliased replace, copy to new string.
    2068             :             flex_string temporary;
    2069             :             temporary.reserve(size() - n1 + n2);
    2070             :             temporary.append(begin(), i1).append(s1, s2).append(i2, end());
    2071             :             swap(temporary);
    2072             :             return;
    2073             :         }
    2074             : 
    2075             :         if (n1 > n2)
    2076             :         {
    2077             :             // Shrinks
    2078             :             std::copy(s1, s2, i1);
    2079             :             erase(i1 + n2, i2);
    2080             :         }
    2081             :         else
    2082             :         {
    2083             :             // Grows
    2084             :             flex_string_details::copy_n(s1, n1, i1);
    2085             :             std::advance(s1, n1);
    2086             :             insert(i2, s1, s2);
    2087             :         }
    2088             :     }
    2089             : 
    2090             :     template <class InputIterator>
    2091             :     void ReplaceImpl(iterator i1, iterator i2,
    2092             :         InputIterator b, InputIterator e, std::input_iterator_tag)
    2093             :     {
    2094             :         flex_string temp(begin(), i1);
    2095             :         temp.append(b, e).append(i2, end());
    2096             :         swap(temp);
    2097             :     }
    2098             : 
    2099             : public:
    2100             :     template <class T1, class T2>
    2101             :     flex_string& replace(iterator i1, iterator i2,
    2102             :         T1 first_or_n_or_s, T2 last_or_c_or_n)
    2103             :     {
    2104             :         const bool
    2105             :             num1 = std::numeric_limits<T1>::is_specialized,
    2106             :             num2 = std::numeric_limits<T2>::is_specialized;
    2107             :         return ReplaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n,
    2108             :             Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
    2109             :     }
    2110             : 
    2111             :     size_type copy(value_type* s, size_type n, size_type pos = 0) const
    2112             :     {
    2113             :         Enforce(pos <= size(), (std::out_of_range*)0, "");
    2114             :         n = Min(n, size() - pos);
    2115             : 
    2116             :         flex_string_details::pod_copy(
    2117             :             &*begin() + pos,
    2118             :             &*begin() + pos + n,
    2119             :             s);
    2120             :         return n;
    2121             :     }
    2122             : 
    2123             :     void swap(flex_string& rhs)
    2124             :     {
    2125             :         Storage& srhs = rhs;
    2126             :         this->Storage::swap(srhs);
    2127             :     }
    2128             : 
    2129             :     // 21.3.6 string operations:
    2130           0 :     const value_type* c_str() const
    2131           0 :     { return Storage::c_str(); }
    2132             : 
    2133           0 :     const value_type* data() const
    2134           0 :     { return Storage::data(); }
    2135             : 
    2136             :     allocator_type get_allocator() const
    2137             :     { return Storage::get_allocator(); }
    2138             : 
    2139             :     size_type find(const flex_string& str, size_type pos = 0) const
    2140             :     { return find(str.data(), pos, str.length()); }
    2141             : 
    2142           0 :     size_type find (const value_type* s, size_type pos, size_type n) const
    2143             :     {
    2144           0 :         const size_type size_(size());
    2145           0 :         if (n + pos > size_)
    2146             :             return npos;
    2147           0 :         for (; pos < size_; ++pos)
    2148             :         {
    2149           0 :             if (traits_type::compare(&*begin() + pos, s, n) == 0)
    2150             :             {
    2151           0 :                 return pos;
    2152             :             }
    2153             :         }
    2154             :         return npos;
    2155             :     }
    2156             : 
    2157           0 :     size_type find (const value_type* s, size_type pos = 0) const
    2158           0 :     { return find(s, pos, traits_type::length(s)); }
    2159             : 
    2160             :     size_type find (value_type c, size_type pos = 0) const
    2161             :     { return find(&c, pos, 1); }
    2162             : 
    2163             :     size_type rfind(const flex_string& str, size_type pos = npos) const
    2164             :     { return rfind(str.c_str(), pos, str.length()); }
    2165             : 
    2166             :     size_type rfind(const value_type* s, size_type pos, size_type n) const
    2167             :     {
    2168             :         if (n > length()) return npos;
    2169             :         pos = Min(pos, length() - n);
    2170             :         if (n == 0) return pos;
    2171             : 
    2172             :         const_iterator i(begin() + pos);
    2173             :         for (; ; --i)
    2174             :         {
    2175             :             if (traits_type::eq(*i, *s)
    2176             :                 && traits_type::compare(&*i, s, n) == 0)
    2177             :             {
    2178             :                 return i - begin();
    2179             :             }
    2180             :             if (i == begin()) break;
    2181             :         }
    2182             :         return npos;
    2183             :     }
    2184             : 
    2185             :     size_type rfind(const value_type* s, size_type pos = npos) const
    2186             :     { return rfind(s, pos, traits_type::length(s)); }
    2187             : 
    2188             :     size_type rfind(value_type c, size_type pos = npos) const
    2189             :     { return rfind(&c, pos, 1); }
    2190             : 
    2191             :     size_type find_first_of(const flex_string& str, size_type pos = 0) const
    2192             :     { return find_first_of(str.c_str(), pos, str.length()); }
    2193             : 
    2194           0 :     size_type find_first_of(const value_type* s,
    2195             :         size_type pos, size_type n) const
    2196             :     {
    2197           0 :         if (pos > length() || n == 0) return npos;
    2198           0 :         const_iterator i(begin() + pos),
    2199           0 :             finish(end());
    2200           0 :         for (; i != finish; ++i)
    2201             :         {
    2202           0 :             if (traits_type::find(s, n, *i) != 0)
    2203             :             {
    2204           0 :                 return i - begin();
    2205             :             }
    2206             :         }
    2207             :         return npos;
    2208             :     }
    2209             : 
    2210           0 :     size_type find_first_of(const value_type* s, size_type pos = 0) const
    2211           0 :     { return find_first_of(s, pos, traits_type::length(s)); }
    2212             : 
    2213           0 :     size_type find_first_of(value_type c, size_type pos = 0) const
    2214           0 :     { return find_first_of(&c, pos, 1); }
    2215             : 
    2216             :     size_type find_last_of (const flex_string& str,
    2217             :         size_type pos = npos) const
    2218             :     { return find_last_of(str.c_str(), pos, str.length()); }
    2219             : 
    2220           0 :     size_type find_last_of (const value_type* s, size_type pos,
    2221             :         size_type n) const
    2222             :     {
    2223           0 :         if (!empty() && n > 0)
    2224             :         {
    2225           0 :             pos = Min(pos, length() - 1);
    2226           0 :             const_iterator i(begin() + pos);
    2227           0 :             for (;; --i)
    2228             :             {
    2229           0 :                 if (traits_type::find(s, n, *i) != 0)
    2230             :                 {
    2231           0 :                     return i - begin();
    2232             :                 }
    2233           0 :                 if (i == begin()) break;
    2234             :             }
    2235             :         }
    2236             :         return npos;
    2237             :     }
    2238             : 
    2239             :     size_type find_last_of (const value_type* s,
    2240             :         size_type pos = npos) const
    2241             :     { return find_last_of(s, pos, traits_type::length(s)); }
    2242             : 
    2243           0 :     size_type find_last_of (value_type c, size_type pos = npos) const
    2244           0 :     { return find_last_of(&c, pos, 1); }
    2245             : 
    2246             :     size_type find_first_not_of(const flex_string& str,
    2247             :         size_type pos = 0) const
    2248             :     { return find_first_not_of(str.data(), pos, str.size()); }
    2249             : 
    2250           0 :     size_type find_first_not_of(const value_type* s, size_type pos,
    2251             :         size_type n) const
    2252             :     {
    2253           0 :         if (pos < length())
    2254             :         {
    2255             :             const_iterator
    2256           0 :                 i(begin() + pos),
    2257           0 :                 finish(end());
    2258           0 :             for (; i != finish; ++i)
    2259             :             {
    2260           0 :                 if (traits_type::find(s, n, *i) == 0)
    2261             :                 {
    2262           0 :                     return i - begin();
    2263             :                 }
    2264             :             }
    2265             :         }
    2266             :         return npos;
    2267             :     }
    2268             : 
    2269           0 :     size_type find_first_not_of(const value_type* s,
    2270             :         size_type pos = 0) const
    2271           0 :     { return find_first_not_of(s, pos, traits_type::length(s)); }
    2272             : 
    2273             :     size_type find_first_not_of(value_type c, size_type pos = 0) const
    2274             :     { return find_first_not_of(&c, pos, 1); }
    2275             : 
    2276             :     size_type find_last_not_of(const flex_string& str,
    2277             :         size_type pos = npos) const
    2278             :     { return find_last_not_of(str.c_str(), pos, str.length()); }
    2279             : 
    2280           0 :     size_type find_last_not_of(const value_type* s, size_type pos,
    2281             :         size_type n) const
    2282             :     {
    2283           0 :         if (!empty())
    2284             :         {
    2285           0 :             pos = Min(pos, size() - 1);
    2286           0 :             const_iterator i(begin() + pos);
    2287           0 :             for (;; --i)
    2288             :             {
    2289           0 :                 if (traits_type::find(s, n, *i) == 0)
    2290             :                 {
    2291           0 :                     return i - begin();
    2292             :                 }
    2293           0 :                 if (i == begin()) break;
    2294             :             }
    2295             :         }
    2296             :         return npos;
    2297             :     }
    2298             : 
    2299           0 :     size_type find_last_not_of(const value_type* s,
    2300             :         size_type pos = npos) const
    2301           0 :     { return find_last_not_of(s, pos, traits_type::length(s)); }
    2302             : 
    2303           0 :     size_type find_last_not_of (value_type c, size_type pos = npos) const
    2304           0 :     { return find_last_not_of(&c, pos, 1); }
    2305             : 
    2306           0 :     flex_string substr(size_type pos = 0, size_type n = npos) const
    2307             :     {
    2308           0 :         Enforce(pos <= size(), (std::out_of_range*)0, "");
    2309           0 :         return flex_string(data() + pos, Min(n, size() - pos));
    2310             :     }
    2311             : 
    2312           0 :     std::ptrdiff_t compare(const flex_string& str) const
    2313             :     {
    2314             :         // FIX due to Goncalo N M de Carvalho July 18, 2005
    2315           0 :         return compare(0, size(), str);
    2316             :     }
    2317             : 
    2318           0 :     std::ptrdiff_t compare(size_type pos1, size_type n1,
    2319             :         const flex_string& str) const
    2320           0 :     { return compare(pos1, n1, str.data(), str.size()); }
    2321             : 
    2322             :     // FIX to compare: added the TC
    2323             :     // (http://www.comeaucomputing.com/iso/lwg-defects.html number 5)
    2324             :     // Thanks to Caleb Epstein for the fix
    2325             :     std::ptrdiff_t compare(size_type pos1, size_type n1,
    2326             :         const value_type* s) const
    2327             :     {
    2328             :         return compare(pos1, n1, s, traits_type::length(s));
    2329             :     }
    2330             : 
    2331           0 :     std::ptrdiff_t compare(size_type pos1, size_type n1,
    2332             :         const value_type* s, size_type n2) const
    2333             :     {
    2334           0 :         Enforce(pos1 <= size(), (std::out_of_range*)0, "");
    2335           0 :         Procust(n1, size() - pos1);
    2336           0 :         const int r = traits_type::compare(pos1 + data(), s, Min(n1, n2));
    2337           0 :         return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
    2338             :     }
    2339             : 
    2340             :     std::ptrdiff_t compare(size_type pos1, size_type n1,
    2341             :         const flex_string& str,
    2342             :         size_type pos2, size_type n2) const
    2343             :     {
    2344             :         Enforce(pos2 <= str.size(), (std::out_of_range*)0, "");
    2345             :         return compare(pos1, n1, str.data() + pos2, Min(n2, str.size() - pos2));
    2346             :     }
    2347             : 
    2348           0 :     std::ptrdiff_t compare(const value_type* s) const
    2349             :     {
    2350             :         // Could forward to compare(0, size(), s, traits_type::length(s))
    2351             :         // but that does two extra checks
    2352           0 :         const size_type n1(size()), n2(traits_type::length(s));
    2353           0 :         const int r = traits_type::compare(data(), s, Min(n1, n2));
    2354           0 :         return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
    2355             :     }
    2356             : };
    2357             : 
    2358             : // non-member functions
    2359             : template <typename E, class T, class A, class S>
    2360           0 : flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
    2361             :     const flex_string<E, T, A, S>& rhs)
    2362             : {
    2363           0 :     flex_string<E, T, A, S> result;
    2364           0 :     result.reserve(lhs.size() + rhs.size());
    2365           0 :     result.append(lhs).append(rhs);
    2366           0 :     return result;
    2367             : }
    2368             : 
    2369             : template <typename E, class T, class A, class S>
    2370             : flex_string<E, T, A, S> operator+(const typename flex_string<E, T, A, S>::value_type* lhs,
    2371             :     const flex_string<E, T, A, S>& rhs)
    2372             : {
    2373             :     flex_string<E, T, A, S> result;
    2374             :     const typename flex_string<E, T, A, S>::size_type len =
    2375             :         flex_string<E, T, A, S>::traits_type::length(lhs);
    2376             :     result.reserve(len + rhs.size());
    2377             :     result.append(lhs, len).append(rhs);
    2378             :     return result;
    2379             : }
    2380             : 
    2381             : template <typename E, class T, class A, class S>
    2382             : flex_string<E, T, A, S> operator+(
    2383             :     typename flex_string<E, T, A, S>::value_type lhs,
    2384             :     const flex_string<E, T, A, S>& rhs)
    2385             : {
    2386             :     flex_string<E, T, A, S> result;
    2387             :     result.reserve(1 + rhs.size());
    2388             :     result.push_back(lhs);
    2389             :     result.append(rhs);
    2390             :     return result;
    2391             : }
    2392             : 
    2393             : template <typename E, class T, class A, class S>
    2394           0 : flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
    2395             :     const typename flex_string<E, T, A, S>::value_type* rhs)
    2396             : {
    2397             :     typedef typename flex_string<E, T, A, S>::size_type size_type;
    2398             :     typedef typename flex_string<E, T, A, S>::traits_type traits_type;
    2399             : 
    2400           0 :     flex_string<E, T, A, S> result;
    2401           0 :     const size_type len = traits_type::length(rhs);
    2402           0 :     result.reserve(lhs.size() + len);
    2403           0 :     result.append(lhs).append(rhs, len);
    2404           0 :     return result;
    2405             : }
    2406             : 
    2407             : template <typename E, class T, class A, class S>
    2408             : flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
    2409             :     typename flex_string<E, T, A, S>::value_type rhs)
    2410             : {
    2411             :     flex_string<E, T, A, S> result;
    2412             :     result.reserve(lhs.size() + 1);
    2413             :     result.append(lhs);
    2414             :     result.push_back(rhs);
    2415             :     return result;
    2416             : }
    2417             : 
    2418             : template <typename E, class T, class A, class S>
    2419           0 : inline bool operator==(const flex_string<E, T, A, S>& lhs,
    2420             :     const flex_string<E, T, A, S>& rhs)
    2421           0 : { return lhs.compare(rhs) == 0; }
    2422             : 
    2423             : template <typename E, class T, class A, class S>
    2424           0 : inline bool operator==(const typename flex_string<E, T, A, S>::value_type* lhs,
    2425             :     const flex_string<E, T, A, S>& rhs)
    2426           0 : { return rhs == lhs; }
    2427             : 
    2428             : template <typename E, class T, class A, class S>
    2429           0 : inline bool operator==(const flex_string<E, T, A, S>& lhs,
    2430             :     const typename flex_string<E, T, A, S>::value_type* rhs)
    2431           0 : { return lhs.compare(rhs) == 0; }
    2432             : 
    2433             : template <typename E, class T, class A, class S>
    2434           0 : inline bool operator!=(const flex_string<E, T, A, S>& lhs,
    2435             :     const flex_string<E, T, A, S>& rhs)
    2436           0 : { return !(lhs == rhs); }
    2437             : 
    2438             : template <typename E, class T, class A, class S>
    2439             : inline bool operator!=(const typename flex_string<E, T, A, S>::value_type* lhs,
    2440             :     const flex_string<E, T, A, S>& rhs)
    2441             : { return !(lhs == rhs); }
    2442             : 
    2443             : template <typename E, class T, class A, class S>
    2444           0 : inline bool operator!=(const flex_string<E, T, A, S>& lhs,
    2445             :     const typename flex_string<E, T, A, S>::value_type* rhs)
    2446           0 : { return !(lhs == rhs); }
    2447             : 
    2448             : template <typename E, class T, class A, class S>
    2449           0 : inline bool operator<(const flex_string<E, T, A, S>& lhs,
    2450             :     const flex_string<E, T, A, S>& rhs)
    2451           0 : { return lhs.compare(rhs) < 0; }
    2452             : 
    2453             : template <typename E, class T, class A, class S>
    2454             : inline bool operator<(const flex_string<E, T, A, S>& lhs,
    2455             :     const typename flex_string<E, T, A, S>::value_type* rhs)
    2456             : { return lhs.compare(rhs) < 0; }
    2457             : 
    2458             : template <typename E, class T, class A, class S>
    2459             : inline bool operator<(const typename flex_string<E, T, A, S>::value_type* lhs,
    2460             :     const flex_string<E, T, A, S>& rhs)
    2461             : { return rhs.compare(lhs) > 0; }
    2462             : 
    2463             : template <typename E, class T, class A, class S>
    2464             : inline bool operator>(const flex_string<E, T, A, S>& lhs,
    2465             :     const flex_string<E, T, A, S>& rhs)
    2466             : { return rhs < lhs; }
    2467             : 
    2468             : template <typename E, class T, class A, class S>
    2469             : inline bool operator>(const flex_string<E, T, A, S>& lhs,
    2470             :     const typename flex_string<E, T, A, S>::value_type* rhs)
    2471             : { return rhs < lhs; }
    2472             : 
    2473             : template <typename E, class T, class A, class S>
    2474             : bool operator>(const typename flex_string<E, T, A, S>::value_type* lhs,
    2475             :     const flex_string<E, T, A, S>& rhs)
    2476             : { return rhs < lhs; }
    2477             : 
    2478             : template <typename E, class T, class A, class S>
    2479             : inline bool operator<=(const flex_string<E, T, A, S>& lhs,
    2480             :     const flex_string<E, T, A, S>& rhs)
    2481             : { return !(rhs < lhs); }
    2482             : 
    2483             : template <typename E, class T, class A, class S>
    2484             : inline bool operator<=(const flex_string<E, T, A, S>& lhs,
    2485             :     const typename flex_string<E, T, A, S>::value_type* rhs)
    2486             : { return !(rhs < lhs); }
    2487             : 
    2488             : template <typename E, class T, class A, class S>
    2489             : bool operator<=(const typename flex_string<E, T, A, S>::value_type* lhs,
    2490             :     const flex_string<E, T, A, S>& rhs)
    2491             : { return !(rhs < lhs); }
    2492             : 
    2493             : template <typename E, class T, class A, class S>
    2494             : bool operator>=(const flex_string<E, T, A, S>& lhs,
    2495             :     const flex_string<E, T, A, S>& rhs)
    2496             : { return !(lhs < rhs); }
    2497             : 
    2498             : template <typename E, class T, class A, class S>
    2499             : bool operator>=(const flex_string<E, T, A, S>& lhs,
    2500             :     const typename flex_string<E, T, A, S>::value_type* rhs)
    2501             : { return !(lhs < rhs); }
    2502             : 
    2503             : template <typename E, class T, class A, class S>
    2504             : inline bool operator>=(const typename flex_string<E, T, A, S>::value_type* lhs,
    2505             :     const flex_string<E, T, A, S>& rhs)
    2506             : { return !(lhs < rhs); }
    2507             : 
    2508             : template <typename E, class T, class A, class S>
    2509             : void swap(flex_string<E, T, A, S>& lhs, flex_string<E, T, A, S>& rhs)
    2510             : {
    2511             :     // subclause 21.3.7.8:
    2512             :     lhs.swap(rhs);
    2513             : }
    2514             : 
    2515             : template <typename E, class T, class A, class S>
    2516             : inline std::basic_istream<typename flex_string<E, T, A, S>::value_type,
    2517             :     typename flex_string<E, T, A, S>::traits_type>&
    2518             : operator>>(
    2519             :     std::basic_istream<typename flex_string<E, T, A, S>::value_type,
    2520             :     typename flex_string<E, T, A, S>::traits_type>& is,
    2521             :     flex_string<E, T, A, S>& str);
    2522             : 
    2523             : template <typename E, class T, class A, class S>
    2524             : std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
    2525             :     typename flex_string<E, T, A, S>::traits_type>&
    2526           0 : operator<<(
    2527             :     std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
    2528             :     typename flex_string<E, T, A, S>::traits_type>& os,
    2529             :     const flex_string<E, T, A, S>& str)
    2530           0 : { return os << str.c_str(); }
    2531             : 
    2532             : template <typename E1, class T, class A, class S>
    2533             : const typename flex_string<E1, T, A, S>::size_type
    2534             : flex_string<E1, T, A, S>::npos = (typename flex_string<E1, T, A, S>::size_type)(-1);
    2535             : 
    2536             : ///////////////////////////////////////////////////////////////////////////////
    2537             : }   // namespace util
    2538             : }   // namespace wave
    2539             : }   // namespace boost
    2540             : 
    2541             : #if BOOST_WAVE_SERIALIZATION != 0
    2542             : ///////////////////////////////////////////////////////////////////////////////
    2543             : namespace boost { namespace serialization {
    2544             : 
    2545             : #if !defined(BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK)
    2546             : 
    2547             : // FIXME: This doesn't work because of the missing flex_string::operator>>()
    2548             : template <typename E, class T, class A, class S>
    2549             : struct implementation_level<boost::wave::util::flex_string<E, T, A, S> >
    2550             : {
    2551             :     typedef mpl::integral_c_tag tag;
    2552             :     typedef mpl::int_<boost::serialization::primitive_type> type;
    2553             :     BOOST_STATIC_CONSTANT(
    2554             :         int,
    2555             :         value = implementation_level::type::value
    2556             :     );
    2557             : };
    2558             : 
    2559             : #else
    2560             : 
    2561             : //  We serialize flex_strings as vectors of char's for now
    2562             : template<class Archive, typename E, class T, class A, class S>
    2563             : inline void save(Archive & ar,
    2564             :     boost::wave::util::flex_string<E, T, A, S> const &t,
    2565             :     const unsigned int file_version)
    2566             : {
    2567             :     boost::serialization::stl::save_collection<
    2568             :         Archive, wave::util::flex_string<E, T, A, S> >(ar, t);
    2569             : }
    2570             : 
    2571             : template<class Archive, typename E, class T, class A, class S>
    2572             : inline void load(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
    2573             :     const unsigned int file_version)
    2574             : {
    2575             :     boost::serialization::stl::load_collection<
    2576             :         Archive, boost::wave::util::flex_string<E, T, A, S>,
    2577             :         boost::serialization::stl::archive_input_seq<
    2578             :             Archive, boost::wave::util::flex_string<E, T, A, S> >,
    2579             :         boost::serialization::stl::reserve_imp<
    2580             :             boost::wave::util::flex_string<E, T, A, S> >
    2581             :     >(ar, t);
    2582             : }
    2583             : 
    2584             : // split non-intrusive serialization function member into separate
    2585             : // non intrusive save/load member functions
    2586             : template<class Archive, typename E, class T, class A, class S>
    2587             : inline void serialize(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
    2588             :     const unsigned int file_version)
    2589             : {
    2590             :     boost::serialization::split_free(ar, t, file_version);
    2591             : }
    2592             : 
    2593             : #endif
    2594             : 
    2595             : ///////////////////////////////////////////////////////////////////////////////
    2596             : }} // boost::serialization
    2597             : #endif
    2598             : 
    2599             : // the suffix header occurs after all of the code
    2600             : #ifdef BOOST_HAS_ABI_HEADERS
    2601             : #include BOOST_ABI_SUFFIX
    2602             : #endif
    2603             : 
    2604             : #endif // FLEX_STRING_INC_

Generated by: LCOV version 1.14