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