1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2015. 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/move/detail/to_raw_pointer.hpp>
39 #include <boost/container/detail/version_type.hpp>
40 #include <boost/container/detail/type_traits.hpp>
41 #include <boost/container/detail/algorithm.hpp>
42 
43 #include <boost/intrusive/pointer_traits.hpp>
44 
45 #include <boost/move/utility_core.hpp>
46 #include <boost/move/adl_move_swap.hpp>
47 #include <boost/move/traits.hpp>
48 
49 #include <boost/static_assert.hpp>
50 #include <boost/core/no_exceptions_support.hpp>
51 #include <boost/intrusive/detail/hash_combine.hpp>
52 
53 #include <boost/container/detail/minimal_char_traits_header.hpp>  // for char_traits
54 #include <iosfwd>
55 #include <istream>   //
56 #include <ostream>
57 #include <ios>
58 #include <locale>
59 #include <cstddef>
60 #include <climits>
61 
62 //std
63 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
64 #include <initializer_list>   //for std::initializer_list
65 #endif
66 
67 
68 namespace boost {
69 namespace container {
70 
71 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
72 namespace dtl {
73 // ------------------------------------------------------------
74 // Class basic_string_base.
75 
76 // basic_string_base is a helper class that makes it it easier to write
77 // an exception-safe version of basic_string.  The constructor allocates,
78 // but does not initialize, a block of memory.  The destructor
79 // deallocates, but does not destroy elements within, a block of
80 // memory. The destructor assumes that the memory either is the internal buffer,
81 // or else points to a block of memory that was allocated using string_base's
82 // allocator and whose size is this->m_storage.
83 template <class Allocator>
84 class basic_string_base
85 {
86    basic_string_base & operator=(const basic_string_base &);
87    basic_string_base(const basic_string_base &);
88 
89    typedef Allocator allocator_type;
90  public:
91    typedef allocator_traits<allocator_type> allocator_traits_type;
92    typedef allocator_type                              stored_allocator_type;
93    typedef typename allocator_traits_type::pointer     pointer;
94    typedef typename allocator_traits_type::value_type  value_type;
95    typedef typename allocator_traits_type::size_type   size_type;
96    typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
97 
basic_string_base()98    basic_string_base()
99       : members_()
100    {}
101 
basic_string_base(const allocator_type & a)102    explicit basic_string_base(const allocator_type& a)
103       : members_(a)
104    {}
105 
basic_string_base(BOOST_RV_REF (allocator_type)a)106    explicit basic_string_base(BOOST_RV_REF(allocator_type) a)
107       :  members_(boost::move(a))
108    {}
109 
basic_string_base(const allocator_type & a,size_type n)110    basic_string_base(const allocator_type& a, size_type n)
111       : members_(a)
112    {
113       this->allocate_initial_block(n);
114    }
115 
basic_string_base(size_type n)116    explicit basic_string_base(size_type n)
117       : members_()
118    {
119       this->allocate_initial_block(n);
120    }
121 
~basic_string_base()122    ~basic_string_base()
123    {
124       if(!this->is_short()){
125          this->deallocate(this->priv_long_addr(), this->priv_long_storage());
126       }
127    }
128 
129    private:
130 
131    //This is the structure controlling a long string
132    struct long_t
133    {
134       size_type      is_short  : 1;
135       size_type      length    : (sizeof(size_type)*CHAR_BIT - 1);
136       size_type      storage;
137       pointer        start;
138 
long_tboost::container::dtl::basic_string_base::long_t139       long_t()
140          : is_short(0)
141       {}
142 
long_tboost::container::dtl::basic_string_base::long_t143       long_t(size_type len, size_type stor, pointer ptr)
144          : is_short(0), length(len), storage(stor), start(ptr)
145       {}
146 
long_tboost::container::dtl::basic_string_base::long_t147       long_t(const long_t &other)
148       {
149          this->is_short = false;
150          length   = other.length;
151          storage  = other.storage;
152          start    = other.start;
153       }
154 
operator =boost::container::dtl::basic_string_base::long_t155       long_t &operator= (const long_t &other)
156       {
157          length   = other.length;
158          storage  = other.storage;
159          start    = other.start;
160          return *this;
161       }
162    };
163 
164    //This type is the first part of the structure controlling a short string
165    //The "data" member stores
166    struct short_header
167    {
168       unsigned char  is_short  : 1;
169       unsigned char  length    : (CHAR_BIT - 1);
170    };
171 
172    //This type has the same alignment and size as long_t but it's POD
173    //so, unlike long_t, it can be placed in a union
174 
175    typedef typename dtl::aligned_storage
176       <sizeof(long_t), dtl::alignment_of<long_t>::value>::type   long_raw_t;
177 
178    protected:
179    static const size_type  MinInternalBufferChars = 8;
180    static const size_type  AlignmentOfValueType =
181       alignment_of<value_type>::value;
182    static const size_type  ShortDataOffset = ((sizeof(short_header)-1)/AlignmentOfValueType+1)*AlignmentOfValueType;
183    static const size_type  ZeroCostInternalBufferChars =
184       (sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
185    static const size_type  UnalignedFinalInternalBufferChars =
186       (ZeroCostInternalBufferChars > MinInternalBufferChars) ?
187                 ZeroCostInternalBufferChars : MinInternalBufferChars;
188 
189    struct short_t
190    {
191       short_header   h;
192       value_type     data[UnalignedFinalInternalBufferChars];
193    };
194 
195    union repr_t_size_t
196    {
197       long_raw_t  r;
198       short_t     s;
199    };
200 
201    union repr_t
202    {
203       long_raw_t  r_aligner;
204       short_t     s_aligner;
205       unsigned char data[sizeof(repr_t_size_t)];
206    };
207 
208    struct members_holder
209       :  public allocator_type
210    {
initboost::container::dtl::basic_string_base::members_holder211       void init()
212       {
213          short_t &s = *::new(this->m_repr.data) short_t;
214          s.h.is_short = 1;
215          s.h.length = 0;
216       }
217 
members_holderboost::container::dtl::basic_string_base::members_holder218       members_holder()
219          : allocator_type()
220       { this->init(); }
221 
222       template<class AllocatorConvertible>
members_holderboost::container::dtl::basic_string_base::members_holder223       explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
224          :  allocator_type(boost::forward<AllocatorConvertible>(a))
225       { this->init(); }
226 
pshort_reprboost::container::dtl::basic_string_base::members_holder227       const short_t *pshort_repr() const
228       {  return reinterpret_cast<const short_t*>(m_repr.data);  }
229 
plong_reprboost::container::dtl::basic_string_base::members_holder230       const long_t *plong_repr() const
231       {  return reinterpret_cast<const long_t*>(m_repr.data);  }
232 
pshort_reprboost::container::dtl::basic_string_base::members_holder233       short_t *pshort_repr()
234       {  return reinterpret_cast<short_t*>(m_repr.data);  }
235 
plong_reprboost::container::dtl::basic_string_base::members_holder236       long_t *plong_repr()
237       {  return reinterpret_cast<long_t*>(m_repr.data);  }
238 
239       repr_t m_repr;
240    } members_;
241 
alloc() const242    const allocator_type &alloc() const
243    {  return members_;  }
244 
alloc()245    allocator_type &alloc()
246    {  return members_;  }
247 
248    static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
249 
250    private:
251 
252    static const size_type MinAllocation = InternalBufferChars*2;
253 
254    protected:
is_short() const255    bool is_short() const
256    {
257       //Access and copy (to avoid UB) the first byte of the union to know if the
258       //active representation is short or long
259       short_header hdr;
260       BOOST_STATIC_ASSERT((sizeof(short_header) == 1));
261       *(unsigned char*)&hdr = *(unsigned char*)&this->members_.m_repr;
262       return hdr.is_short != 0;
263    }
264 
construct_short()265    short_t *construct_short()
266    {
267       short_t *ps = ::new(this->members_.m_repr.data) short_t;
268       ps->h.is_short = 1;
269       return ps;
270    }
271 
destroy_short()272    void destroy_short()
273    {
274       BOOST_ASSERT(this->is_short());
275       this->members_.pshort_repr()->~short_t();
276    }
277 
assure_short()278    short_t *assure_short()
279    {
280       if (!this->is_short()){
281          this->destroy_long();
282          return construct_short();
283       }
284       return this->members_.pshort_repr();
285    }
286 
construct_long()287    long_t *construct_long()
288    {
289       long_t *pl = ::new(this->members_.m_repr.data) long_t;
290       //is_short flag is written in the constructor
291       return pl;
292    }
293 
destroy_long()294    void destroy_long()
295    {
296       BOOST_ASSERT(!this->is_short());
297       this->members_.plong_repr()->~long_t();
298    }
299 
assure_long()300    long_t *assure_long()
301    {
302       if (this->is_short()){
303          this->destroy_short();
304          return this->construct_long();
305       }
306       return this->members_.plong_repr();
307    }
308 
309 
310    protected:
311 
312    typedef dtl::integral_constant<unsigned,
313       boost::container::dtl::version<allocator_type>::value> alloc_version;
314 
allocation_command(allocation_type command,size_type limit_size,size_type & prefer_in_recvd_out_size,pointer & reuse)315    pointer allocation_command(allocation_type command,
316                          size_type limit_size,
317                          size_type &prefer_in_recvd_out_size,
318                          pointer &reuse)
319    {
320       if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){
321          reuse = 0;
322          command &= ~(expand_fwd | expand_bwd);
323       }
324       return dtl::allocator_version_traits<allocator_type>::allocation_command
325          (this->alloc(), command, limit_size, prefer_in_recvd_out_size, reuse);
326    }
327 
next_capacity(size_type additional_objects) const328    size_type next_capacity(size_type additional_objects) const
329    {
330       return growth_factor_100()
331             ( this->priv_storage(), additional_objects, allocator_traits_type::max_size(this->alloc()));
332    }
333 
deallocate(pointer p,size_type n)334    void deallocate(pointer p, size_type n)
335    {
336       if (p && (n > InternalBufferChars))
337          this->alloc().deallocate(p, n);
338    }
339 
construct(pointer p,const value_type & value=value_type ())340    void construct(pointer p, const value_type &value = value_type())
341    {
342       allocator_traits_type::construct
343          ( this->alloc()
344          , boost::movelib::to_raw_pointer(p)
345          , value
346          );
347    }
348 
destroy(pointer p,size_type n)349    void destroy(pointer p, size_type n)
350    {
351       value_type *raw_p = boost::movelib::to_raw_pointer(p);
352       for(; n--; ++raw_p){
353          allocator_traits_type::destroy( this->alloc(), raw_p);
354       }
355    }
356 
destroy(pointer p)357    void destroy(pointer p)
358    {
359       allocator_traits_type::destroy
360          ( this->alloc()
361          , boost::movelib::to_raw_pointer(p)
362          );
363    }
364 
allocate_initial_block(size_type n)365    void allocate_initial_block(size_type n)
366    {
367       if (n <= this->max_size()) {
368          if(n > InternalBufferChars){
369             size_type new_cap = this->next_capacity(n);
370             pointer reuse = 0;
371             pointer p = this->allocation_command(allocate_new, n, new_cap, reuse);
372             BOOST_ASSERT(this->is_short());
373             this->construct_long();
374             this->priv_long_addr(p);
375             this->priv_long_size(0);
376             this->priv_storage(new_cap);
377          }
378       }
379       else{
380          throw_length_error("basic_string::allocate_initial_block max_size() exceeded");
381       }
382    }
383 
deallocate_block()384    void deallocate_block()
385    {  this->deallocate(this->priv_addr(), this->priv_storage());  }
386 
max_size() const387    size_type max_size() const
388    {  return allocator_traits_type::max_size(this->alloc()) - 1; }
389 
390    protected:
priv_capacity() const391    size_type priv_capacity() const
392    { return this->priv_storage() - 1; }
393 
priv_short_addr() const394    pointer priv_short_addr() const
395    {  return pointer_traits::pointer_to(const_cast<value_type&>(this->members_.pshort_repr()->data[0]));  }
396 
397    //GCC seems a bit confused about uninitialized accesses
398    #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
399    #pragma GCC diagnostic push
400    #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
401    #endif
402 
priv_long_addr() const403    pointer priv_long_addr() const
404    {  return this->members_.plong_repr()->start;  }
405 
priv_addr() const406    pointer priv_addr() const
407    {
408       return this->is_short()
409          ? priv_short_addr()
410          : priv_long_addr()
411          ;
412    }
413 
priv_end_addr() const414    pointer priv_end_addr() const
415    {
416       return this->is_short()
417          ? this->priv_short_addr() + this->priv_short_size()
418          : this->priv_long_addr()  + this->priv_long_size()
419          ;
420    }
421 
priv_long_addr(pointer addr)422    void priv_long_addr(pointer addr)
423    {  this->members_.plong_repr()->start = addr;  }
424 
priv_storage() const425    size_type priv_storage() const
426    {  return this->is_short() ? priv_short_storage() : priv_long_storage();  }
427 
priv_short_storage() const428    size_type priv_short_storage() const
429    {  return InternalBufferChars;  }
430 
priv_long_storage() const431    size_type priv_long_storage() const
432    {  return this->members_.plong_repr()->storage;  }
433 
priv_storage(size_type storage)434    void priv_storage(size_type storage)
435    {
436       if(!this->is_short())
437          this->priv_long_storage(storage);
438    }
439 
priv_long_storage(size_type storage)440    void priv_long_storage(size_type storage)
441    {
442       this->members_.plong_repr()->storage = storage;
443    }
444 
priv_size() const445    size_type priv_size() const
446    {  return this->is_short() ? this->priv_short_size() : this->priv_long_size();  }
447 
priv_short_size() const448    size_type priv_short_size() const
449    {  return this->members_.pshort_repr()->h.length;  }
450 
priv_long_size() const451    size_type priv_long_size() const
452    {  return this->members_.plong_repr()->length;  }
453 
priv_size(size_type sz)454    void priv_size(size_type sz)
455    {
456       if(this->is_short())
457          this->priv_short_size(sz);
458       else
459          this->priv_long_size(sz);
460    }
461 
priv_short_size(size_type sz)462    void priv_short_size(size_type sz)
463    {  this->members_.pshort_repr()->h.length = (unsigned char)sz; }
464 
priv_long_size(size_type sz)465    void priv_long_size(size_type sz)
466    {  this->members_.plong_repr()->length = sz;  }
467 
468    #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
469    #pragma GCC diagnostic pop
470    #endif
471 
swap_data(basic_string_base & other)472    void swap_data(basic_string_base& other)
473    {
474       if(this->is_short()){
475          if(other.is_short()){
476             repr_t tmp(this->members_.m_repr);
477             this->members_.m_repr = other.members_.m_repr;
478             other.members_.m_repr = tmp;
479          }
480          else{
481             short_t short_backup(*this->members_.pshort_repr());
482             this->members_.pshort_repr()->~short_t();
483             ::new(this->members_.plong_repr()) long_t(*other.members_.plong_repr());
484             other.members_.plong_repr()->~long_t();
485             ::new(other.members_.pshort_repr()) short_t(short_backup);
486          }
487       }
488       else{
489          if(other.is_short()){
490             short_t short_backup(*other.members_.pshort_repr());
491             other.members_.pshort_repr()->~short_t();
492             ::new(other.members_.plong_repr()) long_t(*this->members_.plong_repr());
493             this->members_.plong_repr()->~long_t();
494             ::new(this->members_.pshort_repr()) short_t(short_backup);
495          }
496          else{
497             boost::adl_move_swap(*this->members_.plong_repr(), *other.members_.plong_repr());
498          }
499       }
500    }
501 };
502 
503 }  //namespace dtl {
504 
505 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
506 
507 //! The basic_string class represents a Sequence of characters. It contains all the
508 //! usual operations of a Sequence, and, additionally, it contains standard string
509 //! operations such as search and concatenation.
510 //!
511 //! The basic_string class is parameterized by character type, and by that type's
512 //! Character Traits.
513 //!
514 //! This class has performance characteristics very much like vector<>, meaning,
515 //! for example, that it does not perform reference-count or copy-on-write, and that
516 //! concatenation of two strings is an O(N) operation.
517 //!
518 //! Some of basic_string's member functions use an unusual method of specifying positions
519 //! and ranges. In addition to the conventional method using iterators, many of
520 //! basic_string's member functions use a single value pos of type size_type to represent a
521 //! position (in which case the position is begin() + pos, and many of basic_string's
522 //! member functions use two values, pos and n, to represent a range. In that case pos is
523 //! the beginning of the range and n is its size. That is, the range is
524 //! [begin() + pos, begin() + pos + n).
525 //!
526 //! Note that the C++ standard does not specify the complexity of basic_string operations.
527 //! In this implementation, basic_string has performance characteristics very similar to
528 //! those of vector: access to a single character is O(1), while copy and concatenation
529 //! are O(N).
530 //!
531 //! In this implementation, begin(),
532 //! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators.
533 //! In this implementation, iterators are only invalidated by member functions that
534 //! explicitly change the string's contents.
535 //!
536 //! \tparam CharT The type of character it contains.
537 //! \tparam Traits The Character Traits type, which encapsulates basic character operations
538 //! \tparam Allocator The allocator, used for internal memory management.
539 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
540 template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = void >
541 #else
542 template <class CharT, class Traits, class Allocator>
543 #endif
544 class basic_string
545    :  private dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type>
546 {
547    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
548    private:
549    BOOST_COPYABLE_AND_MOVABLE(basic_string)
550    typedef dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type> base_t;
551    typedef typename base_t::allocator_traits_type allocator_traits_type;
552    static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
553 
554    protected:
555    // Allocator helper class to use a char_traits as a function object.
556 
557    template <class Tr>
558    struct Eq_traits
559    {
560       //Compatibility with std::binary_function
561       typedef typename Tr::char_type   first_argument_type;
562       typedef typename Tr::char_type   second_argument_type;
563       typedef bool   result_type;
564 
operator ()boost::container::basic_string::Eq_traits565       bool operator()(const first_argument_type& x, const second_argument_type& y) const
566          { return Tr::eq(x, y); }
567    };
568 
569    template <class Tr>
570    struct Not_within_traits
571    {
572       typedef typename Tr::char_type   argument_type;
573       typedef bool                     result_type;
574 
575       typedef const typename Tr::char_type* Pointer;
576       const Pointer m_first;
577       const Pointer m_last;
578 
Not_within_traitsboost::container::basic_string::Not_within_traits579       Not_within_traits(Pointer f, Pointer l)
580          : m_first(f), m_last(l) {}
581 
operator ()boost::container::basic_string::Not_within_traits582       bool operator()(const typename Tr::char_type& x) const
583       {
584          return boost::container::find_if(m_first, m_last,
585                         boost::container::bind1st(Eq_traits<Tr>(), x)) == m_last;
586       }
587    };
588    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
589 
590    public:
591    //////////////////////////////////////////////
592    //
593    //                    types
594    //
595    //////////////////////////////////////////////
596    typedef Traits                                                                      traits_type;
597    typedef CharT                                                                       value_type;
598    typedef typename real_allocator<CharT, Allocator>::type                             allocator_type;
599    typedef typename ::boost::container::allocator_traits<allocator_type>::pointer           pointer;
600    typedef typename ::boost::container::allocator_traits<allocator_type>::const_pointer     const_pointer;
601    typedef typename ::boost::container::allocator_traits<allocator_type>::reference         reference;
602    typedef typename ::boost::container::allocator_traits<allocator_type>::const_reference   const_reference;
603    typedef typename ::boost::container::allocator_traits<allocator_type>::size_type         size_type;
604    typedef typename ::boost::container::allocator_traits<allocator_type>::difference_type   difference_type;
605    typedef BOOST_CONTAINER_IMPDEF(allocator_type)                                      stored_allocator_type;
606    typedef BOOST_CONTAINER_IMPDEF(pointer)                                             iterator;
607    typedef BOOST_CONTAINER_IMPDEF(const_pointer)                                       const_iterator;
608    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>)        reverse_iterator;
609    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>)  const_reverse_iterator;
610    static const size_type npos = size_type(-1);
611 
612    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
613    private:
614    typedef constant_iterator<CharT, difference_type> cvalue_iterator;
615    typedef typename base_t::alloc_version  alloc_version;
616    typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
617    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
618 
619    public:                         // Constructor, destructor, assignment.
620    //////////////////////////////////////////////
621    //
622    //          construct/copy/destroy
623    //
624    //////////////////////////////////////////////
625    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
626    struct reserve_t {};
627 
basic_string(reserve_t,size_type n,const allocator_type & a=allocator_type ())628    basic_string(reserve_t, size_type n,
629                 const allocator_type& a = allocator_type())
630       //Select allocator as in copy constructor as reserve_t-based constructors
631       //are two step copies optimized for capacity
632       : base_t( allocator_traits_type::select_on_container_copy_construction(a)
633               , n + 1)
634    { this->priv_terminate_string(); }
635 
636    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
637 
638    //! <b>Effects</b>: Default constructs a basic_string.
639    //!
640    //! <b>Throws</b>: If allocator_type's default constructor throws.
BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)641    basic_string() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
642       : base_t()
643    { this->priv_terminate_string(); }
644 
645 
646    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter.
647    //!
648    //! <b>Throws</b>: Nothing
basic_string(const allocator_type & a)649    explicit basic_string(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
650       : base_t(a)
651    { this->priv_terminate_string(); }
652 
653    //! <b>Effects</b>: Copy constructs a basic_string.
654    //!
655    //! <b>Postcondition</b>: x == *this.
656    //!
657    //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
basic_string(const basic_string & s)658    basic_string(const basic_string& s)
659       :  base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
660    {
661       this->priv_terminate_string();
662       this->assign(s.begin(), s.end());
663    }
664 
665    //! <b>Effects</b>: Same as basic_string(sv.data(), sv.size(), a).
666    //!
667    //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
668    template<template <class, class> class BasicStringView>
basic_string(BasicStringView<CharT,Traits> sv,const allocator_type & a=allocator_type ())669    explicit basic_string(BasicStringView<CharT, Traits> sv, const allocator_type& a = allocator_type())
670       :  base_t(allocator_traits_type::select_on_container_copy_construction(a))
671    {
672       this->priv_terminate_string();
673       this->assign(sv);
674    }
675 
676    //! <b>Effects</b>: Move constructor. Moves s's resources to *this.
677    //!
678    //! <b>Throws</b>: Nothing.
679    //!
680    //! <b>Complexity</b>: Constant.
basic_string(BOOST_RV_REF (basic_string)s)681    basic_string(BOOST_RV_REF(basic_string) s) BOOST_NOEXCEPT_OR_NOTHROW
682       : base_t(boost::move(s.alloc()))
683    {
684       if(s.alloc() == this->alloc()){
685          this->swap_data(s);
686       }
687       else{
688          this->assign(s.begin(), s.end());
689       }
690    }
691 
692    //! <b>Effects</b>: Copy constructs a basic_string using the specified allocator.
693    //!
694    //! <b>Postcondition</b>: x == *this.
695    //!
696    //! <b>Throws</b>: If allocation throws.
basic_string(const basic_string & s,const allocator_type & a)697    basic_string(const basic_string& s, const allocator_type &a)
698       :  base_t(a)
699    {
700       this->priv_terminate_string();
701       this->assign(s.begin(), s.end());
702    }
703 
704    //! <b>Effects</b>: Move constructor using the specified allocator.
705    //!                 Moves s's resources to *this.
706    //!
707    //! <b>Throws</b>: If allocation throws.
708    //!
709    //! <b>Complexity</b>: Constant if a == s.get_allocator(), linear otherwise.
basic_string(BOOST_RV_REF (basic_string)s,const allocator_type & a)710    basic_string(BOOST_RV_REF(basic_string) s, const allocator_type &a)
711       : base_t(a)
712    {
713       this->priv_terminate_string();
714       if(s.alloc() == this->alloc()){
715          this->swap_data(s);
716       }
717       else{
718          this->assign(s.begin(), s.end());
719       }
720    }
721 
722    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
723    //!   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)724    basic_string(const basic_string& s, size_type pos, size_type n = npos)
725       : base_t()
726    {
727       this->priv_terminate_string();
728       if (pos > s.size())
729          throw_out_of_range("basic_string::basic_string out of range position");
730       else
731          this->assign
732             (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
733    }
734 
735    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
736    //!   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,const allocator_type & a)737    basic_string(const basic_string& s, size_type pos, size_type n, const allocator_type& a)
738       : base_t(a)
739    {
740       this->priv_terminate_string();
741       if (pos > s.size())
742          throw_out_of_range("basic_string::basic_string out of range position");
743       else
744          this->assign
745             (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
746    }
747 
748    //! <b>Effects</b>: Constructs a basic_string taking a default-constructed allocator,
749    //!   and is initialized by a specific number of characters of the s c-string.
basic_string(const CharT * s,size_type n)750    basic_string(const CharT* s, size_type n)
751       : base_t()
752    {
753       this->priv_terminate_string();
754       this->assign(s, s + n);
755    }
756 
757    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
758    //!   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)759    basic_string(const CharT* s, size_type n, const allocator_type& a)
760       : base_t(a)
761    {
762       this->priv_terminate_string();
763       this->assign(s, s + n);
764    }
765 
766    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
767    //!   and is initialized by the null-terminated s c-string.
basic_string(const CharT * s)768    basic_string(const CharT* s)
769       : base_t()
770    {
771       this->priv_terminate_string();
772       this->assign(s, s + Traits::length(s));
773    }
774 
775    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
776    //!   and is initialized by the null-terminated s c-string.
basic_string(const CharT * s,const allocator_type & a)777    basic_string(const CharT* s, const allocator_type& a)
778       : base_t(a)
779    {
780       this->priv_terminate_string();
781       this->assign(s, s + Traits::length(s));
782    }
783 
784 
785    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
786    //!   and is initialized by n copies of c.
basic_string(size_type n,CharT c)787    basic_string(size_type n, CharT c)
788       : base_t()
789    {
790       this->priv_terminate_string();
791       this->assign(n, c);
792    }
793 
794    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
795    //!   and is initialized by n copies of c.
basic_string(size_type n,CharT c,const allocator_type & a)796    basic_string(size_type n, CharT c, const allocator_type& a)
797       : base_t(a)
798    {
799       this->priv_terminate_string();
800       this->assign(n, c);
801    }
802 
803    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
804    //!   and is initialized by n default-initialized characters.
basic_string(size_type n,default_init_t)805    basic_string(size_type n, default_init_t)
806       : base_t(n + 1)
807    {
808       this->priv_size(n);
809       this->priv_terminate_string();
810    }
811 
812    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
813    //!   and is initialized by n default-initialized characters.
basic_string(size_type n,default_init_t,const allocator_type & a)814    basic_string(size_type n, default_init_t, const allocator_type& a)
815       : base_t(a, n + 1)
816    {
817       this->priv_size(n);
818       this->priv_terminate_string();
819    }
820 
821    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
822    //!   and a range of iterators.
823    template <class InputIterator>
basic_string(InputIterator f,InputIterator l)824    basic_string(InputIterator f, InputIterator l)
825       : base_t()
826    {
827       this->priv_terminate_string();
828       this->assign(f, l);
829    }
830 
831    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
832    //!   and a range of iterators.
833    template <class InputIterator>
basic_string(InputIterator f,InputIterator l,const allocator_type & a)834    basic_string(InputIterator f, InputIterator l, const allocator_type& a)
835       : base_t(a)
836    {
837       this->priv_terminate_string();
838       this->assign(f, l);
839    }
840 
841    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
842    //! <b>Effects</b>: Same as basic_string(il.begin(), il.end(), a).
843    //!
basic_string(std::initializer_list<value_type> il,const allocator_type & a=allocator_type ())844    basic_string(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
845       : base_t(a)
846    {
847       this->priv_terminate_string();
848       this->assign(il.begin(), il.end());
849    }
850    #endif
851 
852    //! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
853    //!
854    //! <b>Throws</b>: Nothing.
855    //!
856    //! <b>Complexity</b>: Constant.
~basic_string()857    ~basic_string() BOOST_NOEXCEPT_OR_NOTHROW
858    {}
859 
860    //! <b>Effects</b>: Copy constructs a string.
861    //!
862    //! <b>Postcondition</b>: x == *this.
863    //!
864    //! <b>Complexity</b>: Linear to the elements x contains.
operator =(BOOST_COPY_ASSIGN_REF (basic_string)x)865    basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
866    {
867       if (BOOST_LIKELY(this != &x)) {
868          allocator_type &this_alloc     = this->alloc();
869          const allocator_type &x_alloc  = x.alloc();
870          dtl::bool_<allocator_traits_type::
871             propagate_on_container_copy_assignment::value> flag;
872          if(flag && this_alloc != x_alloc){
873             if(!this->is_short()){
874                this->deallocate_block();
875                this->assure_short();
876                Traits::assign(*this->priv_addr(), CharT(0));
877                this->priv_short_size(0);
878             }
879          }
880          dtl::assign_alloc(this->alloc(), x.alloc(), flag);
881          this->assign(x.begin(), x.end());
882       }
883       return *this;
884    }
885 
886    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
887    //!
888    //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
889    //!   is false and allocation throws
890    //!
891    //! <b>Complexity</b>: Constant if allocator_traits_type::
892    //!   propagate_on_container_move_assignment is true or
893    //!   this->get>allocator() == x.get_allocator(). Linear otherwise.
operator =(BOOST_RV_REF (basic_string)x)894    basic_string& operator=(BOOST_RV_REF(basic_string) x)
895       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
896                                   || allocator_traits_type::is_always_equal::value)
897    {
898       if (BOOST_LIKELY(this != &x)) {
899          allocator_type &this_alloc = this->alloc();
900          allocator_type &x_alloc    = x.alloc();
901          const bool propagate_alloc = allocator_traits_type::
902                propagate_on_container_move_assignment::value;
903          dtl::bool_<propagate_alloc> flag;
904          const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
905          //Resources can be transferred if both allocators are
906          //going to be equal after this function (either propagated or already equal)
907          if(propagate_alloc || allocators_equal){
908             //Destroy objects but retain memory in case x reuses it in the future
909             this->clear();
910             //Move allocator if needed
911             dtl::move_alloc(this_alloc, x_alloc, flag);
912             //Nothrow swap
913             this->swap_data(x);
914          }
915          //Else do a one by one move
916          else{
917             this->assign( x.begin(), x.end());
918          }
919       }
920       return *this;
921    }
922 
923    //! <b>Effects</b>: Assignment from a null-terminated c-string.
924    //!
operator =(const CharT * s)925    basic_string& operator=(const CharT* s)
926    { return this->assign(s, s + Traits::length(s)); }
927 
928    //! <b>Effects</b>: Returns *this = basic_string(1, c).
929    //!
operator =(CharT c)930    basic_string& operator=(CharT c)
931    { return this->assign(static_cast<size_type>(1), c); }
932 
933    //! <b>Effects</b>: Equivalent to return assign(sv).
934    //!
935    template<template <class, class> class BasicStringView>
operator =(BasicStringView<CharT,Traits> sv)936    basic_string& operator=(BasicStringView<CharT, Traits> sv)
937    { return this->assign(sv.data(), sv.size()); }
938 
939    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
940    //! <b>Effects</b>: Returns *this = basic_string(il);
941    //!
operator =(std::initializer_list<CharT> il)942    basic_string& operator=(std::initializer_list<CharT> il)
943    {
944       return this->assign(il.begin(), il.end());
945    }
946    #endif
947 
948    //! <b>Effects</b>: Returns a copy of the internal allocator.
949    //!
950    //! <b>Throws</b>: If allocator's copy constructor throws.
951    //!
952    //! <b>Complexity</b>: Constant.
953    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
get_allocator() const954       allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
955    { return this->alloc(); }
956 
957    //! <b>Effects</b>: Returns a reference to the internal allocator.
958    //!
959    //! <b>Throws</b>: Nothing
960    //!
961    //! <b>Complexity</b>: Constant.
962    //!
963    //! <b>Note</b>: Non-standard extension.
964    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
get_stored_allocator()965       stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
966    {  return this->alloc(); }
967 
968    //! <b>Effects</b>: Returns a reference to the internal allocator.
969    //!
970    //! <b>Throws</b>: Nothing
971    //!
972    //! <b>Complexity</b>: Constant.
973    //!
974    //! <b>Note</b>: Non-standard extension.
975    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
get_stored_allocator() const976       const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
977    {  return this->alloc(); }
978 
979    //////////////////////////////////////////////
980    //
981    //                iterators
982    //
983    //////////////////////////////////////////////
984 
985    //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
986    //!
987    //! <b>Throws</b>: Nothing.
988    //!
989    //! <b>Complexity</b>: Constant.
990    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
begin()991       iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
992    { return this->priv_addr(); }
993 
994    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
995    //!
996    //! <b>Throws</b>: Nothing.
997    //!
998    //! <b>Complexity</b>: Constant.
999    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
begin() const1000       const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1001    { return this->priv_addr(); }
1002 
1003    //! <b>Effects</b>: Returns an iterator to the end of the vector.
1004    //!
1005    //! <b>Throws</b>: Nothing.
1006    //!
1007    //! <b>Complexity</b>: Constant.
1008    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
end()1009       iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1010    { return this->priv_end_addr(); }
1011 
1012    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1013    //!
1014    //! <b>Throws</b>: Nothing.
1015    //!
1016    //! <b>Complexity</b>: Constant.
1017    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
end() const1018       const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1019    { return this->priv_end_addr(); }
1020 
1021    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
1022    //! of the reversed vector.
1023    //!
1024    //! <b>Throws</b>: Nothing.
1025    //!
1026    //! <b>Complexity</b>: Constant.
1027    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rbegin()1028       reverse_iterator rbegin()  BOOST_NOEXCEPT_OR_NOTHROW
1029    { return reverse_iterator(this->priv_end_addr()); }
1030 
1031    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1032    //! of the reversed vector.
1033    //!
1034    //! <b>Throws</b>: Nothing.
1035    //!
1036    //! <b>Complexity</b>: Constant.
1037    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rbegin() const1038       const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1039    { return this->crbegin(); }
1040 
1041    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
1042    //! of the reversed vector.
1043    //!
1044    //! <b>Throws</b>: Nothing.
1045    //!
1046    //! <b>Complexity</b>: Constant.
1047    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rend()1048       reverse_iterator rend()  BOOST_NOEXCEPT_OR_NOTHROW
1049    { return reverse_iterator(this->priv_addr()); }
1050 
1051    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1052    //! of the reversed vector.
1053    //!
1054    //! <b>Throws</b>: Nothing.
1055    //!
1056    //! <b>Complexity</b>: Constant.
1057    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rend() const1058       const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1059    { return this->crend(); }
1060 
1061    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1062    //!
1063    //! <b>Throws</b>: Nothing.
1064    //!
1065    //! <b>Complexity</b>: Constant.
1066    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
cbegin() const1067       const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1068    { return this->priv_addr(); }
1069 
1070    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1071    //!
1072    //! <b>Throws</b>: Nothing.
1073    //!
1074    //! <b>Complexity</b>: Constant.
1075    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
cend() const1076       const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1077    { return this->priv_end_addr(); }
1078 
1079    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1080    //! of the reversed vector.
1081    //!
1082    //! <b>Throws</b>: Nothing.
1083    //!
1084    //! <b>Complexity</b>: Constant.
1085    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
crbegin() const1086       const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1087    { return const_reverse_iterator(this->priv_end_addr()); }
1088 
1089    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1090    //! of the reversed vector.
1091    //!
1092    //! <b>Throws</b>: Nothing.
1093    //!
1094    //! <b>Complexity</b>: Constant.
1095    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
crend() const1096       const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
1097    { return const_reverse_iterator(this->priv_addr()); }
1098 
1099    //////////////////////////////////////////////
1100    //
1101    //                capacity
1102    //
1103    //////////////////////////////////////////////
1104 
1105    //! <b>Effects</b>: Returns true if the vector contains no elements.
1106    //!
1107    //! <b>Throws</b>: Nothing.
1108    //!
1109    //! <b>Complexity</b>: Constant.
1110    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
empty() const1111       bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1112    { return !this->priv_size(); }
1113 
1114    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
1115    //!
1116    //! <b>Throws</b>: Nothing.
1117    //!
1118    //! <b>Complexity</b>: Constant.
1119    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
size() const1120       size_type size() const    BOOST_NOEXCEPT_OR_NOTHROW
1121    { return this->priv_size(); }
1122 
1123    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
1124    //!
1125    //! <b>Throws</b>: Nothing.
1126    //!
1127    //! <b>Complexity</b>: Constant.
1128    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
length() const1129       size_type length() const BOOST_NOEXCEPT_OR_NOTHROW
1130    { return this->size(); }
1131 
1132    //! <b>Effects</b>: Returns the largest possible size of the vector.
1133    //!
1134    //! <b>Throws</b>: Nothing.
1135    //!
1136    //! <b>Complexity</b>: Constant
1137    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
max_size() const1138       size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1139    { return base_t::max_size(); }
1140 
1141    //! <b>Effects</b>: Inserts or erases elements at the end such that
1142    //!   the size becomes n. New elements are copy constructed from x.
1143    //!
1144    //! <b>Throws</b>: If memory allocation throws
1145    //!
1146    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
resize(size_type n,CharT c)1147    void resize(size_type n, CharT c)
1148    {
1149       if (n <= this->size())
1150          this->erase(this->begin() + n, this->end());
1151       else
1152          this->append(n - this->size(), c);
1153    }
1154 
1155    //! <b>Effects</b>: Inserts or erases elements at the end such that
1156    //!   the size becomes n. New elements are value initialized.
1157    //!
1158    //! <b>Throws</b>: If memory allocation throws
1159    //!
1160    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
resize(size_type n)1161    void resize(size_type n)
1162    { resize(n, CharT()); }
1163 
1164    //! <b>Effects</b>: Inserts or erases elements at the end such that
1165    //!   the size becomes n. New elements are uninitialized.
1166    //!
1167    //! <b>Throws</b>: If memory allocation throws
1168    //!
1169    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1170    //!
1171    //! <b>Note</b>: Non-standard extension
resize(size_type n,default_init_t)1172    void resize(size_type n, default_init_t)
1173    {
1174       if (n <= this->size())
1175          this->erase(this->begin() + n, this->end());
1176       else{
1177          this->priv_reserve(n, false);
1178          this->priv_size(n);
1179          this->priv_terminate_string();
1180       }
1181    }
1182 
1183    //! <b>Effects</b>: Number of elements for which memory has been allocated.
1184    //!   capacity() is always greater than or equal to size().
1185    //!
1186    //! <b>Throws</b>: Nothing.
1187    //!
1188    //! <b>Complexity</b>: Constant.
1189    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
capacity() const1190       size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1191    { return this->priv_capacity(); }
1192 
1193    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1194    //!   effect. Otherwise, it is a request for allocation of additional memory.
1195    //!   If the request is successful, then capacity() is greater than or equal to
1196    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1197    //!
1198    //! <b>Throws</b>: If memory allocation allocation throws
reserve(size_type res_arg)1199    void reserve(size_type res_arg)
1200    {  this->priv_reserve(res_arg);  }
1201 
1202    //! <b>Effects</b>: Tries to deallocate the excess of memory created
1203    //!   with previous allocations. The size of the string is unchanged
1204    //!
1205    //! <b>Throws</b>: Nothing
1206    //!
1207    //! <b>Complexity</b>: Linear to size().
shrink_to_fit()1208    void shrink_to_fit()
1209    {
1210       //Check if shrinking is possible
1211       if(this->priv_storage() > InternalBufferChars){
1212          //Check if we should pass from dynamically allocated buffer
1213          //to the internal storage
1214          if(this->priv_size() < InternalBufferChars){
1215             //Dynamically allocated buffer attributes
1216             pointer   long_addr    = this->priv_long_addr();
1217             size_type long_storage = this->priv_long_storage();
1218             size_type long_size    = this->priv_long_size();
1219             //Shrink from allocated buffer to the internal one, including trailing null
1220             Traits::copy( boost::movelib::to_raw_pointer(this->priv_short_addr())
1221                         , boost::movelib::to_raw_pointer(long_addr)
1222                         , long_size+1);
1223             BOOST_ASSERT(!this->is_short());
1224             this->destroy_long();
1225             this->construct_short();
1226             this->alloc().deallocate(long_addr, long_storage);
1227          }
1228          else{
1229             //Shrinking in dynamic buffer
1230             this->priv_shrink_to_fit_dynamic_buffer(alloc_version());
1231          }
1232       }
1233    }
1234 
1235    //////////////////////////////////////////////
1236    //
1237    //               element access
1238    //
1239    //////////////////////////////////////////////
1240 
1241    //! <b>Requires</b>: !empty()
1242    //!
1243    //! <b>Effects</b>: Returns a reference to the first
1244    //!   element of the container.
1245    //!
1246    //! <b>Throws</b>: Nothing.
1247    //!
1248    //! <b>Complexity</b>: Constant.
1249    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
front()1250       reference         front() BOOST_NOEXCEPT_OR_NOTHROW
1251    {
1252       BOOST_ASSERT(!this->empty());
1253       return *this->priv_addr();
1254    }
1255 
1256    //! <b>Requires</b>: !empty()
1257    //!
1258    //! <b>Effects</b>: Returns a const reference to the first
1259    //!   element of the container.
1260    //!
1261    //! <b>Throws</b>: Nothing.
1262    //!
1263    //! <b>Complexity</b>: Constant.
1264    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
front() const1265       const_reference   front() const BOOST_NOEXCEPT_OR_NOTHROW
1266    {
1267       BOOST_ASSERT(!this->empty());
1268       return *this->priv_addr();
1269    }
1270 
1271    //! <b>Requires</b>: !empty()
1272    //!
1273    //! <b>Effects</b>: Returns a reference to the last
1274    //!   element of the container.
1275    //!
1276    //! <b>Throws</b>: Nothing.
1277    //!
1278    //! <b>Complexity</b>: Constant.
1279    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
back()1280       reference         back() BOOST_NOEXCEPT_OR_NOTHROW
1281    {
1282       BOOST_ASSERT(!this->empty());
1283       return *(this->priv_addr() + (this->size() - 1u) );
1284    }
1285 
1286    //! <b>Requires</b>: !empty()
1287    //!
1288    //! <b>Effects</b>: Returns a const reference to the last
1289    //!   element of the container.
1290    //!
1291    //! <b>Throws</b>: Nothing.
1292    //!
1293    //! <b>Complexity</b>: Constant.
1294    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
back() const1295       const_reference   back()  const BOOST_NOEXCEPT_OR_NOTHROW
1296    {
1297       BOOST_ASSERT(!this->empty());
1298       return *(this->priv_addr() + (this->size() - 1u) );
1299    }
1300 
1301    //! <b>Requires</b>: size() > n.
1302    //!
1303    //! <b>Effects</b>: Returns a reference to the nth element
1304    //!   from the beginning of the container.
1305    //!
1306    //! <b>Throws</b>: Nothing.
1307    //!
1308    //! <b>Complexity</b>: Constant.
1309    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
operator [](size_type n)1310       reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1311    {
1312       BOOST_ASSERT(this->size() > n);
1313       return *(this->priv_addr() + n);
1314    }
1315 
1316    //! <b>Requires</b>: size() > n.
1317    //!
1318    //! <b>Effects</b>: Returns a const reference to the nth element
1319    //!   from the beginning of the container.
1320    //!
1321    //! <b>Throws</b>: Nothing.
1322    //!
1323    //! <b>Complexity</b>: Constant.
1324    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
operator [](size_type n) const1325       const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1326    {
1327       BOOST_ASSERT(this->size() > n);
1328       return *(this->priv_addr() + n);
1329    }
1330 
1331    //! <b>Requires</b>: size() > n.
1332    //!
1333    //! <b>Effects</b>: Returns a reference to the nth element
1334    //!   from the beginning of the container.
1335    //!
1336    //! <b>Throws</b>: range_error if n >= size()
1337    //!
1338    //! <b>Complexity</b>: Constant.
1339    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
at(size_type n)1340       reference at(size_type n)
1341    {
1342       if (n >= this->size())
1343          throw_out_of_range("basic_string::at invalid subscript");
1344       return *(this->priv_addr() + n);
1345    }
1346 
1347    //! <b>Requires</b>: size() > n.
1348    //!
1349    //! <b>Effects</b>: Returns a const reference to the nth element
1350    //!   from the beginning of the container.
1351    //!
1352    //! <b>Throws</b>: range_error if n >= size()
1353    //!
1354    //! <b>Complexity</b>: Constant.
1355    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
at(size_type n) const1356       const_reference at(size_type n) const {
1357       if (n >= this->size())
1358          throw_out_of_range("basic_string::at invalid subscript");
1359       return *(this->priv_addr() + n);
1360    }
1361 
1362    //////////////////////////////////////////////
1363    //
1364    //                modifiers
1365    //
1366    //////////////////////////////////////////////
1367 
1368    //! <b>Effects</b>: Calls append(str.data, str.size()).
1369    //!
1370    //! <b>Returns</b>: *this
operator +=(const basic_string & s)1371    basic_string& operator+=(const basic_string& s)
1372    {  return this->append(s); }
1373 
1374    //! <b>Effects</b>: Same as `return append(sv)`.
1375    //!
1376    template<template<class, class> class BasicStringView>
operator +=(BasicStringView<CharT,Traits> sv)1377    basic_string& operator+=(BasicStringView<CharT, Traits> sv)
1378    {
1379       return this->append(sv);
1380    }
1381 
1382    //! <b>Effects</b>: Calls append(s).
1383    //!
1384    //! <b>Returns</b>: *this
operator +=(const CharT * s)1385    basic_string& operator+=(const CharT* s)
1386    {  return this->append(s); }
1387 
1388    //! <b>Effects</b>: Calls append(1, c).
1389    //!
1390    //! <b>Returns</b>: *this
operator +=(CharT c)1391    basic_string& operator+=(CharT c)
1392    {  this->push_back(c); return *this;   }
1393 
1394    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1395    //! <b>Effects</b>: Returns append(il)
1396    //!
operator +=(std::initializer_list<CharT> il)1397    basic_string& operator+=(std::initializer_list<CharT> il)
1398    {
1399       return this->append(il);
1400    }
1401    #endif
1402 
1403    //! <b>Effects</b>: Calls append(str.data(), str.size()).
1404    //!
1405    //! <b>Returns</b>: *this
append(const basic_string & s)1406    basic_string& append(const basic_string& s)
1407    {  return this->append(s.begin(), s.end());  }
1408 
1409    //! <b>Effects</b>: Same as return append(sv.data(), sv.size()).
1410    //!
1411    template<template<class, class> class BasicStringView>
append(BasicStringView<CharT,Traits> sv)1412    basic_string& append(BasicStringView<CharT, Traits> sv)
1413    {  return this->append(sv.data(), sv.size());  }
1414 
1415    //! <b>Requires</b>: pos <= str.size()
1416    //!
1417    //! <b>Effects</b>: Determines the effective length rlen of the string to append
1418    //! as the smaller of n and str.size() - pos and calls append(str.data() + pos, rlen).
1419    //!
1420    //! <b>Throws</b>: If memory allocation throws and out_of_range if pos > str.size()
1421    //!
1422    //! <b>Returns</b>: *this
append(const basic_string & s,size_type pos,size_type n=npos)1423    basic_string& append(const basic_string& s, size_type pos, size_type n = npos)
1424    {
1425       if (pos > s.size())
1426          throw_out_of_range("basic_string::append out of range position");
1427       return this->append(s.begin() + pos,
1428                           s.begin() + pos + dtl::min_value(n, s.size() - pos));
1429    }
1430 
1431    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1432    //!
1433    //! <b>Effects</b>: The function replaces the string controlled by *this with
1434    //!   a string of length size() + n whose irst size() elements are a copy of the
1435    //!   original string controlled by *this and whose remaining
1436    //!   elements are a copy of the initial n elements of s.
1437    //!
1438    //! <b>Throws</b>: If memory allocation throws length_error if size() + n > max_size().
1439    //!
1440    //! <b>Returns</b>: *this
append(const CharT * s,size_type n)1441    basic_string& append(const CharT* s, size_type n)
1442    {  return this->append(s, s + n);  }
1443 
1444    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1445    //!
1446    //! <b>Effects</b>: Calls append(s, traits::length(s)).
1447    //!
1448    //! <b>Returns</b>: *this
append(const CharT * s)1449    basic_string& append(const CharT* s)
1450    {  return this->append(s, s + Traits::length(s));  }
1451 
1452    //! <b>Effects</b>: Equivalent to append(basic_string(n, c)).
1453    //!
1454    //! <b>Returns</b>: *this
append(size_type n,CharT c)1455    basic_string& append(size_type n, CharT c)
1456    {  return this->append(cvalue_iterator(c, n), cvalue_iterator()); }
1457 
1458    //! <b>Requires</b>: [first,last) is a valid range.
1459    //!
1460    //! <b>Effects</b>: Equivalent to append(basic_string(first, last)).
1461    //!
1462    //! <b>Returns</b>: *this
1463    template <class InputIter>
append(InputIter first,InputIter last)1464    basic_string& append(InputIter first, InputIter last)
1465    {  this->insert(this->end(), first, last);   return *this;  }
1466 
1467    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1468    //! <b>Effects</b>: Returns append(il.begin(), il.size()).
1469    //!
append(std::initializer_list<CharT> il)1470    basic_string& append(std::initializer_list<CharT> il)
1471    {
1472       return this->append(il.begin(), il.size());
1473    }
1474    #endif
1475 
1476    //! <b>Effects</b>: Equivalent to append(static_cast<size_type>(1), c).
1477    //!
push_back(CharT c)1478    void push_back(CharT c)
1479    {
1480       const size_type old_size = this->priv_size();
1481       if (old_size < this->capacity()){
1482          const pointer addr = this->priv_addr();
1483          this->priv_construct_null(addr + old_size + 1);
1484          Traits::assign(addr[old_size], c);
1485          this->priv_size(old_size+1);
1486       }
1487       else{
1488          //No enough memory, insert a new object at the end
1489          this->append(size_type(1), c);
1490       }
1491    }
1492 
1493    //! <b>Effects</b>: Equivalent to assign(str, 0, npos).
1494    //!
1495    //! <b>Returns</b>: *this
assign(const basic_string & s)1496    basic_string& assign(const basic_string& s)
1497    {  return this->operator=(s); }
1498 
1499    //! <b>Effects</b>: Equivalent to return assign(sv.data(), sv.size()).
1500    //!
1501    //! <b>Returns</b>: *this
1502    template<template <class, class> class BasicStringView>
assign(BasicStringView<CharT,Traits> sv)1503    basic_string& assign(BasicStringView<CharT, Traits> sv)
1504    {  return this->operator=(sv); }
1505 
1506    //! <b>Effects</b>: The function replaces the string controlled by *this
1507    //!    with a string of length str.size() whose elements are a copy of the string
1508    //!   controlled by str. Leaves str in a valid but unspecified state.
1509    //!
1510    //! <b>Throws</b>: Nothing
1511    //!
1512    //! <b>Returns</b>: *this
assign(BOOST_RV_REF (basic_string)ms)1513    basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_NOEXCEPT_OR_NOTHROW
1514    {  return this->swap_data(ms), *this;  }
1515 
1516    //! <b>Requires</b>: pos <= str.size()
1517    //!
1518    //! <b>Effects</b>: Determines the effective length rlen of the string to assign as
1519    //!   the smaller of n and str.size() - pos and calls assign(str.data() + pos rlen).
1520    //!
1521    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > str.size().
1522    //!
1523    //! <b>Returns</b>: *this
assign(const basic_string & s,size_type pos,size_type n)1524    basic_string& assign(const basic_string& s, size_type pos, size_type n)
1525    {
1526       if (pos > s.size())
1527          throw_out_of_range("basic_string::assign out of range position");
1528       return this->assign(s.begin() + pos,
1529                           s.begin() + pos + dtl::min_value(n, s.size() - pos));
1530    }
1531 
1532    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1533    //!
1534    //! <b>Effects</b>: Replaces the string controlled by *this with a string of
1535    //! length n whose elements are a copy of those pointed to by s.
1536    //!
1537    //! <b>Throws</b>: If memory allocation throws or length_error if n > max_size().
1538    //!
1539    //! <b>Returns</b>: *this
assign(const CharT * s,size_type n)1540    basic_string& assign(const CharT* s, size_type n)
1541    {  return this->assign(s, s + n);   }
1542 
1543    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1544    //!
1545    //! <b>Effects</b>: Calls assign(s, traits::length(s)).
1546    //!
1547    //! <b>Returns</b>: *this
assign(const CharT * s)1548    basic_string& assign(const CharT* s)
1549    { return this->assign(s, s + Traits::length(s)); }
1550 
1551    //! <b>Effects</b>: Equivalent to assign(basic_string(n, c)).
1552    //!
1553    //! <b>Returns</b>: *this
assign(size_type n,CharT c)1554    basic_string& assign(size_type n, CharT c)
1555    {  return this->assign(cvalue_iterator(c, n), cvalue_iterator()); }
1556 
1557    //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
1558     //!
1559     //! <b>Returns</b>: *this
assign(const CharT * first,const CharT * last)1560     basic_string& assign(const CharT* first, const CharT* last)
1561     {
1562        size_type n = static_cast<size_type>(last - first);
1563        this->reserve(n);
1564        CharT* ptr = boost::movelib::to_raw_pointer(this->priv_addr());
1565        Traits::copy(ptr, first, n);
1566        this->priv_construct_null(ptr + n);
1567        this->priv_size(n);
1568        return *this;
1569     }
1570 
1571    //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
1572    //!
1573    //! <b>Returns</b>: *this
1574    template <class InputIter>
assign(InputIter first,InputIter last,typename dtl::disable_if_convertible<InputIter,size_type>::type * =0)1575    basic_string& assign(InputIter first, InputIter last
1576       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1577       , typename dtl::disable_if_convertible<InputIter, size_type>::type * = 0
1578       #endif
1579       )
1580    {
1581       size_type cur = 0;
1582       const pointer addr = this->priv_addr();
1583       CharT *ptr = boost::movelib::to_raw_pointer(addr);
1584       const size_type old_size = this->priv_size();
1585       while (first != last && cur != old_size) {
1586          Traits::assign(*ptr, *first);
1587          ++first;
1588          ++cur;
1589          ++ptr;
1590       }
1591       if (first == last)
1592          this->erase(addr + cur, addr + old_size);
1593       else
1594          this->append(first, last);
1595       return *this;
1596    }
1597 
1598    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1599    //! <b>Effects</b>: Returns assign(il.begin(), il.size()).
1600    //!
assign(std::initializer_list<CharT> il)1601    basic_string& assign(std::initializer_list<CharT> il)
1602    {
1603       return this->assign(il.begin(), il.size());
1604    }
1605    #endif
1606 
1607    //! <b>Requires</b>: pos <= size().
1608    //!
1609    //! <b>Effects</b>: Calls insert(pos, str.data(), str.size()).
1610    //!
1611    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
1612    //!
1613    //! <b>Returns</b>: *this
insert(size_type pos,const basic_string & s)1614    basic_string& insert(size_type pos, const basic_string& s)
1615    {
1616       const size_type sz = this->size();
1617       if (pos > sz)
1618          throw_out_of_range("basic_string::insert out of range position");
1619       if (sz > this->max_size() - s.size())
1620          throw_length_error("basic_string::insert max_size() exceeded");
1621       this->insert(this->priv_addr() + pos, s.begin(), s.end());
1622       return *this;
1623    }
1624 
1625    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
1626    //!
1627    //! <b>Effects</b>: Determines the effective length rlen of the string to insert as
1628    //!   the smaller of n and str.size() - pos2 and calls insert(pos1, str.data() + pos2, rlen).
1629    //!
1630    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size().
1631    //!
1632    //! <b>Returns</b>: *this
insert(size_type pos1,const basic_string & s,size_type pos2,size_type n=npos)1633    basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n = npos)
1634    {
1635       const size_type sz = this->size();
1636       const size_type str_size = s.size();
1637       if (pos1 > sz || pos2 > str_size)
1638          throw_out_of_range("basic_string::insert out of range position");
1639       size_type len = dtl::min_value(n, str_size - pos2);
1640       if (sz > this->max_size() - len)
1641          throw_length_error("basic_string::insert max_size() exceeded");
1642       const CharT *beg_ptr = boost::movelib::to_raw_pointer(s.begin()) + pos2;
1643       const CharT *end_ptr = beg_ptr + len;
1644       this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
1645       return *this;
1646    }
1647 
1648    //! <b>Requires</b>: s points to an array of at least n elements of CharT and pos <= size().
1649    //!
1650    //! <b>Effects</b>: Replaces the string controlled by *this with a string of length size() + n
1651    //!   whose first pos elements are a copy of the initial elements of the original string
1652    //!   controlled by *this and whose next n elements are a copy of the elements in s and whose
1653    //!   remaining elements are a copy of the remaining elements of the original string controlled by *this.
1654    //!
1655    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size() or
1656    //!   length_error if size() + n > max_size().
1657    //!
1658    //! <b>Returns</b>: *this
insert(size_type pos,const CharT * s,size_type n)1659    basic_string& insert(size_type pos, const CharT* s, size_type n)
1660    {
1661       if (pos > this->size())
1662          throw_out_of_range("basic_string::insert out of range position");
1663       if (this->size() > this->max_size() - n)
1664          throw_length_error("basic_string::insert max_size() exceeded");
1665       this->insert(this->priv_addr() + pos, s, s + n);
1666       return *this;
1667    }
1668 
1669    //! <b>Requires</b>: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of CharT
1670    //!
1671    //! <b>Effects</b>: Calls insert(pos, s, traits::length(s)).
1672    //!
1673    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1674    //!   length_error if size() > max_size() - Traits::length(s)
1675    //!
1676    //! <b>Returns</b>: *this
insert(size_type pos,const CharT * s)1677    basic_string& insert(size_type pos, const CharT* s)
1678    {
1679       if (pos > this->size())
1680          throw_out_of_range("basic_string::insert out of range position");
1681       size_type len = Traits::length(s);
1682       if (this->size() > this->max_size() - len)
1683          throw_length_error("basic_string::insert max_size() exceeded");
1684       this->insert(this->priv_addr() + pos, s, s + len);
1685       return *this;
1686    }
1687 
1688    //! <b>Effects</b>: Equivalent to insert(pos, basic_string(n, c)).
1689    //!
1690    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1691    //!   length_error if size() > max_size() - n
1692    //!
1693    //! <b>Returns</b>: *this
insert(size_type pos,size_type n,CharT c)1694    basic_string& insert(size_type pos, size_type n, CharT c)
1695    {
1696       if (pos > this->size())
1697          throw_out_of_range("basic_string::insert out of range position");
1698       if (this->size() > this->max_size() - n)
1699          throw_length_error("basic_string::insert max_size() exceeded");
1700       this->insert(const_iterator(this->priv_addr() + pos), n, c);
1701       return *this;
1702    }
1703 
1704    //! <b>Effects</b>: Same as `return insert(pos, sv.data(), sv.size())`.
1705    //!
1706    template<template<class, class> class BasicStringView>
insert(size_type pos,BasicStringView<CharT,Traits> sv)1707    basic_string& insert(size_type pos, BasicStringView<CharT, Traits> sv)
1708    {  return this->insert(pos, sv.data(), sv.size());  }
1709 
1710    //! <b>Requires</b>: p is a valid iterator on *this.
1711    //!
1712    //! <b>Effects</b>: inserts a copy of c before the character referred to by p.
1713    //!
1714    //! <b>Returns</b>: An iterator which refers to the copy of the inserted character.
insert(const_iterator p,CharT c)1715    iterator insert(const_iterator p, CharT c)
1716    {
1717       size_type new_offset = p - this->priv_addr();
1718       this->insert(p, cvalue_iterator(c, 1), cvalue_iterator());
1719       return this->priv_addr() + new_offset;
1720    }
1721 
1722    //! <b>Requires</b>: p is a valid iterator on *this.
1723    //!
1724    //! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
1725    //!
1726    //! <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)1727    iterator insert(const_iterator p, size_type n, CharT c)
1728    {  return this->insert(p, cvalue_iterator(c, n), cvalue_iterator());  }
1729 
1730    //! <b>Requires</b>: p is a valid iterator on *this. [first,last) is a valid range.
1731    //!
1732    //! <b>Effects</b>: Equivalent to insert(p - begin(), basic_string(first, last)).
1733    //!
1734    //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
1735    template <class InputIter>
insert(const_iterator p,InputIter first,InputIter last,typename dtl::disable_if_or<void,dtl::is_convertible<InputIter,size_type>,dtl::is_not_input_iterator<InputIter>>::type * =0)1736    iterator insert(const_iterator p, InputIter first, InputIter last
1737       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1738       , typename dtl::disable_if_or
1739          < void
1740          , dtl::is_convertible<InputIter, size_type>
1741          , dtl::is_not_input_iterator<InputIter>
1742          >::type * = 0
1743       #endif
1744       )
1745    {
1746       const size_type n_pos = p - this->cbegin();
1747       for ( ; first != last; ++first, ++p) {
1748          p = this->insert(p, *first);
1749       }
1750       return this->begin() + n_pos;
1751    }
1752 
1753    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1754    template <class ForwardIter>
insert(const_iterator p,ForwardIter first,ForwardIter last,typename dtl::disable_if_or<void,dtl::is_convertible<ForwardIter,size_type>,dtl::is_input_iterator<ForwardIter>>::type * =0)1755    iterator insert(const_iterator p, ForwardIter first, ForwardIter last
1756       , typename dtl::disable_if_or
1757          < void
1758          , dtl::is_convertible<ForwardIter, size_type>
1759          , dtl::is_input_iterator<ForwardIter>
1760          >::type * = 0
1761       )
1762    {
1763       const size_type n_pos = p - this->cbegin();
1764       if (first != last) {
1765          const size_type n = boost::container::iterator_distance(first, last);
1766          const size_type old_size = this->priv_size();
1767          const size_type remaining = this->capacity() - old_size;
1768          const pointer old_start = this->priv_addr();
1769          bool enough_capacity = false;
1770          size_type new_cap = 0;
1771 
1772          //Check if we have enough capacity
1773          pointer hint = pointer();
1774          pointer allocation_ret = pointer();
1775          if (remaining >= n){
1776             enough_capacity = true;
1777          }
1778          else {
1779             //Otherwise expand current buffer or allocate new storage
1780             new_cap  = this->next_capacity(n);
1781             hint = old_start;
1782             allocation_ret = this->allocation_command
1783                   (allocate_new | expand_fwd | expand_bwd, old_size + n + 1, new_cap, hint);
1784 
1785             //Check forward expansion
1786             if(old_start == allocation_ret){
1787                enough_capacity = true;
1788                this->priv_storage(new_cap);
1789             }
1790          }
1791 
1792          //Reuse same buffer
1793          if(enough_capacity){
1794             const size_type elems_after = old_size - (p - old_start);
1795             const size_type old_length = old_size;
1796             if (elems_after >= n) {
1797                const pointer pointer_past_last = old_start + old_size + 1;
1798                priv_uninitialized_copy(old_start + (old_size - n + 1),
1799                                        pointer_past_last, pointer_past_last);
1800 
1801                this->priv_size(old_size+n);
1802                Traits::move(const_cast<CharT*>(boost::movelib::to_raw_pointer(p + n)),
1803                            boost::movelib::to_raw_pointer(p),
1804                            (elems_after - n) + 1);
1805                this->priv_copy(first, last, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
1806             }
1807             else {
1808                ForwardIter mid = first;
1809                boost::container::iterator_advance(mid, elems_after + 1);
1810 
1811                priv_uninitialized_copy(mid, last, old_start + old_size + 1);
1812                const size_type newer_size = old_size + (n - elems_after);
1813                this->priv_size(newer_size);
1814                priv_uninitialized_copy
1815                   (p, const_iterator(old_start + old_length + 1),
1816                   old_start + newer_size);
1817                this->priv_size(newer_size + elems_after);
1818                this->priv_copy(first, mid, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
1819             }
1820          }
1821          else{
1822             pointer new_start = allocation_ret;
1823             if(!hint){
1824                //Copy data to new buffer
1825                size_type new_length = 0;
1826                //This can't throw, since characters are POD
1827                new_length += priv_uninitialized_copy
1828                               (const_iterator(old_start), p, new_start);
1829                new_length += priv_uninitialized_copy
1830                               (first, last, new_start + new_length);
1831                new_length += priv_uninitialized_copy
1832                               (p, const_iterator(old_start + old_size),
1833                               new_start + new_length);
1834                this->priv_construct_null(new_start + new_length);
1835 
1836                this->deallocate_block();
1837                this->assure_long();
1838                this->priv_long_addr(new_start);
1839                this->priv_long_size(new_length);
1840                this->priv_long_storage(new_cap);
1841             }
1842             else{
1843                //value_type is POD, so backwards expansion is much easier
1844                //than with vector<T>
1845                value_type * const oldbuf     = boost::movelib::to_raw_pointer(old_start);
1846                value_type * const newbuf     = boost::movelib::to_raw_pointer(new_start);
1847                const value_type *const pos   = boost::movelib::to_raw_pointer(p);
1848                const size_type before  = pos - oldbuf;
1849 
1850                //First move old data
1851                Traits::move(newbuf, oldbuf, before);
1852                Traits::move(newbuf + before + n, pos, old_size - before);
1853                //Now initialize the new data
1854                priv_uninitialized_copy(first, last, new_start + before);
1855                this->priv_construct_null(new_start + (old_size + n));
1856                this->assure_long();
1857                this->priv_long_addr(new_start);
1858                this->priv_long_size(old_size + n);
1859                this->priv_long_storage(new_cap);
1860             }
1861          }
1862       }
1863       return this->begin() + n_pos;
1864    }
1865    #endif
1866 
1867    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1868    //! <b>Effects</b>: As if by insert(p, il.begin(), il.end()).
1869    //!
1870    //! <b>Returns</b>: An iterator which refers to the copy of the first inserted
1871    //!   character, or p if i1 is empty.
insert(const_iterator p,std::initializer_list<CharT> il)1872    iterator insert(const_iterator p, std::initializer_list<CharT> il)
1873    {
1874       return this->insert(p, il.begin(), il.end());
1875    }
1876    #endif
1877 
1878    //! <b>Effects</b>: Removes the last element from the container.
1879    //!
1880    //! <b>Throws</b>: Nothing.
1881    //!
1882    //! <b>Complexity</b>: Constant time.
pop_back()1883    void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
1884    {
1885       BOOST_ASSERT(!this->empty());
1886       iterator p = this->end();
1887       this->erase(--p);
1888    }
1889 
1890    //! <b>Requires</b>: pos <= size()
1891    //!
1892    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos.
1893    //!   The function then replaces the string controlled by *this with a string of length size() - xlen
1894    //!   whose first pos elements are a copy of the initial elements of the original string controlled by *this,
1895    //!   and whose remaining elements are a copy of the elements of the original string controlled by *this
1896    //!   beginning at position pos + xlen.
1897    //!
1898    //! <b>Throws</b>: out_of_range if pos > size().
1899    //!
1900    //! <b>Returns</b>: *this
erase(size_type pos=0,size_type n=npos)1901    basic_string& erase(size_type pos = 0, size_type n = npos)
1902    {
1903       if (pos > this->size())
1904          throw_out_of_range("basic_string::erase out of range position");
1905       const pointer addr = this->priv_addr();
1906       erase(addr + pos, addr + pos + dtl::min_value(n, this->size() - pos));
1907       return *this;
1908    }
1909 
1910    //! <b>Effects</b>: Removes the character referred to by p.
1911    //!
1912    //! <b>Throws</b>: Nothing
1913    //!
1914    //! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being
1915    //!    erased. If no such element exists, end() is returned.
erase(const_iterator p)1916    iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1917    {
1918       // The move includes the terminating null.
1919       CharT * const ptr = const_cast<CharT*>(boost::movelib::to_raw_pointer(p));
1920       const size_type old_size = this->priv_size();
1921       Traits::move(ptr,
1922                    boost::movelib::to_raw_pointer(p + 1),
1923                    old_size - (p - this->priv_addr()));
1924       this->priv_size(old_size-1);
1925       return iterator(ptr);
1926    }
1927 
1928    //! <b>Requires</b>: first and last are valid iterators on *this, defining a range [first,last).
1929    //!
1930    //! <b>Effects</b>: Removes the characters in the range [first,last).
1931    //!
1932    //! <b>Throws</b>: Nothing
1933    //!
1934    //! <b>Returns</b>: An iterator which points to the element pointed to by last prior to
1935    //!   the other elements being erased. If no such element exists, end() is returned.
erase(const_iterator first,const_iterator last)1936    iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
1937    {
1938       CharT * f = const_cast<CharT*>(boost::movelib::to_raw_pointer(first));
1939       if (first != last) { // The move includes the terminating null.
1940          const size_type num_erased = last - first;
1941          const size_type old_size = this->priv_size();
1942          Traits::move(f,
1943                       boost::movelib::to_raw_pointer(last),
1944                       (old_size + 1)-(last - this->priv_addr()));
1945          const size_type new_length = old_size - num_erased;
1946          this->priv_size(new_length);
1947       }
1948       return iterator(f);
1949    }
1950 
1951    //! <b>Effects</b>: Erases all the elements of the vector.
1952    //!
1953    //! <b>Throws</b>: Nothing.
1954    //!
1955    //! <b>Complexity</b>: Linear to the number of elements in the vector.
clear()1956    void clear() BOOST_NOEXCEPT_OR_NOTHROW
1957    {
1958       if (!this->empty()) {
1959          Traits::assign(*this->priv_addr(), CharT(0));
1960          this->priv_size(0);
1961       }
1962    }
1963 
1964    //! <b>Requires</b>: pos1 <= size().
1965    //!
1966    //! <b>Effects</b>: Calls replace(pos1, n1, str.data(), str.size()).
1967    //!
1968    //! <b>Throws</b>: if memory allocation throws or out_of_range if pos1 > size().
1969    //!
1970    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,const basic_string & str)1971    basic_string& replace(size_type pos1, size_type n1, const basic_string& str)
1972    {
1973       if (pos1 > this->size())
1974          throw_out_of_range("basic_string::replace out of range position");
1975       const size_type len = dtl::min_value(n1, this->size() - pos1);
1976       if (this->size() - len >= this->max_size() - str.size())
1977          throw_length_error("basic_string::replace max_size() exceeded");
1978       const pointer addr = this->priv_addr();
1979       return this->replace( const_iterator(addr + pos1)
1980                           , const_iterator(addr + pos1 + len)
1981                           , str.begin(), str.end());
1982    }
1983 
1984    //! <b>Effects</b>: Calls `return replace(pos1, n1, sv.data(), sv.size());`.
1985    //!
1986    template<template<class, class> class BasicStringView>
replace(size_type pos1,size_type n1,BasicStringView<CharT,Traits> sv)1987    basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv)
1988    {
1989       return this->replace(pos1, n1, sv.data(), sv.size());
1990    }
1991 
1992    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size().
1993    //!
1994    //! <b>Effects</b>: Determines the effective length rlen of the string to be
1995    //!   inserted as the smaller of n2 and str.size() - pos2 and calls
1996    //!   replace(pos1, n1, str.data() + pos2, rlen).
1997    //!
1998    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or pos2 > str.size().
1999    //!
2000    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,const basic_string & str,size_type pos2,size_type n2=npos)2001    basic_string& replace(size_type pos1, size_type n1,
2002                          const basic_string& str, size_type pos2, size_type n2 = npos)
2003    {
2004       if (pos2 > str.size())
2005          throw_out_of_range("basic_string::replace out of range position");
2006       return this->replace(pos1, n1, str.data()+pos2, dtl::min_value(n2, str.size() - pos2));
2007    }
2008 
2009    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size().
2010    //!
2011    //! <b>Effects</b>: Determines the effective length rlen of the string to be inserted as the
2012    //!   smaller of n2 and sv.size() - pos2 and calls `replace(pos1, n1, sv.data() + pos2, rlen)`.
2013    //!
2014    //! <b>Returns</b>: *this.
2015    template<template<class, class> class BasicStringView>
replace(size_type pos1,size_type n1,BasicStringView<CharT,Traits> sv,size_type pos2,size_type n2=npos)2016    basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv,
2017                          size_type pos2, size_type n2 = npos)
2018    {
2019       if (pos2 > sv.size())
2020          throw_out_of_range("basic_string::replace out of range position");
2021       return this->replace(pos1, n1, sv.data()+pos2, dtl::min_value(n2, sv.size() - pos2));
2022    }
2023 
2024    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
2025    //!
2026    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the
2027    //!   smaller of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error.
2028    //!   Otherwise, the function replaces the string controlled by *this with a string of
2029    //!   length size() - xlen + n2 whose first pos1 elements are a copy of the initial elements
2030    //!   of the original string controlled by *this, whose next n2 elements are a copy of the
2031    //!   initial n2 elements of s, and whose remaining elements are a copy of the elements of
2032    //!   the original string controlled by *this beginning at position pos + xlen.
2033    //!
2034    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
2035    //!   if the length of the resulting string would exceed max_size()
2036    //!
2037    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,const CharT * s,size_type n2)2038    basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
2039    {
2040       if (pos1 > this->size())
2041          throw_out_of_range("basic_string::replace out of range position");
2042       const size_type len = dtl::min_value(n1, this->size() - pos1);
2043       const size_type max_size = this->max_size();
2044       if (n2 > max_size || (this->size() - len) >= (max_size - n2))
2045          throw_length_error("basic_string::replace max_size() exceeded");
2046       const pointer addr = this->priv_addr() + pos1;
2047       return this->replace(addr, addr + len, s, s + n2);
2048    }
2049 
2050    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
2051    //!
2052    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller
2053    //! of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. Otherwise,
2054    //! the function replaces the string controlled by *this with a string of length size() - xlen + n2
2055    //! whose first pos1 elements are a copy of the initial elements of the original string controlled
2056    //! by *this, whose next n2 elements are a copy of the initial n2 elements of s, and whose
2057    //! remaining elements are a copy of the elements of the original string controlled by *this
2058    //! beginning at position pos + xlen.
2059    //!
2060    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
2061    //!   if the length of the resulting string would exceed max_size()
2062    //!
2063    //! <b>Returns</b>: *this
replace(size_type pos,size_type n1,const CharT * s)2064    basic_string& replace(size_type pos, size_type n1, const CharT* s)
2065    {
2066       return this->replace(pos, n1, s, Traits::length(s));
2067    }
2068 
2069    //! <b>Requires</b>: pos1 <= size().
2070    //!
2071    //! <b>Effects</b>: Equivalent to replace(pos1, n1, basic_string(n2, c)).
2072    //!
2073    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
2074    //!   if the length of the  resulting string would exceed max_size()
2075    //!
2076    //! <b>Returns</b>: *this
replace(size_type pos1,size_type n1,size_type n2,CharT c)2077    basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c)
2078    {
2079       if (pos1 > this->size())
2080          throw_out_of_range("basic_string::replace out of range position");
2081       const size_type len = dtl::min_value(n1, this->size() - pos1);
2082       if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
2083          throw_length_error("basic_string::replace max_size() exceeded");
2084       const pointer addr    = this->priv_addr();
2085       return this->replace(addr + pos1, addr + pos1 + len, n2, c);
2086    }
2087 
2088    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
2089    //!
2090    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, str).
2091    //!
2092    //! <b>Throws</b>: if memory allocation throws
2093    //!
2094    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,const basic_string & str)2095    basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str)
2096    { return this->replace(i1, i2, str.data(), str.data()+str.size()); }
2097 
2098    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and
2099    //!   s points to an array of at least n elements
2100    //!
2101    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, n).
2102    //!
2103    //! <b>Throws</b>: if memory allocation throws
2104    //!
2105    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,const CharT * s,size_type n)2106    basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n)
2107    { return this->replace(i1, i2, s, s + n); }
2108 
2109    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and s points to an
2110    //!   array of at least traits::length(s) + 1 elements of CharT.
2111    //!
2112    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, traits::length(s)).
2113    //!
2114    //! <b>Throws</b>: if memory allocation throws
2115    //!
2116    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,const CharT * s)2117    basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s)
2118    {  return this->replace(i1, i2, s, s + Traits::length(s));   }
2119 
2120    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
2121    //!
2122    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(n, c)).
2123    //!
2124    //! <b>Throws</b>: if memory allocation throws
2125    //!
2126    //! <b>Returns</b>: *this
replace(const_iterator i1,const_iterator i2,size_type n,CharT c)2127    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, CharT c)
2128    {
2129       const size_type len = static_cast<size_type>(i2 - i1);
2130       if (len >= n) {
2131          Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), n, c);
2132          erase(i1 + n, i2);
2133       }
2134       else {
2135          Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), len, c);
2136          insert(i2, n - len, c);
2137       }
2138       return *this;
2139    }
2140 
2141    //! <b>Requires</b>: [begin(),i1), [i1,i2) and [j1,j2) are valid ranges.
2142    //!
2143    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(j1, j2)).
2144    //!
2145    //! <b>Throws</b>: if memory allocation throws
2146    //!
2147    //! <b>Returns</b>: *this
2148    template <class InputIter>
replace(const_iterator i1,const_iterator i2,InputIter j1,InputIter j2,typename dtl::disable_if_or<void,dtl::is_convertible<InputIter,size_type>,dtl::is_input_iterator<InputIter>>::type * =0)2149    basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
2150       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2151       , typename dtl::disable_if_or
2152          < void
2153          , dtl::is_convertible<InputIter, size_type>
2154          , dtl::is_input_iterator<InputIter>
2155          >::type * = 0
2156       #endif
2157       )
2158    {
2159       for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
2160          Traits::assign(*const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), *j1);
2161       }
2162 
2163       if (j1 == j2)
2164          this->erase(i1, i2);
2165       else
2166          this->insert(i2, j1, j2);
2167       return *this;
2168    }
2169 
2170    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2171    template <class ForwardIter>
replace(const_iterator i1,const_iterator i2,ForwardIter j1,ForwardIter j2,typename dtl::disable_if_or<void,dtl::is_convertible<ForwardIter,size_type>,dtl::is_not_input_iterator<ForwardIter>>::type * =0)2172    basic_string& replace(const_iterator i1, const_iterator i2, ForwardIter j1, ForwardIter j2
2173       , typename dtl::disable_if_or
2174          < void
2175          , dtl::is_convertible<ForwardIter, size_type>
2176          , dtl::is_not_input_iterator<ForwardIter>
2177          >::type * = 0
2178       )
2179    {
2180       difference_type n = boost::container::iterator_distance(j1, j2);
2181       const difference_type len = i2 - i1;
2182       if (len >= n) {
2183          this->priv_copy(j1, j2, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
2184          this->erase(i1 + n, i2);
2185       }
2186       else {
2187          ForwardIter m = j1;
2188          boost::container::iterator_advance(m, len);
2189          this->priv_copy(j1, m, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
2190          this->insert(i2, m, j2);
2191       }
2192       return *this;
2193    }
2194    #endif
2195 
2196    //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
2197    //!
2198    //! <b>Effects</b>: Calls `replace(i1 - begin(), i2 - i1, sv).`.
2199    //!
2200    //! <b>Returns</b>: *this.
2201    template<template <class, class> class BasicStringView>
replace(const_iterator i1,const_iterator i2,BasicStringView<CharT,Traits> sv)2202    basic_string& replace(const_iterator i1, const_iterator i2, BasicStringView<CharT, Traits> sv)
2203    {
2204       return this->replace( static_cast<size_type>(i1 - this->cbegin())
2205                           , static_cast<size_type>(i2 - i1), sv);
2206    }
2207 
2208    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2209    //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
2210    //!
2211    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, il.begin(), il.size()).
2212    //!
2213    //! <b>Returns</b>: *this.
replace(const_iterator i1,const_iterator i2,std::initializer_list<CharT> il)2214    basic_string& replace(const_iterator i1, const_iterator i2, std::initializer_list<CharT> il)
2215    {
2216       return this->replace( static_cast<size_type>(i1 - this->cbegin())
2217                           , static_cast<size_type>(i2 - i1)
2218                           , il.begin(), il.size());
2219    }
2220    #endif
2221 
2222    //! <b>Requires</b>: pos <= size()
2223    //!
2224    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as the
2225    //!   smaller of n and size() - pos. s shall designate an array of at least rlen elements.
2226    //!   The function then replaces the string designated by s with a string of length rlen
2227    //!   whose elements are a copy of the string controlled by *this beginning at position pos.
2228    //!   The function does not append a null object to the string designated by s.
2229    //!
2230    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos > size().
2231    //!
2232    //! <b>Returns</b>: rlen
copy(CharT * s,size_type n,size_type pos=0) const2233    size_type copy(CharT* s, size_type n, size_type pos = 0) const
2234    {
2235       if (pos > this->size())
2236          throw_out_of_range("basic_string::copy out of range position");
2237       const size_type len = dtl::min_value(n, this->size() - pos);
2238       Traits::copy(s, boost::movelib::to_raw_pointer(this->priv_addr() + pos), len);
2239       return len;
2240    }
2241 
2242    //! <b>Effects</b>: *this contains the same sequence of characters that was in s,
2243    //!   s contains the same sequence of characters that was in *this.
2244    //!
2245    //! <b>Throws</b>: Nothing
swap(basic_string & x)2246    void swap(basic_string& x)
2247       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value
2248                                || allocator_traits_type::is_always_equal::value)
2249    {
2250       this->base_t::swap_data(x);
2251       dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
2252       dtl::swap_alloc(this->alloc(), x.alloc(), flag);
2253    }
2254 
2255    //////////////////////////////////////////////
2256    //
2257    //                 data access
2258    //
2259    //////////////////////////////////////////////
2260 
2261    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
2262    //!
2263    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
2264    //!
2265    //! <b>Complexity</b>: constant time.
2266    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
c_str() const2267       const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW
2268    {  return boost::movelib::to_raw_pointer(this->priv_addr()); }
2269 
2270    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
2271    //!
2272    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
2273    //!
2274    //! <b>Complexity</b>: constant time.
2275    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
data() const2276       const CharT* data()  const BOOST_NOEXCEPT_OR_NOTHROW
2277    {  return boost::movelib::to_raw_pointer(this->priv_addr()); }
2278 
2279    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
2280    //!
2281    //! <b>Complexity</b>: constant time.
2282    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
data()2283       CharT* data()  BOOST_NOEXCEPT_OR_NOTHROW
2284    {  return boost::movelib::to_raw_pointer(this->priv_addr()); }
2285 
2286    #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
2287    //! <b>Returns</b>: a string_view to the characters in the string.
2288    //!
2289    //! <b>Complexity</b>: constant time.
2290    template<template <class, class> class BasicStringView>
operator BasicStringView<CharT,Traits>() const2291    operator BasicStringView<CharT, Traits>() const BOOST_NOEXCEPT_OR_NOTHROW
2292    { return this->to_view< BasicStringView<CharT, Traits> >(); }
2293    #endif
2294 
2295    //! <b>Returns</b>: a string_view to the characters in the string.
2296    //!
2297    //! <b>Complexity</b>: constant time.
2298    //!
2299    //! <b>Note</b>: This function is available to write portable code for compilers
2300    //!   that don't support templated conversion operators.
2301    template<class BasicStringView>
2302    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
to_view() const2303       BasicStringView to_view() const BOOST_NOEXCEPT_OR_NOTHROW
2304    { return BasicStringView(this->data(), this->size()); }
2305 
2306    //////////////////////////////////////////////
2307    //
2308    //             string operations
2309    //
2310    //////////////////////////////////////////////
2311 
2312    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
2313    //!   of the following conditions hold:
2314    //!   1) pos <= xpos and xpos + str.size() <= size();
2315    //!   2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
2316    //!
2317    //! <b>Throws</b>: Nothing
2318    //!
2319    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2320    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find(const basic_string & s,size_type pos=0) const2321       size_type find(const basic_string& s, size_type pos = 0) const
2322    { return find(s.c_str(), pos, s.size()); }
2323 
2324    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
2325    //!   of the following conditions hold:
2326    //!   1) pos <= xpos and xpos + sv.size() <= size();
2327    //!   2) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
2328    //!
2329    //! <b>Throws</b>: Nothing
2330    //!
2331    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2332    template<template <class, class> class BasicStringView>
2333    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find(BasicStringView<CharT,Traits> sv,size_type pos=0) const2334       size_type find(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2335    { return this->find(sv.data(), pos, sv.size()); }
2336 
2337    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2338    //!
2339    //! <b>Throws</b>: Nothing
2340    //!
2341    //! <b>Returns</b>: find(basic_string<CharT,traits,allocator_type>(s,n),pos).
2342    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find(const CharT * s,size_type pos,size_type n) const2343       size_type find(const CharT* s, size_type pos, size_type n) const
2344    {
2345       if (pos + n > this->size())
2346          return npos;
2347       else {
2348          const pointer addr = this->priv_addr();
2349          pointer finish = addr + this->priv_size();
2350          const const_iterator result =
2351             boost::container::search(boost::movelib::to_raw_pointer(addr + pos),
2352                    boost::movelib::to_raw_pointer(finish),
2353                    s, s + n, Eq_traits<Traits>());
2354          return result != finish ? result - begin() : npos;
2355       }
2356    }
2357 
2358    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2359    //!
2360    //! <b>Throws</b>: Nothing
2361    //!
2362    //! <b>Returns</b>: find(basic_string(s), pos).
2363    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find(const CharT * s,size_type pos=0) const2364       size_type find(const CharT* s, size_type pos = 0) const
2365    { return this->find(s, pos, Traits::length(s)); }
2366 
2367    //! <b>Throws</b>: Nothing
2368    //!
2369    //! <b>Returns</b>: find(basic_string<CharT,traits,allocator_type>(1,c), pos).
2370    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find(CharT c,size_type pos=0) const2371       size_type find(CharT c, size_type pos = 0) const
2372    {
2373       const size_type sz = this->size();
2374       if (pos >= sz)
2375          return npos;
2376       else {
2377          const pointer addr    = this->priv_addr();
2378          pointer finish = addr + sz;
2379          const const_iterator result =
2380             boost::container::find_if(addr + pos, finish,
2381                   boost::container::bind2nd(Eq_traits<Traits>(), c));
2382          return result != finish ? result - begin() : npos;
2383       }
2384    }
2385 
2386    //! <b>Effects</b>: Determines the highest position xpos, if possible, such
2387    //!   that both of the following conditions obtain:
2388    //!   a) xpos <= pos and xpos + str.size() <= size();
2389    //!   b) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
2390    //!
2391    //! <b>Throws</b>: Nothing
2392    //!
2393    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2394    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rfind(const basic_string & str,size_type pos=npos) const2395       size_type rfind(const basic_string& str, size_type pos = npos) const
2396       { return this->rfind(str.c_str(), pos, str.size()); }
2397 
2398    //! <b>Effects</b>: Determines the highest position xpos, if possible, such
2399    //!   that both of the following conditions obtain:
2400    //!   a) xpos <= pos and xpos + sv.size() <= size();
2401    //!   b) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
2402    //!
2403    //! <b>Throws</b>: Nothing
2404    //!
2405    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2406    template<template <class, class> class BasicStringView>
2407    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rfind(BasicStringView<CharT,Traits> sv,size_type pos=npos) const2408       size_type rfind(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2409       { return this->rfind(sv.data(), pos, sv.size()); }
2410 
2411    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2412    //!
2413    //! <b>Throws</b>: Nothing
2414    //!
2415    //! <b>Returns</b>: rfind(basic_string(s, n), pos).
2416    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rfind(const CharT * s,size_type pos,size_type n) const2417       size_type rfind(const CharT* s, size_type pos, size_type n) const
2418    {
2419       const size_type len = this->size();
2420 
2421       if (n > len)
2422          return npos;
2423       else if (n == 0)
2424          return dtl::min_value(len, pos);
2425       else {
2426          const const_iterator last = begin() + dtl::min_value(len - n, pos) + n;
2427          const const_iterator result = boost::container::find_end
2428             (begin(), last, s, s + n, Eq_traits<Traits>());
2429          return result != last ? result - begin() : npos;
2430       }
2431    }
2432 
2433    //! <b>Requires</b>: pos <= size() and s points to an array of at least
2434    //!   traits::length(s) + 1 elements of CharT.
2435    //!
2436    //! <b>Throws</b>: Nothing
2437    //!
2438    //! <b>Returns</b>: rfind(basic_string(s), pos).
2439    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rfind(const CharT * s,size_type pos=npos) const2440       size_type rfind(const CharT* s, size_type pos = npos) const
2441       { return this->rfind(s, pos, Traits::length(s)); }
2442 
2443    //! <b>Throws</b>: Nothing
2444    //!
2445    //! <b>Returns</b>: rfind(basic_string<CharT,traits,allocator_type>(1,c),pos).
2446    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
rfind(CharT c,size_type pos=npos) const2447       size_type rfind(CharT c, size_type pos = npos) const
2448    {
2449       const size_type len = this->size();
2450 
2451       if (len < 1)
2452          return npos;
2453       else {
2454          const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2455          const_reverse_iterator rresult =
2456             boost::container::find_if(const_reverse_iterator(last), rend(),
2457                   boost::container::bind2nd(Eq_traits<Traits>(), c));
2458          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
2459       }
2460    }
2461 
2462    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
2463    //!   following conditions obtain: a) pos <= xpos and xpos < size();
2464    //!   b) traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2465    //!
2466    //! <b>Throws</b>: Nothing
2467    //!
2468    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2469    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_of(const basic_string & str,size_type pos=0) const2470       size_type find_first_of(const basic_string& str, size_type pos = 0) const
2471       { return this->find_first_of(str.c_str(), pos, str.size()); }
2472 
2473    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
2474    //!   following conditions obtain: a) pos <= xpos and xpos < size();
2475    //!   b) traits::eq(at(xpos), sv.at(I)) for some element I of the string controlled by sv.
2476    //!
2477    //! <b>Throws</b>: Nothing
2478    //!
2479    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2480    template<template <class, class> class BasicStringView>
2481    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_of(BasicStringView<CharT,Traits> sv,size_type pos=0) const2482       size_type find_first_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2483       { return this->find_first_of(sv.data(), pos, sv.size()); }
2484 
2485    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2486    //!
2487    //! <b>Throws</b>: Nothing
2488    //!
2489    //! <b>Returns</b>: find_first_of(basic_string(s, n), pos).
2490    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_of(const CharT * s,size_type pos,size_type n) const2491       size_type find_first_of(const CharT* s, size_type pos, size_type n) const
2492    {
2493       const size_type sz = this->size();
2494       if (pos >= sz)
2495          return npos;
2496       else {
2497          const pointer addr    = this->priv_addr();
2498          pointer finish = addr + sz;
2499          const_iterator result = boost::container::find_first_of
2500             (addr + pos, finish, s, s + n, Eq_traits<Traits>());
2501          return result != finish ? result - this->begin() : npos;
2502       }
2503    }
2504 
2505    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2506    //!
2507    //! <b>Throws</b>: Nothing
2508    //!
2509    //! <b>Returns</b>: find_first_of(basic_string(s), pos).
2510    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_of(const CharT * s,size_type pos=0) const2511       size_type find_first_of(const CharT* s, size_type pos = 0) const
2512       { return this->find_first_of(s, pos, Traits::length(s)); }
2513 
2514    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2515    //!
2516    //! <b>Throws</b>: Nothing
2517    //!
2518    //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,allocator_type>(1,c), pos).
2519    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_of(CharT c,size_type pos=0) const2520       size_type find_first_of(CharT c, size_type pos = 0) const
2521     { return this->find(c, pos); }
2522 
2523    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
2524    //!   the following conditions obtain: a) xpos <= pos and xpos < size(); b)
2525    //!   traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2526    //!
2527    //! <b>Throws</b>: Nothing
2528    //!
2529    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2530    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_of(const basic_string & str,size_type pos=npos) const2531       size_type find_last_of(const basic_string& str, size_type pos = npos) const
2532       { return this->find_last_of(str.c_str(), pos, str.size()); }
2533 
2534    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
2535    //!   the following conditions obtain: a) xpos <= pos and xpos < size(); b)
2536    //!   traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2537    //!
2538    //! <b>Throws</b>: Nothing
2539    //!
2540    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2541    template<template <class, class> class BasicStringView>
2542    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_of(BasicStringView<CharT,Traits> sv,size_type pos=npos) const2543       size_type find_last_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2544       { return this->find_last_of(sv.data(), pos, sv.size()); }
2545 
2546    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2547    //!
2548    //! <b>Throws</b>: Nothing
2549    //!
2550    //! <b>Returns</b>: find_last_of(basic_string(s, n), pos).
2551    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_of(const CharT * s,size_type pos,size_type n) const2552       size_type find_last_of(const CharT* s, size_type pos, size_type n) const
2553    {
2554       const size_type len = this->size();
2555 
2556       if (len < 1)
2557          return npos;
2558       else {
2559          const pointer addr    = this->priv_addr();
2560          const const_iterator last = addr + dtl::min_value(len - 1, pos) + 1;
2561          const const_reverse_iterator rresult =
2562             boost::container::find_first_of(const_reverse_iterator(last), rend(),
2563                                s, s + n, Eq_traits<Traits>());
2564          return rresult != rend() ? (rresult.base() - 1) - addr : npos;
2565       }
2566    }
2567 
2568    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2569    //!
2570    //! <b>Throws</b>: Nothing
2571    //!
2572    //! <b>Returns</b>: find_last_of(basic_string<CharT,traits,allocator_type>(1,c),pos).
2573    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_of(const CharT * s,size_type pos=npos) const2574       size_type find_last_of(const CharT* s, size_type pos = npos) const
2575       { return this->find_last_of(s, pos, Traits::length(s)); }
2576 
2577    //! <b>Throws</b>: Nothing
2578    //!
2579    //! <b>Returns</b>: find_last_of(basic_string(s), pos).
2580    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_of(CharT c,size_type pos=npos) const2581       size_type find_last_of(CharT c, size_type pos = npos) const
2582       {  return this->rfind(c, pos);   }
2583 
2584    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that
2585    //!   both of the following conditions obtain:
2586    //!   a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), str.at(I)) for no
2587    //!   element I of the string controlled by str.
2588    //!
2589    //! <b>Throws</b>: Nothing
2590    //!
2591    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2592    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_not_of(const basic_string & str,size_type pos=0) const2593       size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
2594       { return this->find_first_not_of(str.c_str(), pos, str.size()); }
2595 
2596    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that
2597    //!   both of the following conditions obtain:
2598    //!   a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), sv.at(I)) for no
2599    //!   element I of the string controlled by sv.
2600    //!
2601    //! <b>Throws</b>: Nothing
2602    //!
2603    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2604    template<template <class, class> class BasicStringView>
2605    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_not_of(BasicStringView<CharT,Traits> sv,size_type pos=0) const2606       size_type find_first_not_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2607       { return this->find_first_not_of(sv.data(), pos, sv.size()); }
2608 
2609    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2610    //!
2611    //! <b>Throws</b>: Nothing
2612    //!
2613    //! <b>Returns</b>: find_first_not_of(basic_string(s, n), pos).
2614    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_not_of(const CharT * s,size_type pos,size_type n) const2615       size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const
2616    {
2617       if (pos > this->size())
2618          return npos;
2619       else {
2620          const pointer addr   = this->priv_addr();
2621          const pointer finish = addr + this->priv_size();
2622          const const_iterator result = boost::container::find_if
2623             (addr + pos, finish, Not_within_traits<Traits>(s, s + n));
2624          return result != finish ? result - addr : npos;
2625       }
2626    }
2627 
2628    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2629    //!
2630    //! <b>Throws</b>: Nothing
2631    //!
2632    //! <b>Returns</b>: find_first_not_of(basic_string(s), pos).
2633    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_not_of(const CharT * s,size_type pos=0) const2634       size_type find_first_not_of(const CharT* s, size_type pos = 0) const
2635       { return this->find_first_not_of(s, pos, Traits::length(s)); }
2636 
2637    //! <b>Throws</b>: Nothing
2638    //!
2639    //! <b>Returns</b>: find_first_not_of(basic_string(1, c), pos).
2640    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_first_not_of(CharT c,size_type pos=0) const2641       size_type find_first_not_of(CharT c, size_type pos = 0) const
2642    {
2643       if (pos > this->size())
2644          return npos;
2645       else {
2646          const pointer addr   = this->priv_addr();
2647          const pointer finish = addr + this->priv_size();
2648          const const_iterator result
2649             = boost::container::find_if(addr + pos, finish,
2650                      boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
2651          return result != finish ? result - begin() : npos;
2652       }
2653    }
2654 
2655    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
2656    //!   both of the following conditions obtain: a) xpos <= pos and xpos < size();
2657    //!   b) traits::eq(at(xpos), str.at(I)) for no element I of the string controlled by str.
2658    //!
2659    //! <b>Throws</b>: Nothing
2660    //!
2661    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2662    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_not_of(const basic_string & str,size_type pos=npos) const2663       size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
2664       { return this->find_last_not_of(str.c_str(), pos, str.size()); }
2665 
2666    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
2667    //!   both of the following conditions obtain: a) xpos <= pos and xpos < size();
2668    //!   b) traits::eq(at(xpos), sv.at(I)) for no element I of the string controlled by sv.
2669    //!
2670    //! <b>Throws</b>: Nothing
2671    //!
2672    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2673    template<template <class, class> class BasicStringView>
2674    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_not_of(BasicStringView<CharT,Traits> sv,size_type pos=npos) const2675       size_type find_last_not_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2676       { return this->find_last_not_of(sv.data(), pos, sv.size()); }
2677 
2678    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2679    //!
2680    //! <b>Throws</b>: Nothing
2681    //!
2682    //! <b>Returns</b>: find_last_not_of(basic_string(s, n), pos).
2683    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_not_of(const CharT * s,size_type pos,size_type n) const2684       size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const
2685    {
2686       const size_type len = this->size();
2687 
2688       if (len < 1)
2689          return npos;
2690       else {
2691          const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2692          const const_reverse_iterator rresult =
2693             boost::container::find_if(const_reverse_iterator(last), rend(),
2694                     Not_within_traits<Traits>(s, s + n));
2695          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
2696       }
2697    }
2698 
2699    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2700    //!
2701    //! <b>Throws</b>: Nothing
2702    //!
2703    //! <b>Returns</b>: find_last_not_of(basic_string(s), pos).
2704    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_not_of(const CharT * s,size_type pos=npos) const2705       size_type find_last_not_of(const CharT* s, size_type pos = npos) const
2706       { return this->find_last_not_of(s, pos, Traits::length(s)); }
2707 
2708    //! <b>Throws</b>: Nothing
2709    //!
2710    //! <b>Returns</b>: find_last_not_of(basic_string(1, c), pos).
2711    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
find_last_not_of(CharT c,size_type pos=npos) const2712       size_type find_last_not_of(CharT c, size_type pos = npos) const
2713    {
2714       const size_type len = this->size();
2715 
2716       if (len < 1)
2717          return npos;
2718       else {
2719          const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2720          const const_reverse_iterator rresult =
2721             boost::container::find_if(const_reverse_iterator(last), rend(),
2722                   boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
2723          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
2724       }
2725    }
2726 
2727    //! <b>Requires</b>: Requires: pos <= size()
2728    //!
2729    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2730    //!   the smaller of n and size() - pos.
2731    //!
2732    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
2733    //!
2734    //! <b>Returns</b>: basic_string<CharT,traits,allocator_type>(data()+pos,rlen).
2735    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
substr(size_type pos=0,size_type n=npos) const2736       basic_string substr(size_type pos = 0, size_type n = npos) const
2737    {
2738       if (pos > this->size())
2739          throw_out_of_range("basic_string::substr out of range position");
2740       const pointer addr = this->priv_addr();
2741       return basic_string(addr + pos,
2742                           addr + pos + dtl::min_value(n, size() - pos), this->alloc());
2743    }
2744 
2745    //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
2746    //!   the smaller of size() and str.size(). The function then compares the two strings by
2747    //!   calling traits::compare(data(), str.data(), rlen).
2748    //!
2749    //! <b>Throws</b>: Nothing
2750    //!
2751    //! <b>Returns</b>: The nonzero result if the result of the comparison is nonzero.
2752    //!   Otherwise, returns a value < 0 if size() < str.size(), a 0 value if size() == str.size(),
2753    //!   and value > 0 if size() > str.size()
2754    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(const basic_string & str) const2755       int compare(const basic_string& str) const
2756    {
2757       const pointer addr     = this->priv_addr();
2758       const pointer str_addr = str.priv_addr();
2759       return this->s_compare(addr, addr + this->priv_size(), str_addr, str_addr + str.priv_size());
2760    }
2761 
2762    //! <b>Throws</b>: Nothing
2763    //!
2764    //! <b>Returns</b>: compare(basic_string(sv)).
2765    template<template <class, class> class BasicStringView>
2766    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(BasicStringView<CharT,Traits> sv) const2767       int compare(BasicStringView<CharT,Traits> sv) const
2768    {
2769       const pointer addr = this->priv_addr();
2770       return this->s_compare(addr, addr + this->priv_size(), sv.data(), sv.data() + sv.size());
2771    }
2772 
2773    //! <b>Requires</b>: pos1 <= size()
2774    //!
2775    //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
2776    //!   the smaller of (this->size() - pos1), n1 and str.size(). The function then compares the two strings by
2777    //!   calling traits::compare(data()+pos1, str.data(), rlen).
2778    //!
2779    //! <b>Throws</b>: out_of_range if pos1 > size()
2780    //!
2781    //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(str).
2782    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(size_type pos1,size_type n1,const basic_string & str) const2783       int compare(size_type pos1, size_type n1, const basic_string& str) const
2784    {
2785       if (pos1 > this->size())
2786          throw_out_of_range("basic_string::compare out of range position");
2787       const pointer addr    = this->priv_addr();
2788       const pointer str_addr = str.priv_addr();
2789       return this->s_compare(addr + pos1,
2790                         addr + pos1 + dtl::min_value(n1, this->size() - pos1),
2791                         str_addr, str_addr + str.priv_size());
2792    }
2793 
2794    //! <b>Requires</b>: pos1 <= size()
2795    //!
2796    //! <b>Throws</b>: out_of_range if pos1 > size()
2797    //!
2798    //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(sv).
2799    template<template <class, class> class BasicStringView>
2800    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(size_type pos1,size_type n1,BasicStringView<CharT,Traits> sv) const2801       int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv) const
2802    {
2803       if (pos1 > this->size())
2804          throw_out_of_range("basic_string::compare out of range position");
2805       const pointer addr    = this->priv_addr() + pos1;
2806       const CharT* str_addr = sv.data();
2807       return this->s_compare(addr, addr + dtl::min_value(n1, this->size() - pos1),
2808                        str_addr, str_addr + sv.size());
2809    }
2810 
2811    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
2812    //!
2813    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2814    //!   the smaller of
2815    //!
2816    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > str.size()
2817    //!
2818    //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)).
2819    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(size_type pos1,size_type n1,const basic_string & str,size_type pos2,size_type n2=npos) const2820       int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos) const
2821    {
2822       if (pos1 > this->size() || pos2 > str.size())
2823          throw_out_of_range("basic_string::compare out of range position");
2824       const pointer addr     = this->priv_addr() + pos1;
2825       const pointer str_addr = str.priv_addr() + pos2;
2826       return this->s_compare(addr, addr + dtl::min_value(n1, this->size() - pos1),
2827                         str_addr, str_addr + dtl::min_value(n2, str.size() - pos2));
2828    }
2829 
2830    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
2831    //!
2832    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2833    //!   the smaller of
2834    //!
2835    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size()
2836    //!
2837    //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(BasicStringView<CharT, Traits>(sv, pos2, n2)).
2838    template<template <class, class> class BasicStringView>
2839    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(size_type pos1,size_type n1,BasicStringView<CharT,Traits> sv,size_type pos2,size_type n2) const2840       int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv, size_type pos2, size_type n2) const
2841    {
2842       if (pos1 > this->size() || pos2 > sv.size())
2843          throw_out_of_range("basic_string::compare out of range position");
2844       const pointer addr     = this->priv_addr() + pos1;
2845       const CharT * str_addr = sv.data() + pos2;
2846       return this->s_compare(addr, addr + dtl::min_value(n1, this->size() - pos1),
2847                        str_addr, str_addr + dtl::min_value(n2, sv.size() - pos2));
2848    }
2849 
2850    //! <b>Throws</b>: Nothing
2851    //!
2852    //! <b>Returns</b>: compare(basic_string(s)).
2853    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(const CharT * s) const2854       int compare(const CharT* s) const
2855    {
2856       const pointer addr = this->priv_addr();
2857       return this->s_compare(addr, addr + this->priv_size(), s, s + Traits::length(s));
2858    }
2859 
2860    //! <b>Requires</b>: pos1 > size() and s points to an array of at least n2 elements of CharT.
2861    //!
2862    //! <b>Throws</b>: out_of_range if pos1 > size()
2863    //!
2864    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
2865    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(size_type pos1,size_type n1,const CharT * s,size_type n2) const2866       int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
2867    {
2868       if (pos1 > this->size())
2869          throw_out_of_range("basic_string::compare out of range position");
2870       const pointer addr = this->priv_addr();
2871       return this->s_compare( addr + pos1,
2872                         addr + pos1 + dtl::min_value(n1, this->size() - pos1),
2873                         s, s + n2);
2874    }
2875 
2876    //! <b>Requires</b>: pos1 > size() and s points to an array of at least traits::length(s) + 1 elements of CharT.
2877    //!
2878    //! <b>Throws</b>: out_of_range if pos1 > size()
2879    //!
2880    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
2881    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
compare(size_type pos1,size_type n1,const CharT * s) const2882       int compare(size_type pos1, size_type n1, const CharT* s) const
2883    {  return this->compare(pos1, n1, s, Traits::length(s)); }
2884 
2885    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2886    private:
priv_reserve(size_type res_arg,const bool null_terminate=true)2887    void priv_reserve(size_type res_arg, const bool null_terminate = true)
2888    {
2889       if (res_arg > this->max_size()){
2890          throw_length_error("basic_string::reserve max_size() exceeded");
2891       }
2892 
2893       if (this->capacity() < res_arg){
2894          size_type n = dtl::max_value(res_arg, this->size()) + 1;
2895          size_type new_cap = this->next_capacity(n);
2896          pointer reuse = 0;
2897          pointer new_start = this->allocation_command(allocate_new, n, new_cap, reuse);
2898          size_type new_length = 0;
2899 
2900          const pointer addr = this->priv_addr();
2901          new_length += priv_uninitialized_copy
2902             (addr, addr + this->priv_size(), new_start);
2903          if(null_terminate){
2904             this->priv_construct_null(new_start + new_length);
2905          }
2906          this->deallocate_block();
2907          this->assure_long();
2908          this->priv_long_addr(new_start);
2909          this->priv_long_size(new_length);
2910          this->priv_storage(new_cap);
2911       }
2912    }
2913 
2914    template<class It1, class It2>
s_compare(It1 f1,It1 l1,It2 f2,It2 l2)2915    static int s_compare(It1 f1, It1 l1, It2 f2, It2 l2)
2916    {
2917       const difference_type n1 = l1 - f1;
2918       const difference_type n2 = l2 - f2;
2919       const int cmp = Traits::compare(boost::movelib::to_raw_pointer(f1),
2920                                       boost::movelib::to_raw_pointer(f2),
2921                                       dtl::min_value(n1, n2));
2922       return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
2923    }
2924 
2925    template<class AllocVersion>
priv_shrink_to_fit_dynamic_buffer(AllocVersion,typename dtl::enable_if<dtl::is_same<AllocVersion,version_1>>::type * =0)2926    void priv_shrink_to_fit_dynamic_buffer
2927       ( AllocVersion
2928       , typename dtl::enable_if<dtl::is_same<AllocVersion, version_1> >::type* = 0)
2929    {
2930       //Allocate a new buffer.
2931       size_type real_cap = 0;
2932       const pointer   long_addr    = this->priv_long_addr();
2933       const size_type long_size    = this->priv_long_size();
2934       const size_type long_storage = this->priv_long_storage();
2935       //We can make this nothrow as chars are always NoThrowCopyables
2936       BOOST_TRY{
2937          pointer reuse = 0;
2938          real_cap = long_size+1;
2939          const pointer ret = this->allocation_command(allocate_new, long_size+1, real_cap, reuse);
2940          //Copy and update
2941          Traits::copy( boost::movelib::to_raw_pointer(ret)
2942                      , boost::movelib::to_raw_pointer(this->priv_long_addr())
2943                      , long_size+1);
2944          this->priv_long_addr(ret);
2945          this->priv_storage(real_cap);
2946          //And release old buffer
2947          this->alloc().deallocate(long_addr, long_storage);
2948       }
2949       BOOST_CATCH(...){
2950          return;
2951       }
2952       BOOST_CATCH_END
2953    }
2954 
2955    template<class AllocVersion>
priv_shrink_to_fit_dynamic_buffer(AllocVersion,typename dtl::enable_if<dtl::is_same<AllocVersion,version_2>>::type * =0)2956    void priv_shrink_to_fit_dynamic_buffer
2957       ( AllocVersion
2958       , typename dtl::enable_if<dtl::is_same<AllocVersion, version_2> >::type* = 0)
2959    {
2960       size_type received_size = this->priv_long_size()+1;
2961       pointer hint = this->priv_long_addr();
2962       if(this->alloc().allocation_command
2963          ( shrink_in_place | nothrow_allocation, this->priv_long_storage(), received_size, hint)){
2964          this->priv_storage(received_size);
2965       }
2966    }
2967 
priv_construct_null(pointer p)2968    void priv_construct_null(pointer p)
2969    {  this->construct(p, CharT(0));  }
2970 
2971    // Helper functions used by constructors.  It is a severe error for
2972    // any of them to be called anywhere except from within constructors.
priv_terminate_string()2973    void priv_terminate_string()
2974    {  this->priv_construct_null(this->priv_end_addr());  }
2975 
2976    template<class FwdIt, class Count> inline
priv_uninitialized_fill_n(FwdIt first,Count count,const CharT val)2977    void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val)
2978    {
2979       //Save initial position
2980       FwdIt init = first;
2981 
2982       BOOST_TRY{
2983          //Construct objects
2984          for (; count--; ++first){
2985             this->construct(first, val);
2986          }
2987       }
2988       BOOST_CATCH(...){
2989          //Call destructors
2990          for (; init != first; ++init){
2991             this->destroy(init);
2992          }
2993          BOOST_RETHROW
2994       }
2995       BOOST_CATCH_END
2996    }
2997 
2998    template<class InpIt, class FwdIt> inline
priv_uninitialized_copy(InpIt first,InpIt last,FwdIt dest)2999    size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest)
3000    {
3001       //Save initial destination position
3002       FwdIt dest_init = dest;
3003       size_type constructed = 0;
3004 
3005       BOOST_TRY{
3006          //Try to build objects
3007          for (; first != last; ++dest, ++first, ++constructed){
3008             this->construct(dest, *first);
3009          }
3010       }
3011       BOOST_CATCH(...){
3012          //Call destructors
3013          for (; constructed--; ++dest_init){
3014             this->destroy(dest_init);
3015          }
3016          BOOST_RETHROW
3017       }
3018       BOOST_CATCH_END
3019       return (constructed);
3020    }
3021 
3022    template <class InputIterator, class OutIterator>
priv_copy(InputIterator first,InputIterator last,OutIterator result)3023    void priv_copy(InputIterator first, InputIterator last, OutIterator result)
3024    {
3025       for ( ; first != last; ++first, ++result)
3026          Traits::assign(*result, *first);
3027    }
3028 
priv_copy(const CharT * first,const CharT * last,CharT * result)3029    void priv_copy(const CharT* first, const CharT* last, CharT* result)
3030    {  Traits::copy(result, first, last - first);  }
3031 
3032    template <class Integer>
priv_replace_dispatch(const_iterator first,const_iterator last,Integer n,Integer x,dtl::true_)3033    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
3034                                        Integer n, Integer x,
3035                                        dtl::true_)
3036    {  return this->replace(first, last, (size_type) n, (CharT) x);   }
3037 
3038    template <class InputIter>
priv_replace_dispatch(const_iterator first,const_iterator last,InputIter f,InputIter l,dtl::false_)3039    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
3040                                        InputIter f, InputIter l,
3041                                        dtl::false_)
3042    {
3043       typedef typename boost::container::iterator_traits<InputIter>::iterator_category Category;
3044       return this->priv_replace(first, last, f, l, Category());
3045    }
3046 
3047    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3048 };
3049 
3050 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3051 
3052 template <typename InputIterator>
3053 basic_string(InputIterator, InputIterator) ->
3054    basic_string<typename iterator_traits<InputIterator>::value_type>;
3055 
3056 template <typename InputIterator, typename Allocator>
3057 basic_string(InputIterator, InputIterator, Allocator const&) ->
3058    basic_string<typename iterator_traits<InputIterator>::value_type, Allocator>;
3059 
3060 #endif
3061 
3062 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
3063 
3064 //!Typedef for a basic_string of
3065 //!narrow characters
3066 typedef basic_string
3067    <char
3068    ,std::char_traits<char>
3069    ,new_allocator<char> >
3070 string;
3071 
3072 //!Typedef for a basic_string of
3073 //!narrow characters
3074 typedef basic_string
3075    <wchar_t
3076    ,std::char_traits<wchar_t>
3077    ,new_allocator<wchar_t> >
3078 wstring;
3079 
3080 #else
3081 
3082 template <class CharT, class Traits, class Allocator>
3083 const typename basic_string<CharT,Traits,Allocator>::size_type
3084    basic_string<CharT,Traits,Allocator>::npos;
3085 
3086 template<class S>
3087 struct is_string
3088 {
3089    static const bool value = false;
3090 };
3091 
3092 template<class C, class T, class A>
3093 struct is_string< basic_string<C, T, A> >
3094 {
3095    static const bool value = true;
3096 };
3097 
3098 #endif
3099 
3100 // ------------------------------------------------------------
3101 // Non-member functions.
3102 
3103 // Operator+
3104 
3105 template <class CharT, class Traits, class Allocator> inline
3106    basic_string<CharT,Traits,Allocator>
operator +(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)3107    operator+(const basic_string<CharT,Traits,Allocator>& x
3108             ,const basic_string<CharT,Traits,Allocator>& y)
3109 {
3110    typedef basic_string<CharT,Traits,Allocator> str_t;
3111    typedef typename str_t::reserve_t reserve_t;
3112    reserve_t reserve;
3113    str_t result(reserve, x.size() + y.size(), x.get_stored_allocator());
3114    result.append(x);
3115    result.append(y);
3116    return result;
3117 }
3118 
3119 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)3120    basic_string<CharT, Traits, Allocator> operator+
3121       ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
3122       , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
3123 {
3124    x += y;
3125    return boost::move(x);
3126 }
3127 
3128 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)3129    basic_string<CharT, Traits, Allocator> operator+
3130       ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
3131       , const basic_string<CharT,Traits,Allocator>& y)
3132 {
3133    x += y;
3134    return boost::move(x);
3135 }
3136 
3137 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)3138    basic_string<CharT, Traits, Allocator> operator+
3139       (const basic_string<CharT,Traits,Allocator>& x
3140       ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
3141 {
3142    y.insert(y.begin(), x.begin(), x.end());
3143    return boost::move(y);
3144 }
3145 
3146 template <class CharT, class Traits, class Allocator> inline
operator +(const CharT * s,basic_string<CharT,Traits,Allocator> y)3147    basic_string<CharT, Traits, Allocator> operator+
3148       (const CharT* s, basic_string<CharT, Traits, Allocator> y)
3149 {
3150    y.insert(y.begin(), s, s + Traits::length(s));
3151    return y;
3152 }
3153 
3154 template <class CharT, class Traits, class Allocator> inline
operator +(basic_string<CharT,Traits,Allocator> x,const CharT * s)3155    basic_string<CharT,Traits,Allocator> operator+
3156       (basic_string<CharT,Traits,Allocator> x, const CharT* s)
3157 {
3158    x += s;
3159    return x;
3160 }
3161 
3162 template <class CharT, class Traits, class Allocator> inline
operator +(CharT c,basic_string<CharT,Traits,Allocator> y)3163    basic_string<CharT,Traits,Allocator> operator+
3164       (CharT c, basic_string<CharT,Traits,Allocator> y)
3165 {
3166    y.insert(y.begin(), c);
3167    return y;
3168 }
3169 
3170 template <class CharT, class Traits, class Allocator> inline
operator +(basic_string<CharT,Traits,Allocator> x,const CharT c)3171    basic_string<CharT,Traits,Allocator> operator+
3172       (basic_string<CharT,Traits,Allocator> x, const CharT c)
3173 {
3174    x += c;
3175    return x;
3176 }
3177 
3178 // Operator== and operator!=
3179 
3180 template <class CharT, class Traits, class Allocator>
3181 inline bool
operator ==(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)3182 operator==(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3183 {
3184    return x.size() == y.size() &&
3185           Traits::compare(x.data(), y.data(), x.size()) == 0;
3186 }
3187 
3188 template <class CharT, class Traits, class Allocator>
3189 inline bool
operator ==(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)3190 operator==(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3191 {
3192    typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
3193    return n == y.size() && Traits::compare(s, y.data(), n) == 0;
3194 }
3195 
3196 template <class CharT, class Traits, class Allocator>
3197 inline bool
operator ==(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)3198 operator==(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3199 {
3200    typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
3201    return x.size() == n && Traits::compare(x.data(), s, n) == 0;
3202 }
3203 
3204 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3205 inline
3206    BOOST_CONTAINER_DOC1ST( bool,
3207                            typename dtl::disable_if
3208                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3209       operator==( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3210 {
3211    return x.size() == y.size() &&
3212           Traits::compare(x.data(), y.data(), x.size()) == 0;
3213 }
3214 
3215 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3216 inline
3217    BOOST_CONTAINER_DOC1ST( bool,
3218                            typename dtl::disable_if
3219                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3220       operator==( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3221 {
3222    return x.size() == y.size() &&
3223           Traits::compare(x.data(), y.data(), x.size()) == 0;
3224 }
3225 
3226 template <class CharT, class Traits, class Allocator>
3227 inline bool
operator !=(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)3228 operator!=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3229    {  return !(x == y);  }
3230 
3231 template <class CharT, class Traits, class Allocator>
3232 inline bool
operator !=(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)3233 operator!=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3234    {  return !(s == y); }
3235 
3236 template <class CharT, class Traits, class Allocator>
3237 inline bool
operator !=(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)3238 operator!=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3239    {  return !(x == s);   }
3240 
3241 
3242 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3243 inline
3244    BOOST_CONTAINER_DOC1ST( bool,
3245                            typename dtl::disable_if
3246                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3247 operator!=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3248    {  return !(x == y);  }
3249 
3250 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3251 inline
3252    BOOST_CONTAINER_DOC1ST( bool,
3253                            typename dtl::disable_if
3254                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3255 operator!=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3256    {  return !(x == y);  }
3257 
3258 // Operator< (and also >, <=, and >=).
3259 template <class CharT, class Traits, class Allocator>
3260 inline bool
operator <(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)3261 operator<(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3262 {
3263    return x.compare(y) < 0;
3264 }
3265 
3266 template <class CharT, class Traits, class Allocator>
3267 inline bool
operator <(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)3268 operator<(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3269 {
3270    return y.compare(s) > 0;
3271 }
3272 
3273 template <class CharT, class Traits, class Allocator>
3274 inline bool
operator <(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)3275 operator<(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3276 {
3277    return x.compare(s) < 0;
3278 }
3279 
3280 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3281 inline
3282    BOOST_CONTAINER_DOC1ST( bool,
3283                            typename dtl::disable_if
3284                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3285 operator<( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3286    {  return y.compare(x) > 0;  }
3287 
3288 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3289 inline
3290    BOOST_CONTAINER_DOC1ST( bool,
3291                            typename dtl::disable_if
3292                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3293 operator<(  const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3294    {  return x.compare(y) < 0;  }
3295 
3296 template <class CharT, class Traits, class Allocator>
3297 inline bool
operator >(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)3298 operator>(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y) {
3299    return y < x;
3300 }
3301 
3302 template <class CharT, class Traits, class Allocator>
3303 inline bool
operator >(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)3304 operator>(const CharT* s, const basic_string<CharT,Traits,Allocator>& y) {
3305    return y < s;
3306 }
3307 
3308 template <class CharT, class Traits, class Allocator>
3309 inline bool
operator >(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)3310 operator>(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3311 {
3312    return s < x;
3313 }
3314 
3315 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3316 inline
BOOST_CONTAINER_DOC1ST(bool,typename dtl::disable_if<is_string<BasicStringView<CharT BOOST_MOVE_I Traits>> BOOST_MOVE_I bool>::type)3317    BOOST_CONTAINER_DOC1ST( bool,
3318                            typename dtl::disable_if
3319                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3320 operator>( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3321    {  return y < x;  }
3322 
3323 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3324 inline
BOOST_CONTAINER_DOC1ST(bool,typename dtl::disable_if<is_string<BasicStringView<CharT BOOST_MOVE_I Traits>> BOOST_MOVE_I bool>::type)3325    BOOST_CONTAINER_DOC1ST( bool,
3326                            typename dtl::disable_if
3327                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3328 operator>( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3329    {  return y < x;  }
3330 
3331 template <class CharT, class Traits, class Allocator>
3332 inline bool
operator <=(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)3333 operator<=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3334 {
3335   return !(y < x);
3336 }
3337 
3338 template <class CharT, class Traits, class Allocator>
3339 inline bool
operator <=(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)3340 operator<=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3341    {  return !(y < s);  }
3342 
3343 template <class CharT, class Traits, class Allocator>
3344 inline bool
operator <=(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)3345 operator<=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3346    {  return !(s < x);  }
3347 
3348 
3349 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3350 inline
3351    BOOST_CONTAINER_DOC1ST( bool,
3352                            typename dtl::disable_if
3353                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3354 operator<=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3355    {  return !(y < x);  }
3356 
3357 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3358 inline
3359    BOOST_CONTAINER_DOC1ST( bool,
3360                            typename dtl::disable_if
3361                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3362 operator<=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3363    {  return !(y < x);  }
3364 
3365 template <class CharT, class Traits, class Allocator>
3366 inline bool
operator >=(const basic_string<CharT,Traits,Allocator> & x,const basic_string<CharT,Traits,Allocator> & y)3367 operator>=(const basic_string<CharT,Traits,Allocator>& x,
3368            const basic_string<CharT,Traits,Allocator>& y)
3369    {  return !(x < y);  }
3370 
3371 template <class CharT, class Traits, class Allocator>
3372 inline bool
operator >=(const CharT * s,const basic_string<CharT,Traits,Allocator> & y)3373 operator>=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3374    {  return !(s < y);  }
3375 
3376 template <class CharT, class Traits, class Allocator>
3377 inline bool
operator >=(const basic_string<CharT,Traits,Allocator> & x,const CharT * s)3378 operator>=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3379    {  return !(x < s);  }
3380 
3381 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3382 inline
BOOST_CONTAINER_DOC1ST(bool,typename dtl::disable_if<is_string<BasicStringView<CharT BOOST_MOVE_I Traits>> BOOST_MOVE_I bool>::type)3383    BOOST_CONTAINER_DOC1ST( bool,
3384                            typename dtl::disable_if
3385                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3386 operator>=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3387    {  return !(x < y);  }
3388 
3389 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3390 inline
BOOST_CONTAINER_DOC1ST(bool,typename dtl::disable_if<is_string<BasicStringView<CharT BOOST_MOVE_I Traits>> BOOST_MOVE_I bool>::type)3391    BOOST_CONTAINER_DOC1ST( bool,
3392                            typename dtl::disable_if
3393                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3394 operator>=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3395    {  return !(x < y);  }
3396 
3397 // Swap.
3398 template <class CharT, class Traits, class Allocator>
swap(basic_string<CharT,Traits,Allocator> & x,basic_string<CharT,Traits,Allocator> & y)3399 inline void swap(basic_string<CharT,Traits,Allocator>& x, basic_string<CharT,Traits,Allocator>& y)
3400     BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
3401 {  x.swap(y);  }
3402 
3403 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3404 // I/O.
3405 namespace dtl {
3406 
3407 template <class CharT, class Traits>
3408 inline bool
string_fill(std::basic_ostream<CharT,Traits> & os,std::basic_streambuf<CharT,Traits> * buf,std::size_t n)3409 string_fill(std::basic_ostream<CharT, Traits>& os,
3410                   std::basic_streambuf<CharT, Traits>* buf,
3411                   std::size_t n)
3412 {
3413    CharT f = os.fill();
3414    std::size_t i;
3415    bool ok = true;
3416 
3417    for (i = 0; i < n; i++)
3418       ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof());
3419    return ok;
3420 }
3421 
3422 }  //namespace dtl {
3423 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3424 
3425 template <class CharT, class Traits, class Allocator>
3426 std::basic_ostream<CharT, Traits>&
operator <<(std::basic_ostream<CharT,Traits> & os,const basic_string<CharT,Traits,Allocator> & s)3427 operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Traits,Allocator>& s)
3428 {
3429    typename std::basic_ostream<CharT, Traits>::sentry sentry(os);
3430    bool ok = false;
3431 
3432    if (sentry) {
3433       ok = true;
3434       typename basic_string<CharT,Traits,Allocator>::size_type n = s.size();
3435       typename basic_string<CharT,Traits,Allocator>::size_type pad_len = 0;
3436       const bool left = (os.flags() & std::ios::left) != 0;
3437       const std::size_t w = os.width(0);
3438       std::basic_streambuf<CharT, Traits>* buf = os.rdbuf();
3439 
3440       if (w != 0 && n < w)
3441          pad_len = w - n;
3442 
3443       if (!left)
3444          ok = dtl::string_fill(os, buf, pad_len);
3445 
3446       ok = ok &&
3447             buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n);
3448 
3449       if (left)
3450          ok = ok && dtl::string_fill(os, buf, pad_len);
3451    }
3452 
3453    if (!ok)
3454       os.setstate(std::ios_base::failbit);
3455 
3456    return os;
3457 }
3458 
3459 
3460 template <class CharT, class Traits, class Allocator>
3461 std::basic_istream<CharT, Traits>&
operator >>(std::basic_istream<CharT,Traits> & is,basic_string<CharT,Traits,Allocator> & s)3462 operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
3463 {
3464    typename std::basic_istream<CharT, Traits>::sentry sentry(is);
3465 
3466    if (sentry) {
3467       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
3468       const std::ctype<CharT>& ctype = std::use_facet<std::ctype<CharT> >(is.getloc());
3469 
3470       s.clear();
3471       std::size_t n = is.width(0);
3472       if (n == 0)
3473          n = static_cast<std::size_t>(-1);
3474       else
3475          s.reserve(n);
3476 
3477       while (n-- > 0) {
3478          typename Traits::int_type c1 = buf->sbumpc();
3479 
3480          if (Traits::eq_int_type(c1, Traits::eof())) {
3481             is.setstate(std::ios_base::eofbit);
3482             break;
3483          }
3484          else {
3485             CharT c = Traits::to_char_type(c1);
3486 
3487             if (ctype.is(std::ctype<CharT>::space, c)) {
3488                if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof()))
3489                   is.setstate(std::ios_base::failbit);
3490                break;
3491             }
3492             else
3493                s.push_back(c);
3494          }
3495       }
3496 
3497       // If we have read no characters, then set failbit.
3498       if (s.size() == 0)
3499          is.setstate(std::ios_base::failbit);
3500    }
3501    else
3502       is.setstate(std::ios_base::failbit);
3503 
3504    return is;
3505 }
3506 
3507 template <class CharT, class Traits, class Allocator>
3508 std::basic_istream<CharT, Traits>&
getline(std::istream & is,basic_string<CharT,Traits,Allocator> & s,CharT delim)3509 getline(std::istream& is, basic_string<CharT,Traits,Allocator>& s,CharT delim)
3510 {
3511    typename basic_string<CharT,Traits,Allocator>::size_type nread = 0;
3512    typename std::basic_istream<CharT, Traits>::sentry sentry(is, true);
3513    if (sentry) {
3514       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
3515       s.clear();
3516 
3517       while (nread < s.max_size()) {
3518          int c1 = buf->sbumpc();
3519          if (Traits::eq_int_type(c1, Traits::eof())) {
3520             is.setstate(std::ios_base::eofbit);
3521             break;
3522          }
3523          else {
3524             ++nread;
3525             CharT c = Traits::to_char_type(c1);
3526             if (!Traits::eq(c, delim))
3527                s.push_back(c);
3528             else
3529                break;              // Character is extracted but not appended.
3530          }
3531       }
3532    }
3533    if (nread == 0 || nread >= s.max_size())
3534       is.setstate(std::ios_base::failbit);
3535 
3536    return is;
3537 }
3538 
3539 template <class CharT, class Traits, class Allocator>
3540 inline std::basic_istream<CharT, Traits>&
getline(std::basic_istream<CharT,Traits> & is,basic_string<CharT,Traits,Allocator> & s)3541 getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
3542 {
3543    return getline(is, s, '\n');
3544 }
3545 
3546 template <class Ch, class Allocator>
hash_value(basic_string<Ch,std::char_traits<Ch>,Allocator> const & v)3547 inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, Allocator> const& v)
3548 {
3549    std::size_t seed = 0;
3550    const Ch *first = v.data();
3551 
3552    for(std::size_t i = 0, i_max = v.size(); i != i_max; ++i)
3553    {
3554       boost::intrusive::detail::hash_combine_size_t(seed, static_cast<std::size_t>(*first));
3555       ++first;
3556    }
3557 
3558    return seed;
3559 }
3560 
3561 }}
3562 
3563 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3564 
3565 namespace boost {
3566 
3567 //!has_trivial_destructor_after_move<> == true_type
3568 //!specialization for optimizations
3569 template <class C, class T, class Allocator>
3570 struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
3571 {
3572    typedef typename boost::container::basic_string<C, T, Allocator>::allocator_type allocator_type;
3573    typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3574    static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3575                              ::boost::has_trivial_destructor_after_move<pointer>::value;
3576 };
3577 
3578 }
3579 
3580 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3581 
3582 #include <boost/container/detail/config_end.hpp>
3583 
3584 #endif // BOOST_CONTAINER_STRING_HPP
3585