Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/wave/util/flex_string.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

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