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