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