1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_CONTAINER_STRING_HPP
12 #define BOOST_CONTAINER_STRING_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/container/detail/config_begin.hpp>
23 #include <boost/container/detail/workaround.hpp>
24 #include <boost/container/container_fwd.hpp>
25 // container
26 #include <boost/container/allocator_traits.hpp>
27 #include <boost/container/new_allocator.hpp> //new_allocator
28 #include <boost/container/throw_exception.hpp>
29 // container/detail
30 #include <boost/container/detail/alloc_helpers.hpp>
31 #include <boost/container/detail/allocator_version_traits.hpp>
32 #include <boost/container/detail/allocation_type.hpp>
33 #include <boost/container/detail/iterator.hpp>
34 #include <boost/container/detail/iterators.hpp>
35 #include <boost/container/detail/min_max.hpp>
36 #include <boost/container/detail/mpl.hpp>
37 #include <boost/container/detail/next_capacity.hpp>
38 #include <boost/container/detail/to_raw_pointer.hpp>
39 #include <boost/container/detail/version_type.hpp>
40 
41 #include <boost/move/utility_core.hpp>
42 #include <boost/move/adl_move_swap.hpp>
43 #include <boost/static_assert.hpp>
44 #include <boost/intrusive/pointer_traits.hpp>
45 #include <boost/core/no_exceptions_support.hpp>
46 #include <boost/container/detail/minimal_char_traits_header.hpp>
47 #include <boost/functional/hash.hpp>
48 
49 
50 #include <algorithm>
51 #include <functional>   //bind2nd, etc.
52 #include <iosfwd>
53 #include <istream>
54 #include <ostream>
55 #include <ios>
56 #include <locale>
57 #include <cstddef>
58 #include <climits>
59 #include <boost/container/detail/type_traits.hpp>
60 #include <boost/move/traits.hpp>
61 
62 namespace boost {
63 namespace container {
64 
65 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
66 namespace container_detail {
67 // ------------------------------------------------------------
68 // Class basic_string_base.
69 
70 // basic_string_base is a helper class that makes it it easier to write
71 // an exception-safe version of basic_string.  The constructor allocates,
72 // but does not initialize, a block of memory.  The destructor
73 // deallocates, but does not destroy elements within, a block of
74 // memory. The destructor assumes that the memory either is the internal buffer,
75 // or else points to a block of memory that was allocated using string_base's
76 // allocator and whose size is this->m_storage.
77 template <class Allocator>
78 class basic_string_base
79 {
80    basic_string_base & operator=(const basic_string_base &);
81    basic_string_base(const basic_string_base &);
82 
83    typedef allocator_traits<Allocator> allocator_traits_type;
84  public:
85    typedef Allocator                                   allocator_type;
86    typedef allocator_type                              stored_allocator_type;
87    typedef typename allocator_traits_type::pointer     pointer;
88    typedef typename allocator_traits_type::value_type  value_type;
89    typedef typename allocator_traits_type::size_type   size_type;
90    typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
91 
basic_string_base()92    basic_string_base()
93       : members_()
94    {  init(); }
95 
basic_string_base(const allocator_type & a)96    basic_string_base(const allocator_type& a)
97       : members_(a)
98    {  init(); }
99 
basic_string_base(BOOST_RV_REF (allocator_type)a)100    basic_string_base(BOOST_RV_REF(allocator_type) a)
101       :  members_(boost::move(a))
102    {  this->init();  }
103 
basic_string_base(const allocator_type & a,size_type n)104    basic_string_base(const allocator_type& a, size_type n)
105       : members_(a)
106    {
107       this->init();
108       this->allocate_initial_block(n);
109    }
110 
~basic_string_base()111    ~basic_string_base()
112    {
113       if(!this->is_short()){
114          this->deallocate(this->priv_long_addr(), this->priv_long_storage());
115       }
116    }
117 
118    private:
119 
120    //This is the structure controlling a long string
121    struct long_t
122    {
123       size_type      is_short  : 1;
124       size_type      length    : (sizeof(size_type)*CHAR_BIT - 1);
125       size_type      storage;
126       pointer        start;
127 
long_tboost::container::container_detail::basic_string_base::long_t128       long_t()
129       {}
130 
long_tboost::container::container_detail::basic_string_base::long_t131       long_t(const long_t &other)
132       {
133          this->is_short = false;
134          length   = other.length;
135          storage  = other.storage;
136          start    = other.start;
137       }
138 
operator =boost::container::container_detail::basic_string_base::long_t139       long_t &operator= (const long_t &other)
140       {
141          length   = other.length;
142          storage  = other.storage;
143          start    = other.start;
144          return *this;
145       }
146    };
147 
148    //This type is the first part of the structure controlling a short string
149    //The "data" member stores
150    struct short_header
151    {
152       unsigned char  is_short  : 1;
153       unsigned char  length    : (CHAR_BIT - 1);
154    };
155 
156    //This type has the same alignment and size as long_t but it's POD
157    //so, unlike long_t, it can be placed in a union
158 
159    typedef typename container_detail::aligned_storage
160       <sizeof(long_t), container_detail::alignment_of<long_t>::value>::type   long_raw_t;
161 
162    protected:
163    static const size_type  MinInternalBufferChars = 8;
164    static const size_type  AlignmentOfValueType =
165       alignment_of<value_type>::value;
166    static const size_type  ShortDataOffset = ((sizeof(short_header)-1)/AlignmentOfValueType+1)*AlignmentOfValueType;
167    static const size_type  ZeroCostInternalBufferChars =
168       (sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
169    static const size_type  UnalignedFinalInternalBufferChars =
170       (ZeroCostInternalBufferChars > MinInternalBufferChars) ?
171                 ZeroCostInternalBufferChars : MinInternalBufferChars;
172 
173    struct short_t
174    {
175       short_header   h;
176       value_type     data[UnalignedFinalInternalBufferChars];
177    };
178 
179    union repr_t
180    {
181       long_raw_t  r;
182       short_t     s;
183 
short_repr() const184       const short_t &short_repr() const
185       {  return s;  }
186 
long_repr() const187       const long_t &long_repr() const
188       {  return *static_cast<const long_t*>(static_cast<const void*>(&r));  }
189 
short_repr()190       short_t &short_repr()
191       {  return s;  }
192 
long_repr()193       long_t &long_repr()
194       {  return *static_cast<long_t*>(static_cast<void*>(&r));  }
195    };
196 
197    struct members_holder
198       :  public Allocator
199    {
members_holderboost::container::container_detail::basic_string_base::members_holder200       members_holder()
201          : Allocator()
202       {}
203 
204       template<class AllocatorConvertible>
members_holderboost::container::container_detail::basic_string_base::members_holder205       explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
206          :  Allocator(boost::forward<AllocatorConvertible>(a))
207       {}
208 
209       repr_t m_repr;
210    } members_;
211 
alloc() const212    const Allocator &alloc() const
213    {  return members_;  }
214 
alloc()215    Allocator &alloc()
216    {  return members_;  }
217 
218    static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
219 
220    private:
221 
222    static const size_type MinAllocation = InternalBufferChars*2;
223 
224    protected:
is_short() const225    bool is_short() const
226    {  return static_cast<bool>(this->members_.m_repr.s.h.is_short != 0);  }
227 
is_short(bool yes)228    void is_short(bool yes)
229    {
230       const bool was_short = this->is_short();
231       if(yes && !was_short){
232          allocator_traits_type::destroy
233             ( this->alloc()
234             , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
235             );
236          this->members_.m_repr.s.h.is_short = true;
237       }
238       else if(!yes && was_short){
239          allocator_traits_type::construct
240             ( this->alloc()
241             , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
242             );
243          this->members_.m_repr.s.h.is_short = false;
244       }
245    }
246 
247    private:
init()248    void init()
249    {
250       this->members_.m_repr.s.h.is_short = 1;
251       this->members_.m_repr.s.h.length   = 0;
252    }
253 
254    protected:
255 
256    typedef container_detail::integral_constant<unsigned,
257       boost::container::container_detail::version<Allocator>::value> alloc_version;
258 
allocation_command(allocation_type command,size_type limit_size,size_type & prefer_in_recvd_out_size,pointer & reuse)259    pointer allocation_command(allocation_type command,
260                          size_type limit_size,
261                          size_type &prefer_in_recvd_out_size,
262                          pointer &reuse)
263    {
264       if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){
265          reuse = 0;
266          command &= ~(expand_fwd | expand_bwd);
267       }
268       return container_detail::allocator_version_traits<Allocator>::allocation_command
269          (this->alloc(), command, limit_size, prefer_in_recvd_out_size, reuse);
270    }
271 
next_capacity(size_type additional_objects) const272    size_type next_capacity(size_type additional_objects) const
273    {
274       return next_capacity_calculator
275          <size_type, NextCapacityDouble /*NextCapacity60Percent*/>::
276             get( allocator_traits_type::max_size(this->alloc())
277                , this->priv_storage(), additional_objects );
278    }
279 
deallocate(pointer p,size_type n)280    void deallocate(pointer p, size_type n)
281    {
282       if (p && (n > InternalBufferChars))
283          this->alloc().deallocate(p, n);
284    }
285 
construct(pointer p,const value_type & value=value_type ())286    void construct(pointer p, const value_type &value = value_type())
287    {
288       allocator_traits_type::construct
289          ( this->alloc()
290          , container_detail::to_raw_pointer(p)
291          , value
292          );
293    }
294 
destroy(pointer p,size_type n)295    void destroy(pointer p, size_type n)
296    {
297       value_type *raw_p = container_detail::to_raw_pointer(p);
298       for(; n--; ++raw_p){
299          allocator_traits_type::destroy( this->alloc(), raw_p);
300       }
301    }
302 
destroy(pointer p)303    void destroy(pointer p)
304    {
305       allocator_traits_type::destroy
306          ( this->alloc()
307          , container_detail::to_raw_pointer(p)
308          );
309    }
310 
allocate_initial_block(size_type n)311    void allocate_initial_block(size_type n)
312    {
313       if (n <= this->max_size()) {
314          if(n > InternalBufferChars){
315             size_type new_cap = this->next_capacity(n);
316             pointer reuse = 0;
317             pointer p = this->allocation_command(allocate_new, n, new_cap, reuse);
318             this->is_short(false);
319             this->priv_long_addr(p);
320             this->priv_long_size(0);
321             this->priv_storage(new_cap);
322          }
323       }
324       else{
325          throw_length_error("basic_string::allocate_initial_block max_size() exceeded");
326       }
327    }
328 
deallocate_block()329    void deallocate_block()
330    {  this->deallocate(this->priv_addr(), this->priv_storage());  }
331 
max_size() const332    size_type max_size() const
333    {  return allocator_traits_type::max_size(this->alloc()) - 1; }
334 
335    protected:
priv_capacity() const336    size_type priv_capacity() const
337    { return this->priv_storage() - 1; }
338 
priv_short_addr() const339    pointer priv_short_addr() const
340    {  return pointer_traits::pointer_to(const_cast<value_type&>(this->members_.m_repr.short_repr().data[0]));  }
341 
priv_long_addr() const342    pointer priv_long_addr() const
343    {  return this->members_.m_repr.long_repr().start;  }
344 
priv_addr() const345    pointer priv_addr() const
346    {
347       return this->is_short()
348          ? priv_short_addr()
349          : priv_long_addr()
350          ;
351    }
352 
priv_end_addr() const353    pointer priv_end_addr() const
354    {
355       return this->is_short()
356          ? this->priv_short_addr() + this->priv_short_size()
357          : this->priv_long_addr()  + this->priv_long_size()
358          ;
359    }
360 
priv_long_addr(pointer addr)361    void priv_long_addr(pointer addr)
362    {  this->members_.m_repr.long_repr().start = addr;  }
363 
priv_storage() const364    size_type priv_storage() const
365    {  return this->is_short() ? priv_short_storage() : priv_long_storage();  }
366 
priv_short_storage() const367    size_type priv_short_storage() const
368    {  return InternalBufferChars;  }
369 
priv_long_storage() const370    size_type priv_long_storage() const
371    {  return this->members_.m_repr.long_repr().storage;  }
372 
priv_storage(size_type storage)373    void priv_storage(size_type storage)
374    {
375       if(!this->is_short())
376          this->priv_long_storage(storage);
377    }
378 
priv_long_storage(size_type storage)379    void priv_long_storage(size_type storage)
380    {
381       this->members_.m_repr.long_repr().storage = storage;
382    }
383 
priv_size() const384    size_type priv_size() const
385    {  return this->is_short() ? this->priv_short_size() : this->priv_long_size();  }
386 
priv_short_size() const387    size_type priv_short_size() const
388    {  return this->members_.m_repr.short_repr().h.length;  }
389 
priv_long_size() const390    size_type priv_long_size() const
391    {  return this->members_.m_repr.long_repr().length;  }
392 
priv_size(size_type sz)393    void priv_size(size_type sz)
394    {
395       if(this->is_short())
396          this->priv_short_size(sz);
397       else
398          this->priv_long_size(sz);
399    }
400 
priv_short_size(size_type sz)401    void priv_short_size(size_type sz)
402    {
403       this->members_.m_repr.s.h.length = (unsigned char)sz;
404    }
405 
priv_long_size(size_type sz)406    void priv_long_size(size_type sz)
407    {
408       this->members_.m_repr.long_repr().length = sz;
409    }
410 
swap_data(basic_string_base & other)411    void swap_data(basic_string_base& other)
412    {
413       if(this->is_short()){
414          if(other.is_short()){
415             repr_t tmp(this->members_.m_repr);
416             this->members_.m_repr = other.members_.m_repr;
417             other.members_.m_repr = tmp;
418          }
419          else{
420             short_t short_backup(this->members_.m_repr.short_repr());
421             this->members_.m_repr.short_repr().~short_t();
422             ::new(&this->members_.m_repr.long_repr()) long_t(other.members_.m_repr.long_repr());
423             other.members_.m_repr.long_repr().~long_t();
424             ::new(&other.members_.m_repr.short_repr()) short_t(short_backup);
425          }
426       }
427       else{
428          if(other.is_short()){
429             short_t short_backup(other.members_.m_repr.short_repr());
430             other.members_.m_repr.short_repr().~short_t();
431             ::new(&other.members_.m_repr.long_repr()) long_t(this->members_.m_repr.long_repr());
432             this->members_.m_repr.long_repr().~long_t();
433             ::new(&this->members_.m_repr.short_repr()) short_t(short_backup);
434          }
435          else{
436             boost::adl_move_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
437          }
438       }
439    }
440 };
441 
442 }  //namespace container_detail {
443 
444 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
445 
446 //! The basic_string class represents a Sequence of characters. It contains all the
447 //! usual operations of a Sequence, and, additionally, it contains standard string
448 //! operations such as search and concatenation.
449 //!
450 //! The basic_string class is parameterized by character type, and by that type's
451 //! Character Traits.
452 //!
453 //! This class has performance characteristics very much like vector<>, meaning,
454 //! for example, that it does not perform reference-count or copy-on-write, and that
455 //! concatenation of two strings is an O(N) operation.
456 //!
457 //! Some of basic_string's member functions use an unusual method of specifying positions
458 //! and ranges. In addition to the conventional method using iterators, many of
459 //! basic_string's member functions use a single value pos of type size_type to represent a
460 //! position (in which case the position is begin() + pos, and many of basic_string's
461 //! member functions use two values, pos and n, to represent a range. In that case pos is
462 //! the beginning of the range and n is its size. That is, the range is
463 //! [begin() + pos, begin() + pos + n).
464 //!
465 //! Note that the C++ standard does not specify the complexity of basic_string operations.
466 //! In this implementation, basic_string has performance characteristics very similar to
467 //! those of vector: access to a single character is O(1), while copy and concatenation
468 //! are O(N).
469 //!
470 //! In this implementation, begin(),
471 //! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators.
472 //! In this implementation, iterators are only invalidated by member functions that
473 //! explicitly change the string's contents.
474 //!
475 //! \tparam CharT The type of character it contains.
476 //! \tparam Traits The Character Traits type, which encapsulates basic character operations
477 //! \tparam Allocator The allocator, used for internal memory management.
478 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
479 template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = new_allocator<CharT> >
480 #else
481 template <class CharT, class Traits, class Allocator>
482 #endif
483 class basic_string
484    :  private container_detail::basic_string_base<Allocator>
485 {
486    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
487    private:
488    typedef allocator_traits<Allocator> allocator_traits_type;
489    BOOST_COPYABLE_AND_MOVABLE(basic_string)
490    typedef container_detail::basic_string_base<Allocator> base_t;
491    static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
492 
493    protected:
494    // Allocator helper class to use a char_traits as a function object.
495 
496    template <class Tr>
497    struct Eq_traits
498    {
499       //Compatibility with std::binary_function
500       typedef typename Tr::char_type   first_argument_type;
501       typedef typename Tr::char_type   second_argument_type;
502       typedef bool   result_type;
503 
operator ()boost::container::basic_string::Eq_traits504       bool operator()(const first_argument_type& x, const second_argument_type& y) const
505          { return Tr::eq(x, y); }
506    };
507 
508    template <class Tr>
509    struct Not_within_traits
510    {
511       typedef typename Tr::char_type   argument_type;
512       typedef bool                     result_type;
513 
514       typedef const typename Tr::char_type* Pointer;
515       const Pointer m_first;
516       const Pointer m_last;
517 
Not_within_traitsboost::container::basic_string::Not_within_traits518       Not_within_traits(Pointer f, Pointer l)
519          : m_first(f), m_last(l) {}
520 
operator ()boost::container::basic_string::Not_within_traits521       bool operator()(const typename Tr::char_type& x) const
522       {
523          return std::find_if(m_first, m_last,
524                         std::bind1st(Eq_traits<Tr>(), x)) == m_last;
525       }
526    };
527    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
528 
529    public:
530    //////////////////////////////////////////////
531    //
532    //                    types
533    //
534    //////////////////////////////////////////////
535    typedef Traits                                                                      traits_type;
536    typedef CharT                                                                       value_type;
537    typedef typename ::boost::container::allocator_traits<Allocator>::pointer           pointer;
538    typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer     const_pointer;
539    typedef typename ::boost::container::allocator_traits<Allocator>::reference         reference;
540    typedef typename ::boost::container::allocator_traits<Allocator>::const_reference   const_reference;
541    typedef typename ::boost::container::allocator_traits<Allocator>::size_type         size_type;
542    typedef typename ::boost::container::allocator_traits<Allocator>::difference_type   difference_type;
543    typedef Allocator                                                                   allocator_type;
544    typedef BOOST_CONTAINER_IMPDEF(allocator_type)                                      stored_allocator_type;
545    typedef BOOST_CONTAINER_IMPDEF(pointer)                                             iterator;
546    typedef BOOST_CONTAINER_IMPDEF(const_pointer)                                       const_iterator;
547    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>)        reverse_iterator;
548    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>)  const_reverse_iterator;
549    static const size_type npos = size_type(-1);
550 
551    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
552    private:
553    typedef constant_iterator<CharT, difference_type> cvalue_iterator;
554    typedef typename base_t::alloc_version  alloc_version;
555    typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
556    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
557 
558    public:                         // Constructor, destructor, assignment.
559    //////////////////////////////////////////////
560    //
561    //          construct/copy/destroy
562    //
563    //////////////////////////////////////////////
564    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
565    struct reserve_t {};
566 
basic_string(reserve_t,size_type n,const allocator_type & a=allocator_type ())567    basic_string(reserve_t, size_type n,
568                 const allocator_type& a = allocator_type())
569       //Select allocator as in copy constructor as reserve_t-based constructors
570       //are two step copies optimized for capacity
571       : base_t( allocator_traits_type::select_on_container_copy_construction(a)
572               , n + 1)
573    { this->priv_terminate_string(); }
574 
575    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
576 
577    //! <b>Effects</b>: Default constructs a basic_string.
578    //!
579    //! <b>Throws</b>: If allocator_type's default constructor throws.
basic_string()580    basic_string()
581       : base_t()
582    { this->priv_terminate_string(); }
583 
584 
585    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter.
586    //!
587    //! <b>Throws</b>: Nothing
basic_string(const allocator_type & a)588    explicit basic_string(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
589       : base_t(a)
590    { this->priv_terminate_string(); }
591 
592    //! <b>Effects</b>: Copy constructs a basic_string.
593    //!
594    //! <b>Postcondition</b>: x == *this.
595    //!
596    //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
basic_string(const basic_string & s)597    basic_string(const basic_string& s)
598       :  base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
599    {
600       this->priv_terminate_string();
601       this->assign(s.begin(), s.end());
602    }
603 
604    //! <b>Effects</b>: Move constructor. Moves s's resources to *this.
605    //!
606    //! <b>Throws</b>: Nothing.
607    //!
608    //! <b>Complexity</b>: Constant.
basic_string(BOOST_RV_REF (basic_string)s)609    basic_string(BOOST_RV_REF(basic_string) s) BOOST_NOEXCEPT_OR_NOTHROW
610       : base_t(boost::move(s.alloc()))
611    {
612       if(s.alloc() == this->alloc()){
613          this->swap_data(s);
614       }
615       else{
616          this->assign(s.begin(), s.end());
617       }
618    }
619 
620    //! <b>Effects</b>: Copy constructs a basic_string using the specified allocator.
621    //!
622    //! <b>Postcondition</b>: x == *this.
623    //!
624    //! <b>Throws</b>: If allocation throws.
basic_string(const basic_string & s,const allocator_type & a)625    basic_string(const basic_string& s, const allocator_type &a)
626       :  base_t(a)
627    {
628       this->priv_terminate_string();
629       this->assign(s.begin(), s.end());
630    }
631 
632    //! <b>Effects</b>: Move constructor using the specified allocator.
633    //!                 Moves s's resources to *this.
634    //!
635    //! <b>Throws</b>: If allocation throws.
636    //!
637    //! <b>Complexity</b>: Constant if a == s.get_allocator(), linear otherwise.
basic_string(BOOST_RV_REF (basic_string)s,const allocator_type & a)638    basic_string(BOOST_RV_REF(basic_string) s, const allocator_type &a)
639       : base_t(a)
640    {
641       this->priv_terminate_string();
642       if(a == this->alloc()){
643          this->swap_data(s);
644       }
645       else{
646          this->assign(s.begin(), s.end());
647       }
648    }
649 
650    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
651    //!   and is initialized by a specific number of characters of the s string.
basic_string(const basic_string & s,size_type pos,size_type n=npos,const allocator_type & a=allocator_type ())652    basic_string(const basic_string& s, size_type pos, size_type n = npos,
653                 const allocator_type& a = allocator_type())
654       : base_t(a)
655    {
656       this->priv_terminate_string();
657       if (pos > s.size())
658          throw_out_of_range("basic_string::basic_string out of range position");
659       else
660          this->assign
661             (s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos));
662    }
663 
664    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
665    //!   and is initialized by a specific number of characters of the s c-string.
basic_string(const CharT * s,size_type n,const allocator_type & a=allocator_type ())666    basic_string(const CharT* s, size_type n, const allocator_type& a = allocator_type())
667       : base_t(a)
668    {
669       this->priv_terminate_string();
670       this->assign(s, s + n);
671    }
672 
673    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
674    //!   and is initialized by the null-terminated s c-string.
basic_string(const CharT * s,const allocator_type & a=allocator_type ())675    basic_string(const CharT* s, const allocator_type& a = allocator_type())
676       : base_t(a)
677    {
678       this->priv_terminate_string();
679       this->assign(s, s + Traits::length(s));
680    }
681 
682    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
683    //!   and is initialized by n copies of c.
basic_string(size_type n,CharT c,const allocator_type & a=allocator_type ())684    basic_string(size_type n, CharT c, const allocator_type& a = allocator_type())
685       : base_t(a)
686    {
687       this->priv_terminate_string();
688       this->assign(n, c);
689    }
690 
691    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
692    //!   and is initialized by n default-initialized characters.
basic_string(size_type n,default_init_t,const allocator_type & a=allocator_type ())693    basic_string(size_type n, default_init_t, const allocator_type& a = allocator_type())
694       : base_t(a, n + 1)
695    {
696       this->priv_size(n);
697       this->priv_terminate_string();
698    }
699 
700    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
701    //!   and a range of iterators.
702    template <class InputIterator>
basic_string(InputIterator f,InputIterator l,const allocator_type & a=allocator_type ())703    basic_string(InputIterator f, InputIterator l, const allocator_type& a = allocator_type())
704       : base_t(a)
705    {
706       this->priv_terminate_string();
707       this->assign(f, l);
708    }
709 
710    //! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
711    //!
712    //! <b>Throws</b>: Nothing.
713    //!
714    //! <b>Complexity</b>: Constant.
~basic_string()715    ~basic_string() BOOST_NOEXCEPT_OR_NOTHROW
716    {}
717 
718    //! <b>Effects</b>: Copy constructs a string.
719    //!
720    //! <b>Postcondition</b>: x == *this.
721    //!
722    //! <b>Complexity</b>: Linear to the elements x contains.
operator =(BOOST_COPY_ASSIGN_REF (basic_string)x)723    basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
724    {
725       if (&x != this){
726          allocator_type &this_alloc     = this->alloc();
727          const allocator_type &x_alloc  = x.alloc();
728          container_detail::bool_<allocator_traits_type::
729             propagate_on_container_copy_assignment::value> flag;
730          if(flag && this_alloc != x_alloc){
731             if(!this->is_short()){
732                this->deallocate_block();
733                this->is_short(true);
734                Traits::assign(*this->priv_addr(), CharT(0));
735                this->priv_short_size(0);
736             }
737          }
738          container_detail::assign_alloc(this->alloc(), x.alloc(), flag);
739          this->assign(x.begin(), x.end());
740       }
741       return *this;
742    }
743 
744    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
745    //!
746    //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
747    //!   is false and allocation throws
748    //!
749    //! <b>Complexity</b>: Constant if allocator_traits_type::
750    //!   propagate_on_container_move_assignment is true or
751    //!   this->get>allocator() == x.get_allocator(). Linear otherwise.
operator =(BOOST_RV_REF (basic_string)x)752    basic_string& operator=(BOOST_RV_REF(basic_string) x)
753       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
754                                   || allocator_traits_type::is_always_equal::value)
755    {
756       //for move constructor, no aliasing (&x != this) is assummed.
757       BOOST_ASSERT(this != &x);
758       allocator_type &this_alloc = this->alloc();
759       allocator_type &x_alloc    = x.alloc();
760       const bool propagate_alloc = allocator_traits_type::
761             propagate_on_container_move_assignment::value;
762       container_detail::bool_<propagate_alloc> flag;
763       const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
764       //Resources can be transferred if both allocators are
765       //going to be equal after this function (either propagated or already equal)
766       if(propagate_alloc || allocators_equal){
767          //Destroy objects but retain memory in case x reuses it in the future
768          this->clear();
769          //Move allocator if needed
770          container_detail::move_alloc(this_alloc, x_alloc, flag);
771          //Nothrow swap
772          this->swap_data(x);
773       }
774       //Else do a one by one move
775       else{
776          this->assign( x.begin(), x.end());
777       }
778       return *this;
779    }
780 
781    //! <b>Effects</b>: Assignment from a null-terminated c-string.
operator =(const CharT * s)782    basic_string& operator=(const CharT* s)
783    { return this->assign(s, s + Traits::length(s)); }
784 
785    //! <b>Effects</b>: Assignment from character.
operator =(CharT c)786    basic_string& operator=(CharT c)
787    { return this->assign(static_cast<size_type>(1), c); }
788 
789    //! <b>Effects</b>: Returns a copy of the internal allocator.
790    //!
791    //! <b>Throws</b>: If allocator's copy constructor throws.
792    //!
793    //! <b>Complexity</b>: Constant.
get_allocator() const794    allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
795    { return this->alloc(); }
796 
797    //! <b>Effects</b>: Returns a reference to the internal allocator.
798    //!
799    //! <b>Throws</b>: Nothing
800    //!
801    //! <b>Complexity</b>: Constant.
802    //!
803    //! <b>Note</b>: Non-standard extension.
get_stored_allocator()804    stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
805    {  return this->alloc(); }
806 
807    //! <b>Effects</b>: Returns a reference to the internal allocator.
808    //!
809    //! <b>Throws</b>: Nothing
810    //!
811    //! <b>Complexity</b>: Constant.
812    //!
813    //! <b>Note</b>: Non-standard extension.
get_stored_allocator() const814    const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
815    {  return this->alloc(); }
816 
817    //////////////////////////////////////////////
818    //
819    //                iterators
820    //
821    //////////////////////////////////////////////
822 
823    //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
824    //!
825    //! <b>Throws</b>: Nothing.
826    //!
827    //! <b>Complexity</b>: Constant.
begin()828    iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
829    { return this->priv_addr(); }
830 
831    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
832    //!
833    //! <b>Throws</b>: Nothing.
834    //!
835    //! <b>Complexity</b>: Constant.
begin() const836    const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
837    { return this->priv_addr(); }
838 
839    //! <b>Effects</b>: Returns an iterator to the end of the vector.
840    //!
841    //! <b>Throws</b>: Nothing.
842    //!
843    //! <b>Complexity</b>: Constant.
end()844    iterator end() BOOST_NOEXCEPT_OR_NOTHROW
845    { return this->priv_end_addr(); }
846 
847    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
848    //!
849    //! <b>Throws</b>: Nothing.
850    //!
851    //! <b>Complexity</b>: Constant.
end() const852    const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
853    { return this->priv_end_addr(); }
854 
855    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
856    //! of the reversed vector.
857    //!
858    //! <b>Throws</b>: Nothing.
859    //!
860    //! <b>Complexity</b>: Constant.
rbegin()861    reverse_iterator rbegin()  BOOST_NOEXCEPT_OR_NOTHROW
862    { return reverse_iterator(this->priv_end_addr()); }
863 
864    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
865    //! of the reversed vector.
866    //!
867    //! <b>Throws</b>: Nothing.
868    //!
869    //! <b>Complexity</b>: Constant.
rbegin() const870    const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
871    { return this->crbegin(); }
872 
873    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
874    //! of the reversed vector.
875    //!
876    //! <b>Throws</b>: Nothing.
877    //!
878    //! <b>Complexity</b>: Constant.
rend()879    reverse_iterator rend()  BOOST_NOEXCEPT_OR_NOTHROW
880    { return reverse_iterator(this->priv_addr()); }
881 
882    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
883    //! of the reversed vector.
884    //!
885    //! <b>Throws</b>: Nothing.
886    //!
887    //! <b>Complexity</b>: Constant.
rend() const888    const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
889    { return this->crend(); }
890 
891    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
892    //!
893    //! <b>Throws</b>: Nothing.
894    //!
895    //! <b>Complexity</b>: Constant.
cbegin() const896    const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
897    { return this->priv_addr(); }
898 
899    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
900    //!
901    //! <b>Throws</b>: Nothing.
902    //!
903    //! <b>Complexity</b>: Constant.
cend() const904    const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
905    { return this->priv_end_addr(); }
906 
907    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
908    //! of the reversed vector.
909    //!
910    //! <b>Throws</b>: Nothing.
911    //!
912    //! <b>Complexity</b>: Constant.
crbegin() const913    const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
914    { return const_reverse_iterator(this->priv_end_addr()); }
915 
916    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
917    //! of the reversed vector.
918    //!
919    //! <b>Throws</b>: Nothing.
920    //!
921    //! <b>Complexity</b>: Constant.
crend() const922    const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
923    { return const_reverse_iterator(this->priv_addr()); }
924 
925    //////////////////////////////////////////////
926    //
927    //                capacity
928    //
929    //////////////////////////////////////////////
930 
931    //! <b>Effects</b>: Returns true if the vector contains no elements.
932    //!
933    //! <b>Throws</b>: Nothing.
934    //!
935    //! <b>Complexity</b>: Constant.
empty() const936    bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
937    { return !this->priv_size(); }
938 
939    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
940    //!
941    //! <b>Throws</b>: Nothing.
942    //!
943    //! <b>Complexity</b>: Constant.
size() const944    size_type size() const    BOOST_NOEXCEPT_OR_NOTHROW
945    { return this->priv_size(); }
946 
947    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
948    //!
949    //! <b>Throws</b>: Nothing.
950    //!
951    //! <b>Complexity</b>: Constant.
length() const952    size_type length() const BOOST_NOEXCEPT_OR_NOTHROW
953    { return this->size(); }
954 
955    //! <b>Effects</b>: Returns the largest possible size of the vector.
956    //!
957    //! <b>Throws</b>: Nothing.
958    //!
959    //! <b>Complexity</b>: Constant.
max_size() const960    size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
961    { return base_t::max_size(); }
962 
963    //! <b>Effects</b>: Inserts or erases elements at the end such that
964    //!   the size becomes n. New elements are copy constructed from x.
965    //!
966    //! <b>Throws</b>: If memory allocation throws
967    //!
968    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
resize(size_type n,CharT c)969    void resize(size_type n, CharT c)
970    {
971       if (n <= this->size())
972          this->erase(this->begin() + n, this->end());
973       else
974          this->append(n - this->size(), c);
975    }
976 
977    //! <b>Effects</b>: Inserts or erases elements at the end such that
978    //!   the size becomes n. New elements are value initialized.
979    //!
980    //! <b>Throws</b>: If memory allocation throws
981    //!
982    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
resize(size_type n)983    void resize(size_type n)
984    { resize(n, CharT()); }
985 
986 
987    //! <b>Effects</b>: Inserts or erases elements at the end such that
988    //!   the size becomes n. New elements are uninitialized.
989    //!
990    //! <b>Throws</b>: If memory allocation throws
991    //!
992    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
993    //!
994    //! <b>Note</b>: Non-standard extension
resize(size_type n,default_init_t)995    void resize(size_type n, default_init_t)
996    {
997       if (n <= this->size())
998          this->erase(this->begin() + n, this->end());
999       else{
1000          this->priv_reserve(n, false);
1001          this->priv_size(n);
1002          this->priv_terminate_string();
1003       }
1004    }
1005 
1006    //! <b>Effects</b>: Number of elements for which memory has been allocated.
1007    //!   capacity() is always greater than or equal to size().
1008    //!
1009    //! <b>Throws</b>: Nothing.
1010    //!
1011    //! <b>Complexity</b>: Constant.
capacity() const1012    size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1013    { return this->priv_capacity(); }
1014 
1015    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1016    //!   effect. Otherwise, it is a request for allocation of additional memory.
1017    //!   If the request is successful, then capacity() is greater than or equal to
1018    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1019    //!
1020    //! <b>Throws</b>: If memory allocation allocation throws
reserve(size_type res_arg)1021    void reserve(size_type res_arg)
1022    {  this->priv_reserve(res_arg);  }
1023 
1024    //! <b>Effects</b>: Tries to deallocate the excess of memory created
1025    //!   with previous allocations. The size of the string is unchanged
1026    //!
1027    //! <b>Throws</b>: Nothing
1028    //!
1029    //! <b>Complexity</b>: Linear to size().
shrink_to_fit()1030    void shrink_to_fit()
1031    {
1032       //Check if shrinking is possible
1033       if(this->priv_storage() > InternalBufferChars){
1034          //Check if we should pass from dynamically allocated buffer
1035          //to the internal storage
1036          if(this->priv_size() < InternalBufferChars){
1037             //Dynamically allocated buffer attributes
1038             pointer   long_addr    = this->priv_long_addr();
1039             size_type long_storage = this->priv_long_storage();
1040             size_type long_size    = this->priv_long_size();
1041             //Shrink from allocated buffer to the internal one, including trailing null
1042             Traits::copy( container_detail::to_raw_pointer(this->priv_short_addr())
1043                         , container_detail::to_raw_pointer(long_addr)
1044                         , long_size+1);
1045             this->is_short(true);
1046             this->alloc().deallocate(long_addr, long_storage);
1047          }
1048          else{
1049             //Shrinking in dynamic buffer
1050             this->priv_shrink_to_fit_dynamic_buffer(alloc_version());
1051          }
1052       }
1053    }
1054 
1055    //////////////////////////////////////////////
1056    //
1057    //               element access
1058    //
1059    //////////////////////////////////////////////
1060 
1061    //! <b>Requires</b>: size() > n.
1062    //!
1063    //! <b>Effects</b>: Returns a reference to the nth element
1064    //!   from the beginning of the container.
1065    //!
1066    //! <b>Throws</b>: Nothing.
1067    //!
1068    //! <b>Complexity</b>: Constant.
operator [](size_type n)1069    reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1070       { return *(this->priv_addr() + n); }
1071 
1072    //! <b>Requires</b>: size() > n.
1073    //!
1074    //! <b>Effects</b>: Returns a const reference to the nth element
1075    //!   from the beginning of the container.
1076    //!
1077    //! <b>Throws</b>: Nothing.
1078    //!
1079    //! <b>Complexity</b>: Constant.
operator [](size_type n) const1080    const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1081       { return *(this->priv_addr() + n); }
1082 
1083    //! <b>Requires</b>: size() > n.
1084    //!
1085    //! <b>Effects</b>: Returns a reference to the nth element
1086    //!   from the beginning of the container.
1087    //!
1088    //! <b>Throws</b>: std::range_error if n >= size()
1089    //!
1090    //! <b>Complexity</b>: Constant.
at(size_type n)1091    reference at(size_type n)
1092    {
1093       if (n >= this->size())
1094          throw_out_of_range("basic_string::at invalid subscript");
1095       return *(this->priv_addr() + n);
1096    }
1097 
1098    //! <b>Requires</b>: size() > n.
1099    //!
1100    //! <b>Effects</b>: Returns a const reference to the nth element
1101    //!   from the beginning of the container.
1102    //!
1103    //! <b>Throws</b>: std::range_error if n >= size()
1104    //!
1105    //! <b>Complexity</b>: Constant.
at(size_type n) const1106    const_reference at(size_type n) const {
1107       if (n >= this->size())
1108          throw_out_of_range("basic_string::at invalid subscript");
1109       return *(this->priv_addr() + n);
1110    }
1111 
1112    //////////////////////////////////////////////
1113    //
1114    //                modifiers
1115    //
1116    //////////////////////////////////////////////
1117 
1118    //! <b>Effects</b>: Calls append(str.data, str.size()).
1119    //!
1120    //! <b>Returns</b>: *this
operator +=(const basic_string & s)1121    basic_string& operator+=(const basic_string& s)
1122    {  return this->append(s); }
1123 
1124    //! <b>Effects</b>: Calls append(s).
1125    //!
1126    //! <b>Returns</b>: *this
operator +=(const CharT * s)1127    basic_string& operator+=(const CharT* s)
1128    {  return this->append(s); }
1129 
1130    //! <b>Effects</b>: Calls append(1, c).
1131    //!
1132    //! <b>Returns</b>: *this
operator +=(CharT c)1133    basic_string& operator+=(CharT c)
1134    {  this->push_back(c); return *this;   }
1135 
1136    //! <b>Effects</b>: Calls append(str.data(), str.size()).
1137    //!
1138    //! <b>Returns</b>: *this
append(const basic_string & s)1139    basic_string& append(const basic_string& s)
1140    {  return this->append(s.begin(), s.end());  }
1141 
1142    //! <b>Requires</b>: pos <= str.size()
1143    //!
1144    //! <b>Effects</b>: Determines the effective length rlen of the string to append
1145    //! as the smaller of n and str.size() - pos and calls append(str.data() + pos, rlen).
1146    //!
1147    //! <b>Throws</b>: If memory allocation throws and out_of_range if pos > str.size()
1148    //!
1149    //! <b>Returns</b>: *this
append(const basic_string & s,size_type pos,size_type n)1150    basic_string& append(const basic_string& s, size_type pos, size_type n)
1151    {
1152       if (pos > s.size())
1153          throw_out_of_range("basic_string::append out of range position");
1154       return this->append(s.begin() + pos,
1155                           s.begin() + pos + container_detail::min_value(n, s.size() - pos));
1156    }
1157 
1158    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1159    //!
1160    //! <b>Effects</b>: The function replaces the string controlled by *this with
1161    //!   a string of length size() + n whose irst size() elements are a copy of the
1162    //!   original string controlled by *this and whose remaining
1163    //!   elements are a copy of the initial n elements of s.
1164    //!
1165    //! <b>Throws</b>: If memory allocation throws length_error if size() + n > max_size().
1166    //!
1167    //! <b>Returns</b>: *this
append(const CharT * s,size_type n)1168    basic_string& append(const CharT* s, size_type n)
1169    {  return this->append(s, s + n);  }
1170 
1171    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1172    //!
1173    //! <b>Effects</b>: Calls append(s, traits::length(s)).
1174    //!
1175    //! <b>Returns</b>: *this
append(const CharT * s)1176    basic_string& append(const CharT* s)
1177    {  return this->append(s, s + Traits::length(s));  }
1178 
1179    //! <b>Effects</b>: Equivalent to append(basic_string(n, c)).
1180    //!
1181    //! <b>Returns</b>: *this
append(size_type n,CharT c)1182    basic_string& append(size_type n, CharT c)
1183    {  return this->append(cvalue_iterator(c, n), cvalue_iterator()); }
1184 
1185    //! <b>Requires</b>: [first,last) is a valid range.
1186    //!
1187    //! <b>Effects</b>: Equivalent to append(basic_string(first, last)).
1188    //!
1189    //! <b>Returns</b>: *this
1190    template <class InputIter>
append(InputIter first,InputIter last)1191    basic_string& append(InputIter first, InputIter last)
1192    {  this->insert(this->end(), first, last);   return *this;  }
1193 
1194    //! <b>Effects</b>: Equivalent to append(static_cast<size_type>(1), c).
push_back(CharT c)1195    void push_back(CharT c)
1196    {
1197       const size_type old_size = this->priv_size();
1198       if (old_size < this->capacity()){
1199          const pointer addr = this->priv_addr();
1200          this->priv_construct_null(addr + old_size + 1);
1201          Traits::assign(addr[old_size], c);
1202          this->priv_size(old_size+1);
1203       }
1204       else{
1205          //No enough memory, insert a new object at the end
1206          this->append(size_type(1), c);
1207       }
1208    }
1209 
1210    //! <b>Effects</b>: Equivalent to assign(str, 0, npos).
1211    //!
1212    //! <b>Returns</b>: *this
assign(const basic_string & s)1213    basic_string& assign(const basic_string& s)
1214    {  return this->operator=(s); }
1215 
1216    //! <b>Effects</b>: The function replaces the string controlled by *this
1217    //!    with a string of length str.size() whose elements are a copy of the string
1218    //!   controlled by str. Leaves str in a valid but unspecified state.
1219    //!
1220    //! <b>Throws</b>: Nothing
1221    //!
1222    //! <b>Returns</b>: *this
assign(BOOST_RV_REF (basic_string)ms)1223    basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_NOEXCEPT_OR_NOTHROW
1224    {  return this->swap_data(ms), *this;  }
1225 
1226    //! <b>Requires</b>: pos <= str.size()
1227    //!
1228    //! <b>Effects</b>: Determines the effective length rlen of the string to assign as
1229    //!   the smaller of n and str.size() - pos and calls assign(str.data() + pos rlen).
1230    //!
1231    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > str.size().
1232    //!
1233    //! <b>Returns</b>: *this
assign(const basic_string & s,size_type pos,size_type n)1234    basic_string& assign(const basic_string& s, size_type pos, size_type n)
1235    {
1236       if (pos > s.size())
1237          throw_out_of_range("basic_string::assign out of range position");
1238       return this->assign(s.begin() + pos,
1239                           s.begin() + pos + container_detail::min_value(n, s.size() - pos));
1240    }
1241 
1242    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1243    //!
1244    //! <b>Effects</b>: Replaces the string controlled by *this with a string of
1245    //! length n whose elements are a copy of those pointed to by s.
1246    //!
1247    //! <b>Throws</b>: If memory allocation throws or length_error if n > max_size().
1248    //!
1249    //! <b>Returns</b>: *this
assign(const CharT * s,size_type n)1250    basic_string& assign(const CharT* s, size_type n)
1251    {  return this->assign(s, s + n);   }
1252 
1253    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1254    //!
1255    //! <b>Effects</b>: Calls assign(s, traits::length(s)).
1256    //!
1257    //! <b>Returns</b>: *this
assign(const CharT * s)1258    basic_string& assign(const CharT* s)
1259    { return this->assign(s, s + Traits::length(s)); }
1260 
1261    //! <b>Effects</b>: Equivalent to assign(basic_string(n, c)).
1262    //!
1263    //! <b>Returns</b>: *this
assign(size_type n,CharT c)1264    basic_string& assign(size_type n, CharT c)
1265    {  return this->assign(cvalue_iterator(c, n), cvalue_iterator()); }
1266 
1267    //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
1268     //!
1269     //! <b>Returns</b>: *this
assign(const CharT * first,const CharT * last)1270     basic_string& assign(const CharT* first, const CharT* last)
1271     {
1272        size_type n = static_cast<size_type>(last - first);
1273        this->reserve(n);
1274        CharT* ptr = container_detail::to_raw_pointer(this->priv_addr());
1275        Traits::copy(ptr, first, n);
1276        this->priv_construct_null(ptr + n);
1277        this->priv_size(n);
1278        return *this;
1279     }
1280 
1281    //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
1282    //!
1283    //! <b>Returns</b>: *this
1284    template <class InputIter>
assign(InputIter first,InputIter last,typename container_detail::disable_if_convertible<InputIter,size_type>::type * =0)1285    basic_string& assign(InputIter first, InputIter last
1286       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1287       , typename container_detail::disable_if_convertible<InputIter, size_type>::type * = 0
1288       #endif
1289       )
1290    {
1291       size_type cur = 0;
1292       const pointer addr = this->priv_addr();
1293       CharT *ptr = container_detail::to_raw_pointer(addr);
1294       const size_type old_size = this->priv_size();
1295       while (first != last && cur != old_size) {
1296          Traits::assign(*ptr, *first);
1297          ++first;
1298          ++cur;
1299          ++ptr;
1300       }
1301       if (first == last)
1302          this->erase(addr + cur, addr + old_size);
1303       else
1304          this->append(first, last);
1305       return *this;
1306    }
1307 
1308    //! <b>Requires</b>: pos <= size().
1309    //!
1310    //! <b>Effects</b>: Calls insert(pos, str.data(), str.size()).
1311    //!
1312    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
1313    //!
1314    //! <b>Returns</b>: *this
insert(size_type pos,const basic_string & s)1315    basic_string& insert(size_type pos, const basic_string& s)
1316    {
1317       const size_type sz = this->size();
1318       if (pos > sz)
1319          throw_out_of_range("basic_string::insert out of range position");
1320       if (sz > this->max_size() - s.size())
1321          throw_length_error("basic_string::insert max_size() exceeded");
1322       this->insert(this->priv_addr() + pos, s.begin(), s.end());
1323       return *this;
1324    }
1325 
1326    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
1327    //!
1328    //! <b>Effects</b>: Determines the effective length rlen of the string to insert as
1329    //!   the smaller of n and str.size() - pos2 and calls insert(pos1, str.data() + pos2, rlen).
1330    //!
1331    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size().
1332    //!
1333    //! <b>Returns</b>: *this
insert(size_type pos1,const basic_string & s,size_type pos2,size_type n)1334    basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n)
1335    {
1336       const size_type sz = this->size();
1337       const size_type str_size = s.size();
1338       if (pos1 > sz || pos2 > str_size)
1339          throw_out_of_range("basic_string::insert out of range position");
1340       size_type len = container_detail::min_value(n, str_size - pos2);
1341       if (sz > this->max_size() - len)
1342          throw_length_error("basic_string::insert max_size() exceeded");
1343       const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2;
1344       const CharT *end_ptr = beg_ptr + len;
1345       this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
1346       return *this;
1347    }
1348 
1349    //! <b>Requires</b>: s points to an array of at least n elements of CharT and pos <= size().
1350    //!
1351    //! <b>Effects</b>: Replaces the string controlled by *this with a string of length size() + n
1352    //!   whose first pos elements are a copy of the initial elements of the original string
1353    //!   controlled by *this and whose next n elements are a copy of the elements in s and whose
1354    //!   remaining elements are a copy of the remaining elements of the original string controlled by *this.
1355    //!
1356    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size() or
1357    //!   length_error if size() + n > max_size().
1358    //!
1359    //! <b>Returns</b>: *this
insert(size_type pos,const CharT * s,size_type n)1360    basic_string& insert(size_type pos, const CharT* s, size_type n)
1361    {
1362       if (pos > this->size())
1363          throw_out_of_range("basic_string::insert out of range position");
1364       if (this->size() > this->max_size() - n)
1365          throw_length_error("basic_string::insert max_size() exceeded");
1366       this->insert(this->priv_addr() + pos, s, s + n);
1367       return *this;
1368    }
1369 
1370    //! <b>Requires</b>: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of CharT
1371    //!
1372    //! <b>Effects</b>: Calls insert(pos, s, traits::length(s)).
1373    //!
1374    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1375    //!   length_error if size() > max_size() - Traits::length(s)
1376    //!
1377    //! <b>Returns</b>: *this
insert(size_type pos,const CharT * s)1378    basic_string& insert(size_type pos, const CharT* s)
1379    {
1380       if (pos > this->size())
1381          throw_out_of_range("basic_string::insert out of range position");
1382       size_type len = Traits::length(s);
1383       if (this->size() > this->max_size() - len)
1384          throw_length_error("basic_string::insert max_size() exceeded");
1385       this->insert(this->priv_addr() + pos, s, s + len);
1386       return *this;
1387    }
1388 
1389    //! <b>Effects</b>: Equivalent to insert(pos, basic_string(n, c)).
1390    //!
1391    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1392    //!   length_error if size() > max_size() - n
1393    //!
1394    //! <b>Returns</b>: *this
insert(size_type pos,size_type n,CharT c)1395    basic_string& insert(size_type pos, size_type n, CharT c)
1396    {
1397       if (pos > this->size())
1398          throw_out_of_range("basic_string::insert out of range position");
1399       if (this->size() > this->max_size() - n)
1400          throw_length_error("basic_string::insert max_size() exceeded");
1401       this->insert(const_iterator(this->priv_addr() + pos), n, c);
1402       return *this;
1403    }
1404 
1405    //! <b>Requires</b>: p is a valid iterator on *this.
1406    //!
1407    //! <b>Effects</b>: inserts a copy of c before the character referred to by p.
1408    //!
1409    //! <b>Returns</b>: An iterator which refers to the copy of the inserted character.
insert(const_iterator p,CharT c)1410    iterator insert(const_iterator p, CharT c)
1411    {
1412       size_type new_offset = p - this->priv_addr();
1413       this->insert(p, cvalue_iterator(c, 1), cvalue_iterator());
1414       return this->priv_addr() + new_offset;
1415    }
1416 
1417 
1418    //! <b>Requires</b>: p is a valid iterator on *this.
1419    //!
1420    //! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
1421    //!
1422    //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
insert(const_iterator p,size_type n,CharT c)1423    iterator insert(const_iterator p, size_type n, CharT c)
1424    {  return this->insert(p, cvalue_iterator(c, n), cvalue_iterator());  }
1425 
1426    //! <b>Requires</b>: p is a valid iterator on *this. [first,last) is a valid range.
1427    //!
1428    //! <b>Effects</b>: Equivalent to insert(p - begin(), basic_string(first, last)).
1429    //!
1430    //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
1431    template <class InputIter>
insert(const_iterator p,InputIter first,InputIter last,typename container_detail::disable_if_or<void,container_detail::is_convertible<InputIter,size_type>,container_detail::is_not_input_iterator<InputIter>>::type * =0)1432    iterator insert(const_iterator p, InputIter first, InputIter last
1433       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1434       , typename container_detail::disable_if_or
1435          < void
1436          , container_detail::is_convertible<InputIter, size_type>
1437          , container_detail::is_not_input_iterator<InputIter>
1438          >::type * = 0
1439       #endif
1440       )
1441    {
1442       const size_type n_pos = p - this->cbegin();
1443       for ( ; first != last; ++first, ++p) {
1444          p = this->insert(p, *first);
1445       }
1446       return this->begin() + n_pos;
1447    }
1448 
1449    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1450    template <class ForwardIter>
insert(const_iterator p,ForwardIter first,ForwardIter last,typename container_detail::disable_if_or<void,container_detail::is_convertible<ForwardIter,size_type>,container_detail::is_input_iterator<ForwardIter>>::type * =0)1451    iterator insert(const_iterator p, ForwardIter first, ForwardIter last
1452       , typename container_detail::disable_if_or
1453          < void
1454          , container_detail::is_convertible<ForwardIter, size_type>
1455          , container_detail::is_input_iterator<ForwardIter>
1456          >::type * = 0
1457       )
1458    {
1459       const size_type n_pos = p - this->cbegin();
1460       if (first != last) {
1461          const size_type n = boost::container::iterator_distance(first, last);
1462          const size_type old_size = this->priv_size();
1463          const size_type remaining = this->capacity() - old_size;
1464          const pointer old_start = this->priv_addr();
1465          bool enough_capacity = false;
1466          size_type new_cap = 0;
1467 
1468          //Check if we have enough capacity
1469          pointer hint = pointer();
1470          pointer allocation_ret = pointer();
1471          if (remaining >= n){
1472             enough_capacity = true;
1473          }
1474          else {
1475             //Otherwise expand current buffer or allocate new storage
1476             new_cap  = this->next_capacity(n);
1477             hint = old_start;
1478             allocation_ret = this->allocation_command
1479                   (allocate_new | expand_fwd | expand_bwd, old_size + n + 1, new_cap, hint);
1480 
1481             //Check forward expansion
1482             if(old_start == allocation_ret){
1483                enough_capacity = true;
1484                this->priv_storage(new_cap);
1485             }
1486          }
1487 
1488          //Reuse same buffer
1489          if(enough_capacity){
1490             const size_type elems_after = old_size - (p - old_start);
1491             const size_type old_length = old_size;
1492             if (elems_after >= n) {
1493                const pointer pointer_past_last = old_start + old_size + 1;
1494                priv_uninitialized_copy(old_start + (old_size - n + 1),
1495                                        pointer_past_last, pointer_past_last);
1496 
1497                this->priv_size(old_size+n);
1498                Traits::move(const_cast<CharT*>(container_detail::to_raw_pointer(p + n)),
1499                            container_detail::to_raw_pointer(p),
1500                            (elems_after - n) + 1);
1501                this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(p)));
1502             }
1503             else {
1504                ForwardIter mid = first;
1505                boost::container::iterator_advance(mid, elems_after + 1);
1506 
1507                priv_uninitialized_copy(mid, last, old_start + old_size + 1);
1508                const size_type newer_size = old_size + (n - elems_after);
1509                this->priv_size(newer_size);
1510                priv_uninitialized_copy
1511                   (p, const_iterator(old_start + old_length + 1),
1512                   old_start + newer_size);
1513                this->priv_size(newer_size + elems_after);
1514                this->priv_copy(first, mid, const_cast<CharT*>(container_detail::to_raw_pointer(p)));
1515             }
1516          }
1517          else{
1518             pointer new_start = allocation_ret;
1519             if(!hint){
1520                //Copy data to new buffer
1521                size_type new_length = 0;
1522                //This can't throw, since characters are POD
1523                new_length += priv_uninitialized_copy
1524                               (const_iterator(old_start), p, new_start);
1525                new_length += priv_uninitialized_copy
1526                               (first, last, new_start + new_length);
1527                new_length += priv_uninitialized_copy
1528                               (p, const_iterator(old_start + old_size),
1529                               new_start + new_length);
1530                this->priv_construct_null(new_start + new_length);
1531 
1532                this->deallocate_block();
1533                this->is_short(false);
1534                this->priv_long_addr(new_start);
1535                this->priv_long_size(new_length);
1536                this->priv_long_storage(new_cap);
1537             }
1538             else{
1539                //value_type is POD, so backwards expansion is much easier
1540                //than with vector<T>
1541                value_type * const oldbuf     = container_detail::to_raw_pointer(old_start);
1542                value_type * const newbuf     = container_detail::to_raw_pointer(new_start);
1543                const value_type *const pos   = container_detail::to_raw_pointer(p);
1544                const size_type before  = pos - oldbuf;
1545 
1546                //First move old data
1547                Traits::move(newbuf, oldbuf, before);
1548                Traits::move(newbuf + before + n, pos, old_size - before);
1549                //Now initialize the new data
1550                priv_uninitialized_copy(first, last, new_start + before);
1551                this->priv_construct_null(new_start + (old_size + n));
1552                this->is_short(false);
1553                this->priv_long_addr(new_start);
1554                this->priv_long_size(old_size + n);
1555                this->priv_long_storage(new_cap);
1556             }
1557          }
1558       }
1559       return this->begin() + n_pos;
1560    }
1561    #endif
1562 
1563    //! <b>Requires</b>: pos <= size()
1564    //!
1565    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos.
1566    //!   The function then replaces the string controlled by *this with a string of length size() - xlen
1567    //!   whose first pos elements are a copy of the initial elements of the original string controlled by *this,
1568    //!   and whose remaining elements are a copy of the elements of the original string controlled by *this
1569    //!   beginning at position pos + xlen.
1570    //!
1571    //! <b>Throws</b>: out_of_range if pos > size().
1572    //!
1573    //! <b>Returns</b>: *this
erase(size_type pos=0,size_type n=npos)1574    basic_string& erase(size_type pos = 0, size_type n = npos)
1575    {
1576       if (pos > this->size())
1577          throw_out_of_range("basic_string::erase out of range position");
1578       const pointer addr = this->priv_addr();
1579       erase(addr + pos, addr + pos + container_detail::min_value(n, this->size() - pos));
1580       return *this;
1581    }
1582 
1583    //! <b>Effects</b>: Removes the character referred to by p.
1584    //!
1585    //! <b>Throws</b>: Nothing
1586    //!
1587    //! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being
1588    //!    erased. If no such element exists, end() is returned.
erase(const_iterator p)1589    iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1590    {
1591       // The move includes the terminating null.
1592       CharT * const ptr = const_cast<CharT*>(container_detail::to_raw_pointer(p));
1593       const size_type old_size = this->priv_size();
1594       Traits::move(ptr,
1595                    container_detail::to_raw_pointer(p + 1),
1596                    old_size - (p - this->priv_addr()));
1597       this->priv_size(old_size-1);
1598       return iterator(ptr);
1599    }
1600 
1601    //! <b>Requires</b>: first and last are valid iterators on *this, defining a range [first,last).
1602    //!
1603    //! <b>Effects</b>: Removes the characters in the range [first,last).
1604    //!
1605    //! <b>Throws</b>: Nothing
1606    //!
1607    //! <b>Returns</b>: An iterator which points to the element pointed to by last prior to
1608    //!   the other elements being erased. If no such element exists, end() is returned.
erase(const_iterator first,const_iterator last)1609    iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
1610    {
1611       CharT * f = const_cast<CharT*>(container_detail::to_raw_pointer(first));
1612       if (first != last) { // The move includes the terminating null.
1613          const size_type num_erased = last - first;
1614          const size_type old_size = this->priv_size();
1615          Traits::move(f,
1616                       container_detail::to_raw_pointer(last),
1617                       (old_size + 1)-(last - this->priv_addr()));
1618          const size_type new_length = old_size - num_erased;
1619          this->priv_size(new_length);
1620       }
1621       return iterator(f);
1622    }
1623 
1624    //! <b>Requires</b>: !empty()
1625    //!
1626    //! <b>Throws</b>: Nothing
1627    //!
1628    //! <b>Effects</b>: Equivalent to erase(size() - 1, 1).
pop_back()1629    void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
1630    {
1631       const size_type old_size = this->priv_size();
1632       Traits::assign(this->priv_addr()[old_size-1], CharT(0));
1633       this->priv_size(old_size-1);;
1634    }
1635 
1636    //! <b>Effects</b>: Erases all the elements of the vector.
1637    //!
1638    //! <b>Throws</b>: Nothing.
1639    //!
1640    //! <b>Complexity</b>: Linear to the number of elements in the vector.
clear()1641    void clear() BOOST_NOEXCEPT_OR_NOTHROW
1642    {
1643       if (!this->empty()) {
1644          Traits::assign(*this->priv_addr(), CharT(0));
1645          this->priv_size(0);
1646       }
1647    }
1648 
1649    //! <b>Requires</b>: pos1 <= size().
1650    //!
1651    //! <b>Effects</b>: Calls replace(pos1, n1, str.data(), str.size()).
1652    //!
1653    //! <b>Throws</b>: if memory allocation throws or out_of_range if pos1 > size().
1654    //!
1655    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,const basic_string & str)1656    basic_string& replace(size_type pos1, size_type n1, const basic_string& str)
1657    {
1658       if (pos1 > this->size())
1659          throw_out_of_range("basic_string::replace out of range position");
1660       const size_type len = container_detail::min_value(n1, this->size() - pos1);
1661       if (this->size() - len >= this->max_size() - str.size())
1662          throw_length_error("basic_string::replace max_size() exceeded");
1663       const pointer addr = this->priv_addr();
1664       return this->replace( const_iterator(addr + pos1)
1665                           , const_iterator(addr + pos1 + len)
1666                           , str.begin(), str.end());
1667    }
1668 
1669    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size().
1670    //!
1671    //! <b>Effects</b>: Determines the effective length rlen of the string to be
1672    //!   inserted as the smaller of n2 and str.size() - pos2 and calls
1673    //!   replace(pos1, n1, str.data() + pos2, rlen).
1674    //!
1675    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or pos2 > str.size().
1676    //!
1677    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,const basic_string & str,size_type pos2,size_type n2)1678    basic_string& replace(size_type pos1, size_type n1,
1679                          const basic_string& str, size_type pos2, size_type n2)
1680    {
1681       if (pos1 > this->size() || pos2 > str.size())
1682          throw_out_of_range("basic_string::replace out of range position");
1683       const size_type len1 = container_detail::min_value(n1, this->size() - pos1);
1684       const size_type len2 = container_detail::min_value(n2, str.size() - pos2);
1685       if (this->size() - len1 >= this->max_size() - len2)
1686          throw_length_error("basic_string::replace max_size() exceeded");
1687       const pointer addr    = this->priv_addr();
1688       const pointer straddr = str.priv_addr();
1689       return this->replace(addr + pos1, addr + pos1 + len1,
1690                      straddr + pos2, straddr + pos2 + len2);
1691    }
1692 
1693    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
1694    //!
1695    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the
1696    //!   smaller of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error.
1697    //!   Otherwise, the function replaces the string controlled by *this with a string of
1698    //!   length size() - xlen + n2 whose first pos1 elements are a copy of the initial elements
1699    //!   of the original string controlled by *this, whose next n2 elements are a copy of the
1700    //!   initial n2 elements of s, and whose remaining elements are a copy of the elements of
1701    //!   the original string controlled by *this beginning at position pos + xlen.
1702    //!
1703    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
1704    //!   if the length of the  resulting string would exceed max_size()
1705    //!
1706    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,const CharT * s,size_type n2)1707    basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
1708    {
1709       if (pos1 > this->size())
1710          throw_out_of_range("basic_string::replace out of range position");
1711       const size_type len = container_detail::min_value(n1, this->size() - pos1);
1712       if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
1713          throw_length_error("basic_string::replace max_size() exceeded");
1714       const pointer addr    = this->priv_addr();
1715       return this->replace(addr + pos1, addr + pos1 + len, s, s + n2);
1716    }
1717 
1718    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
1719    //!
1720    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller
1721    //! of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. Otherwise,
1722    //! the function replaces the string controlled by *this with a string of length size() - xlen + n2
1723    //! whose first pos1 elements are a copy of the initial elements of the original string controlled
1724    //! by *this, whose next n2 elements are a copy of the initial n2 elements of s, and whose
1725    //! remaining elements are a copy of the elements of the original string controlled by *this
1726    //! beginning at position pos + xlen.
1727    //!
1728    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
1729    //!   if the length of the resulting string would exceed max_size()
1730    //!
1731    //! <b>Returns</b>: *this
replace(size_type pos,size_type n1,const CharT * s)1732    basic_string& replace(size_type pos, size_type n1, const CharT* s)
1733    {
1734       if (pos > this->size())
1735          throw_out_of_range("basic_string::replace out of range position");
1736       const size_type len = container_detail::min_value(n1, this->size() - pos);
1737       const size_type n2 = Traits::length(s);
1738       if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
1739          throw_length_error("basic_string::replace max_size() exceeded");
1740       const pointer addr    = this->priv_addr();
1741       return this->replace(addr + pos, addr + pos + len,
1742                      s, s + Traits::length(s));
1743    }
1744 
1745    //! <b>Requires</b>: pos1 <= size().
1746    //!
1747    //! <b>Effects</b>: Equivalent to replace(pos1, n1, basic_string(n2, c)).
1748    //!
1749    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
1750    //!   if the length of the  resulting string would exceed max_size()
1751    //!
1752    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,size_type n2,CharT c)1753    basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c)
1754    {
1755       if (pos1 > this->size())
1756          throw_out_of_range("basic_string::replace out of range position");
1757       const size_type len = container_detail::min_value(n1, this->size() - pos1);
1758       if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
1759          throw_length_error("basic_string::replace max_size() exceeded");
1760       const pointer addr    = this->priv_addr();
1761       return this->replace(addr + pos1, addr + pos1 + len, n2, c);
1762    }
1763 
1764    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
1765    //!
1766    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, str).
1767    //!
1768    //! <b>Throws</b>: if memory allocation throws
1769    //!
1770    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,const basic_string & str)1771    basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str)
1772    { return this->replace(i1, i2, str.begin(), str.end()); }
1773 
1774    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and
1775    //!   s points to an array of at least n elements
1776    //!
1777    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, n).
1778    //!
1779    //! <b>Throws</b>: if memory allocation throws
1780    //!
1781    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,const CharT * s,size_type n)1782    basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n)
1783    { return this->replace(i1, i2, s, s + n); }
1784 
1785    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and s points to an
1786    //!   array of at least traits::length(s) + 1 elements of CharT.
1787    //!
1788    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, traits::length(s)).
1789    //!
1790    //! <b>Throws</b>: if memory allocation throws
1791    //!
1792    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,const CharT * s)1793    basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s)
1794    {  return this->replace(i1, i2, s, s + Traits::length(s));   }
1795 
1796    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
1797    //!
1798    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(n, c)).
1799    //!
1800    //! <b>Throws</b>: if memory allocation throws
1801    //!
1802    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,size_type n,CharT c)1803    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, CharT c)
1804    {
1805       const size_type len = static_cast<size_type>(i2 - i1);
1806       if (len >= n) {
1807          Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), n, c);
1808          erase(i1 + n, i2);
1809       }
1810       else {
1811          Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), len, c);
1812          insert(i2, n - len, c);
1813       }
1814       return *this;
1815    }
1816 
1817    //! <b>Requires</b>: [begin(),i1), [i1,i2) and [j1,j2) are valid ranges.
1818    //!
1819    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(j1, j2)).
1820    //!
1821    //! <b>Throws</b>: if memory allocation throws
1822    //!
1823    //! <b>Returns</b>: *this
1824    template <class InputIter>
replace(const_iterator i1,const_iterator i2,InputIter j1,InputIter j2,typename container_detail::disable_if_or<void,container_detail::is_convertible<InputIter,size_type>,container_detail::is_input_iterator<InputIter>>::type * =0)1825    basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
1826       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1827       , typename container_detail::disable_if_or
1828          < void
1829          , container_detail::is_convertible<InputIter, size_type>
1830          , container_detail::is_input_iterator<InputIter>
1831          >::type * = 0
1832       #endif
1833       )
1834    {
1835       for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
1836          Traits::assign(*const_cast<CharT*>(container_detail::to_raw_pointer(i1)), *j1);
1837       }
1838 
1839       if (j1 == j2)
1840          this->erase(i1, i2);
1841       else
1842          this->insert(i2, j1, j2);
1843       return *this;
1844    }
1845 
1846    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1847    template <class ForwardIter>
replace(const_iterator i1,const_iterator i2,ForwardIter j1,ForwardIter j2,typename container_detail::disable_if_or<void,container_detail::is_convertible<ForwardIter,size_type>,container_detail::is_not_input_iterator<ForwardIter>>::type * =0)1848    basic_string& replace(const_iterator i1, const_iterator i2, ForwardIter j1, ForwardIter j2
1849       , typename container_detail::disable_if_or
1850          < void
1851          , container_detail::is_convertible<ForwardIter, size_type>
1852          , container_detail::is_not_input_iterator<ForwardIter>
1853          >::type * = 0
1854       )
1855    {
1856       difference_type n = boost::container::iterator_distance(j1, j2);
1857       const difference_type len = i2 - i1;
1858       if (len >= n) {
1859          this->priv_copy(j1, j2, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
1860          this->erase(i1 + n, i2);
1861       }
1862       else {
1863          ForwardIter m = j1;
1864          boost::container::iterator_advance(m, len);
1865          this->priv_copy(j1, m, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
1866          this->insert(i2, m, j2);
1867       }
1868       return *this;
1869    }
1870    #endif
1871 
1872    //! <b>Requires</b>: pos <= size()
1873    //!
1874    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as the
1875    //!   smaller of n and size() - pos. s shall designate an array of at least rlen elements.
1876    //!   The function then replaces the string designated by s with a string of length rlen
1877    //!   whose elements are a copy of the string controlled by *this beginning at position pos.
1878    //!   The function does not append a null object to the string designated by s.
1879    //!
1880    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos > size().
1881    //!
1882    //! <b>Returns</b>: rlen
copy(CharT * s,size_type n,size_type pos=0) const1883    size_type copy(CharT* s, size_type n, size_type pos = 0) const
1884    {
1885       if (pos > this->size())
1886          throw_out_of_range("basic_string::copy out of range position");
1887       const size_type len = container_detail::min_value(n, this->size() - pos);
1888       Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len);
1889       return len;
1890    }
1891 
1892    //! <b>Effects</b>: *this contains the same sequence of characters that was in s,
1893    //!   s contains the same sequence of characters that was in *this.
1894    //!
1895    //! <b>Throws</b>: Nothing
swap(basic_string & x)1896    void swap(basic_string& x)
1897       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value
1898                                || allocator_traits_type::is_always_equal::value)
1899    {
1900       this->base_t::swap_data(x);
1901       container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
1902       container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
1903    }
1904 
1905    //////////////////////////////////////////////
1906    //
1907    //                 data access
1908    //
1909    //////////////////////////////////////////////
1910 
1911    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
1912    //!
1913    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
1914    //!
1915    //! <b>Complexity</b>: constant time.
c_str() const1916    const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW
1917    {  return container_detail::to_raw_pointer(this->priv_addr()); }
1918 
1919    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
1920    //!
1921    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
1922    //!
1923    //! <b>Complexity</b>: constant time.
data() const1924    const CharT* data()  const BOOST_NOEXCEPT_OR_NOTHROW
1925    {  return container_detail::to_raw_pointer(this->priv_addr()); }
1926 
1927    //////////////////////////////////////////////
1928    //
1929    //             string operations
1930    //
1931    //////////////////////////////////////////////
1932 
1933    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
1934    //!   of the following conditions obtain: 19 pos <= xpos and xpos + str.size() <= size();
1935    //!   2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
1936    //!
1937    //! <b>Throws</b>: Nothing
1938    //!
1939    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
find(const basic_string & s,size_type pos=0) const1940    size_type find(const basic_string& s, size_type pos = 0) const
1941    { return find(s.c_str(), pos, s.size()); }
1942 
1943    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1944    //!
1945    //! <b>Throws</b>: Nothing
1946    //!
1947    //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(s,n),pos).
find(const CharT * s,size_type pos,size_type n) const1948    size_type find(const CharT* s, size_type pos, size_type n) const
1949    {
1950       if (pos + n > this->size())
1951          return npos;
1952       else {
1953          const pointer addr = this->priv_addr();
1954          pointer finish = addr + this->priv_size();
1955          const const_iterator result =
1956             std::search(container_detail::to_raw_pointer(addr + pos),
1957                    container_detail::to_raw_pointer(finish),
1958                    s, s + n, Eq_traits<Traits>());
1959          return result != finish ? result - begin() : npos;
1960       }
1961    }
1962 
1963    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1964    //!
1965    //! <b>Throws</b>: Nothing
1966    //!
1967    //! <b>Returns</b>: find(basic_string(s), pos).
find(const CharT * s,size_type pos=0) const1968    size_type find(const CharT* s, size_type pos = 0) const
1969    { return this->find(s, pos, Traits::length(s)); }
1970 
1971    //! <b>Throws</b>: Nothing
1972    //!
1973    //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(1,c), pos).
find(CharT c,size_type pos=0) const1974    size_type find(CharT c, size_type pos = 0) const
1975    {
1976       const size_type sz = this->size();
1977       if (pos >= sz)
1978          return npos;
1979       else {
1980          const pointer addr    = this->priv_addr();
1981          pointer finish = addr + sz;
1982          const const_iterator result =
1983             std::find_if(addr + pos, finish,
1984                   std::bind2nd(Eq_traits<Traits>(), c));
1985          return result != finish ? result - begin() : npos;
1986       }
1987    }
1988 
1989    //! <b>Effects</b>: Determines the highest position xpos, if possible, such
1990    //!   that both of the following conditions obtain:
1991    //!   a) xpos <= pos and xpos + str.size() <= size();
1992    //!   b) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
1993    //!
1994    //! <b>Throws</b>: Nothing
1995    //!
1996    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
rfind(const basic_string & str,size_type pos=npos) const1997    size_type rfind(const basic_string& str, size_type pos = npos) const
1998       { return rfind(str.c_str(), pos, str.size()); }
1999 
2000    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2001    //!
2002    //! <b>Throws</b>: Nothing
2003    //!
2004    //! <b>Returns</b>: rfind(basic_string(s, n), pos).
rfind(const CharT * s,size_type pos,size_type n) const2005    size_type rfind(const CharT* s, size_type pos, size_type n) const
2006    {
2007       const size_type len = this->size();
2008 
2009       if (n > len)
2010          return npos;
2011       else if (n == 0)
2012          return container_detail::min_value(len, pos);
2013       else {
2014          const const_iterator last = begin() + container_detail::min_value(len - n, pos) + n;
2015          const const_iterator result = find_end(begin(), last,
2016                                                 s, s + n,
2017                                                 Eq_traits<Traits>());
2018          return result != last ? result - begin() : npos;
2019       }
2020    }
2021 
2022    //! <b>Requires</b>: pos <= size() and s points to an array of at least
2023    //!   traits::length(s) + 1 elements of CharT.
2024    //!
2025    //! <b>Throws</b>: Nothing
2026    //!
2027    //! <b>Returns</b>: rfind(basic_string(s), pos).
rfind(const CharT * s,size_type pos=npos) const2028    size_type rfind(const CharT* s, size_type pos = npos) const
2029       { return rfind(s, pos, Traits::length(s)); }
2030 
2031    //! <b>Throws</b>: Nothing
2032    //!
2033    //! <b>Returns</b>: rfind(basic_string<CharT,traits,Allocator>(1,c),pos).
rfind(CharT c,size_type pos=npos) const2034    size_type rfind(CharT c, size_type pos = npos) const
2035    {
2036       const size_type len = this->size();
2037 
2038       if (len < 1)
2039          return npos;
2040       else {
2041          const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
2042          const_reverse_iterator rresult =
2043             std::find_if(const_reverse_iterator(last), rend(),
2044                   std::bind2nd(Eq_traits<Traits>(), c));
2045          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
2046       }
2047    }
2048 
2049    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
2050    //!   following conditions obtain: a) pos <= xpos and xpos < size();
2051    //!   b) traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2052    //!
2053    //! <b>Throws</b>: Nothing
2054    //!
2055    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
find_first_of(const basic_string & s,size_type pos=0) const2056    size_type find_first_of(const basic_string& s, size_type pos = 0) const
2057       { return find_first_of(s.c_str(), pos, s.size()); }
2058 
2059    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2060    //!
2061    //! <b>Throws</b>: Nothing
2062    //!
2063    //! <b>Returns</b>: find_first_of(basic_string(s, n), pos).
find_first_of(const CharT * s,size_type pos,size_type n) const2064    size_type find_first_of(const CharT* s, size_type pos, size_type n) const
2065    {
2066       const size_type sz = this->size();
2067       if (pos >= sz)
2068          return npos;
2069       else {
2070          const pointer addr    = this->priv_addr();
2071          pointer finish = addr + sz;
2072          const_iterator result = std::find_first_of
2073             (addr + pos, finish, s, s + n, Eq_traits<Traits>());
2074          return result != finish ? result - this->begin() : npos;
2075       }
2076    }
2077 
2078    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2079    //!
2080    //! <b>Throws</b>: Nothing
2081    //!
2082    //! <b>Returns</b>: find_first_of(basic_string(s), pos).
find_first_of(const CharT * s,size_type pos=0) const2083    size_type find_first_of(const CharT* s, size_type pos = 0) const
2084       { return find_first_of(s, pos, Traits::length(s)); }
2085 
2086    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2087    //!
2088    //! <b>Throws</b>: Nothing
2089    //!
2090    //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,Allocator>(1,c), pos).
find_first_of(CharT c,size_type pos=0) const2091    size_type find_first_of(CharT c, size_type pos = 0) const
2092     { return find(c, pos); }
2093 
2094    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
2095    //!   the following conditions obtain: a) xpos <= pos and xpos < size(); b)
2096    //!   traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2097    //!
2098    //! <b>Throws</b>: Nothing
2099    //!
2100    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
find_last_of(const basic_string & str,size_type pos=npos) const2101    size_type find_last_of(const basic_string& str, size_type pos = npos) const
2102       { return find_last_of(str.c_str(), pos, str.size()); }
2103 
2104    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2105    //!
2106    //! <b>Throws</b>: Nothing
2107    //!
2108    //! <b>Returns</b>: find_last_of(basic_string(s, n), pos).
find_last_of(const CharT * s,size_type pos,size_type n) const2109    size_type find_last_of(const CharT* s, size_type pos, size_type n) const
2110    {
2111       const size_type len = this->size();
2112 
2113       if (len < 1)
2114          return npos;
2115       else {
2116          const pointer addr    = this->priv_addr();
2117          const const_iterator last = addr + container_detail::min_value(len - 1, pos) + 1;
2118          const const_reverse_iterator rresult =
2119             std::find_first_of(const_reverse_iterator(last), rend(),
2120                                s, s + n, Eq_traits<Traits>());
2121          return rresult != rend() ? (rresult.base() - 1) - addr : npos;
2122       }
2123    }
2124 
2125    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2126    //!
2127    //! <b>Throws</b>: Nothing
2128    //!
2129    //! <b>Returns</b>: find_last_of(basic_string<CharT,traits,Allocator>(1,c),pos).
find_last_of(const CharT * s,size_type pos=npos) const2130    size_type find_last_of(const CharT* s, size_type pos = npos) const
2131       { return find_last_of(s, pos, Traits::length(s)); }
2132 
2133    //! <b>Throws</b>: Nothing
2134    //!
2135    //! <b>Returns</b>: find_last_of(basic_string(s), pos).
find_last_of(CharT c,size_type pos=npos) const2136    size_type find_last_of(CharT c, size_type pos = npos) const
2137       {  return rfind(c, pos);   }
2138 
2139    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that
2140    //!   both of the following conditions obtain:
2141    //!   a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), str.at(I)) for no
2142    //!   element I of the string controlled by str.
2143    //!
2144    //! <b>Throws</b>: Nothing
2145    //!
2146    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
find_first_not_of(const basic_string & str,size_type pos=0) const2147    size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
2148       { return find_first_not_of(str.c_str(), pos, str.size()); }
2149 
2150    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2151    //!
2152    //! <b>Throws</b>: Nothing
2153    //!
2154    //! <b>Returns</b>: find_first_not_of(basic_string(s, n), pos).
find_first_not_of(const CharT * s,size_type pos,size_type n) const2155    size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const
2156    {
2157       if (pos > this->size())
2158          return npos;
2159       else {
2160          const pointer addr   = this->priv_addr();
2161          const pointer finish = addr + this->priv_size();
2162          const const_iterator result = std::find_if
2163             (addr + pos, finish, Not_within_traits<Traits>(s, s + n));
2164          return result != finish ? result - addr : npos;
2165       }
2166    }
2167 
2168    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2169    //!
2170    //! <b>Throws</b>: Nothing
2171    //!
2172    //! <b>Returns</b>: find_first_not_of(basic_string(s), pos).
find_first_not_of(const CharT * s,size_type pos=0) const2173    size_type find_first_not_of(const CharT* s, size_type pos = 0) const
2174       { return find_first_not_of(s, pos, Traits::length(s)); }
2175 
2176    //! <b>Throws</b>: Nothing
2177    //!
2178    //! <b>Returns</b>: find_first_not_of(basic_string(1, c), pos).
find_first_not_of(CharT c,size_type pos=0) const2179    size_type find_first_not_of(CharT c, size_type pos = 0) const
2180    {
2181       if (pos > this->size())
2182          return npos;
2183       else {
2184          const pointer addr   = this->priv_addr();
2185          const pointer finish = addr + this->priv_size();
2186          const const_iterator result
2187             = std::find_if(addr + pos, finish,
2188                      std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
2189          return result != finish ? result - begin() : npos;
2190       }
2191    }
2192 
2193    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
2194    //!   both of the following conditions obtain: a) xpos <= pos and xpos < size();
2195    //!   b) traits::eq(at(xpos), str.at(I)) for no element I of the string controlled by str.
2196    //!
2197    //! <b>Throws</b>: Nothing
2198    //!
2199    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
find_last_not_of(const basic_string & str,size_type pos=npos) const2200    size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
2201       { return find_last_not_of(str.c_str(), pos, str.size()); }
2202 
2203    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2204    //!
2205    //! <b>Throws</b>: Nothing
2206    //!
2207    //! <b>Returns</b>: find_last_not_of(basic_string(s, n), pos).
find_last_not_of(const CharT * s,size_type pos,size_type n) const2208    size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const
2209    {
2210       const size_type len = this->size();
2211 
2212       if (len < 1)
2213          return npos;
2214       else {
2215          const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
2216          const const_reverse_iterator rresult =
2217             std::find_if(const_reverse_iterator(last), rend(),
2218                     Not_within_traits<Traits>(s, s + n));
2219          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
2220       }
2221    }
2222 
2223    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2224    //!
2225    //! <b>Throws</b>: Nothing
2226    //!
2227    //! <b>Returns</b>: find_last_not_of(basic_string(s), pos).
find_last_not_of(const CharT * s,size_type pos=npos) const2228    size_type find_last_not_of(const CharT* s, size_type pos = npos) const
2229       { return find_last_not_of(s, pos, Traits::length(s)); }
2230 
2231    //! <b>Throws</b>: Nothing
2232    //!
2233    //! <b>Returns</b>: find_last_not_of(basic_string(1, c), pos).
find_last_not_of(CharT c,size_type pos=npos) const2234    size_type find_last_not_of(CharT c, size_type pos = npos) const
2235    {
2236       const size_type len = this->size();
2237 
2238       if (len < 1)
2239          return npos;
2240       else {
2241          const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
2242          const const_reverse_iterator rresult =
2243             std::find_if(const_reverse_iterator(last), rend(),
2244                   std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
2245          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
2246       }
2247    }
2248 
2249    //! <b>Requires</b>: Requires: pos <= size()
2250    //!
2251    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2252    //!   the smaller of n and size() - pos.
2253    //!
2254    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
2255    //!
2256    //! <b>Returns</b>: basic_string<CharT,traits,Allocator>(data()+pos,rlen).
substr(size_type pos=0,size_type n=npos) const2257    basic_string substr(size_type pos = 0, size_type n = npos) const
2258    {
2259       if (pos > this->size())
2260          throw_out_of_range("basic_string::substr out of range position");
2261       const pointer addr = this->priv_addr();
2262       return basic_string(addr + pos,
2263                           addr + pos + container_detail::min_value(n, size() - pos), this->alloc());
2264    }
2265 
2266    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2267    //!   the smaller of size() and str.size(). The function then compares the two strings by
2268    //!   calling traits::compare(data(), str.data(), rlen).
2269    //!
2270    //! <b>Throws</b>: Nothing
2271    //!
2272    //! <b>Returns</b>: The nonzero result if the result of the comparison is nonzero.
2273    //!   Otherwise, returns a value < 0 if size() < str.size(), a 0 value if size() == str.size(),
2274    //!   and value > 0 if size() > str.size()
compare(const basic_string & str) const2275    int compare(const basic_string& str) const
2276    {
2277       const pointer addr     = this->priv_addr();
2278       const pointer str_addr = str.priv_addr();
2279       return s_compare(addr, addr + this->priv_size(), str_addr, str_addr + str.priv_size());
2280    }
2281 
2282    //! <b>Requires</b>: pos1 <= size()
2283    //!
2284    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2285    //!   the smaller of
2286    //!
2287    //! <b>Throws</b>: out_of_range if pos1 > size()
2288    //!
2289    //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(str).
compare(size_type pos1,size_type n1,const basic_string & str) const2290    int compare(size_type pos1, size_type n1, const basic_string& str) const
2291    {
2292       if (pos1 > this->size())
2293          throw_out_of_range("basic_string::compare out of range position");
2294       const pointer addr    = this->priv_addr();
2295       const pointer str_addr = str.priv_addr();
2296       return s_compare(addr + pos1,
2297                         addr + pos1 + container_detail::min_value(n1, this->size() - pos1),
2298                         str_addr, str_addr + str.priv_size());
2299    }
2300 
2301    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
2302    //!
2303    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2304    //!   the smaller of
2305    //!
2306    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > str.size()
2307    //!
2308    //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)).
compare(size_type pos1,size_type n1,const basic_string & str,size_type pos2,size_type n2) const2309    int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) const
2310    {
2311       if (pos1 > this->size() || pos2 > str.size())
2312          throw_out_of_range("basic_string::compare out of range position");
2313       const pointer addr     = this->priv_addr();
2314       const pointer str_addr = str.priv_addr();
2315       return s_compare(addr + pos1,
2316                         addr + pos1 + container_detail::min_value(n1, this->size() - pos1),
2317                         str_addr + pos2,
2318                         str_addr + pos2 + container_detail::min_value(n2, str.size() - pos2));
2319    }
2320 
2321    //! <b>Throws</b>: Nothing
2322    //!
2323    //! <b>Returns</b>: compare(basic_string(s)).
compare(const CharT * s) const2324    int compare(const CharT* s) const
2325    {
2326       const pointer addr = this->priv_addr();
2327       return s_compare(addr, addr + this->priv_size(), s, s + Traits::length(s));
2328    }
2329 
2330 
2331    //! <b>Requires</b>: pos1 > size() and s points to an array of at least n2 elements of CharT.
2332    //!
2333    //! <b>Throws</b>: out_of_range if pos1 > size()
2334    //!
2335    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
compare(size_type pos1,size_type n1,const CharT * s,size_type n2) const2336    int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
2337    {
2338       if (pos1 > this->size())
2339          throw_out_of_range("basic_string::compare out of range position");
2340       const pointer addr = this->priv_addr();
2341       return s_compare( addr + pos1,
2342                         addr + pos1 + container_detail::min_value(n1, this->size() - pos1),
2343                         s, s + n2);
2344    }
2345 
2346    //! <b>Requires</b>: pos1 > size() and s points to an array of at least traits::length(s) + 1 elements of CharT.
2347    //!
2348    //! <b>Throws</b>: out_of_range if pos1 > size()
2349    //!
2350    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
compare(size_type pos1,size_type n1,const CharT * s) const2351    int compare(size_type pos1, size_type n1, const CharT* s) const
2352    {  return this->compare(pos1, n1, s, Traits::length(s)); }
2353 
2354    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2355    private:
priv_reserve(size_type res_arg,const bool null_terminate=true)2356    void priv_reserve(size_type res_arg, const bool null_terminate = true)
2357    {
2358       if (res_arg > this->max_size()){
2359          throw_length_error("basic_string::reserve max_size() exceeded");
2360       }
2361 
2362       if (this->capacity() < res_arg){
2363          size_type n = container_detail::max_value(res_arg, this->size()) + 1;
2364          size_type new_cap = this->next_capacity(n);
2365          pointer reuse = 0;
2366          pointer new_start = this->allocation_command(allocate_new, n, new_cap, reuse);
2367          size_type new_length = 0;
2368 
2369          const pointer addr = this->priv_addr();
2370          new_length += priv_uninitialized_copy
2371             (addr, addr + this->priv_size(), new_start);
2372          if(null_terminate){
2373             this->priv_construct_null(new_start + new_length);
2374          }
2375          this->deallocate_block();
2376          this->is_short(false);
2377          this->priv_long_addr(new_start);
2378          this->priv_long_size(new_length);
2379          this->priv_storage(new_cap);
2380       }
2381    }
2382 
s_compare(const_pointer f1,const_pointer l1,const_pointer f2,const_pointer l2)2383    static int s_compare(const_pointer f1, const_pointer l1,
2384                         const_pointer f2, const_pointer l2)
2385    {
2386       const difference_type n1 = l1 - f1;
2387       const difference_type n2 = l2 - f2;
2388       const int cmp = Traits::compare(container_detail::to_raw_pointer(f1),
2389                                       container_detail::to_raw_pointer(f2),
2390                                       container_detail::min_value(n1, n2));
2391       return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
2392    }
2393 
2394    template<class AllocVersion>
priv_shrink_to_fit_dynamic_buffer(AllocVersion,typename container_detail::enable_if<container_detail::is_same<AllocVersion,version_1>>::type * =0)2395    void priv_shrink_to_fit_dynamic_buffer
2396       ( AllocVersion
2397       , typename container_detail::enable_if<container_detail::is_same<AllocVersion, version_1> >::type* = 0)
2398    {
2399       //Allocate a new buffer.
2400       size_type real_cap = 0;
2401       const pointer   long_addr    = this->priv_long_addr();
2402       const size_type long_size    = this->priv_long_size();
2403       const size_type long_storage = this->priv_long_storage();
2404       //We can make this nothrow as chars are always NoThrowCopyables
2405       BOOST_TRY{
2406          pointer reuse = 0;
2407          real_cap = long_size+1;
2408          const pointer ret = this->allocation_command(allocate_new, long_size+1, real_cap, reuse);
2409          //Copy and update
2410          Traits::copy( container_detail::to_raw_pointer(ret)
2411                      , container_detail::to_raw_pointer(this->priv_long_addr())
2412                      , long_size+1);
2413          this->priv_long_addr(ret);
2414          this->priv_storage(real_cap);
2415          //And release old buffer
2416          this->alloc().deallocate(long_addr, long_storage);
2417       }
2418       BOOST_CATCH(...){
2419          return;
2420       }
2421       BOOST_CATCH_END
2422    }
2423 
2424    template<class AllocVersion>
priv_shrink_to_fit_dynamic_buffer(AllocVersion,typename container_detail::enable_if<container_detail::is_same<AllocVersion,version_2>>::type * =0)2425    void priv_shrink_to_fit_dynamic_buffer
2426       ( AllocVersion
2427       , typename container_detail::enable_if<container_detail::is_same<AllocVersion, version_2> >::type* = 0)
2428    {
2429       size_type received_size = this->priv_long_size()+1;
2430       pointer hint = this->priv_long_addr();
2431       if(this->alloc().allocation_command
2432          ( shrink_in_place | nothrow_allocation, this->priv_long_storage(), received_size, hint)){
2433          this->priv_storage(received_size);
2434       }
2435    }
2436 
priv_construct_null(pointer p)2437    void priv_construct_null(pointer p)
2438    {  this->construct(p, CharT(0));  }
2439 
2440    // Helper functions used by constructors.  It is a severe error for
2441    // any of them to be called anywhere except from within constructors.
priv_terminate_string()2442    void priv_terminate_string()
2443    {  this->priv_construct_null(this->priv_end_addr());  }
2444 
2445    template<class FwdIt, class Count> inline
priv_uninitialized_fill_n(FwdIt first,Count count,const CharT val)2446    void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val)
2447    {
2448       //Save initial position
2449       FwdIt init = first;
2450 
2451       BOOST_TRY{
2452          //Construct objects
2453          for (; count--; ++first){
2454             this->construct(first, val);
2455          }
2456       }
2457       BOOST_CATCH(...){
2458          //Call destructors
2459          for (; init != first; ++init){
2460             this->destroy(init);
2461          }
2462          BOOST_RETHROW
2463       }
2464       BOOST_CATCH_END
2465    }
2466 
2467    template<class InpIt, class FwdIt> inline
priv_uninitialized_copy(InpIt first,InpIt last,FwdIt dest)2468    size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest)
2469    {
2470       //Save initial destination position
2471       FwdIt dest_init = dest;
2472       size_type constructed = 0;
2473 
2474       BOOST_TRY{
2475          //Try to build objects
2476          for (; first != last; ++dest, ++first, ++constructed){
2477             this->construct(dest, *first);
2478          }
2479       }
2480       BOOST_CATCH(...){
2481          //Call destructors
2482          for (; constructed--; ++dest_init){
2483             this->destroy(dest_init);
2484          }
2485          BOOST_RETHROW
2486       }
2487       BOOST_CATCH_END
2488       return (constructed);
2489    }
2490 
2491    template <class InputIterator, class OutIterator>
priv_copy(InputIterator first,InputIterator last,OutIterator result)2492    void priv_copy(InputIterator first, InputIterator last, OutIterator result)
2493    {
2494       for ( ; first != last; ++first, ++result)
2495          Traits::assign(*result, *first);
2496    }
2497 
priv_copy(const CharT * first,const CharT * last,CharT * result)2498    void priv_copy(const CharT* first, const CharT* last, CharT* result)
2499    {  Traits::copy(result, first, last - first);  }
2500 
2501    template <class Integer>
priv_replace_dispatch(const_iterator first,const_iterator last,Integer n,Integer x,container_detail::true_)2502    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
2503                                        Integer n, Integer x,
2504                                        container_detail::true_)
2505    {  return this->replace(first, last, (size_type) n, (CharT) x);   }
2506 
2507    template <class InputIter>
priv_replace_dispatch(const_iterator first,const_iterator last,InputIter f,InputIter l,container_detail::false_)2508    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
2509                                        InputIter f, InputIter l,
2510                                        container_detail::false_)
2511    {
2512       typedef typename boost::container::iterator_traits<InputIter>::iterator_category Category;
2513       return this->priv_replace(first, last, f, l, Category());
2514    }
2515 
2516    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2517 };
2518 
2519 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
2520 
2521 //!Typedef for a basic_string of
2522 //!narrow characters
2523 typedef basic_string
2524    <char
2525    ,std::char_traits<char>
2526    ,new_allocator<char> >
2527 string;
2528 
2529 //!Typedef for a basic_string of
2530 //!narrow characters
2531 typedef basic_string
2532    <wchar_t
2533    ,std::char_traits<wchar_t>
2534    ,new_allocator<wchar_t> >
2535 wstring;
2536 
2537 #endif
2538 
2539 // ------------------------------------------------------------
2540 // Non-member functions.
2541 
2542 // Operator+
2543 
2544 template <class CharT, class Traits, class Allocator> inline
2545    basic_string<CharT,Traits,Allocator>
operator +(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)2546    operator+(const basic_string<CharT,Traits,Allocator>& x
2547             ,const basic_string<CharT,Traits,Allocator>& y)
2548 {
2549    typedef basic_string<CharT,Traits,Allocator> str_t;
2550    typedef typename str_t::reserve_t reserve_t;
2551    reserve_t reserve;
2552    str_t result(reserve, x.size() + y.size(), x.get_stored_allocator());
2553    result.append(x);
2554    result.append(y);
2555    return result;
2556 }
2557 
2558 template <class CharT, class Traits, class Allocator> inline
operator +(BOOST_RV_REF_BEG basic_string<CharT,Traits,Allocator> BOOST_RV_REF_END x,BOOST_RV_REF_BEG basic_string<CharT,Traits,Allocator> BOOST_RV_REF_END y)2559    basic_string<CharT, Traits, Allocator> operator+
2560       ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
2561       , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
2562 {
2563    x += y;
2564    return boost::move(x);
2565 }
2566 
2567 template <class CharT, class Traits, class Allocator> inline
operator +(BOOST_RV_REF_BEG basic_string<CharT,Traits,Allocator> BOOST_RV_REF_END x,const basic_string<CharT,Traits,Allocator> & y)2568    basic_string<CharT, Traits, Allocator> operator+
2569       ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
2570       , const basic_string<CharT,Traits,Allocator>& y)
2571 {
2572    x += y;
2573    return boost::move(x);
2574 }
2575 
2576 template <class CharT, class Traits, class Allocator> inline
operator +(const basic_string<CharT,Traits,Allocator> & x,BOOST_RV_REF_BEG basic_string<CharT,Traits,Allocator> BOOST_RV_REF_END y)2577    basic_string<CharT, Traits, Allocator> operator+
2578       (const basic_string<CharT,Traits,Allocator>& x
2579       ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
2580 {
2581    y.insert(y.begin(), x.begin(), x.end());
2582    return boost::move(y);
2583 }
2584 
2585 template <class CharT, class Traits, class Allocator> inline
operator +(const CharT * s,basic_string<CharT,Traits,Allocator> y)2586    basic_string<CharT, Traits, Allocator> operator+
2587       (const CharT* s, basic_string<CharT, Traits, Allocator> y)
2588 {
2589    y.insert(y.begin(), s, s + Traits::length(s));
2590    return y;
2591 }
2592 
2593 template <class CharT, class Traits, class Allocator> inline
operator +(basic_string<CharT,Traits,Allocator> x,const CharT * s)2594    basic_string<CharT,Traits,Allocator> operator+
2595       (basic_string<CharT,Traits,Allocator> x, const CharT* s)
2596 {
2597    x += s;
2598    return x;
2599 }
2600 
2601 template <class CharT, class Traits, class Allocator> inline
operator +(CharT c,basic_string<CharT,Traits,Allocator> y)2602    basic_string<CharT,Traits,Allocator> operator+
2603       (CharT c, basic_string<CharT,Traits,Allocator> y)
2604 {
2605    y.insert(y.begin(), c);
2606    return y;
2607 }
2608 
2609 template <class CharT, class Traits, class Allocator> inline
operator +(basic_string<CharT,Traits,Allocator> x,const CharT c)2610    basic_string<CharT,Traits,Allocator> operator+
2611       (basic_string<CharT,Traits,Allocator> x, const CharT c)
2612 {
2613    x += c;
2614    return x;
2615 }
2616 
2617 // Operator== and operator!=
2618 
2619 template <class CharT, class Traits, class Allocator>
2620 inline bool
operator ==(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)2621 operator==(const basic_string<CharT,Traits,Allocator>& x,
2622            const basic_string<CharT,Traits,Allocator>& y)
2623 {
2624    return x.size() == y.size() &&
2625           Traits::compare(x.data(), y.data(), x.size()) == 0;
2626 }
2627 
2628 template <class CharT, class Traits, class Allocator>
2629 inline bool
operator ==(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)2630 operator==(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
2631 {
2632    typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
2633    return n == y.size() && Traits::compare(s, y.data(), n) == 0;
2634 }
2635 
2636 template <class CharT, class Traits, class Allocator>
2637 inline bool
operator ==(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)2638 operator==(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
2639 {
2640    typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
2641    return x.size() == n && Traits::compare(x.data(), s, n) == 0;
2642 }
2643 
2644 template <class CharT, class Traits, class Allocator>
2645 inline bool
operator !=(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)2646 operator!=(const basic_string<CharT,Traits,Allocator>& x,
2647            const basic_string<CharT,Traits,Allocator>& y)
2648    {  return !(x == y);  }
2649 
2650 template <class CharT, class Traits, class Allocator>
2651 inline bool
operator !=(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)2652 operator!=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
2653    {  return !(s == y); }
2654 
2655 template <class CharT, class Traits, class Allocator>
2656 inline bool
operator !=(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)2657 operator!=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
2658    {  return !(x == s);   }
2659 
2660 
2661 // Operator< (and also >, <=, and >=).
2662 
2663 template <class CharT, class Traits, class Allocator>
2664 inline bool
operator <(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)2665 operator<(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
2666 {
2667    return x.compare(y) < 0;
2668 //   return basic_string<CharT,Traits,Allocator>
2669 //      ::s_compare(x.begin(), x.end(), y.begin(), y.end()) < 0;
2670 }
2671 
2672 template <class CharT, class Traits, class Allocator>
2673 inline bool
operator <(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)2674 operator<(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
2675 {
2676    return y.compare(s) > 0;
2677 //   basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
2678 //   return basic_string<CharT,Traits,Allocator>
2679 //          ::s_compare(s, s + n, y.begin(), y.end()) < 0;
2680 }
2681 
2682 template <class CharT, class Traits, class Allocator>
2683 inline bool
operator <(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)2684 operator<(const basic_string<CharT,Traits,Allocator>& x,
2685           const CharT* s)
2686 {
2687    return x.compare(s) < 0;
2688 //   basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
2689 //   return basic_string<CharT,Traits,Allocator>
2690 //      ::s_compare(x.begin(), x.end(), s, s + n) < 0;
2691 }
2692 
2693 template <class CharT, class Traits, class Allocator>
2694 inline bool
operator >(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)2695 operator>(const basic_string<CharT,Traits,Allocator>& x,
2696           const basic_string<CharT,Traits,Allocator>& y) {
2697    return y < x;
2698 }
2699 
2700 template <class CharT, class Traits, class Allocator>
2701 inline bool
operator >(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)2702 operator>(const CharT* s, const basic_string<CharT,Traits,Allocator>& y) {
2703    return y < s;
2704 }
2705 
2706 template <class CharT, class Traits, class Allocator>
2707 inline bool
operator >(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)2708 operator>(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
2709 {
2710    return s < x;
2711 }
2712 
2713 template <class CharT, class Traits, class Allocator>
2714 inline bool
operator <=(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)2715 operator<=(const basic_string<CharT,Traits,Allocator>& x,
2716            const basic_string<CharT,Traits,Allocator>& y)
2717 {
2718   return !(y < x);
2719 }
2720 
2721 template <class CharT, class Traits, class Allocator>
2722 inline bool
operator <=(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)2723 operator<=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
2724    {  return !(y < s);  }
2725 
2726 template <class CharT, class Traits, class Allocator>
2727 inline bool
operator <=(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)2728 operator<=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
2729    {  return !(s < x);  }
2730 
2731 template <class CharT, class Traits, class Allocator>
2732 inline bool
operator >=(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)2733 operator>=(const basic_string<CharT,Traits,Allocator>& x,
2734            const basic_string<CharT,Traits,Allocator>& y)
2735    {  return !(x < y);  }
2736 
2737 template <class CharT, class Traits, class Allocator>
2738 inline bool
operator >=(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)2739 operator>=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
2740    {  return !(s < y);  }
2741 
2742 template <class CharT, class Traits, class Allocator>
2743 inline bool
operator >=(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)2744 operator>=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
2745    {  return !(x < s);  }
2746 
2747 // Swap.
2748 template <class CharT, class Traits, class Allocator>
swap(basic_string<CharT,Traits,Allocator> & x,basic_string<CharT,Traits,Allocator> & y)2749 inline void swap(basic_string<CharT,Traits,Allocator>& x, basic_string<CharT,Traits,Allocator>& y)
2750 {  x.swap(y);  }
2751 
2752 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2753 // I/O.
2754 namespace container_detail {
2755 
2756 template <class CharT, class Traits>
2757 inline bool
string_fill(std::basic_ostream<CharT,Traits> & os,std::basic_streambuf<CharT,Traits> * buf,std::size_t n)2758 string_fill(std::basic_ostream<CharT, Traits>& os,
2759                   std::basic_streambuf<CharT, Traits>* buf,
2760                   std::size_t n)
2761 {
2762    CharT f = os.fill();
2763    std::size_t i;
2764    bool ok = true;
2765 
2766    for (i = 0; i < n; i++)
2767       ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof());
2768    return ok;
2769 }
2770 
2771 }  //namespace container_detail {
2772 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2773 
2774 template <class CharT, class Traits, class Allocator>
2775 std::basic_ostream<CharT, Traits>&
operator <<(std::basic_ostream<CharT,Traits> & os,const basic_string<CharT,Traits,Allocator> & s)2776 operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Traits,Allocator>& s)
2777 {
2778    typename std::basic_ostream<CharT, Traits>::sentry sentry(os);
2779    bool ok = false;
2780 
2781    if (sentry) {
2782       ok = true;
2783       typename basic_string<CharT,Traits,Allocator>::size_type n = s.size();
2784       typename basic_string<CharT,Traits,Allocator>::size_type pad_len = 0;
2785       const bool left = (os.flags() & std::ios::left) != 0;
2786       const std::size_t w = os.width(0);
2787       std::basic_streambuf<CharT, Traits>* buf = os.rdbuf();
2788 
2789       if (w != 0 && n < w)
2790          pad_len = w - n;
2791 
2792       if (!left)
2793          ok = container_detail::string_fill(os, buf, pad_len);
2794 
2795       ok = ok &&
2796             buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n);
2797 
2798       if (left)
2799          ok = ok && container_detail::string_fill(os, buf, pad_len);
2800    }
2801 
2802    if (!ok)
2803       os.setstate(std::ios_base::failbit);
2804 
2805    return os;
2806 }
2807 
2808 
2809 template <class CharT, class Traits, class Allocator>
2810 std::basic_istream<CharT, Traits>&
operator >>(std::basic_istream<CharT,Traits> & is,basic_string<CharT,Traits,Allocator> & s)2811 operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
2812 {
2813    typename std::basic_istream<CharT, Traits>::sentry sentry(is);
2814 
2815    if (sentry) {
2816       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
2817       const std::ctype<CharT>& ctype = std::use_facet<std::ctype<CharT> >(is.getloc());
2818 
2819       s.clear();
2820       std::size_t n = is.width(0);
2821       if (n == 0)
2822          n = static_cast<std::size_t>(-1);
2823       else
2824          s.reserve(n);
2825 
2826       while (n-- > 0) {
2827          typename Traits::int_type c1 = buf->sbumpc();
2828 
2829          if (Traits::eq_int_type(c1, Traits::eof())) {
2830             is.setstate(std::ios_base::eofbit);
2831             break;
2832          }
2833          else {
2834             CharT c = Traits::to_char_type(c1);
2835 
2836             if (ctype.is(std::ctype<CharT>::space, c)) {
2837                if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof()))
2838                   is.setstate(std::ios_base::failbit);
2839                break;
2840             }
2841             else
2842                s.push_back(c);
2843          }
2844       }
2845 
2846       // If we have read no characters, then set failbit.
2847       if (s.size() == 0)
2848          is.setstate(std::ios_base::failbit);
2849    }
2850    else
2851       is.setstate(std::ios_base::failbit);
2852 
2853    return is;
2854 }
2855 
2856 template <class CharT, class Traits, class Allocator>
2857 std::basic_istream<CharT, Traits>&
getline(std::istream & is,basic_string<CharT,Traits,Allocator> & s,CharT delim)2858 getline(std::istream& is, basic_string<CharT,Traits,Allocator>& s,CharT delim)
2859 {
2860    typename basic_string<CharT,Traits,Allocator>::size_type nread = 0;
2861    typename std::basic_istream<CharT, Traits>::sentry sentry(is, true);
2862    if (sentry) {
2863       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
2864       s.clear();
2865 
2866       while (nread < s.max_size()) {
2867          int c1 = buf->sbumpc();
2868          if (Traits::eq_int_type(c1, Traits::eof())) {
2869             is.setstate(std::ios_base::eofbit);
2870             break;
2871          }
2872          else {
2873             ++nread;
2874             CharT c = Traits::to_char_type(c1);
2875             if (!Traits::eq(c, delim))
2876                s.push_back(c);
2877             else
2878                break;              // Character is extracted but not appended.
2879          }
2880       }
2881    }
2882    if (nread == 0 || nread >= s.max_size())
2883       is.setstate(std::ios_base::failbit);
2884 
2885    return is;
2886 }
2887 
2888 template <class CharT, class Traits, class Allocator>
2889 inline std::basic_istream<CharT, Traits>&
getline(std::basic_istream<CharT,Traits> & is,basic_string<CharT,Traits,Allocator> & s)2890 getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
2891 {
2892    return getline(is, s, '\n');
2893 }
2894 
2895 template <class Ch, class Allocator>
hash_value(basic_string<Ch,std::char_traits<Ch>,Allocator> const & v)2896 inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, Allocator> const& v)
2897 {
2898    return hash_range(v.begin(), v.end());
2899 }
2900 
2901 }}
2902 
2903 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2904 
2905 namespace boost {
2906 
2907 //!has_trivial_destructor_after_move<> == true_type
2908 //!specialization for optimizations
2909 template <class C, class T, class Allocator>
2910 struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
2911 {
2912    typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
2913    static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
2914                              ::boost::has_trivial_destructor_after_move<pointer>::value;
2915 };
2916 
2917 }
2918 
2919 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2920 
2921 #include <boost/container/detail/config_end.hpp>
2922 
2923 #endif // BOOST_CONTAINER_STRING_HPP
2924