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