File indexing completed on 2025-01-18 09:53:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifndef BOOST_FLEX_STRING_INC_
0039 #define BOOST_FLEX_STRING_INC_
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 #include <boost/config.hpp>
0087 #include <boost/assert.hpp>
0088 #include <boost/throw_exception.hpp>
0089
0090 #include <boost/core/allocator_access.hpp>
0091 #include <boost/iterator/reverse_iterator.hpp>
0092
0093 #include <boost/wave/wave_config.hpp>
0094 #if BOOST_WAVE_SERIALIZATION != 0
0095 #include <boost/serialization/serialization.hpp>
0096 #include <boost/serialization/split_free.hpp>
0097 #include <boost/serialization/collections_save_imp.hpp>
0098 #include <boost/serialization/collections_load_imp.hpp>
0099 #define BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK 1
0100 #endif
0101
0102 #include <memory>
0103 #include <new>
0104 #include <vector>
0105 #include <algorithm>
0106 #include <functional>
0107 #include <limits>
0108 #include <stdexcept>
0109 #include <ios>
0110
0111 #include <cstddef>
0112 #include <cstring>
0113 #include <cstdlib>
0114
0115
0116 #ifdef BOOST_HAS_ABI_HEADERS
0117 #include BOOST_ABI_PREFIX
0118 #endif
0119
0120
0121 namespace boost {
0122 namespace wave {
0123 namespace util {
0124
0125 namespace flex_string_details
0126 {
0127 template <class InIt, class OutIt>
0128 OutIt copy_n(InIt b,
0129 typename std::iterator_traits<InIt>::difference_type n, OutIt d)
0130 {
0131 for (; n != 0; --n, ++b, ++d)
0132 {
0133 *d = *b;
0134 }
0135 return d;
0136 }
0137
0138 template <class Pod, class T>
0139 inline void pod_fill(Pod* b, Pod* e, T c)
0140 {
0141 switch ((e - b) & 7)
0142 {
0143 case 0:
0144 while (b != e)
0145 {
0146 *b = c; ++b; BOOST_FALLTHROUGH;
0147 case 7: *b = c; ++b; BOOST_FALLTHROUGH;
0148 case 6: *b = c; ++b; BOOST_FALLTHROUGH;
0149 case 5: *b = c; ++b; BOOST_FALLTHROUGH;
0150 case 4: *b = c; ++b; BOOST_FALLTHROUGH;
0151 case 3: *b = c; ++b; BOOST_FALLTHROUGH;
0152 case 2: *b = c; ++b; BOOST_FALLTHROUGH;
0153 case 1: *b = c; ++b;
0154 }
0155 }
0156 }
0157
0158 template <class Pod>
0159 inline void pod_move(const Pod* b, const Pod* e, Pod* d)
0160 {
0161 using namespace std;
0162 memmove(d, b, (e - b) * sizeof(*b));
0163 }
0164
0165 template <class Pod>
0166 inline Pod* pod_copy(const Pod* b, const Pod* e, Pod* d)
0167 {
0168 const std::size_t s = e - b;
0169 using namespace std;
0170 memcpy(d, b, s * sizeof(*b));
0171 return d + s;
0172 }
0173
0174 template <typename T> struct get_unsigned
0175 {
0176 typedef T result;
0177 };
0178
0179 template <> struct get_unsigned<char>
0180 {
0181 typedef unsigned char result;
0182 };
0183
0184 template <> struct get_unsigned<signed char>
0185 {
0186 typedef unsigned char result;
0187 };
0188
0189 template <> struct get_unsigned<short int>
0190 {
0191 typedef unsigned short int result;
0192 };
0193
0194 template <> struct get_unsigned<int>
0195 {
0196 typedef unsigned int result;
0197 };
0198
0199 template <> struct get_unsigned<long int>
0200 {
0201 typedef unsigned long int result;
0202 };
0203
0204 enum Shallow {};
0205 }
0206
0207 template <class T> class mallocator
0208 {
0209 public:
0210 typedef T value_type;
0211 typedef value_type* pointer;
0212 typedef const value_type* const_pointer;
0213 typedef value_type& reference;
0214 typedef const value_type& const_reference;
0215 typedef std::size_t size_type;
0216
0217
0218 typedef int difference_type;
0219
0220 template <class U>
0221 struct rebind { typedef mallocator<U> other; };
0222
0223 mallocator() {}
0224 mallocator(const mallocator&) {}
0225
0226
0227 ~mallocator() {}
0228
0229 pointer address(reference x) const { return &x; }
0230 const_pointer address(const_reference x) const
0231 {
0232 return x;
0233 }
0234
0235 pointer allocate(size_type n, const_pointer = 0)
0236 {
0237 using namespace std;
0238 void* p = malloc(n * sizeof(T));
0239 if (!p) boost::throw_exception(std::bad_alloc());
0240 return static_cast<pointer>(p);
0241 }
0242
0243 void deallocate(pointer p, size_type)
0244 {
0245 using namespace std;
0246 free(p);
0247 }
0248
0249 size_type max_size() const
0250 {
0251 return static_cast<size_type>(-1) / sizeof(T);
0252 }
0253
0254 void construct(pointer p, const value_type& x)
0255 {
0256 new(p) value_type(x);
0257 }
0258
0259 void destroy(pointer p)
0260 {
0261 p->~value_type();
0262 }
0263
0264 private:
0265 void operator=(const mallocator&);
0266 };
0267
0268 template<> class mallocator<void>
0269 {
0270 typedef void value_type;
0271 typedef void* pointer;
0272 typedef const void* const_pointer;
0273
0274 template <class U>
0275 struct rebind { typedef mallocator<U> other; };
0276 };
0277
0278 template <class T>
0279 inline bool operator==(const mallocator<T>&,
0280 const mallocator<T>&) {
0281 return true;
0282 }
0283
0284 template <class T>
0285 inline bool operator!=(const mallocator<T>&,
0286 const mallocator<T>&) {
0287 return false;
0288 }
0289
0290 #if defined(BOOST_GCC) && BOOST_GCC >= 40700
0291
0292
0293
0294
0295 #define BOOST_WAVE_COMPILE_TIME_ASSERT(x) if (!(x)) __builtin_unreachable()
0296 #else
0297 #define BOOST_WAVE_COMPILE_TIME_ASSERT(x)
0298 #endif
0299
0300
0301
0302
0303
0304
0305 template <typename E, class A = std::allocator<E> >
0306 class SimpleStringStorage
0307 {
0308
0309 public:
0310 struct Data
0311 {
0312 Data() : pEnd_(buffer_), pEndOfMem_(buffer_) { buffer_[0] = E(0); }
0313
0314 E* pEnd_;
0315 E* pEndOfMem_;
0316 E buffer_[1];
0317 };
0318 static const Data emptyString_;
0319
0320 typedef typename boost::allocator_size_type<A>::type size_type;
0321
0322 private:
0323 Data* pData_;
0324
0325 void Init(size_type size, size_type capacity)
0326 {
0327 BOOST_ASSERT(size <= capacity);
0328 if (capacity == 0)
0329 {
0330 pData_ = const_cast<Data*>(&emptyString_);
0331 }
0332 else
0333 {
0334
0335
0336
0337
0338 pData_ = static_cast<Data*>(
0339 malloc(sizeof(Data) + capacity * sizeof(E)));
0340 if (!pData_) boost::throw_exception(std::bad_alloc());
0341 pData_->pEnd_ = pData_->buffer_ + size;
0342 pData_->pEndOfMem_ = pData_->buffer_ + capacity;
0343 }
0344 }
0345
0346 private:
0347
0348 SimpleStringStorage()
0349 { }
0350
0351 public:
0352 typedef E value_type;
0353 typedef E* iterator;
0354 typedef const E* const_iterator;
0355 typedef A allocator_type;
0356
0357 SimpleStringStorage(const SimpleStringStorage& rhs)
0358 {
0359 const size_type sz = rhs.size();
0360 Init(sz, sz);
0361 if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
0362 }
0363
0364 SimpleStringStorage(const SimpleStringStorage& s,
0365 flex_string_details::Shallow)
0366 : pData_(s.pData_)
0367 {
0368 }
0369
0370 SimpleStringStorage(const A&)
0371 { pData_ = const_cast<Data*>(&emptyString_); }
0372
0373 SimpleStringStorage(const E* s, size_type len, const A&)
0374 {
0375 Init(len, len);
0376 flex_string_details::pod_copy(s, s + len, begin());
0377 }
0378
0379 SimpleStringStorage(size_type len, E c, const A&)
0380 {
0381 Init(len, len);
0382 flex_string_details::pod_fill(begin(), end(), c);
0383 }
0384
0385 SimpleStringStorage& operator=(const SimpleStringStorage& rhs)
0386 {
0387 const size_type sz = rhs.size();
0388 reserve(sz);
0389 flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
0390 pData_->pEnd_ = &*begin() + sz;
0391 return *this;
0392 }
0393
0394 ~SimpleStringStorage()
0395 {
0396 BOOST_ASSERT(begin() <= end());
0397 if (capacity() > 0)
0398 {
0399 BOOST_WAVE_COMPILE_TIME_ASSERT(pData_ != &emptyString_);
0400 free(pData_);
0401 }
0402 }
0403
0404 iterator begin()
0405 { return pData_->buffer_; }
0406
0407 const_iterator begin() const
0408 { return pData_->buffer_; }
0409
0410 iterator end()
0411 { return pData_->pEnd_; }
0412
0413 const_iterator end() const
0414 { return pData_->pEnd_; }
0415
0416 size_type size() const
0417 { return pData_->pEnd_ - pData_->buffer_; }
0418
0419 size_type max_size() const
0420 { return std::size_t(-1) / sizeof(E) - sizeof(Data) - 1; }
0421
0422 size_type capacity() const
0423 { return pData_->pEndOfMem_ - pData_->buffer_; }
0424
0425 void reserve(size_type res_arg)
0426 {
0427 size_type cap = capacity();
0428 if (res_arg <= cap)
0429 {
0430
0431 return;
0432 }
0433
0434 if (cap == 0)
0435 {
0436 Init(0, res_arg);
0437 }
0438 else
0439 {
0440 const size_type sz = size();
0441
0442 void* p = realloc(pData_,
0443 sizeof(Data) + res_arg * sizeof(E));
0444 if (!p) boost::throw_exception(std::bad_alloc());
0445
0446 if (p != pData_)
0447 {
0448 pData_ = static_cast<Data*>(p);
0449 pData_->pEnd_ = pData_->buffer_ + sz;
0450 }
0451 pData_->pEndOfMem_ = pData_->buffer_ + res_arg;
0452 }
0453 }
0454
0455 void append(const E* s, size_type sz)
0456 {
0457 const size_type neededCapacity = size() + sz;
0458
0459 if (capacity() < neededCapacity)
0460 {
0461 const iterator b = begin();
0462 static std::less_equal<const E*> le;
0463 if (le(b, s) && le(s, end()))
0464 {
0465
0466 const size_type offset = s - b;
0467 reserve(neededCapacity);
0468 s = begin() + offset;
0469 }
0470 else
0471 {
0472 reserve(neededCapacity);
0473 }
0474 }
0475 flex_string_details::pod_copy(s, s + sz, end());
0476 pData_->pEnd_ += sz;
0477 }
0478
0479 template <class InputIterator>
0480 void append(InputIterator b, InputIterator e)
0481 {
0482
0483 for (; b != e; ++b)
0484 {
0485 *this += *b;
0486 }
0487 }
0488
0489 void resize(size_type newSize, E fill)
0490 {
0491 const int delta = int(newSize - size());
0492 if (delta == 0) return;
0493
0494 if (delta > 0)
0495 {
0496 if (newSize > capacity())
0497 {
0498 reserve(newSize);
0499 }
0500 E* e = &*end();
0501 flex_string_details::pod_fill(e, e + delta, fill);
0502 }
0503 pData_->pEnd_ = pData_->buffer_ + newSize;
0504 }
0505
0506 void swap(SimpleStringStorage& rhs)
0507 {
0508 std::swap(pData_, rhs.pData_);
0509 }
0510
0511 const E* c_str() const
0512 {
0513 if (capacity() > 0) *pData_->pEnd_ = E();
0514 return pData_->buffer_;
0515 }
0516
0517 const E* data() const
0518 { return pData_->buffer_; }
0519
0520 A get_allocator() const
0521 { return A(); }
0522 };
0523
0524 template <typename E, class A>
0525 const typename SimpleStringStorage<E, A>::Data
0526 SimpleStringStorage<E, A>::emptyString_ =
0527 typename SimpleStringStorage<E, A>::Data();
0528
0529
0530
0531
0532
0533
0534
0535 template <typename E, class A = std::allocator<E> >
0536 class AllocatorStringStorage : public A
0537 {
0538 typedef typename boost::allocator_size_type<A>::type size_type;
0539 typedef typename SimpleStringStorage<E, A>::Data Data;
0540
0541 void* Alloc(size_type sz, const void* p = 0)
0542 {
0543 return boost::allocator_allocate(static_cast<A&>(*this), 1 + (sz - 1) / sizeof(E),
0544 static_cast<const char*>(p));
0545 }
0546
0547 void Free(void* p, size_type sz)
0548 {
0549 boost::allocator_deallocate(static_cast<A&>(*this), static_cast<E*>(p), sz);
0550 }
0551
0552 Data* pData_;
0553
0554 void Init(size_type size, size_type cap)
0555 {
0556 BOOST_ASSERT(size <= cap);
0557
0558 if (cap == 0)
0559 {
0560 pData_ = const_cast<Data*>(
0561 &SimpleStringStorage<E, A>::emptyString_);
0562 }
0563 else
0564 {
0565 pData_ = static_cast<Data*>(Alloc(
0566 cap * sizeof(E) + sizeof(Data)));
0567 pData_->pEnd_ = pData_->buffer_ + size;
0568 pData_->pEndOfMem_ = pData_->buffer_ + cap;
0569 }
0570 }
0571
0572 public:
0573 typedef E value_type;
0574 typedef E* iterator;
0575 typedef const E* const_iterator;
0576 typedef A allocator_type;
0577
0578 AllocatorStringStorage()
0579 : A(), pData_(0)
0580 {
0581 }
0582
0583 AllocatorStringStorage(const AllocatorStringStorage& rhs)
0584 : A(rhs.get_allocator())
0585 {
0586 const size_type sz = rhs.size();
0587 Init(sz, sz);
0588 if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
0589 }
0590
0591 AllocatorStringStorage(const AllocatorStringStorage& s,
0592 flex_string_details::Shallow)
0593 : A(s.get_allocator())
0594 {
0595 pData_ = s.pData_;
0596 }
0597
0598 AllocatorStringStorage(const A& a) : A(a)
0599 {
0600 pData_ = const_cast<Data*>(
0601 &SimpleStringStorage<E, A>::emptyString_);
0602 }
0603
0604 AllocatorStringStorage(const E* s, size_type len, const A& a)
0605 : A(a)
0606 {
0607 Init(len, len);
0608 flex_string_details::pod_copy(s, s + len, begin());
0609 }
0610
0611 AllocatorStringStorage(size_type len, E c, const A& a)
0612 : A(a)
0613 {
0614 Init(len, len);
0615 flex_string_details::pod_fill(&*begin(), &*end(), c);
0616 }
0617
0618 AllocatorStringStorage& operator=(const AllocatorStringStorage& rhs)
0619 {
0620 const size_type sz = rhs.size();
0621 reserve(sz);
0622 flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
0623 pData_->pEnd_ = &*begin() + rhs.size();
0624 return *this;
0625 }
0626
0627 ~AllocatorStringStorage()
0628 {
0629 if (capacity())
0630 {
0631 BOOST_WAVE_COMPILE_TIME_ASSERT(pData_ != (&SimpleStringStorage<E, A>::emptyString_));
0632 Free(pData_,
0633 sizeof(Data) + capacity() * sizeof(E));
0634 }
0635 }
0636
0637 iterator begin()
0638 { return pData_->buffer_; }
0639
0640 const_iterator begin() const
0641 { return pData_->buffer_; }
0642
0643 iterator end()
0644 { return pData_->pEnd_; }
0645
0646 const_iterator end() const
0647 { return pData_->pEnd_; }
0648
0649 size_type size() const
0650 { return size_type(end() - begin()); }
0651
0652 size_type max_size() const
0653 { return boost::allocator_max_size(static_cast<const A&>(*this)); }
0654
0655 size_type capacity() const
0656 { return size_type(pData_->pEndOfMem_ - pData_->buffer_); }
0657
0658 void resize(size_type n, E c)
0659 {
0660 reserve(n);
0661 iterator newEnd = begin() + n;
0662 iterator oldEnd = end();
0663 if (newEnd > oldEnd)
0664 {
0665
0666 flex_string_details::pod_fill(oldEnd, newEnd, c);
0667 }
0668 if (capacity()) pData_->pEnd_ = newEnd;
0669 }
0670
0671 void reserve(size_type res_arg)
0672 {
0673 if (res_arg <= capacity())
0674 {
0675
0676 return;
0677 }
0678
0679 A& myAlloc = *this;
0680 AllocatorStringStorage newStr(myAlloc);
0681 newStr.Init(size(), res_arg);
0682
0683 flex_string_details::pod_copy(begin(), end(), newStr.begin());
0684
0685 swap(newStr);
0686 }
0687
0688 template <class ForwardIterator>
0689 void append(ForwardIterator b, ForwardIterator e)
0690 {
0691 const size_type
0692 sz = std::distance(b, e),
0693 neededCapacity = size() + sz;
0694
0695 if (capacity() < neededCapacity)
0696 {
0697
0698
0699 reserve(neededCapacity);
0700 }
0701 std::copy(b, e, end());
0702 pData_->pEnd_ += sz;
0703 }
0704
0705 void swap(AllocatorStringStorage& rhs)
0706 {
0707
0708
0709 std::swap(pData_, rhs.pData_);
0710 }
0711
0712 const E* c_str() const
0713 {
0714 if (capacity() > 0)
0715 {
0716 *pData_->pEnd_ = E();
0717 }
0718 return &*begin();
0719 }
0720
0721 const E* data() const
0722 { return &*begin(); }
0723
0724 A get_allocator() const
0725 { return *this; }
0726 };
0727
0728
0729
0730
0731
0732
0733
0734 template <typename E, class A = std::allocator<E> >
0735 class VectorStringStorage : protected std::vector<E, A>
0736 {
0737 typedef std::vector<E, A> base;
0738
0739 public:
0740 typedef E value_type;
0741 typedef typename base::iterator iterator;
0742 typedef typename base::const_iterator const_iterator;
0743 typedef A allocator_type;
0744 typedef typename boost::allocator_size_type<A>::type size_type;
0745
0746 VectorStringStorage(const VectorStringStorage& s) : base(s)
0747 { }
0748
0749 VectorStringStorage(const A& a) : base(1, E(), a)
0750 { }
0751
0752 VectorStringStorage(const E* s, size_type len, const A& a)
0753 : base(a)
0754 {
0755 base::reserve(len + 1);
0756 base::insert(base::end(), s, s + len);
0757
0758 base::insert(base::end(), E());
0759 }
0760
0761 VectorStringStorage(size_type len, E c, const A& a)
0762 : base(len + 1, c, a)
0763 {
0764
0765 base::back() = E();
0766 }
0767
0768 VectorStringStorage& operator=(const VectorStringStorage& rhs)
0769 {
0770 base& v = *this;
0771 v = rhs;
0772 return *this;
0773 }
0774
0775 iterator begin()
0776 { return base::begin(); }
0777
0778 const_iterator begin() const
0779 { return base::begin(); }
0780
0781 iterator end()
0782 { return base::end() - 1; }
0783
0784 const_iterator end() const
0785 { return base::end() - 1; }
0786
0787 size_type size() const
0788 { return base::size() - 1; }
0789
0790 size_type max_size() const
0791 { return base::max_size() - 1; }
0792
0793 size_type capacity() const
0794 { return base::capacity() - 1; }
0795
0796 void reserve(size_type res_arg)
0797 {
0798 BOOST_ASSERT(res_arg < max_size());
0799 base::reserve(res_arg + 1);
0800 }
0801
0802 void append(const E* s, size_type sz)
0803 {
0804
0805 static std::less_equal<const E*> le;
0806 if (!base::empty())
0807 {
0808 const E* start = &base::front();
0809 if (le(start, s) && le(s, start + size()))
0810 {
0811
0812 const size_type offset = s - start;
0813 reserve(size() + sz);
0814 s = &base::front() + offset;
0815 }
0816 }
0817 base::insert(end(), s, s + sz);
0818 }
0819
0820 template <class InputIterator>
0821 void append(InputIterator b, InputIterator e)
0822 {
0823 base::insert(end(), b, e);
0824 }
0825
0826 void resize(size_type n, E c)
0827 {
0828 base::reserve(n + 1);
0829 base::back() = c;
0830 base::resize(n + 1, c);
0831 base::back() = E();
0832 }
0833
0834 void swap(VectorStringStorage& rhs)
0835 { base::swap(rhs); }
0836
0837 const E* c_str() const
0838 { return &*begin(); }
0839
0840 const E* data() const
0841 { return &*begin(); }
0842
0843 A get_allocator() const
0844 { return base::get_allocator(); }
0845 };
0846
0847
0848
0849
0850
0851
0852 template <class Storage, unsigned int threshold,
0853 typename Align = typename Storage::value_type*>
0854 class SmallStringOpt
0855 {
0856 public:
0857 typedef typename Storage::value_type value_type;
0858 typedef value_type* iterator;
0859 typedef const value_type* const_iterator;
0860 typedef typename Storage::allocator_type allocator_type;
0861 typedef typename boost::allocator_size_type<allocator_type>::type size_type;
0862
0863 private:
0864 enum { temp1 = threshold * sizeof(value_type) > sizeof(Storage)
0865 ? threshold * sizeof(value_type)
0866 : sizeof(Storage) };
0867
0868 enum { temp2 = temp1 > sizeof(Align) ? temp1 : sizeof(Align) };
0869
0870 public:
0871 enum { maxSmallString =
0872 (temp2 + sizeof(value_type) - 1) / sizeof(value_type) };
0873
0874 private:
0875 enum { magic = maxSmallString + 1 };
0876
0877 union
0878 {
0879 mutable value_type buf_[maxSmallString + 1];
0880 Align align_;
0881 };
0882
0883 Storage& GetStorage()
0884 {
0885 BOOST_ASSERT(buf_[maxSmallString] == magic);
0886 Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
0887 return *p;
0888 }
0889
0890 const Storage& GetStorage() const
0891 {
0892 BOOST_ASSERT(buf_[maxSmallString] == magic);
0893 const Storage *p = reinterpret_cast<const Storage*>(&buf_[0]);
0894 return *p;
0895 }
0896
0897 bool Small() const
0898 {
0899 return buf_[maxSmallString] != magic;
0900 }
0901
0902 public:
0903 SmallStringOpt(const SmallStringOpt& s)
0904 {
0905 if (s.Small())
0906 {
0907 flex_string_details::pod_copy(
0908 s.buf_,
0909 s.buf_ + s.size(),
0910 buf_);
0911 }
0912 else
0913 {
0914 new(buf_) Storage(s.GetStorage());
0915 }
0916 buf_[maxSmallString] = s.buf_[maxSmallString];
0917 }
0918
0919 SmallStringOpt(const allocator_type&)
0920 {
0921 buf_[maxSmallString] = maxSmallString;
0922 }
0923
0924 SmallStringOpt(const value_type* s, size_type len, const allocator_type& a)
0925 {
0926 if (len <= maxSmallString)
0927 {
0928 flex_string_details::pod_copy(s, s + len, buf_);
0929 buf_[maxSmallString] = value_type(maxSmallString - len);
0930 }
0931 else
0932 {
0933 new(buf_) Storage(s, len, a);
0934 buf_[maxSmallString] = magic;
0935 }
0936 }
0937
0938 SmallStringOpt(size_type len, value_type c, const allocator_type& a)
0939 {
0940 if (len <= maxSmallString)
0941 {
0942 flex_string_details::pod_fill(buf_, buf_ + len, c);
0943 buf_[maxSmallString] = value_type(maxSmallString - len);
0944 }
0945 else
0946 {
0947 new(buf_) Storage(len, c, a);
0948 buf_[maxSmallString] = magic;
0949 }
0950 }
0951
0952 SmallStringOpt& operator=(const SmallStringOpt& rhs)
0953 {
0954 reserve(rhs.size());
0955 resize(0, 0);
0956 append(rhs.data(), rhs.size());
0957 return *this;
0958 }
0959
0960 ~SmallStringOpt()
0961 {
0962 if (!Small()) GetStorage().~Storage();
0963 }
0964
0965 iterator begin()
0966 {
0967 if (Small()) return buf_;
0968 return &*GetStorage().begin();
0969 }
0970
0971 const_iterator begin() const
0972 {
0973 if (Small()) return buf_;
0974 return &*GetStorage().begin();
0975 }
0976
0977 iterator end()
0978 {
0979 if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
0980 return &*GetStorage().end();
0981 }
0982
0983 const_iterator end() const
0984 {
0985 if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
0986 return &*GetStorage().end();
0987 }
0988
0989 size_type size() const
0990 {
0991 BOOST_ASSERT(!Small() || maxSmallString >= buf_[maxSmallString]);
0992 return Small()
0993 ? maxSmallString - buf_[maxSmallString]
0994 : GetStorage().size();
0995 }
0996
0997 size_type max_size() const
0998 { return boost::allocator_max_size(get_allocator()); }
0999
1000 size_type capacity() const
1001 { return Small() ? maxSmallString : GetStorage().capacity(); }
1002
1003 void reserve(size_type res_arg)
1004 {
1005 if (Small())
1006 {
1007 if (res_arg <= maxSmallString) return;
1008 SmallStringOpt temp(*this);
1009 this->~SmallStringOpt();
1010 new(buf_) Storage(temp.data(), temp.size(),
1011 temp.get_allocator());
1012 buf_[maxSmallString] = magic;
1013 GetStorage().reserve(res_arg);
1014 }
1015 else
1016 {
1017 GetStorage().reserve(res_arg);
1018 }
1019 BOOST_ASSERT(capacity() >= res_arg);
1020 }
1021
1022 void append(const value_type* s, size_type sz)
1023 {
1024 if (!Small())
1025 {
1026 GetStorage().append(s, sz);
1027 }
1028 else
1029 {
1030
1031 const size_type neededCapacity =
1032 maxSmallString - buf_[maxSmallString] + sz;
1033
1034 if (maxSmallString < neededCapacity)
1035 {
1036
1037 allocator_type alloc;
1038 Storage temp(alloc);
1039 temp.reserve(neededCapacity);
1040 temp.append(buf_, maxSmallString - buf_[maxSmallString]);
1041 temp.append(s, sz);
1042 buf_[maxSmallString] = magic;
1043 new(buf_) Storage(temp.get_allocator());
1044 GetStorage().swap(temp);
1045 }
1046 else
1047 {
1048 flex_string_details::pod_move(s, s + sz,
1049 buf_ + maxSmallString - buf_[maxSmallString]);
1050 buf_[maxSmallString] -= value_type(sz);
1051 }
1052 }
1053 }
1054
1055 template <class InputIterator>
1056 void append(InputIterator b, InputIterator e)
1057 {
1058
1059 for (; b != e; ++b)
1060 {
1061 *this += *b;
1062 }
1063 }
1064
1065 void resize(size_type n, value_type c)
1066 {
1067 if (Small())
1068 {
1069 if (n > maxSmallString)
1070 {
1071
1072 SmallStringOpt temp(*this);
1073
1074 Storage newString(temp.data(), temp.size(),
1075 temp.get_allocator());
1076 newString.resize(n, c);
1077
1078
1079 this->~SmallStringOpt();
1080 new(&buf_[0]) Storage(temp.get_allocator());
1081 buf_[maxSmallString] = value_type(magic);
1082 GetStorage().swap(newString);
1083 }
1084 else
1085 {
1086
1087
1088 size_type toFill = n > size() ? n - size() : 0;
1089 flex_string_details::pod_fill(end(), end() + toFill, c);
1090 buf_[maxSmallString] = value_type(maxSmallString - n);
1091 }
1092 }
1093 else
1094 {
1095 if (n > maxSmallString)
1096 {
1097
1098 GetStorage().resize(n, c);
1099 }
1100 else
1101 {
1102
1103
1104 BOOST_ASSERT(capacity() > n);
1105 SmallStringOpt newObj(data(), n, get_allocator());
1106 newObj.swap(*this);
1107 }
1108 }
1109 }
1110
1111 void swap(SmallStringOpt& rhs)
1112 {
1113 if (Small())
1114 {
1115 if (rhs.Small())
1116 {
1117
1118 std::swap_ranges(buf_, buf_ + maxSmallString + 1,
1119 rhs.buf_);
1120 }
1121 else
1122 {
1123
1124
1125 SmallStringOpt temp(*this);
1126
1127 this->~SmallStringOpt();
1128
1129 new(buf_) Storage(0, value_type(), rhs.get_allocator());
1130 buf_[maxSmallString] = magic;
1131
1132 swap(rhs);
1133
1134 rhs.~SmallStringOpt();
1135
1136 new(&rhs) SmallStringOpt(temp);
1137 }
1138 }
1139 else
1140 {
1141 if (rhs.Small())
1142 {
1143
1144
1145 rhs.swap(*this);
1146 }
1147 else
1148 {
1149
1150 GetStorage().swap(rhs.GetStorage());
1151 }
1152 }
1153 }
1154
1155 const value_type* c_str() const
1156 {
1157 if (!Small()) return GetStorage().c_str();
1158 buf_[maxSmallString - buf_[maxSmallString]] = value_type();
1159 return buf_;
1160 }
1161
1162 const value_type* data() const
1163 { return Small() ? buf_ : GetStorage().data(); }
1164
1165 allocator_type get_allocator() const
1166 { return allocator_type(); }
1167 };
1168
1169
1170
1171
1172
1173
1174 template <
1175 typename Storage,
1176 typename Align = BOOST_DEDUCED_TYPENAME Storage::value_type*
1177 >
1178 class CowString
1179 {
1180 typedef typename Storage::value_type E;
1181 typedef typename flex_string_details::get_unsigned<E>::result RefCountType;
1182
1183 public:
1184 typedef E value_type;
1185 typedef typename Storage::iterator iterator;
1186 typedef typename Storage::const_iterator const_iterator;
1187 typedef typename Storage::allocator_type allocator_type;
1188 typedef typename boost::allocator_size_type<allocator_type>::type size_type;
1189 typedef typename Storage::value_type& reference;
1190
1191 private:
1192 union
1193 {
1194 mutable char buf_[sizeof(Storage)];
1195 Align align_;
1196 };
1197
1198 Storage& Data() const
1199 {
1200 Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
1201 return *p;
1202 }
1203
1204 RefCountType GetRefs() const
1205 {
1206 const Storage& d = Data();
1207 BOOST_ASSERT(d.size() > 0);
1208 BOOST_ASSERT(static_cast<RefCountType>(*d.begin()) != 0);
1209 return *d.begin();
1210 }
1211
1212 RefCountType& Refs()
1213 {
1214 Storage& d = Data();
1215 BOOST_ASSERT(d.size() > 0);
1216 return reinterpret_cast<RefCountType&>(*d.begin());
1217 }
1218
1219 void MakeUnique() const
1220 {
1221 BOOST_ASSERT(GetRefs() >= 1);
1222 if (GetRefs() == 1) return;
1223
1224 union
1225 {
1226 char buf_[sizeof(Storage)];
1227 Align align_;
1228 } temp;
1229
1230 --(*Data().begin());
1231
1232 Storage* p = reinterpret_cast<Storage*>(&temp.buf_[0]);
1233 new(buf_) Storage(
1234 *new(p) Storage(Data()),
1235 flex_string_details::Shallow());
1236 *Data().begin() = 1;
1237 }
1238
1239 public:
1240 CowString(const CowString& s)
1241 {
1242 if (s.GetRefs() == (std::numeric_limits<RefCountType>::max)())
1243 {
1244
1245 new(buf_) Storage(s.Data());
1246 Refs() = 1;
1247 }
1248 else
1249 {
1250 new(buf_) Storage(s.Data(), flex_string_details::Shallow());
1251 ++Refs();
1252 }
1253 BOOST_ASSERT(Data().size() > 0);
1254 }
1255
1256 CowString(const allocator_type& a)
1257 {
1258 new(buf_) Storage(1, 1, a);
1259 }
1260
1261 CowString(const E* s, size_type len, const allocator_type& a)
1262 {
1263
1264
1265
1266 new(buf_) Storage(a);
1267 Data().reserve(len + 1);
1268 Data().resize(1, 1);
1269 Data().append(s, s + len);
1270 }
1271
1272 CowString(size_type len, E c, const allocator_type& a)
1273 {
1274 new(buf_) Storage(len + 1, c, a);
1275 Refs() = 1;
1276 }
1277
1278 CowString& operator=(const CowString& rhs)
1279 {
1280
1281 if (--Refs() == 0)
1282 Data().~Storage();
1283 if (rhs.GetRefs() == (std::numeric_limits<RefCountType>::max)())
1284 {
1285
1286 new(buf_) Storage(rhs.Data());
1287 Refs() = 1;
1288 }
1289 else
1290 {
1291 new(buf_) Storage(rhs.Data(), flex_string_details::Shallow());
1292 ++Refs();
1293 }
1294 BOOST_ASSERT(Data().size() > 0);
1295 return *this;
1296 }
1297
1298 ~CowString()
1299 {
1300 BOOST_ASSERT(Data().size() > 0);
1301 if (--Refs() == 0)
1302 Data().~Storage();
1303 }
1304
1305 iterator begin()
1306 {
1307 BOOST_ASSERT(Data().size() > 0);
1308 MakeUnique();
1309 return Data().begin() + 1;
1310 }
1311
1312 const_iterator begin() const
1313 {
1314 BOOST_ASSERT(Data().size() > 0);
1315 return Data().begin() + 1;
1316 }
1317
1318 iterator end()
1319 {
1320 MakeUnique();
1321 return Data().end();
1322 }
1323
1324 const_iterator end() const
1325 {
1326 return Data().end();
1327 }
1328
1329 size_type size() const
1330 {
1331 BOOST_ASSERT(Data().size() > 0);
1332 return Data().size() - 1;
1333 }
1334
1335 size_type max_size() const
1336 {
1337 BOOST_ASSERT(Data().max_size() > 0);
1338 return Data().max_size() - 1;
1339 }
1340
1341 size_type capacity() const
1342 {
1343 BOOST_ASSERT(Data().capacity() > 0);
1344 return Data().capacity() - 1;
1345 }
1346
1347 void resize(size_type n, E c)
1348 {
1349 BOOST_ASSERT(Data().size() > 0);
1350 MakeUnique();
1351 Data().resize(n + 1, c);
1352 }
1353
1354 template <class FwdIterator>
1355 void append(FwdIterator b, FwdIterator e)
1356 {
1357 MakeUnique();
1358 Data().append(b, e);
1359 }
1360
1361 void reserve(size_type res_arg)
1362 {
1363 if (capacity() > res_arg) return;
1364 MakeUnique();
1365 Data().reserve(res_arg + 1);
1366 }
1367
1368 void swap(CowString& rhs)
1369 {
1370 Data().swap(rhs.Data());
1371 }
1372
1373 const E* c_str() const
1374 {
1375 BOOST_ASSERT(Data().size() > 0);
1376 return Data().c_str() + 1;
1377 }
1378
1379 const E* data() const
1380 {
1381 BOOST_ASSERT(Data().size() > 0);
1382 return Data().data() + 1;
1383 }
1384
1385 allocator_type get_allocator() const
1386 {
1387 return Data().get_allocator();
1388 }
1389 };
1390
1391
1392
1393
1394
1395
1396
1397 template <typename E,
1398 class T = std::char_traits<E>,
1399 class A = std::allocator<E>,
1400 class Storage = AllocatorStringStorage<E, A> >
1401 class flex_string : private Storage
1402 {
1403 #if defined(BOOST_WAVE_FLEXSTRING_THROW_ON_ENFORCE)
1404 template <typename Exception>
1405 static void Enforce(bool condition, Exception*, const char* msg)
1406 { if (!condition) boost::throw_exception(Exception(msg)); }
1407 #else
1408 template <typename Exception>
1409 static inline void Enforce(bool condition, Exception*, const char* msg)
1410 { BOOST_ASSERT(condition && msg); }
1411 #endif
1412
1413 #ifndef NDEBUG
1414 bool Sane() const
1415 {
1416 return
1417 begin() <= end() &&
1418 empty() == (size() == 0) &&
1419 empty() == (begin() == end()) &&
1420 size() <= max_size() &&
1421 capacity() <= max_size() &&
1422 size() <= capacity();
1423 }
1424
1425 struct Invariant;
1426 friend struct Invariant;
1427 struct Invariant
1428 {
1429 Invariant(const flex_string& s) : s_(s)
1430 {
1431 BOOST_ASSERT(s_.Sane());
1432 }
1433 ~Invariant()
1434 {
1435 BOOST_ASSERT(s_.Sane());
1436 }
1437 private:
1438 const flex_string& s_;
1439 Invariant& operator=(const Invariant&);
1440 };
1441 #endif
1442
1443 public:
1444
1445 typedef T traits_type;
1446 typedef typename traits_type::char_type value_type;
1447 typedef A allocator_type;
1448
1449 typedef typename boost::allocator_value_type<A>::type& reference;
1450 typedef typename boost::allocator_value_type<A>::type const& const_reference;
1451 typedef typename boost::allocator_pointer<A>::type pointer;
1452 typedef typename boost::allocator_const_pointer<A>::type const_pointer;
1453 typedef typename boost::allocator_size_type<A>::type size_type;
1454
1455 typedef typename Storage::iterator iterator;
1456 typedef typename Storage::const_iterator const_iterator;
1457
1458 typedef boost::reverse_iterator<iterator> reverse_iterator;
1459 typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
1460
1461 static const size_type npos;
1462
1463 private:
1464 static size_type Min(size_type lhs, size_type rhs)
1465 { return lhs < rhs ? lhs : rhs; }
1466 static void Procust(size_type& n, size_type nmax)
1467 { if (n > nmax) n = nmax; }
1468
1469 public:
1470
1471 explicit flex_string(const A& a = A())
1472 : Storage(a)
1473 {}
1474
1475 flex_string(const flex_string& str)
1476 : Storage(str)
1477 {
1478 }
1479
1480 flex_string(const flex_string& str, size_type pos,
1481 size_type n = npos, const A& a = A())
1482 : Storage(a)
1483 {
1484 Enforce(pos <= str.size(), (std::out_of_range*)0, "");
1485 assign(str, pos, n);
1486 }
1487
1488 flex_string(const value_type* s, const A& a = A())
1489 : Storage(s, traits_type::length(s), a)
1490 {}
1491
1492 flex_string(const value_type* s, size_type n, const A& a = A())
1493 : Storage(s, n, a)
1494 {}
1495
1496 flex_string(size_type n, value_type c, const A& a = A())
1497 : Storage(n, c, a)
1498 {}
1499
1500 template <class InputIterator>
1501 flex_string(InputIterator begin, InputIterator end, const A& a = A())
1502 : Storage(a)
1503 {
1504 assign(begin, end);
1505 }
1506
1507 ~flex_string()
1508 {}
1509
1510 flex_string& operator=(const flex_string& str)
1511 {
1512 if (this != &str) {
1513 Storage& s = *this;
1514 s = str;
1515 }
1516 return *this;
1517 }
1518
1519 flex_string& operator=(const value_type* s)
1520 {
1521 assign(s);
1522 return *this;
1523 }
1524
1525 flex_string& operator=(value_type c)
1526 {
1527 assign(1, c);
1528 return *this;
1529 }
1530
1531
1532 iterator begin()
1533 { return Storage::begin(); }
1534
1535 const_iterator begin() const
1536 { return Storage::begin(); }
1537
1538 iterator end()
1539 { return Storage::end(); }
1540
1541 const_iterator end() const
1542 { return Storage::end(); }
1543
1544 reverse_iterator rbegin()
1545 { return reverse_iterator(end()); }
1546
1547 const_reverse_iterator rbegin() const
1548 { return const_reverse_iterator(end()); }
1549
1550 reverse_iterator rend()
1551 { return reverse_iterator(begin()); }
1552
1553 const_reverse_iterator rend() const
1554 { return const_reverse_iterator(begin()); }
1555
1556 #if BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK != 0
1557
1558
1559 value_type & back() { return *(begin()+size()-1); }
1560 value_type const& back() const { return *(begin()+size()-1); }
1561 #endif
1562
1563
1564 size_type size() const
1565 { return Storage::size(); }
1566
1567 size_type length() const
1568 { return size(); }
1569
1570 size_type max_size() const
1571 { return Storage::max_size(); }
1572
1573 void resize(size_type n, value_type c)
1574 { Storage::resize(n, c); }
1575
1576 void resize(size_type n)
1577 { resize(n, value_type()); }
1578
1579 size_type capacity() const
1580 { return Storage::capacity(); }
1581
1582 void reserve(size_type res_arg = 0)
1583 {
1584 Enforce(res_arg <= max_size(), (std::length_error*)0, "");
1585 Storage::reserve(res_arg);
1586 }
1587
1588 void clear()
1589 { resize(0); }
1590
1591 bool empty() const
1592 { return size() == 0; }
1593
1594
1595 const_reference operator[](size_type pos) const
1596 { return *(begin() + pos); }
1597
1598 reference operator[](size_type pos)
1599 { return *(begin() + pos); }
1600
1601 const_reference at(size_type n) const
1602 {
1603 Enforce(n < size(), (std::out_of_range*)0, "");
1604 return (*this)[n];
1605 }
1606
1607 reference at(size_type n)
1608 {
1609 Enforce(n < size(), (std::out_of_range*)0, "");
1610 return (*this)[n];
1611 }
1612
1613
1614 flex_string& operator+=(const flex_string& str)
1615 { return append(str); }
1616
1617 flex_string& operator+=(const value_type* s)
1618 { return append(s); }
1619
1620 flex_string& operator+=(value_type c)
1621 {
1622 push_back(c);
1623 return *this;
1624 }
1625
1626 flex_string& append(const flex_string& str)
1627 { return append(str, 0, npos); }
1628
1629 flex_string& append(const flex_string& str, const size_type pos,
1630 size_type n)
1631 {
1632 const size_type sz = str.size();
1633 Enforce(pos <= sz, (std::out_of_range*)0, "");
1634 Procust(n, sz - pos);
1635 return append(str.c_str() + pos, n);
1636 }
1637
1638 flex_string& append(const value_type* s, const size_type n)
1639 {
1640 #ifndef NDEBUG
1641 Invariant checker(*this);
1642 #endif
1643 if (IsAliasedRange(s, s + n))
1644 {
1645 const size_type offset = s - &*begin();
1646 Storage::reserve(size() + n);
1647 s = &*begin() + offset;
1648 }
1649 Storage::append(s, s+ n);
1650 return *this;
1651 }
1652
1653 flex_string& append(const value_type* s)
1654 { return append(s, traits_type::length(s)); }
1655
1656 flex_string& append(size_type n, value_type c)
1657 {
1658 resize(size() + n, c);
1659 return *this;
1660 }
1661
1662 template<class InputIterator>
1663 flex_string& append(InputIterator first, InputIterator last)
1664 {
1665 insert(end(), first, last);
1666 return *this;
1667 }
1668
1669 void push_back(value_type c)
1670 {
1671 const size_type cap = capacity();
1672 if (size() == cap)
1673 {
1674 reserve(cap << 1u);
1675 }
1676 Storage::append(&c, &c + 1);
1677 }
1678
1679 flex_string& assign(const flex_string& str)
1680 {
1681 if (&str == this) return *this;
1682 return assign(str.data(), str.size());
1683 }
1684
1685 flex_string& assign(const flex_string& str, size_type pos,
1686 size_type n)
1687 {
1688 const size_type sz = str.size();
1689 Enforce(pos <= str.size(), (std::out_of_range*)0, "");
1690 Procust(n, sz - pos);
1691 return assign(str.data() + pos, n);
1692 }
1693
1694 flex_string& assign(const value_type* s, size_type n)
1695 {
1696 #ifndef NDEBUG
1697 Invariant checker(*this);
1698 #endif
1699 if (size() >= n)
1700 {
1701 std::copy(s, s + n, begin());
1702 resize(n);
1703 }
1704 else
1705 {
1706 const value_type *const s2 = s + size();
1707 std::copy(s, s2, begin());
1708 append(s2, n - size());
1709 }
1710 return *this;
1711 }
1712
1713 flex_string& assign(const value_type* s)
1714 { return assign(s, traits_type::length(s)); }
1715
1716 template <class ItOrLength, class ItOrChar>
1717 flex_string& assign(ItOrLength first_or_n, ItOrChar last_or_c)
1718 { return replace(begin(), end(), first_or_n, last_or_c); }
1719
1720 flex_string& insert(size_type pos1, const flex_string& str)
1721 { return insert(pos1, str.data(), str.size()); }
1722
1723 flex_string& insert(size_type pos1, const flex_string& str,
1724 size_type pos2, size_type n)
1725 {
1726 Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
1727 Procust(n, str.length() - pos2);
1728 return insert(pos1, str.data() + pos2, n);
1729 }
1730
1731 flex_string& insert(size_type pos, const value_type* s, size_type n)
1732 {
1733 Enforce(pos <= length(), (std::out_of_range*)0, "");
1734 insert(begin() + pos, s, s + n);
1735 return *this;
1736 }
1737
1738 flex_string& insert(size_type pos, const value_type* s)
1739 { return insert(pos, s, traits_type::length(s)); }
1740
1741 flex_string& insert(size_type pos, size_type n, value_type c)
1742 {
1743 Enforce(pos <= length(), (std::out_of_range*)0, "");
1744 insert(begin() + pos, n, c);
1745 return *this;
1746 }
1747
1748 iterator insert(iterator p, value_type c = value_type())
1749 {
1750 const size_type pos = p - begin();
1751 insert(pos, &c, 1);
1752 return begin() + pos;
1753 }
1754
1755 private:
1756
1757
1758
1759
1760 template<class Iterator>
1761 const typename std::iterator_traits<Iterator>::value_type*
1762 DereferenceValidIterator(Iterator it) const
1763 {
1764 return &*it;
1765 }
1766
1767
1768
1769
1770 template<typename Iterator>
1771 const typename std::iterator_traits<Iterator>::value_type*
1772 DereferenceValidIterator(std::reverse_iterator<Iterator> it) const
1773 {
1774 return &*--it;
1775 }
1776
1777
1778
1779
1780
1781
1782 template<class Iterator>
1783 bool IsAliasedRange(Iterator beginIterator, Iterator endIterator)
1784 {
1785 if(!empty() && beginIterator != endIterator)
1786 {
1787 typedef const typename std::iterator_traits<Iterator>::value_type *
1788 value_pointer;
1789
1790 value_pointer myBegin(&*begin());
1791 value_pointer myEnd(&*begin() + size());
1792 value_pointer rangeBegin(DereferenceValidIterator(beginIterator));
1793
1794 const std::less_equal<value_pointer> less_equal = std::less_equal<value_pointer>();
1795 if(less_equal(myBegin, rangeBegin) && less_equal(rangeBegin, myEnd))
1796 return true;
1797 }
1798 return false;
1799 }
1800
1801 template <int i> class Selector {};
1802
1803 flex_string& InsertImplDiscr(iterator p,
1804 size_type n, value_type c, Selector<1>)
1805 {
1806 #ifndef NDEBUG
1807 Invariant checker(*this);
1808 #endif
1809 BOOST_ASSERT(begin() <= p && p <= end());
1810 const size_type insertOffset(p - begin());
1811 const size_type originalSize(size());
1812 if(n < originalSize - insertOffset)
1813 {
1814
1815
1816
1817
1818 append(n, value_type(0));
1819 value_type* begin(&*begin());
1820 flex_string_details::pod_move(begin + insertOffset,
1821 begin + originalSize, begin + insertOffset + n);
1822 std::fill(begin + insertOffset, begin + insertOffset + n, c);
1823 }
1824 else
1825 {
1826
1827
1828
1829
1830 append(n, c);
1831 value_type* begin(&*begin());
1832 flex_string_details::pod_copy(begin + insertOffset,
1833 begin + originalSize, begin + insertOffset + n);
1834 std::fill(begin + insertOffset, begin + originalSize, c);
1835 }
1836 return *this;
1837 }
1838
1839 template<class InputIterator>
1840 flex_string& InsertImplDiscr(iterator i,
1841 InputIterator b, InputIterator e, Selector<0>)
1842 {
1843 InsertImpl(i, b, e,
1844 typename std::iterator_traits<InputIterator>::iterator_category());
1845 return *this;
1846 }
1847
1848 template <class FwdIterator>
1849 void InsertImpl(iterator i,
1850 FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
1851 {
1852 if(s1 == s2)
1853 {
1854
1855 return;
1856 }
1857
1858 if(IsAliasedRange(s1, s2))
1859 {
1860
1861
1862 const flex_string temporary(s1, s2);
1863 InsertImpl(i, temporary.begin(), temporary.end(),
1864 typename std::iterator_traits<FwdIterator>::iterator_category());
1865 return;
1866 }
1867
1868 #ifndef NDEBUG
1869 Invariant checker(*this);
1870 #endif
1871 const size_type pos = i - begin();
1872 const typename std::iterator_traits<FwdIterator>::difference_type n2 =
1873 std::distance(s1, s2);
1874
1875 BOOST_ASSERT(n2 >= 0);
1876 using namespace flex_string_details;
1877 BOOST_ASSERT(pos <= size());
1878
1879 const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
1880 capacity() - size();
1881 if (maxn2 < n2)
1882 {
1883
1884 BOOST_ASSERT(!IsAliasedRange(s1, s2));
1885 reserve(size() + n2);
1886 i = begin() + pos;
1887 }
1888 if (pos + n2 <= size())
1889 {
1890 const iterator tailBegin = end() - n2;
1891 Storage::append(tailBegin, tailBegin + n2);
1892 std::copy(reverse_iterator(tailBegin), reverse_iterator(i),
1893 reverse_iterator(tailBegin + n2));
1894 std::copy(s1, s2, i);
1895 }
1896 else
1897 {
1898 FwdIterator t = s1;
1899 const size_type old_size = size();
1900 std::advance(t, old_size - pos);
1901 BOOST_ASSERT(std::distance(t, s2) >= 0);
1902 Storage::append(t, s2);
1903 Storage::append(data() + pos, data() + old_size);
1904 std::copy(s1, t, i);
1905 }
1906 }
1907
1908 template <class InputIterator>
1909 void InsertImpl(iterator insertPosition,
1910 InputIterator inputBegin, InputIterator inputEnd,
1911 std::input_iterator_tag)
1912 {
1913 flex_string temporary(begin(), insertPosition);
1914 for (; inputBegin != inputEnd; ++inputBegin)
1915 {
1916 temporary.push_back(*inputBegin);
1917 }
1918 temporary.append(insertPosition, end());
1919 swap(temporary);
1920 }
1921
1922 public:
1923 template <class ItOrLength, class ItOrChar>
1924 void insert(iterator p, ItOrLength first_or_n, ItOrChar last_or_c)
1925 {
1926 Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
1927 InsertImplDiscr(p, first_or_n, last_or_c, sel);
1928 }
1929
1930 flex_string& erase(size_type pos = 0, size_type n = npos)
1931 {
1932 #ifndef NDEBUG
1933 Invariant checker(*this);
1934 #endif
1935 Enforce(pos <= length(), (std::out_of_range*)0, "");
1936 Procust(n, length() - pos);
1937 std::copy(begin() + pos + n, end(), begin() + pos);
1938 resize(length() - n);
1939 return *this;
1940 }
1941
1942 iterator erase(iterator position)
1943 {
1944 const size_type pos(position - begin());
1945 erase(pos, 1);
1946 return begin() + pos;
1947 }
1948
1949 iterator erase(iterator first, iterator last)
1950 {
1951 const size_type pos(first - begin());
1952 erase(pos, last - first);
1953 return begin() + pos;
1954 }
1955
1956
1957 flex_string& replace(size_type pos1, size_type n1, const flex_string& str)
1958 { return replace(pos1, n1, str, 0, npos); }
1959
1960
1961
1962 flex_string& replace(size_type pos1, size_type n1, const flex_string& str,
1963 size_type pos2, size_type n2)
1964 {
1965 Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
1966 return replace(pos1, n1, str.data() + pos2,
1967 Min(n2, str.size() - pos2));
1968 }
1969
1970
1971 flex_string& replace(size_type pos, size_type n1, const value_type* s)
1972 { return replace(pos, n1, s, traits_type::length(s)); }
1973
1974
1975
1976
1977
1978
1979 template <class StrOrLength, class NumOrChar>
1980 flex_string& replace(size_type pos, size_type n1,
1981 StrOrLength s_or_n2, NumOrChar n_or_c)
1982 {
1983 #ifndef NDEBUG
1984 Invariant checker(*this);
1985 #endif
1986 Enforce(pos <= size(), (std::out_of_range*)0, "");
1987 Procust(n1, length() - pos);
1988 const iterator b = begin() + pos;
1989 return replace(b, b + n1, s_or_n2, n_or_c);
1990 }
1991
1992 flex_string& replace(iterator i1, iterator i2, const flex_string& str)
1993 { return replace(i1, i2, str.c_str(), str.length()); }
1994
1995 flex_string& replace(iterator i1, iterator i2, const value_type* s)
1996 { return replace(i1, i2, s, traits_type::length(s)); }
1997
1998 private:
1999 flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
2000 const value_type* s, size_type n, Selector<2>)
2001 {
2002 BOOST_ASSERT(i1 <= i2);
2003 BOOST_ASSERT(begin() <= i1 && i1 <= end());
2004 BOOST_ASSERT(begin() <= i2 && i2 <= end());
2005 return replace(i1, i2, s, s + n);
2006 }
2007
2008 flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
2009 size_type n2, value_type c, Selector<1>)
2010 {
2011 const size_type n1 = i2 - i1;
2012 if (n1 > n2)
2013 {
2014 std::fill(i1, i1 + n2, c);
2015 erase(i1 + n2, i2);
2016 }
2017 else
2018 {
2019 std::fill(i1, i2, c);
2020 insert(i2, n2 - n1, c);
2021 }
2022 return *this;
2023 }
2024
2025 template <class InputIterator>
2026 flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
2027 InputIterator b, InputIterator e, Selector<0>)
2028 {
2029 ReplaceImpl(i1, i2, b, e,
2030 typename std::iterator_traits<InputIterator>::iterator_category());
2031 return *this;
2032 }
2033
2034 template <class FwdIterator>
2035 void ReplaceImpl(iterator i1, iterator i2,
2036 FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
2037 {
2038 #ifndef NDEBUG
2039 Invariant checker(*this);
2040 #endif
2041 const typename std::iterator_traits<iterator>::difference_type n1 =
2042 i2 - i1;
2043 BOOST_ASSERT(n1 >= 0);
2044 const typename std::iterator_traits<FwdIterator>::difference_type n2 =
2045 std::distance(s1, s2);
2046 BOOST_ASSERT(n2 >= 0);
2047
2048 if (IsAliasedRange(s1, s2))
2049 {
2050
2051 flex_string temporary;
2052 temporary.reserve(size() - n1 + n2);
2053 temporary.append(begin(), i1).append(s1, s2).append(i2, end());
2054 swap(temporary);
2055 return;
2056 }
2057
2058 if (n1 > n2)
2059 {
2060
2061 std::copy(s1, s2, i1);
2062 erase(i1 + n2, i2);
2063 }
2064 else
2065 {
2066
2067 flex_string_details::copy_n(s1, n1, i1);
2068 std::advance(s1, n1);
2069 insert(i2, s1, s2);
2070 }
2071 }
2072
2073 template <class InputIterator>
2074 void ReplaceImpl(iterator i1, iterator i2,
2075 InputIterator b, InputIterator e, std::input_iterator_tag)
2076 {
2077 flex_string temp(begin(), i1);
2078 temp.append(b, e).append(i2, end());
2079 swap(temp);
2080 }
2081
2082 public:
2083 template <class T1, class T2>
2084 flex_string& replace(iterator i1, iterator i2,
2085 T1 first_or_n_or_s, T2 last_or_c_or_n)
2086 {
2087 const bool
2088 num1 = std::numeric_limits<T1>::is_specialized,
2089 num2 = std::numeric_limits<T2>::is_specialized;
2090 return ReplaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n,
2091 Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
2092 }
2093
2094 size_type copy(value_type* s, size_type n, size_type pos = 0) const
2095 {
2096 Enforce(pos <= size(), (std::out_of_range*)0, "");
2097 n = Min(n, size() - pos);
2098
2099 flex_string_details::pod_copy(
2100 &*begin() + pos,
2101 &*begin() + pos + n,
2102 s);
2103 return n;
2104 }
2105
2106 void swap(flex_string& rhs)
2107 {
2108 Storage& srhs = rhs;
2109 this->Storage::swap(srhs);
2110 }
2111
2112
2113 const value_type* c_str() const
2114 { return Storage::c_str(); }
2115
2116 const value_type* data() const
2117 { return Storage::data(); }
2118
2119 allocator_type get_allocator() const
2120 { return Storage::get_allocator(); }
2121
2122 size_type find(const flex_string& str, size_type pos = 0) const
2123 { return find(str.data(), pos, str.length()); }
2124
2125 size_type find (const value_type* s, size_type pos, size_type n) const
2126 {
2127 const size_type size_(size());
2128 if (n + pos > size_)
2129 return npos;
2130 for (; pos < size_; ++pos)
2131 {
2132 if (traits_type::compare(&*begin() + pos, s, n) == 0)
2133 {
2134 return pos;
2135 }
2136 }
2137 return npos;
2138 }
2139
2140 size_type find (const value_type* s, size_type pos = 0) const
2141 { return find(s, pos, traits_type::length(s)); }
2142
2143 size_type find (value_type c, size_type pos = 0) const
2144 { return find(&c, pos, 1); }
2145
2146 size_type rfind(const flex_string& str, size_type pos = npos) const
2147 { return rfind(str.c_str(), pos, str.length()); }
2148
2149 size_type rfind(const value_type* s, size_type pos, size_type n) const
2150 {
2151 if (n > length()) return npos;
2152 pos = Min(pos, length() - n);
2153 if (n == 0) return pos;
2154
2155 const_iterator i(begin() + pos);
2156 for (; ; --i)
2157 {
2158 if (traits_type::eq(*i, *s)
2159 && traits_type::compare(&*i, s, n) == 0)
2160 {
2161 return i - begin();
2162 }
2163 if (i == begin()) break;
2164 }
2165 return npos;
2166 }
2167
2168 size_type rfind(const value_type* s, size_type pos = npos) const
2169 { return rfind(s, pos, traits_type::length(s)); }
2170
2171 size_type rfind(value_type c, size_type pos = npos) const
2172 { return rfind(&c, pos, 1); }
2173
2174 size_type find_first_of(const flex_string& str, size_type pos = 0) const
2175 { return find_first_of(str.c_str(), pos, str.length()); }
2176
2177 size_type find_first_of(const value_type* s,
2178 size_type pos, size_type n) const
2179 {
2180 if (pos > length() || n == 0) return npos;
2181 const_iterator i(begin() + pos),
2182 finish(end());
2183 for (; i != finish; ++i)
2184 {
2185 if (traits_type::find(s, n, *i) != 0)
2186 {
2187 return i - begin();
2188 }
2189 }
2190 return npos;
2191 }
2192
2193 size_type find_first_of(const value_type* s, size_type pos = 0) const
2194 { return find_first_of(s, pos, traits_type::length(s)); }
2195
2196 size_type find_first_of(value_type c, size_type pos = 0) const
2197 { return find_first_of(&c, pos, 1); }
2198
2199 size_type find_last_of (const flex_string& str,
2200 size_type pos = npos) const
2201 { return find_last_of(str.c_str(), pos, str.length()); }
2202
2203 size_type find_last_of (const value_type* s, size_type pos,
2204 size_type n) const
2205 {
2206 if (!empty() && n > 0)
2207 {
2208 pos = Min(pos, length() - 1);
2209 const_iterator i(begin() + pos);
2210 for (;; --i)
2211 {
2212 if (traits_type::find(s, n, *i) != 0)
2213 {
2214 return i - begin();
2215 }
2216 if (i == begin()) break;
2217 }
2218 }
2219 return npos;
2220 }
2221
2222 size_type find_last_of (const value_type* s,
2223 size_type pos = npos) const
2224 { return find_last_of(s, pos, traits_type::length(s)); }
2225
2226 size_type find_last_of (value_type c, size_type pos = npos) const
2227 { return find_last_of(&c, pos, 1); }
2228
2229 size_type find_first_not_of(const flex_string& str,
2230 size_type pos = 0) const
2231 { return find_first_not_of(str.data(), pos, str.size()); }
2232
2233 size_type find_first_not_of(const value_type* s, size_type pos,
2234 size_type n) const
2235 {
2236 if (pos < length())
2237 {
2238 const_iterator
2239 i(begin() + pos),
2240 finish(end());
2241 for (; i != finish; ++i)
2242 {
2243 if (traits_type::find(s, n, *i) == 0)
2244 {
2245 return i - begin();
2246 }
2247 }
2248 }
2249 return npos;
2250 }
2251
2252 size_type find_first_not_of(const value_type* s,
2253 size_type pos = 0) const
2254 { return find_first_not_of(s, pos, traits_type::length(s)); }
2255
2256 size_type find_first_not_of(value_type c, size_type pos = 0) const
2257 { return find_first_not_of(&c, pos, 1); }
2258
2259 size_type find_last_not_of(const flex_string& str,
2260 size_type pos = npos) const
2261 { return find_last_not_of(str.c_str(), pos, str.length()); }
2262
2263 size_type find_last_not_of(const value_type* s, size_type pos,
2264 size_type n) const
2265 {
2266 if (!empty())
2267 {
2268 pos = Min(pos, size() - 1);
2269 const_iterator i(begin() + pos);
2270 for (;; --i)
2271 {
2272 if (traits_type::find(s, n, *i) == 0)
2273 {
2274 return i - begin();
2275 }
2276 if (i == begin()) break;
2277 }
2278 }
2279 return npos;
2280 }
2281
2282 size_type find_last_not_of(const value_type* s,
2283 size_type pos = npos) const
2284 { return find_last_not_of(s, pos, traits_type::length(s)); }
2285
2286 size_type find_last_not_of (value_type c, size_type pos = npos) const
2287 { return find_last_not_of(&c, pos, 1); }
2288
2289 flex_string substr(size_type pos = 0, size_type n = npos) const
2290 {
2291 Enforce(pos <= size(), (std::out_of_range*)0, "");
2292 return flex_string(data() + pos, Min(n, size() - pos));
2293 }
2294
2295 std::ptrdiff_t compare(const flex_string& str) const
2296 {
2297
2298 return compare(0, size(), str);
2299 }
2300
2301 std::ptrdiff_t compare(size_type pos1, size_type n1,
2302 const flex_string& str) const
2303 { return compare(pos1, n1, str.data(), str.size()); }
2304
2305
2306
2307
2308 std::ptrdiff_t compare(size_type pos1, size_type n1,
2309 const value_type* s) const
2310 {
2311 return compare(pos1, n1, s, traits_type::length(s));
2312 }
2313
2314 std::ptrdiff_t compare(size_type pos1, size_type n1,
2315 const value_type* s, size_type n2) const
2316 {
2317 Enforce(pos1 <= size(), (std::out_of_range*)0, "");
2318 Procust(n1, size() - pos1);
2319 const int r = traits_type::compare(pos1 + data(), s, Min(n1, n2));
2320 return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
2321 }
2322
2323 std::ptrdiff_t compare(size_type pos1, size_type n1,
2324 const flex_string& str,
2325 size_type pos2, size_type n2) const
2326 {
2327 Enforce(pos2 <= str.size(), (std::out_of_range*)0, "");
2328 return compare(pos1, n1, str.data() + pos2, Min(n2, str.size() - pos2));
2329 }
2330
2331 std::ptrdiff_t compare(const value_type* s) const
2332 {
2333
2334
2335 const size_type n1(size()), n2(traits_type::length(s));
2336 const int r = traits_type::compare(data(), s, Min(n1, n2));
2337 return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
2338 }
2339 };
2340
2341
2342 template <typename E, class T, class A, class S>
2343 flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
2344 const flex_string<E, T, A, S>& rhs)
2345 {
2346 flex_string<E, T, A, S> result;
2347 result.reserve(lhs.size() + rhs.size());
2348 result.append(lhs).append(rhs);
2349 return result;
2350 }
2351
2352 template <typename E, class T, class A, class S>
2353 flex_string<E, T, A, S> operator+(const typename flex_string<E, T, A, S>::value_type* lhs,
2354 const flex_string<E, T, A, S>& rhs)
2355 {
2356 flex_string<E, T, A, S> result;
2357 const typename flex_string<E, T, A, S>::size_type len =
2358 flex_string<E, T, A, S>::traits_type::length(lhs);
2359 result.reserve(len + rhs.size());
2360 result.append(lhs, len).append(rhs);
2361 return result;
2362 }
2363
2364 template <typename E, class T, class A, class S>
2365 flex_string<E, T, A, S> operator+(
2366 typename flex_string<E, T, A, S>::value_type lhs,
2367 const flex_string<E, T, A, S>& rhs)
2368 {
2369 flex_string<E, T, A, S> result;
2370 result.reserve(1 + rhs.size());
2371 result.push_back(lhs);
2372 result.append(rhs);
2373 return result;
2374 }
2375
2376 template <typename E, class T, class A, class S>
2377 flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
2378 const typename flex_string<E, T, A, S>::value_type* rhs)
2379 {
2380 typedef typename flex_string<E, T, A, S>::size_type size_type;
2381 typedef typename flex_string<E, T, A, S>::traits_type traits_type;
2382
2383 flex_string<E, T, A, S> result;
2384 const size_type len = traits_type::length(rhs);
2385 result.reserve(lhs.size() + len);
2386 result.append(lhs).append(rhs, len);
2387 return result;
2388 }
2389
2390 template <typename E, class T, class A, class S>
2391 flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
2392 typename flex_string<E, T, A, S>::value_type rhs)
2393 {
2394 flex_string<E, T, A, S> result;
2395 result.reserve(lhs.size() + 1);
2396 result.append(lhs);
2397 result.push_back(rhs);
2398 return result;
2399 }
2400
2401 template <typename E, class T, class A, class S>
2402 inline bool operator==(const flex_string<E, T, A, S>& lhs,
2403 const flex_string<E, T, A, S>& rhs)
2404 { return lhs.compare(rhs) == 0; }
2405
2406 template <typename E, class T, class A, class S>
2407 inline bool operator==(const typename flex_string<E, T, A, S>::value_type* lhs,
2408 const flex_string<E, T, A, S>& rhs)
2409 { return rhs == lhs; }
2410
2411 template <typename E, class T, class A, class S>
2412 inline bool operator==(const flex_string<E, T, A, S>& lhs,
2413 const typename flex_string<E, T, A, S>::value_type* rhs)
2414 { return lhs.compare(rhs) == 0; }
2415
2416 template <typename E, class T, class A, class S>
2417 inline bool operator!=(const flex_string<E, T, A, S>& lhs,
2418 const flex_string<E, T, A, S>& rhs)
2419 { return !(lhs == rhs); }
2420
2421 template <typename E, class T, class A, class S>
2422 inline bool operator!=(const typename flex_string<E, T, A, S>::value_type* lhs,
2423 const flex_string<E, T, A, S>& rhs)
2424 { return !(lhs == rhs); }
2425
2426 template <typename E, class T, class A, class S>
2427 inline bool operator!=(const flex_string<E, T, A, S>& lhs,
2428 const typename flex_string<E, T, A, S>::value_type* rhs)
2429 { return !(lhs == rhs); }
2430
2431 template <typename E, class T, class A, class S>
2432 inline bool operator<(const flex_string<E, T, A, S>& lhs,
2433 const flex_string<E, T, A, S>& rhs)
2434 { return lhs.compare(rhs) < 0; }
2435
2436 template <typename E, class T, class A, class S>
2437 inline bool operator<(const flex_string<E, T, A, S>& lhs,
2438 const typename flex_string<E, T, A, S>::value_type* rhs)
2439 { return lhs.compare(rhs) < 0; }
2440
2441 template <typename E, class T, class A, class S>
2442 inline bool operator<(const typename flex_string<E, T, A, S>::value_type* lhs,
2443 const flex_string<E, T, A, S>& rhs)
2444 { return rhs.compare(lhs) > 0; }
2445
2446 template <typename E, class T, class A, class S>
2447 inline bool operator>(const flex_string<E, T, A, S>& lhs,
2448 const flex_string<E, T, A, S>& rhs)
2449 { return rhs < lhs; }
2450
2451 template <typename E, class T, class A, class S>
2452 inline bool operator>(const flex_string<E, T, A, S>& lhs,
2453 const typename flex_string<E, T, A, S>::value_type* rhs)
2454 { return rhs < lhs; }
2455
2456 template <typename E, class T, class A, class S>
2457 bool operator>(const typename flex_string<E, T, A, S>::value_type* lhs,
2458 const flex_string<E, T, A, S>& rhs)
2459 { return rhs < lhs; }
2460
2461 template <typename E, class T, class A, class S>
2462 inline bool operator<=(const flex_string<E, T, A, S>& lhs,
2463 const flex_string<E, T, A, S>& rhs)
2464 { return !(rhs < lhs); }
2465
2466 template <typename E, class T, class A, class S>
2467 inline bool operator<=(const flex_string<E, T, A, S>& lhs,
2468 const typename flex_string<E, T, A, S>::value_type* rhs)
2469 { return !(rhs < lhs); }
2470
2471 template <typename E, class T, class A, class S>
2472 bool operator<=(const typename flex_string<E, T, A, S>::value_type* lhs,
2473 const flex_string<E, T, A, S>& rhs)
2474 { return !(rhs < lhs); }
2475
2476 template <typename E, class T, class A, class S>
2477 bool operator>=(const flex_string<E, T, A, S>& lhs,
2478 const flex_string<E, T, A, S>& rhs)
2479 { return !(lhs < rhs); }
2480
2481 template <typename E, class T, class A, class S>
2482 bool operator>=(const flex_string<E, T, A, S>& lhs,
2483 const typename flex_string<E, T, A, S>::value_type* rhs)
2484 { return !(lhs < rhs); }
2485
2486 template <typename E, class T, class A, class S>
2487 inline bool operator>=(const typename flex_string<E, T, A, S>::value_type* lhs,
2488 const flex_string<E, T, A, S>& rhs)
2489 { return !(lhs < rhs); }
2490
2491 template <typename E, class T, class A, class S>
2492 void swap(flex_string<E, T, A, S>& lhs, flex_string<E, T, A, S>& rhs)
2493 {
2494
2495 lhs.swap(rhs);
2496 }
2497
2498 template <typename E, class T, class A, class S>
2499 inline std::basic_istream<typename flex_string<E, T, A, S>::value_type,
2500 typename flex_string<E, T, A, S>::traits_type>&
2501 operator>>(
2502 std::basic_istream<typename flex_string<E, T, A, S>::value_type,
2503 typename flex_string<E, T, A, S>::traits_type>& is,
2504 flex_string<E, T, A, S>& str);
2505
2506 template <typename E, class T, class A, class S>
2507 std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
2508 typename flex_string<E, T, A, S>::traits_type>&
2509 operator<<(
2510 std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
2511 typename flex_string<E, T, A, S>::traits_type>& os,
2512 const flex_string<E, T, A, S>& str)
2513 { return os << str.c_str(); }
2514
2515 template <typename E1, class T, class A, class S>
2516 const typename flex_string<E1, T, A, S>::size_type
2517 flex_string<E1, T, A, S>::npos = (typename flex_string<E1, T, A, S>::size_type)(-1);
2518
2519
2520 }
2521 }
2522 }
2523
2524 #if BOOST_WAVE_SERIALIZATION != 0
2525
2526 namespace boost { namespace serialization {
2527
2528 #if !defined(BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK)
2529
2530
2531 template <typename E, class T, class A, class S>
2532 struct implementation_level<boost::wave::util::flex_string<E, T, A, S> >
2533 {
2534 typedef mpl::integral_c_tag tag;
2535 typedef mpl::int_<boost::serialization::primitive_type> type;
2536 BOOST_STATIC_CONSTANT(
2537 int,
2538 value = implementation_level::type::value
2539 );
2540 };
2541
2542 #else
2543
2544
2545 template<class Archive, typename E, class T, class A, class S>
2546 inline void save(Archive & ar,
2547 boost::wave::util::flex_string<E, T, A, S> const &t,
2548 const unsigned int file_version)
2549 {
2550 boost::serialization::stl::save_collection<
2551 Archive, wave::util::flex_string<E, T, A, S> >(ar, t);
2552 }
2553
2554 template<class Archive, typename E, class T, class A, class S>
2555 inline void load(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
2556 const unsigned int file_version)
2557 {
2558 boost::serialization::stl::load_collection<
2559 Archive, boost::wave::util::flex_string<E, T, A, S>,
2560 boost::serialization::stl::archive_input_seq<
2561 Archive, boost::wave::util::flex_string<E, T, A, S> >,
2562 boost::serialization::stl::reserve_imp<
2563 boost::wave::util::flex_string<E, T, A, S> >
2564 >(ar, t);
2565 }
2566
2567
2568
2569 template<class Archive, typename E, class T, class A, class S>
2570 inline void serialize(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
2571 const unsigned int file_version)
2572 {
2573 boost::serialization::split_free(ar, t, file_version);
2574 }
2575
2576 #endif
2577
2578
2579 }}
2580 #endif
2581
2582
2583 #ifdef BOOST_HAS_ABI_HEADERS
2584 #include BOOST_ABI_SUFFIX
2585 #endif
2586
2587 #endif