comparison DEPENDENCIES/generic/include/boost/container/string.hpp @ 16:2665513ce2d3

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