File indexing completed on 2025-01-18 09:30:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_CONTAINER_STRING_HPP
0012 #define BOOST_CONTAINER_STRING_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024 #include <boost/container/container_fwd.hpp>
0025
0026 #include <boost/container/allocator_traits.hpp>
0027 #include <boost/container/new_allocator.hpp> //new_allocator
0028 #include <boost/container/throw_exception.hpp>
0029
0030 #include <boost/container/detail/alloc_helpers.hpp>
0031 #include <boost/container/detail/allocator_version_traits.hpp>
0032 #include <boost/container/detail/allocation_type.hpp>
0033 #include <boost/container/detail/iterator.hpp>
0034 #include <boost/container/detail/iterators.hpp>
0035 #include <boost/container/detail/min_max.hpp>
0036 #include <boost/container/detail/mpl.hpp>
0037 #include <boost/container/detail/next_capacity.hpp>
0038 #include <boost/move/detail/to_raw_pointer.hpp>
0039 #include <boost/container/detail/version_type.hpp>
0040 #include <boost/container/detail/type_traits.hpp>
0041 #include <boost/container/detail/algorithm.hpp>
0042 #include <boost/container/detail/minimal_char_traits_header.hpp> // for char_traits
0043
0044 #include <boost/intrusive/pointer_traits.hpp>
0045 #include <boost/intrusive/detail/hash_combine.hpp>
0046 #include <boost/move/detail/force_ptr.hpp>
0047
0048 #include <boost/move/utility_core.hpp>
0049 #include <boost/move/adl_move_swap.hpp>
0050 #include <boost/move/traits.hpp>
0051
0052 #include <boost/static_assert.hpp>
0053
0054 #include <iosfwd>
0055 #include <istream> //
0056 #include <ostream>
0057 #include <ios>
0058 #include <locale>
0059 #include <cstddef>
0060 #include <climits>
0061
0062
0063 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0064 #include <initializer_list> //for std::initializer_list
0065 #endif
0066
0067
0068 #if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
0069 #pragma GCC diagnostic push
0070 #pragma GCC diagnostic ignored "-Warray-bounds"
0071 #endif
0072
0073
0074 namespace boost {
0075 namespace container {
0076
0077 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0078 namespace dtl {
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 template <class Allocator>
0090 class basic_string_base
0091 {
0092 basic_string_base & operator=(const basic_string_base &);
0093 basic_string_base(const basic_string_base &);
0094
0095 typedef Allocator allocator_type;
0096 public:
0097 typedef allocator_traits<allocator_type> allocator_traits_type;
0098 typedef allocator_type stored_allocator_type;
0099 typedef typename allocator_traits_type::pointer pointer;
0100 typedef typename allocator_traits_type::value_type value_type;
0101 typedef typename allocator_traits_type::size_type size_type;
0102 typedef typename allocator_traits_type::difference_type difference_type;
0103
0104 typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
0105
0106 BOOST_CONTAINER_FORCEINLINE basic_string_base()
0107 : members_()
0108 {}
0109
0110 BOOST_CONTAINER_FORCEINLINE explicit basic_string_base(const allocator_type& a)
0111 : members_(a)
0112 {}
0113
0114 BOOST_CONTAINER_FORCEINLINE explicit basic_string_base(BOOST_RV_REF(allocator_type) a)
0115 : members_(boost::move(a))
0116 {}
0117
0118 BOOST_CONTAINER_FORCEINLINE basic_string_base(const allocator_type& a, size_type n)
0119 : members_(a)
0120 {
0121 this->allocate_initial_block(n);
0122 }
0123
0124 BOOST_CONTAINER_FORCEINLINE explicit basic_string_base(size_type n)
0125 : members_()
0126 {
0127 this->allocate_initial_block(n);
0128 }
0129
0130 BOOST_CONTAINER_FORCEINLINE ~basic_string_base()
0131 {
0132 if(!this->is_short()){
0133 this->deallocate(this->priv_long_addr(), this->priv_long_storage());
0134 }
0135 }
0136
0137 private:
0138
0139 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
0140 #pragma GCC diagnostic push
0141 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0142 #endif
0143
0144
0145 struct long_t
0146 {
0147 size_type is_short : 1;
0148 size_type length : (sizeof(size_type)*CHAR_BIT - 1);
0149 size_type storage;
0150 pointer start;
0151
0152 BOOST_CONTAINER_FORCEINLINE long_t()
0153 : is_short(0)
0154 {}
0155
0156 BOOST_CONTAINER_FORCEINLINE long_t(size_type len, size_type stor, pointer ptr)
0157 : is_short(0), length(len), storage(stor), start(ptr)
0158 {}
0159
0160 BOOST_CONTAINER_FORCEINLINE long_t(const long_t &other)
0161 {
0162 this->is_short = false;
0163 length = other.length;
0164 storage = other.storage;
0165 start = other.start;
0166 }
0167
0168 BOOST_CONTAINER_FORCEINLINE long_t &operator= (const long_t &other)
0169 {
0170 length = other.length;
0171 storage = other.storage;
0172 start = other.start;
0173 return *this;
0174 }
0175 };
0176
0177 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
0178 #pragma GCC diagnostic pop
0179 #endif
0180
0181
0182
0183
0184 struct short_header
0185 {
0186 unsigned char is_short : 1;
0187 unsigned char length : (CHAR_BIT - 1);
0188 };
0189
0190
0191
0192
0193 typedef typename dtl::aligned_storage
0194 <sizeof(long_t), dtl::alignment_of<long_t>::value>::type long_raw_t;
0195
0196 protected:
0197 static const size_type MinInternalBufferChars = 8;
0198 static const size_type AlignmentOfValueType =
0199 alignment_of<value_type>::value;
0200 static const size_type ShortDataOffset = ((sizeof(short_header)-1)/AlignmentOfValueType+1)*AlignmentOfValueType;
0201 static const size_type ZeroCostInternalBufferChars =
0202 (sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
0203 static const size_type UnalignedFinalInternalBufferChars =
0204 (ZeroCostInternalBufferChars > MinInternalBufferChars) ?
0205 ZeroCostInternalBufferChars : MinInternalBufferChars;
0206
0207 struct short_t
0208 {
0209 short_header h;
0210 value_type data[UnalignedFinalInternalBufferChars];
0211 };
0212
0213 union repr_t_size_t
0214 {
0215 long_raw_t r;
0216 short_t s;
0217 };
0218
0219 union repr_t
0220 {
0221 long_raw_t r_aligner;
0222 short_t s_aligner;
0223 unsigned char data[sizeof(repr_t_size_t)];
0224 };
0225
0226 struct members_holder
0227 : public allocator_type
0228 {
0229 BOOST_CONTAINER_FORCEINLINE void init()
0230 {
0231 short_t &s = *::new(this->m_repr.data) short_t;
0232 s.h.is_short = 1;
0233 s.h.length = 0;
0234 }
0235
0236 BOOST_CONTAINER_FORCEINLINE members_holder()
0237 : allocator_type()
0238 { this->init(); }
0239
0240 template<class AllocatorConvertible>
0241 BOOST_CONTAINER_FORCEINLINE explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
0242 : allocator_type(boost::forward<AllocatorConvertible>(a))
0243 { this->init(); }
0244
0245 BOOST_CONTAINER_FORCEINLINE const short_t *pshort_repr() const
0246 { return move_detail::force_ptr<const short_t*>(m_repr.data); }
0247
0248 BOOST_CONTAINER_FORCEINLINE const long_t *plong_repr() const
0249 { return move_detail::force_ptr<const long_t*>(m_repr.data); }
0250
0251 BOOST_CONTAINER_FORCEINLINE short_t *pshort_repr()
0252 { return move_detail::force_ptr<short_t*>(m_repr.data); }
0253
0254 BOOST_CONTAINER_FORCEINLINE long_t *plong_repr()
0255 { return move_detail::force_ptr<long_t*>(m_repr.data); }
0256
0257 repr_t m_repr;
0258 } members_;
0259
0260 BOOST_CONTAINER_FORCEINLINE const allocator_type &alloc() const
0261 { return members_; }
0262
0263 BOOST_CONTAINER_FORCEINLINE allocator_type &alloc()
0264 { return members_; }
0265
0266 static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
0267
0268 private:
0269
0270 static const size_type MinAllocation = InternalBufferChars*2;
0271
0272 protected:
0273 BOOST_CONTAINER_FORCEINLINE bool is_short() const
0274 {
0275
0276
0277 short_header hdr;
0278 BOOST_STATIC_ASSERT((sizeof(short_header) == 1));
0279 *(unsigned char*)&hdr = *(unsigned char*)&this->members_.m_repr;
0280 return hdr.is_short != 0;
0281 }
0282
0283 BOOST_CONTAINER_FORCEINLINE short_t *construct_short()
0284 {
0285 short_t *ps = ::new(this->members_.m_repr.data) short_t;
0286 ps->h.is_short = 1;
0287 return ps;
0288 }
0289
0290 BOOST_CONTAINER_FORCEINLINE void destroy_short()
0291 {
0292 BOOST_ASSERT(this->is_short());
0293 this->members_.pshort_repr()->~short_t();
0294 }
0295
0296 short_t *assure_short()
0297 {
0298 if (!this->is_short()){
0299 this->destroy_long();
0300 return construct_short();
0301 }
0302 return this->members_.pshort_repr();
0303 }
0304
0305 BOOST_CONTAINER_FORCEINLINE long_t *construct_long()
0306 {
0307 long_t *pl = ::new(this->members_.m_repr.data) long_t;
0308
0309 return pl;
0310 }
0311
0312 BOOST_CONTAINER_FORCEINLINE void destroy_long()
0313 {
0314 BOOST_ASSERT(!this->is_short());
0315 this->members_.plong_repr()->~long_t();
0316 }
0317
0318 long_t *assure_long()
0319 {
0320 if (this->is_short()){
0321 this->destroy_short();
0322 return this->construct_long();
0323 }
0324 return this->members_.plong_repr();
0325 }
0326
0327
0328 protected:
0329
0330 typedef dtl::integral_constant<unsigned,
0331 boost::container::dtl::version<allocator_type>::value> alloc_version;
0332
0333 pointer allocation_command(allocation_type command,
0334 size_type limit_size,
0335 size_type &prefer_in_recvd_out_size,
0336 pointer &reuse)
0337 {
0338 if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){
0339 reuse = 0;
0340 command &= ~(expand_fwd | expand_bwd);
0341 }
0342 return dtl::allocator_version_traits<allocator_type>::allocation_command
0343 (this->alloc(), command, limit_size, prefer_in_recvd_out_size, reuse);
0344 }
0345
0346 size_type next_capacity(size_type additional_objects) const
0347 {
0348 return growth_factor_100()
0349 ( this->priv_storage(), additional_objects, allocator_traits_type::max_size(this->alloc()));
0350 }
0351
0352 void deallocate(pointer p, size_type n)
0353 {
0354 if (p && (n > InternalBufferChars))
0355 this->alloc().deallocate(p, n);
0356 }
0357
0358 BOOST_CONTAINER_FORCEINLINE void construct(pointer p, const value_type &value = value_type())
0359 {
0360 allocator_traits_type::construct
0361 ( this->alloc()
0362 , boost::movelib::to_raw_pointer(p)
0363 , value
0364 );
0365 }
0366
0367 void destroy(pointer p, size_type n)
0368 {
0369 value_type *raw_p = boost::movelib::to_raw_pointer(p);
0370 for(; n--; ++raw_p){
0371 allocator_traits_type::destroy( this->alloc(), raw_p);
0372 }
0373 }
0374
0375 BOOST_CONTAINER_FORCEINLINE void destroy(pointer p)
0376 {
0377 allocator_traits_type::destroy
0378 ( this->alloc()
0379 , boost::movelib::to_raw_pointer(p)
0380 );
0381 }
0382
0383 void allocate_initial_block(size_type n)
0384 {
0385 if (n <= this->max_size()) {
0386 if(n > InternalBufferChars){
0387 size_type new_cap = this->next_capacity(n);
0388 pointer reuse = 0;
0389 pointer p = this->allocation_command(allocate_new, n, new_cap, reuse);
0390 BOOST_ASSERT(this->is_short());
0391 this->construct_long();
0392 this->priv_long_addr(p);
0393 this->priv_long_size(0);
0394 this->priv_storage(new_cap);
0395 }
0396 }
0397 else{
0398 throw_length_error("basic_string::allocate_initial_block max_size() exceeded");
0399 }
0400 }
0401
0402 BOOST_CONTAINER_FORCEINLINE void deallocate_block()
0403 { this->deallocate(this->priv_addr(), this->priv_storage()); }
0404
0405 BOOST_CONTAINER_FORCEINLINE size_type max_size() const
0406 { return allocator_traits_type::max_size(this->alloc()) - 1; }
0407
0408 protected:
0409 BOOST_CONTAINER_FORCEINLINE size_type priv_capacity() const
0410 { return this->priv_storage() - 1; }
0411
0412 BOOST_CONTAINER_FORCEINLINE pointer priv_short_addr() const
0413 { return pointer_traits::pointer_to(const_cast<value_type&>(this->members_.pshort_repr()->data[0])); }
0414
0415
0416 #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0417 #pragma GCC diagnostic push
0418 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0419 #endif
0420
0421 BOOST_CONTAINER_FORCEINLINE pointer priv_long_addr() const
0422 { return this->members_.plong_repr()->start; }
0423
0424 BOOST_CONTAINER_FORCEINLINE pointer priv_addr() const
0425 {
0426 return this->is_short()
0427 ? priv_short_addr()
0428 : priv_long_addr()
0429 ;
0430 }
0431
0432 BOOST_CONTAINER_FORCEINLINE pointer priv_end_addr() const
0433 {
0434 return this->is_short()
0435 ? this->priv_short_addr() + difference_type(this->priv_short_size())
0436 : this->priv_long_addr() + difference_type(this->priv_long_size())
0437 ;
0438 }
0439
0440 BOOST_CONTAINER_FORCEINLINE void priv_long_addr(pointer addr)
0441 { this->members_.plong_repr()->start = addr; }
0442
0443 BOOST_CONTAINER_FORCEINLINE size_type priv_storage() const
0444 { return this->is_short() ? priv_short_storage() : priv_long_storage(); }
0445
0446 BOOST_CONTAINER_FORCEINLINE size_type priv_short_storage() const
0447 { return InternalBufferChars; }
0448
0449 BOOST_CONTAINER_FORCEINLINE size_type priv_long_storage() const
0450 { return this->members_.plong_repr()->storage; }
0451
0452 BOOST_CONTAINER_FORCEINLINE void priv_storage(size_type storage)
0453 {
0454 if(!this->is_short())
0455 this->priv_long_storage(storage);
0456 }
0457
0458 BOOST_CONTAINER_FORCEINLINE void priv_long_storage(size_type storage)
0459 {
0460 this->members_.plong_repr()->storage = storage;
0461 }
0462
0463 BOOST_CONTAINER_FORCEINLINE size_type priv_size() const
0464 { return this->is_short() ? this->priv_short_size() : this->priv_long_size(); }
0465
0466 BOOST_CONTAINER_FORCEINLINE size_type priv_short_size() const
0467 { return this->members_.pshort_repr()->h.length; }
0468
0469 BOOST_CONTAINER_FORCEINLINE size_type priv_long_size() const
0470 { return this->members_.plong_repr()->length; }
0471
0472 BOOST_CONTAINER_FORCEINLINE void priv_size(size_type sz)
0473 {
0474 if(this->is_short())
0475 this->priv_short_size(sz);
0476 else
0477 this->priv_long_size(sz);
0478 }
0479
0480 BOOST_CONTAINER_FORCEINLINE void priv_short_size(size_type sz)
0481 {
0482 typedef unsigned char uchar_type;
0483 static const uchar_type mask = uchar_type(uchar_type(-1) >> 1U);
0484 BOOST_ASSERT( sz <= mask );
0485
0486 this->members_.pshort_repr()->h.length = uchar_type(uchar_type(sz) & mask);
0487 }
0488
0489 BOOST_CONTAINER_FORCEINLINE void priv_long_size(size_type sz)
0490 {
0491 static const size_type mask = size_type(-1) >> 1U;
0492 BOOST_ASSERT( sz <= mask );
0493
0494 this->members_.plong_repr()->length = sz & mask;
0495 }
0496 #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0497 #pragma GCC diagnostic pop
0498 #endif
0499
0500 void swap_data(basic_string_base& other)
0501 {
0502 if(this->is_short()){
0503 if(other.is_short()){
0504 repr_t tmp(this->members_.m_repr);
0505 this->members_.m_repr = other.members_.m_repr;
0506 other.members_.m_repr = tmp;
0507 }
0508 else{
0509 short_t short_backup(*this->members_.pshort_repr());
0510 this->members_.pshort_repr()->~short_t();
0511 ::new(this->members_.plong_repr()) long_t(*other.members_.plong_repr());
0512 other.members_.plong_repr()->~long_t();
0513 ::new(other.members_.pshort_repr()) short_t(short_backup);
0514 }
0515 }
0516 else{
0517 if(other.is_short()){
0518 short_t short_backup(*other.members_.pshort_repr());
0519 other.members_.pshort_repr()->~short_t();
0520 ::new(other.members_.plong_repr()) long_t(*this->members_.plong_repr());
0521 this->members_.plong_repr()->~long_t();
0522 ::new(this->members_.pshort_repr()) short_t(short_backup);
0523 }
0524 else{
0525 boost::adl_move_swap(*this->members_.plong_repr(), *other.members_.plong_repr());
0526 }
0527 }
0528 }
0529 };
0530
0531 }
0532
0533 #endif
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
0568 template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = void >
0569 #else
0570 template <class CharT, class Traits, class Allocator>
0571 #endif
0572 class basic_string
0573 : private dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type>
0574 {
0575 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0576 private:
0577 BOOST_COPYABLE_AND_MOVABLE(basic_string)
0578 typedef dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type> base_t;
0579 typedef typename base_t::allocator_traits_type allocator_traits_type;
0580 static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
0581
0582 protected:
0583
0584
0585 template <class Tr>
0586 struct Eq_traits
0587 {
0588
0589 typedef typename Tr::char_type first_argument_type;
0590 typedef typename Tr::char_type second_argument_type;
0591 typedef bool result_type;
0592
0593 bool operator()(const first_argument_type& x, const second_argument_type& y) const
0594 { return Tr::eq(x, y); }
0595 };
0596
0597 template <class Tr>
0598 struct Not_within_traits
0599 {
0600 typedef typename Tr::char_type argument_type;
0601 typedef bool result_type;
0602
0603 typedef const typename Tr::char_type* Pointer;
0604 const Pointer m_first;
0605 const Pointer m_last;
0606
0607 Not_within_traits(Pointer f, Pointer l)
0608 : m_first(f), m_last(l) {}
0609
0610 bool operator()(const typename Tr::char_type& x) const
0611 {
0612 return boost::container::find_if(m_first, m_last,
0613 boost::container::bind1st(Eq_traits<Tr>(), x)) == m_last;
0614 }
0615 };
0616 #endif
0617
0618 public:
0619
0620
0621
0622
0623
0624 typedef Traits traits_type;
0625 typedef CharT value_type;
0626 typedef typename real_allocator<CharT, Allocator>::type allocator_type;
0627 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
0628 typedef typename ::boost::container::allocator_traits<allocator_type>::const_pointer const_pointer;
0629 typedef typename ::boost::container::allocator_traits<allocator_type>::reference reference;
0630 typedef typename ::boost::container::allocator_traits<allocator_type>::const_reference const_reference;
0631 typedef typename ::boost::container::allocator_traits<allocator_type>::size_type size_type;
0632 typedef typename ::boost::container::allocator_traits<allocator_type>::difference_type difference_type;
0633 typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type;
0634 typedef BOOST_CONTAINER_IMPDEF(pointer) iterator;
0635 typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator;
0636 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
0637 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
0638 static const size_type npos = size_type(-1);
0639
0640 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0641 private:
0642 typedef constant_iterator<CharT> cvalue_iterator;
0643 typedef typename base_t::alloc_version alloc_version;
0644 typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
0645 #endif
0646
0647 public:
0648
0649
0650
0651
0652
0653 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0654 struct reserve_t {};
0655
0656 basic_string(reserve_t, size_type n,
0657 const allocator_type& a = allocator_type())
0658
0659
0660 : base_t( allocator_traits_type::select_on_container_copy_construction(a)
0661 , n + 1)
0662 { this->priv_terminate_string(); }
0663
0664 #endif
0665
0666
0667
0668
0669 basic_string() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0670 : base_t()
0671 { this->priv_terminate_string(); }
0672
0673
0674
0675
0676
0677 explicit basic_string(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
0678 : base_t(a)
0679 { this->priv_terminate_string(); }
0680
0681
0682
0683
0684
0685
0686 basic_string(const basic_string& s)
0687 : base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
0688 {
0689 this->priv_terminate_string();
0690 this->assign(s.begin(), s.end());
0691 }
0692
0693
0694
0695
0696 template<template <class, class> class BasicStringView>
0697 explicit basic_string(BasicStringView<CharT, Traits> sv, const allocator_type& a = allocator_type())
0698 : base_t(allocator_traits_type::select_on_container_copy_construction(a))
0699 {
0700 this->priv_terminate_string();
0701 this->assign(sv);
0702 }
0703
0704
0705
0706
0707
0708
0709 basic_string(BOOST_RV_REF(basic_string) s) BOOST_NOEXCEPT_OR_NOTHROW
0710 : base_t(boost::move(s.alloc()))
0711 {
0712 if(s.alloc() == this->alloc()){
0713 this->swap_data(s);
0714 }
0715 else{
0716 this->assign(s.begin(), s.end());
0717 }
0718 }
0719
0720
0721
0722
0723
0724
0725 basic_string(const basic_string& s, const allocator_type &a)
0726 : base_t(a)
0727 {
0728 this->priv_terminate_string();
0729 this->assign(s.begin(), s.end());
0730 }
0731
0732
0733
0734
0735
0736
0737
0738 basic_string(BOOST_RV_REF(basic_string) s, const allocator_type &a)
0739 : base_t(a)
0740 {
0741 this->priv_terminate_string();
0742 if(s.alloc() == this->alloc()){
0743 this->swap_data(s);
0744 }
0745 else{
0746 this->assign(s.begin(), s.end());
0747 }
0748 }
0749
0750
0751
0752 basic_string(const basic_string& s, size_type pos, size_type n = npos)
0753 : base_t()
0754 {
0755 this->priv_terminate_string();
0756 if (pos > s.size())
0757 throw_out_of_range("basic_string::basic_string out of range position");
0758 else
0759 this->assign
0760 (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
0761 }
0762
0763
0764
0765 basic_string(const basic_string& s, size_type pos, size_type n, const allocator_type& a)
0766 : base_t(a)
0767 {
0768 this->priv_terminate_string();
0769 if (pos > s.size())
0770 throw_out_of_range("basic_string::basic_string out of range position");
0771 else
0772 this->assign
0773 (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
0774 }
0775
0776
0777
0778 basic_string(const CharT* s, size_type n)
0779 : base_t()
0780 {
0781 this->priv_terminate_string();
0782 this->assign(s, s + difference_type(n));
0783 }
0784
0785
0786
0787 basic_string(const CharT* s, size_type n, const allocator_type& a)
0788 : base_t(a)
0789 {
0790 this->priv_terminate_string();
0791 this->assign(s, s + difference_type(n));
0792 }
0793
0794
0795
0796 basic_string(const CharT* s)
0797 : base_t()
0798 {
0799 this->priv_terminate_string();
0800 this->assign(s, s + Traits::length(s));
0801 }
0802
0803
0804
0805 basic_string(const CharT* s, const allocator_type& a)
0806 : base_t(a)
0807 {
0808 this->priv_terminate_string();
0809 this->assign(s, s + Traits::length(s));
0810 }
0811
0812
0813
0814
0815 basic_string(size_type n, CharT c)
0816 : base_t()
0817 {
0818 this->priv_terminate_string();
0819 this->assign(n, c);
0820 }
0821
0822
0823
0824 basic_string(size_type n, CharT c, const allocator_type& a)
0825 : base_t(a)
0826 {
0827 this->priv_terminate_string();
0828 this->assign(n, c);
0829 }
0830
0831
0832
0833 basic_string(size_type n, default_init_t)
0834 : base_t(n + 1)
0835 {
0836 this->priv_size(n);
0837 this->priv_terminate_string();
0838 }
0839
0840
0841
0842 basic_string(size_type n, default_init_t, const allocator_type& a)
0843 : base_t(a, n + 1)
0844 {
0845 this->priv_size(n);
0846 this->priv_terminate_string();
0847 }
0848
0849
0850
0851 template <class InputIterator>
0852 basic_string(InputIterator f, InputIterator l)
0853 : base_t()
0854 {
0855 this->priv_terminate_string();
0856 this->assign(f, l);
0857 }
0858
0859
0860
0861 template <class InputIterator>
0862 basic_string(InputIterator f, InputIterator l, const allocator_type& a)
0863 : base_t(a)
0864 {
0865 this->priv_terminate_string();
0866 this->assign(f, l);
0867 }
0868
0869 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0870
0871
0872 basic_string(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
0873 : base_t(a)
0874 {
0875 this->priv_terminate_string();
0876 this->assign(il.begin(), il.end());
0877 }
0878 #endif
0879
0880
0881
0882
0883
0884
0885 ~basic_string() BOOST_NOEXCEPT_OR_NOTHROW
0886 {}
0887
0888
0889
0890
0891
0892
0893 basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
0894 {
0895 if (BOOST_LIKELY(this != &x)) {
0896 allocator_type &this_alloc = this->alloc();
0897 const allocator_type &x_alloc = x.alloc();
0898 dtl::bool_<allocator_traits_type::
0899 propagate_on_container_copy_assignment::value> flag;
0900 if(flag && this_alloc != x_alloc){
0901 if(!this->is_short()){
0902 this->deallocate_block();
0903 this->assure_short();
0904 Traits::assign(*this->priv_addr(), CharT(0));
0905 this->priv_short_size(0);
0906 }
0907 }
0908 dtl::assign_alloc(this->alloc(), x.alloc(), flag);
0909 this->assign(x.begin(), x.end());
0910 }
0911 return *this;
0912 }
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922 basic_string& operator=(BOOST_RV_REF(basic_string) x)
0923 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
0924 || allocator_traits_type::is_always_equal::value)
0925 {
0926 if (BOOST_LIKELY(this != &x)) {
0927 allocator_type &this_alloc = this->alloc();
0928 allocator_type &x_alloc = x.alloc();
0929 const bool propagate_alloc = allocator_traits_type::
0930 propagate_on_container_move_assignment::value;
0931 dtl::bool_<propagate_alloc> flag;
0932 const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
0933
0934
0935 if(propagate_alloc || allocators_equal){
0936
0937 this->clear();
0938
0939 dtl::move_alloc(this_alloc, x_alloc, flag);
0940
0941 this->swap_data(x);
0942 }
0943
0944 else{
0945 this->assign( x.begin(), x.end());
0946 }
0947 }
0948 return *this;
0949 }
0950
0951
0952
0953 basic_string& operator=(const CharT* s)
0954 { return this->assign(s, s + Traits::length(s)); }
0955
0956
0957
0958 basic_string& operator=(CharT c)
0959 { return this->assign(static_cast<size_type>(1), c); }
0960
0961
0962
0963 template<template <class, class> class BasicStringView>
0964 basic_string& operator=(BasicStringView<CharT, Traits> sv)
0965 { return this->assign(sv.data(), sv.size()); }
0966
0967 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0968
0969
0970 basic_string& operator=(std::initializer_list<CharT> il)
0971 {
0972 return this->assign(il.begin(), il.end());
0973 }
0974 #endif
0975
0976
0977
0978
0979
0980
0981 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0982 allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
0983 { return this->alloc(); }
0984
0985
0986
0987
0988
0989
0990
0991
0992 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0993 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
0994 { return this->alloc(); }
0995
0996
0997
0998
0999
1000
1001
1002
1003 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1004 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1005 { return this->alloc(); }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1019 iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
1020 { return this->priv_addr(); }
1021
1022
1023
1024
1025
1026
1027 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1028 const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1029 { return this->priv_addr(); }
1030
1031
1032
1033
1034
1035
1036 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1037 iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1038 { return this->priv_end_addr(); }
1039
1040
1041
1042
1043
1044
1045 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1046 const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1047 { return this->priv_end_addr(); }
1048
1049
1050
1051
1052
1053
1054
1055 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1056 reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
1057 { return reverse_iterator(this->priv_end_addr()); }
1058
1059
1060
1061
1062
1063
1064
1065 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1066 const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1067 { return this->crbegin(); }
1068
1069
1070
1071
1072
1073
1074
1075 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1076 reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
1077 { return reverse_iterator(this->priv_addr()); }
1078
1079
1080
1081
1082
1083
1084
1085 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1086 const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1087 { return this->crend(); }
1088
1089
1090
1091
1092
1093
1094 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1095 const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1096 { return this->priv_addr(); }
1097
1098
1099
1100
1101
1102
1103 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1104 const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1105 { return this->priv_end_addr(); }
1106
1107
1108
1109
1110
1111
1112
1113 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1114 const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1115 { return const_reverse_iterator(this->priv_end_addr()); }
1116
1117
1118
1119
1120
1121
1122
1123 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1124 const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
1125 { return const_reverse_iterator(this->priv_addr()); }
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1139 bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1140 { return !this->priv_size(); }
1141
1142
1143
1144
1145
1146
1147 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1148 size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
1149 { return this->priv_size(); }
1150
1151
1152
1153
1154
1155
1156 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1157 size_type length() const BOOST_NOEXCEPT_OR_NOTHROW
1158 { return this->size(); }
1159
1160
1161
1162
1163
1164
1165 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1166 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1167 { return base_t::max_size(); }
1168
1169
1170
1171
1172
1173
1174
1175 void resize(size_type n, CharT c)
1176 {
1177 if (n <= this->size())
1178 this->erase(this->begin() + difference_type(n), this->end());
1179 else
1180 this->append(n - this->size(), c);
1181 }
1182
1183
1184
1185
1186
1187
1188
1189 void resize(size_type n)
1190 { resize(n, CharT()); }
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200 void resize(size_type n, default_init_t)
1201 {
1202 if (n <= this->size())
1203 this->erase(this->begin() + difference_type(n), this->end());
1204 else{
1205 this->priv_reserve(n, false);
1206 this->priv_size(n);
1207 this->priv_terminate_string();
1208 }
1209 }
1210
1211
1212
1213
1214
1215
1216
1217 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1218 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1219 { return this->priv_capacity(); }
1220
1221
1222
1223
1224
1225
1226
1227 void reserve(size_type res_arg)
1228 { this->priv_reserve(res_arg); }
1229
1230
1231
1232
1233
1234
1235
1236 void shrink_to_fit()
1237 {
1238
1239 if(this->priv_storage() > InternalBufferChars){
1240
1241
1242 if(this->priv_size() < InternalBufferChars){
1243
1244 pointer long_addr = this->priv_long_addr();
1245 size_type long_storage = this->priv_long_storage();
1246 size_type long_size = this->priv_long_size();
1247
1248 Traits::copy( boost::movelib::to_raw_pointer(this->priv_short_addr())
1249 , boost::movelib::to_raw_pointer(long_addr)
1250 , long_size+1);
1251 BOOST_ASSERT(!this->is_short());
1252 this->destroy_long();
1253 this->construct_short();
1254 this->alloc().deallocate(long_addr, long_storage);
1255 }
1256 else{
1257
1258 this->priv_shrink_to_fit_dynamic_buffer(alloc_version());
1259 }
1260 }
1261 }
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1278 reference front() BOOST_NOEXCEPT_OR_NOTHROW
1279 {
1280 BOOST_ASSERT(!this->empty());
1281 return *this->priv_addr();
1282 }
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1293 const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
1294 {
1295 BOOST_ASSERT(!this->empty());
1296 return *this->priv_addr();
1297 }
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1308 reference back() BOOST_NOEXCEPT_OR_NOTHROW
1309 {
1310 BOOST_ASSERT(!this->empty());
1311 return *(this->priv_addr() + (this->size() - 1u) );
1312 }
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1323 const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
1324 {
1325 BOOST_ASSERT(!this->empty());
1326 return *(this->priv_addr() + (this->size() - 1u) );
1327 }
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1338 reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1339 {
1340 BOOST_ASSERT(this->size() > n);
1341 return *(this->priv_addr() + difference_type(n));
1342 }
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1353 const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1354 {
1355 BOOST_ASSERT(this->size() > n);
1356 return *(this->priv_addr() + difference_type(n));
1357 }
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1368 reference at(size_type n)
1369 {
1370 if (n >= this->size())
1371 throw_out_of_range("basic_string::at invalid subscript");
1372 return *(this->priv_addr() + difference_type(n));
1373 }
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1384 const_reference at(size_type n) const {
1385 if (n >= this->size())
1386 throw_out_of_range("basic_string::at invalid subscript");
1387 return *(this->priv_addr() + difference_type(n));
1388 }
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399 basic_string& operator+=(const basic_string& s)
1400 { return this->append(s); }
1401
1402
1403
1404 template<template<class, class> class BasicStringView>
1405 basic_string& operator+=(BasicStringView<CharT, Traits> sv)
1406 {
1407 return this->append(sv);
1408 }
1409
1410
1411
1412
1413 basic_string& operator+=(const CharT* s)
1414 { return this->append(s); }
1415
1416
1417
1418
1419 basic_string& operator+=(CharT c)
1420 { this->push_back(c); return *this; }
1421
1422 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1423
1424
1425 basic_string& operator+=(std::initializer_list<CharT> il)
1426 {
1427 return this->append(il);
1428 }
1429 #endif
1430
1431
1432
1433
1434 basic_string& append(const basic_string& s)
1435 { return this->append(s.begin(), s.end()); }
1436
1437
1438
1439 template<template<class, class> class BasicStringView>
1440 basic_string& append(BasicStringView<CharT, Traits> sv)
1441 { return this->append(sv.data(), sv.size()); }
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451 basic_string& append(const basic_string& s, size_type pos, size_type n = npos)
1452 {
1453 if (pos > s.size())
1454 throw_out_of_range("basic_string::append out of range position");
1455 return this->append(s.begin() + pos,
1456 s.begin() + pos + dtl::min_value(n, s.size() - pos));
1457 }
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469 basic_string& append(const CharT* s, size_type n)
1470 { return this->append(s, s + difference_type(n)); }
1471
1472
1473
1474
1475
1476
1477 basic_string& append(const CharT* s)
1478 { return this->append(s, s + Traits::length(s)); }
1479
1480
1481
1482
1483 basic_string& append(size_type n, CharT c)
1484 { return this->append(cvalue_iterator(c, n), cvalue_iterator()); }
1485
1486
1487
1488
1489
1490
1491 template <class InputIter>
1492 basic_string& append(InputIter first, InputIter last)
1493 { this->insert(this->end(), first, last); return *this; }
1494
1495 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1496
1497
1498 basic_string& append(std::initializer_list<CharT> il)
1499 {
1500 return this->append(il.begin(), il.size());
1501 }
1502 #endif
1503
1504
1505
1506 void push_back(CharT c)
1507 {
1508 const size_type old_size = this->priv_size();
1509 if (old_size < this->capacity()){
1510 const pointer addr = this->priv_addr();
1511 this->priv_construct_null(addr + difference_type(old_size + 1u));
1512 Traits::assign(addr[difference_type(old_size)], c);
1513 this->priv_size(old_size+1u);
1514 }
1515 else{
1516
1517 this->append(size_type(1), c);
1518 }
1519 }
1520
1521
1522
1523
1524 basic_string& assign(const basic_string& s)
1525 { return this->operator=(s); }
1526
1527
1528
1529
1530 template<template <class, class> class BasicStringView>
1531 basic_string& assign(BasicStringView<CharT, Traits> sv)
1532 { return this->operator=(sv); }
1533
1534
1535
1536
1537
1538
1539
1540
1541 basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_NOEXCEPT_OR_NOTHROW
1542 { return this->swap_data(ms), *this; }
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552 basic_string& assign(const basic_string& s, size_type pos, size_type n)
1553 {
1554 if (pos > s.size())
1555 throw_out_of_range("basic_string::assign out of range position");
1556 return this->assign(s.begin() + pos,
1557 s.begin() + pos + dtl::min_value(n, s.size() - pos));
1558 }
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568 basic_string& assign(const CharT* s, size_type n)
1569 { return this->assign(s, s + difference_type(n)); }
1570
1571
1572
1573
1574
1575
1576 basic_string& assign(const CharT* s)
1577 { return this->assign(s, s + Traits::length(s)); }
1578
1579
1580
1581
1582 basic_string& assign(size_type n, CharT c)
1583 { return this->assign(cvalue_iterator(c, n), cvalue_iterator()); }
1584
1585
1586
1587
1588 basic_string& assign(const CharT* first, const CharT* last)
1589 {
1590 size_type n = static_cast<size_type>(last - first);
1591 this->reserve(n);
1592 CharT* ptr = boost::movelib::to_raw_pointer(this->priv_addr());
1593 Traits::copy(ptr, first, n);
1594 this->priv_construct_null(ptr + difference_type(n));
1595 this->priv_size(n);
1596 return *this;
1597 }
1598
1599
1600
1601
1602 template <class InputIter>
1603 basic_string& assign(InputIter first, InputIter last
1604 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1605 , typename dtl::disable_if_convertible<InputIter, size_type>::type * = 0
1606 #endif
1607 )
1608 {
1609 size_type cur = 0;
1610 const pointer addr = this->priv_addr();
1611 CharT *ptr = boost::movelib::to_raw_pointer(addr);
1612 const size_type old_size = this->priv_size();
1613 while (first != last && cur != old_size) {
1614 Traits::assign(*ptr, *first);
1615 ++first;
1616 ++cur;
1617 ++ptr;
1618 }
1619 if (first == last)
1620 this->erase(addr + difference_type(cur), addr + difference_type(old_size));
1621 else
1622 this->append(first, last);
1623 return *this;
1624 }
1625
1626 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1627
1628
1629 basic_string& assign(std::initializer_list<CharT> il)
1630 {
1631 return this->assign(il.begin(), il.size());
1632 }
1633 #endif
1634
1635
1636
1637
1638
1639
1640
1641
1642 basic_string& insert(size_type pos, const basic_string& s)
1643 {
1644 const size_type sz = this->size();
1645 if (pos > sz)
1646 throw_out_of_range("basic_string::insert out of range position");
1647 if (sz > this->max_size() - s.size())
1648 throw_length_error("basic_string::insert max_size() exceeded");
1649 this->insert(this->priv_addr() + pos, s.begin(), s.end());
1650 return *this;
1651 }
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661 basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n = npos)
1662 {
1663 const size_type sz = this->size();
1664 const size_type str_size = s.size();
1665 if (pos1 > sz || pos2 > str_size)
1666 throw_out_of_range("basic_string::insert out of range position");
1667 size_type len = dtl::min_value(n, str_size - pos2);
1668 if (sz > this->max_size() - len)
1669 throw_length_error("basic_string::insert max_size() exceeded");
1670 const CharT *beg_ptr = boost::movelib::to_raw_pointer(s.begin()) + pos2;
1671 const CharT *end_ptr = beg_ptr + len;
1672 this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
1673 return *this;
1674 }
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687 basic_string& insert(size_type pos, const CharT* s, size_type n)
1688 {
1689 if (pos > this->size())
1690 throw_out_of_range("basic_string::insert out of range position");
1691 if (this->size() > this->max_size() - n)
1692 throw_length_error("basic_string::insert max_size() exceeded");
1693 this->insert(this->priv_addr() + pos, s, s + difference_type(n));
1694 return *this;
1695 }
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705 basic_string& insert(size_type pos, const CharT* s)
1706 {
1707 if (pos > this->size())
1708 throw_out_of_range("basic_string::insert out of range position");
1709 size_type len = Traits::length(s);
1710 if (this->size() > this->max_size() - len)
1711 throw_length_error("basic_string::insert max_size() exceeded");
1712 this->insert(this->priv_addr() + pos, s, s + len);
1713 return *this;
1714 }
1715
1716
1717
1718
1719
1720
1721
1722 basic_string& insert(size_type pos, size_type n, CharT c)
1723 {
1724 if (pos > this->size())
1725 throw_out_of_range("basic_string::insert out of range position");
1726 if (this->size() > this->max_size() - n)
1727 throw_length_error("basic_string::insert max_size() exceeded");
1728 this->insert(const_iterator(this->priv_addr() + pos), n, c);
1729 return *this;
1730 }
1731
1732
1733
1734 template<template<class, class> class BasicStringView>
1735 basic_string& insert(size_type pos, BasicStringView<CharT, Traits> sv)
1736 { return this->insert(pos, sv.data(), sv.size()); }
1737
1738
1739
1740
1741
1742
1743 iterator insert(const_iterator p, CharT c)
1744 {
1745 size_type new_offset = size_type(p - this->priv_addr());
1746 this->insert(p, cvalue_iterator(c, 1), cvalue_iterator());
1747 return this->priv_addr() + new_offset;
1748 }
1749
1750
1751
1752
1753
1754
1755 iterator insert(const_iterator p, size_type n, CharT c)
1756 { return this->insert(p, cvalue_iterator(c, n), cvalue_iterator()); }
1757
1758
1759
1760
1761
1762
1763 template <class InputIter>
1764 iterator insert(const_iterator p, InputIter first, InputIter last
1765 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1766 , typename dtl::disable_if_or
1767 < void
1768 , dtl::is_convertible<InputIter, size_type>
1769 , dtl::is_not_input_iterator<InputIter>
1770 >::type * = 0
1771 #endif
1772 )
1773 {
1774 const size_type n_pos = p - this->cbegin();
1775 for ( ; first != last; ++first, ++p) {
1776 p = this->insert(p, *first);
1777 }
1778 return this->begin() + difference_type(n_pos);
1779 }
1780
1781 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1782 template <class ForwardIter>
1783 iterator insert(const_iterator p, ForwardIter first, ForwardIter last
1784 , typename dtl::disable_if_or
1785 < void
1786 , dtl::is_convertible<ForwardIter, size_type>
1787 , dtl::is_input_iterator<ForwardIter>
1788 >::type * = 0
1789 )
1790 {
1791 const size_type n_pos = size_type(p - this->cbegin());
1792 if (first != last) {
1793 const size_type n = boost::container::iterator_udistance(first, last);
1794 const size_type old_size = this->priv_size();
1795 const size_type remaining = this->capacity() - old_size;
1796 const pointer old_start = this->priv_addr();
1797 bool enough_capacity = false;
1798 size_type new_cap = 0;
1799
1800
1801 pointer hint = pointer();
1802 pointer allocation_ret = pointer();
1803 if (remaining >= n){
1804 enough_capacity = true;
1805 }
1806 else {
1807
1808 new_cap = this->next_capacity(n);
1809 hint = old_start;
1810 allocation_ret = this->allocation_command
1811 (allocate_new | expand_fwd | expand_bwd, old_size + n + 1u, new_cap, hint);
1812
1813
1814 if(old_start == allocation_ret){
1815 enough_capacity = true;
1816 this->priv_storage(new_cap);
1817 }
1818 }
1819
1820
1821 if(enough_capacity){
1822 const size_type elems_after = old_size - size_type(p - old_start);
1823 const size_type old_length = old_size;
1824 size_type new_size = 0;
1825 if (elems_after >= n) {
1826 const pointer pointer_past_last = old_start + difference_type(old_size + 1u);
1827 priv_uninitialized_copy(old_start + difference_type(old_size - n + 1u),
1828 pointer_past_last, pointer_past_last);
1829
1830 Traits::move(const_cast<CharT*>(boost::movelib::to_raw_pointer(p + difference_type(n))),
1831 boost::movelib::to_raw_pointer(p),
1832 (elems_after - n) + 1u);
1833 (priv_copy)(first, last, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
1834 new_size = old_size + n;
1835 }
1836 else {
1837 ForwardIter mid = first;
1838 boost::container::iterator_uadvance(mid, elems_after + 1u);
1839
1840 priv_uninitialized_copy(mid, last, old_start + difference_type(old_size + 1u));
1841 const size_type newer_size = old_size + (n - elems_after);
1842 this->priv_size(newer_size);
1843 priv_uninitialized_copy
1844 (p, const_iterator(old_start + difference_type(old_length + 1u)),
1845 old_start + difference_type(newer_size));
1846 (priv_copy)(first, mid, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
1847 new_size = newer_size + elems_after;
1848 }
1849 this->priv_size(new_size);
1850 this->priv_construct_null(old_start + difference_type(new_size));
1851 }
1852 else{
1853 pointer new_start = allocation_ret;
1854 if(!hint){
1855
1856 size_type new_length = 0;
1857
1858 new_length += priv_uninitialized_copy
1859 (const_iterator(old_start), p, new_start);
1860 new_length += priv_uninitialized_copy
1861 (first, last, new_start + difference_type(new_length));
1862 new_length += priv_uninitialized_copy
1863 (p, const_iterator(old_start + difference_type(old_size)),
1864 new_start + difference_type(new_length));
1865 this->priv_construct_null(new_start + difference_type(new_length));
1866
1867 this->deallocate_block();
1868 this->assure_long();
1869 this->priv_long_addr(new_start);
1870 this->priv_long_size(new_length);
1871 this->priv_long_storage(new_cap);
1872 }
1873 else{
1874
1875
1876 value_type * const oldbuf = boost::movelib::to_raw_pointer(old_start);
1877 value_type * const newbuf = boost::movelib::to_raw_pointer(new_start);
1878 const value_type *const pos = boost::movelib::to_raw_pointer(p);
1879 const size_type before = size_type(pos - oldbuf);
1880
1881
1882 Traits::move(newbuf, oldbuf, before);
1883 Traits::move(newbuf + difference_type(before + n), pos, old_size - before);
1884
1885 priv_uninitialized_copy(first, last, new_start + difference_type(before));
1886 this->priv_construct_null(new_start + difference_type(old_size + n));
1887 this->assure_long();
1888 this->priv_long_addr(new_start);
1889 this->priv_long_size(old_size + n);
1890 this->priv_long_storage(new_cap);
1891 }
1892 }
1893 }
1894 return this->begin() + difference_type(n_pos);
1895 }
1896 #endif
1897
1898 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1899
1900
1901
1902
1903 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, std::initializer_list<CharT> il)
1904 {
1905 return this->insert(p, il.begin(), il.end());
1906 }
1907 #endif
1908
1909
1910
1911
1912
1913
1914 void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
1915 {
1916 BOOST_ASSERT(!this->empty());
1917 iterator p = this->end();
1918 this->erase(--p);
1919 }
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932 basic_string& erase(size_type pos = 0, size_type n = npos)
1933 {
1934 if (pos > this->size())
1935 throw_out_of_range("basic_string::erase out of range position");
1936 const pointer addr = this->priv_addr();
1937 erase(addr + difference_type(pos), addr + difference_type(pos) + dtl::min_value(n, this->size() - pos));
1938 return *this;
1939 }
1940
1941
1942
1943
1944
1945
1946
1947 iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1948 {
1949
1950 CharT * const ptr = const_cast<CharT*>(boost::movelib::to_raw_pointer(p));
1951 const size_type old_size = this->priv_size();
1952 Traits::move(ptr,
1953 boost::movelib::to_raw_pointer(p + 1),
1954 old_size - size_type(p - this->priv_addr()));
1955 this->priv_size(old_size-1u);
1956 return iterator(ptr);
1957 }
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967 iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
1968 {
1969 CharT * f = const_cast<CharT*>(boost::movelib::to_raw_pointer(first));
1970 if (first != last) {
1971 const size_type num_erased = size_type(last - first);
1972 const size_type old_size = this->priv_size();
1973 Traits::move(f,
1974 boost::movelib::to_raw_pointer(last),
1975 old_size + 1u - size_type(last - this->priv_addr()));
1976 const size_type new_length = old_size - num_erased;
1977 this->priv_size(new_length);
1978 }
1979 return iterator(f);
1980 }
1981
1982
1983
1984
1985
1986
1987 void clear() BOOST_NOEXCEPT_OR_NOTHROW
1988 {
1989 if(this->is_short()) {
1990 Traits::assign(*this->priv_short_addr(), CharT(0));
1991 this->priv_short_size(0);
1992 }
1993 else {
1994 Traits::assign(*this->priv_long_addr(), CharT(0));
1995 this->priv_long_size(0);
1996 }
1997 }
1998
1999
2000
2001
2002
2003
2004
2005
2006 basic_string& replace(size_type pos1, size_type n1, const basic_string& str)
2007 {
2008 if (pos1 > this->size())
2009 throw_out_of_range("basic_string::replace out of range position");
2010 const size_type len = dtl::min_value(n1, this->size() - pos1);
2011 if (this->size() - len >= this->max_size() - str.size())
2012 throw_length_error("basic_string::replace max_size() exceeded");
2013 const pointer addr = this->priv_addr();
2014 return this->replace( const_iterator(addr + difference_type(pos1))
2015 , const_iterator(addr + difference_type(pos1 + len))
2016 , str.begin(), str.end());
2017 }
2018
2019
2020
2021 template<template<class, class> class BasicStringView>
2022 BOOST_CONTAINER_FORCEINLINE basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv)
2023 {
2024 return this->replace(pos1, n1, sv.data(), sv.size());
2025 }
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036 basic_string& replace(size_type pos1, size_type n1,
2037 const basic_string& str, size_type pos2, size_type n2 = npos)
2038 {
2039 if (pos2 > str.size())
2040 throw_out_of_range("basic_string::replace out of range position");
2041 return this->replace(pos1, n1, str.data()+pos2, dtl::min_value(n2, str.size() - pos2));
2042 }
2043
2044
2045
2046
2047
2048
2049
2050 template<template<class, class> class BasicStringView>
2051 basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv,
2052 size_type pos2, size_type n2 = npos)
2053 {
2054 if (pos2 > sv.size())
2055 throw_out_of_range("basic_string::replace out of range position");
2056 return this->replace(pos1, n1, sv.data()+pos2, dtl::min_value(n2, sv.size() - pos2));
2057 }
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073 basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
2074 {
2075 if (pos1 > this->size())
2076 throw_out_of_range("basic_string::replace out of range position");
2077 const size_type len = dtl::min_value(n1, this->size() - pos1);
2078 const size_type max_sz = this->max_size();
2079 if (n2 > max_sz || (this->size() - len) >= (max_sz - n2))
2080 throw_length_error("basic_string::replace max_size() exceeded");
2081 const pointer addr = this->priv_addr() + pos1;
2082 return this->replace(addr, addr + difference_type(len), s, s + difference_type(n2));
2083 }
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099 BOOST_CONTAINER_FORCEINLINE basic_string& replace(size_type pos, size_type n1, const CharT* s)
2100 {
2101 return this->replace(pos, n1, s, Traits::length(s));
2102 }
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112 basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c)
2113 {
2114 if (pos1 > this->size())
2115 throw_out_of_range("basic_string::replace out of range position");
2116 const size_type len = dtl::min_value(n1, this->size() - pos1);
2117 if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
2118 throw_length_error("basic_string::replace max_size() exceeded");
2119 const pointer addr = this->priv_addr();
2120 return this->replace(addr + difference_type(pos1), addr + difference_type(pos1 + len), n2, c);
2121 }
2122
2123
2124
2125
2126
2127
2128
2129
2130 BOOST_CONTAINER_FORCEINLINE basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str)
2131 { return this->replace(i1, i2, str.data(), str.data()+str.size()); }
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141 BOOST_CONTAINER_FORCEINLINE basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n)
2142 { return this->replace(i1, i2, s, s + difference_type(n)); }
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152 BOOST_CONTAINER_FORCEINLINE basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s)
2153 { return this->replace(i1, i2, s, s + Traits::length(s)); }
2154
2155
2156
2157
2158
2159
2160
2161
2162 basic_string& replace(const_iterator i1, const_iterator i2, size_type n, CharT c)
2163 {
2164 const size_type len = static_cast<size_type>(i2 - i1);
2165 if (len >= n) {
2166 Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), n, c);
2167 erase(i1 + difference_type(n), i2);
2168 }
2169 else {
2170 Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), len, c);
2171 insert(i2, n - len, c);
2172 }
2173 return *this;
2174 }
2175
2176
2177
2178
2179
2180
2181
2182
2183 template <class InputIter>
2184 basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
2185 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2186 , typename dtl::disable_if_or
2187 < void
2188 , dtl::is_convertible<InputIter, size_type>
2189 , dtl::is_input_iterator<InputIter>
2190 >::type * = 0
2191 #endif
2192 )
2193 {
2194 for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
2195 Traits::assign(*const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), *j1);
2196 }
2197
2198 if (j1 == j2)
2199 this->erase(i1, i2);
2200 else
2201 this->insert(i2, j1, j2);
2202 return *this;
2203 }
2204
2205 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2206 template <class ForwardIter>
2207 basic_string& replace(const_iterator i1, const_iterator i2, ForwardIter j1, ForwardIter j2
2208 , typename dtl::disable_if_or
2209 < void
2210 , dtl::is_convertible<ForwardIter, size_type>
2211 , dtl::is_not_input_iterator<ForwardIter>
2212 >::type * = 0
2213 )
2214 {
2215 difference_type n = boost::container::iterator_distance(j1, j2);
2216 const difference_type len = i2 - i1;
2217 if (len >= n) {
2218 this->priv_copy(j1, j2, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
2219 this->erase(i1 + difference_type(n), i2);
2220 }
2221 else {
2222 ForwardIter m = j1;
2223 boost::container::iterator_advance(m, len);
2224 this->priv_copy(j1, m, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
2225 this->insert(i2, m, j2);
2226 }
2227 return *this;
2228 }
2229 #endif
2230
2231
2232
2233
2234
2235
2236 template<template <class, class> class BasicStringView>
2237 BOOST_CONTAINER_FORCEINLINE basic_string& replace(const_iterator i1, const_iterator i2, BasicStringView<CharT, Traits> sv)
2238 {
2239 return this->replace( static_cast<size_type>(i1 - this->cbegin())
2240 , static_cast<size_type>(i2 - i1), sv);
2241 }
2242
2243 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2244
2245
2246
2247
2248
2249 BOOST_CONTAINER_FORCEINLINE basic_string& replace(const_iterator i1, const_iterator i2, std::initializer_list<CharT> il)
2250 {
2251 return this->replace( static_cast<size_type>(i1 - this->cbegin())
2252 , static_cast<size_type>(i2 - i1)
2253 , il.begin(), il.size());
2254 }
2255 #endif
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268 size_type copy(CharT* s, size_type n, size_type pos = 0) const
2269 {
2270 if (pos > this->size())
2271 throw_out_of_range("basic_string::copy out of range position");
2272 const size_type len = dtl::min_value(n, this->size() - pos);
2273 Traits::copy(s, boost::movelib::to_raw_pointer(this->priv_addr() + pos), len);
2274 return len;
2275 }
2276
2277
2278
2279
2280
2281 void swap(basic_string& x)
2282 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value
2283 || allocator_traits_type::is_always_equal::value)
2284 {
2285 this->base_t::swap_data(x);
2286 dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
2287 dtl::swap_alloc(this->alloc(), x.alloc(), flag);
2288 }
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2302 const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW
2303 { return boost::movelib::to_raw_pointer(this->priv_addr()); }
2304
2305
2306
2307
2308
2309
2310 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2311 const CharT* data() const BOOST_NOEXCEPT_OR_NOTHROW
2312 { return boost::movelib::to_raw_pointer(this->priv_addr()); }
2313
2314
2315
2316
2317 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2318 CharT* data() BOOST_NOEXCEPT_OR_NOTHROW
2319 { return boost::movelib::to_raw_pointer(this->priv_addr()); }
2320
2321 #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
2322
2323
2324
2325 template<template <class, class> class BasicStringView>
2326 BOOST_CONTAINER_FORCEINLINE operator BasicStringView<CharT, Traits>() const BOOST_NOEXCEPT_OR_NOTHROW
2327 { return this->to_view< BasicStringView<CharT, Traits> >(); }
2328 #endif
2329
2330
2331
2332
2333
2334
2335
2336 template<class BasicStringView>
2337 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2338 BasicStringView to_view() const BOOST_NOEXCEPT_OR_NOTHROW
2339 { return BasicStringView(this->data(), this->size()); }
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2356 size_type find(const basic_string& s, size_type pos = 0) const
2357 { return find(s.c_str(), pos, s.size()); }
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367 template<template <class, class> class BasicStringView>
2368 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2369 size_type find(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2370 { return this->find(sv.data(), pos, sv.size()); }
2371
2372
2373
2374
2375
2376
2377 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2378 size_type find(const CharT* s, size_type pos, size_type n) const
2379 {
2380 if (pos + n > this->size())
2381 return npos;
2382 else {
2383 const pointer addr = this->priv_addr();
2384 pointer finish = addr + difference_type(this->priv_size());
2385 const const_iterator result =
2386 boost::container::search(boost::movelib::to_raw_pointer(addr + difference_type(pos)),
2387 boost::movelib::to_raw_pointer(finish),
2388 s, s + difference_type(n), Eq_traits<Traits>());
2389 return result != finish ? size_type(result - begin()) : npos;
2390 }
2391 }
2392
2393
2394
2395
2396
2397
2398 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2399 size_type find(const CharT* s, size_type pos = 0) const
2400 { return this->find(s, pos, Traits::length(s)); }
2401
2402
2403
2404
2405 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2406 size_type find(CharT c, size_type pos = 0) const
2407 {
2408 const size_type sz = this->size();
2409 if (pos >= sz)
2410 return npos;
2411 else {
2412 const pointer addr = this->priv_addr();
2413 pointer finish = addr + difference_type(sz);
2414 const const_iterator result =
2415 boost::container::find_if(addr + difference_type(pos), finish,
2416 boost::container::bind2nd(Eq_traits<Traits>(), c));
2417 return result != finish ? size_type(result - begin()) : npos;
2418 }
2419 }
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2430 size_type rfind(const basic_string& str, size_type pos = npos) const
2431 { return this->rfind(str.c_str(), pos, str.size()); }
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441 template<template <class, class> class BasicStringView>
2442 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2443 size_type rfind(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2444 { return this->rfind(sv.data(), pos, sv.size()); }
2445
2446
2447
2448
2449
2450
2451 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2452 size_type rfind(const CharT* s, size_type pos, size_type n) const
2453 {
2454 const size_type len = this->size();
2455
2456 if (n > len)
2457 return npos;
2458 else if (n == 0)
2459 return dtl::min_value(len, pos);
2460 else {
2461 const const_iterator last = begin() + difference_type(dtl::min_value(len - n, pos + n));
2462 const const_iterator result = boost::container::find_end
2463 (begin(), last, s, s + difference_type(n), Eq_traits<Traits>());
2464 return result != last ? size_type(result - begin()) : npos;
2465 }
2466 }
2467
2468
2469
2470
2471
2472
2473
2474 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2475 size_type rfind(const CharT* s, size_type pos = npos) const
2476 { return this->rfind(s, pos, Traits::length(s)); }
2477
2478
2479
2480
2481 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2482 size_type rfind(CharT c, size_type pos = npos) const
2483 {
2484 const size_type len = this->size();
2485
2486 if (len < 1)
2487 return npos;
2488 else {
2489 const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2490 const_reverse_iterator rresult =
2491 boost::container::find_if(const_reverse_iterator(last), rend(),
2492 boost::container::bind2nd(Eq_traits<Traits>(), c));
2493 return rresult != rend() ? size_type((rresult.base() - 1) - begin()) : npos;
2494 }
2495 }
2496
2497
2498
2499
2500
2501
2502
2503
2504 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2505 size_type find_first_of(const basic_string& str, size_type pos = 0) const
2506 { return this->find_first_of(str.c_str(), pos, str.size()); }
2507
2508
2509
2510
2511
2512
2513
2514
2515 template<template <class, class> class BasicStringView>
2516 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2517 size_type find_first_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2518 { return this->find_first_of(sv.data(), pos, sv.size()); }
2519
2520
2521
2522
2523
2524
2525 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2526 size_type find_first_of(const CharT* s, size_type pos, size_type n) const
2527 {
2528 const size_type sz = this->size();
2529 if (pos >= sz)
2530 return npos;
2531 else {
2532 const pointer addr = this->priv_addr();
2533 pointer finish = addr + difference_type(sz);
2534 const_iterator result = boost::container::find_first_of
2535 (addr + difference_type(pos), finish, s, s + difference_type(n), Eq_traits<Traits>());
2536 return result != finish ? size_type(result - this->begin()) : npos;
2537 }
2538 }
2539
2540
2541
2542
2543
2544
2545 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2546 size_type find_first_of(const CharT* s, size_type pos = 0) const
2547 { return this->find_first_of(s, pos, Traits::length(s)); }
2548
2549
2550
2551
2552
2553
2554 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2555 size_type find_first_of(CharT c, size_type pos = 0) const
2556 { return this->find(c, pos); }
2557
2558
2559
2560
2561
2562
2563
2564
2565 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2566 size_type find_last_of(const basic_string& str, size_type pos = npos) const
2567 { return this->find_last_of(str.c_str(), pos, str.size()); }
2568
2569
2570
2571
2572
2573
2574
2575
2576 template<template <class, class> class BasicStringView>
2577 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2578 size_type find_last_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2579 { return this->find_last_of(sv.data(), pos, sv.size()); }
2580
2581
2582
2583
2584
2585
2586 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2587 size_type find_last_of(const CharT* s, size_type pos, size_type n) const
2588 {
2589 const size_type len = this->size();
2590
2591 if (len < 1)
2592 return npos;
2593 else {
2594 const pointer addr = this->priv_addr();
2595 const const_iterator last = addr + difference_type(dtl::min_value(len - 1, pos) + 1);
2596 const const_reverse_iterator rresult =
2597 boost::container::find_first_of(const_reverse_iterator(last), rend(),
2598 s, s + difference_type(n), Eq_traits<Traits>());
2599 return rresult != rend() ? size_type((rresult.base() - 1) - addr) : npos;
2600 }
2601 }
2602
2603
2604
2605
2606
2607
2608 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2609 size_type find_last_of(const CharT* s, size_type pos = npos) const
2610 { return this->find_last_of(s, pos, Traits::length(s)); }
2611
2612
2613
2614
2615 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2616 size_type find_last_of(CharT c, size_type pos = npos) const
2617 { return this->rfind(c, pos); }
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2628 size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
2629 { return this->find_first_not_of(str.c_str(), pos, str.size()); }
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639 template<template <class, class> class BasicStringView>
2640 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2641 size_type find_first_not_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2642 { return this->find_first_not_of(sv.data(), pos, sv.size()); }
2643
2644
2645
2646
2647
2648
2649 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2650 size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const
2651 {
2652 if (pos > this->size())
2653 return npos;
2654 else {
2655 const pointer addr = this->priv_addr();
2656 const pointer finish = addr + difference_type(this->priv_size());
2657 const const_iterator result = boost::container::find_if
2658 (addr + difference_type(pos), finish, Not_within_traits<Traits>(s, s + difference_type(n)));
2659 return result != finish ? size_type(result - addr) : npos;
2660 }
2661 }
2662
2663
2664
2665
2666
2667
2668 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2669 size_type find_first_not_of(const CharT* s, size_type pos = 0) const
2670 { return this->find_first_not_of(s, pos, Traits::length(s)); }
2671
2672
2673
2674
2675 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2676 size_type find_first_not_of(CharT c, size_type pos = 0) const
2677 {
2678 if (pos > this->size())
2679 return npos;
2680 else {
2681 const pointer addr = this->priv_addr();
2682 const pointer finish = addr + difference_type(this->priv_size());
2683 const const_iterator result
2684 = boost::container::find_if(addr + difference_type(pos), finish,
2685 boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
2686 return result != finish ? size_type(result - begin()) : npos;
2687 }
2688 }
2689
2690
2691
2692
2693
2694
2695
2696
2697 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2698 size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
2699 { return this->find_last_not_of(str.c_str(), pos, str.size()); }
2700
2701
2702
2703
2704
2705
2706
2707
2708 template<template <class, class> class BasicStringView>
2709 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2710 size_type find_last_not_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2711 { return this->find_last_not_of(sv.data(), pos, sv.size()); }
2712
2713
2714
2715
2716
2717
2718 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2719 size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const
2720 {
2721 const size_type len = this->size();
2722
2723 if (len < 1)
2724 return npos;
2725 else {
2726 const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2727 const const_reverse_iterator rresult =
2728 boost::container::find_if(const_reverse_iterator(last), rend(),
2729 Not_within_traits<Traits>(s, s + difference_type(n)));
2730 return rresult != rend() ? size_type((rresult.base() - 1) - begin()) : npos;
2731 }
2732 }
2733
2734
2735
2736
2737
2738
2739 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2740 size_type find_last_not_of(const CharT* s, size_type pos = npos) const
2741 { return this->find_last_not_of(s, pos, Traits::length(s)); }
2742
2743
2744
2745
2746 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2747 size_type find_last_not_of(CharT c, size_type pos = npos) const
2748 {
2749 const size_type len = this->size();
2750
2751 if (len < 1)
2752 return npos;
2753 else {
2754 const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2755 const const_reverse_iterator rresult =
2756 boost::container::find_if(const_reverse_iterator(last), rend(),
2757 boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
2758 return rresult != rend() ? size_type((rresult.base() - 1) - begin()) : npos;
2759 }
2760 }
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2771 basic_string substr(size_type pos = 0, size_type n = npos) const
2772 {
2773 if (pos > this->size())
2774 throw_out_of_range("basic_string::substr out of range position");
2775 const pointer addr = this->priv_addr();
2776 return basic_string(addr + difference_type(pos),
2777 addr + difference_type(pos + dtl::min_value(n, size() - pos)), this->alloc());
2778 }
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2790 int compare(const basic_string& str) const
2791 {
2792 const pointer addr = this->priv_addr();
2793 const pointer str_addr = str.priv_addr();
2794 return this->s_compare(addr, addr + difference_type(this->priv_size()), str_addr, str_addr + difference_type(str.priv_size()));
2795 }
2796
2797
2798
2799
2800 template<template <class, class> class BasicStringView>
2801 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2802 int compare(BasicStringView<CharT,Traits> sv) const
2803 {
2804 const pointer addr = this->priv_addr();
2805 return this->s_compare(addr, addr + difference_type(this->priv_size()), sv.data(), sv.data() + difference_type(sv.size()));
2806 }
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2818 int compare(size_type pos1, size_type n1, const basic_string& str) const
2819 {
2820 if (pos1 > this->size())
2821 throw_out_of_range("basic_string::compare out of range position");
2822 const pointer addr = this->priv_addr();
2823 const pointer str_addr = str.priv_addr();
2824 return this->s_compare(addr + difference_type(pos1),
2825 addr + difference_type(pos1 + dtl::min_value(n1, this->size() - pos1)),
2826 str_addr, str_addr + difference_type(str.priv_size()));
2827 }
2828
2829
2830
2831
2832
2833
2834 template<template <class, class> class BasicStringView>
2835 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2836 int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv) const
2837 {
2838 if (pos1 > this->size())
2839 throw_out_of_range("basic_string::compare out of range position");
2840 const pointer addr = this->priv_addr() + pos1;
2841 const CharT* str_addr = sv.data();
2842 return this->s_compare(addr, addr + difference_type(dtl::min_value(n1, this->size() - pos1)),
2843 str_addr, str_addr + sv.size());
2844 }
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2855 int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos) const
2856 {
2857 if (pos1 > this->size() || pos2 > str.size())
2858 throw_out_of_range("basic_string::compare out of range position");
2859 const pointer addr = this->priv_addr() + pos1;
2860 const pointer str_addr = str.priv_addr() + pos2;
2861 return this->s_compare(addr, addr + difference_type(dtl::min_value(n1, this->size() - pos1)),
2862 str_addr, str_addr + difference_type(dtl::min_value(n2, str.size() - pos2)));
2863 }
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873 template<template <class, class> class BasicStringView>
2874 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2875 int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv, size_type pos2, size_type n2) const
2876 {
2877 if (pos1 > this->size() || pos2 > sv.size())
2878 throw_out_of_range("basic_string::compare out of range position");
2879 const pointer addr = this->priv_addr() + pos1;
2880 const CharT * str_addr = sv.data() + pos2;
2881 return this->s_compare(addr, addr + difference_type(dtl::min_value(n1, this->size() - pos1)),
2882 str_addr, str_addr + difference_type(dtl::min_value(n2, sv.size() - pos2)));
2883 }
2884
2885
2886
2887
2888 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2889 int compare(const CharT* s) const
2890 {
2891 const pointer addr = this->priv_addr();
2892 return this->s_compare(addr, addr + difference_type(this->priv_size()), s, s + Traits::length(s));
2893 }
2894
2895
2896
2897
2898
2899
2900 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2901 int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
2902 {
2903 if (pos1 > this->size())
2904 throw_out_of_range("basic_string::compare out of range position");
2905 const pointer addr = this->priv_addr();
2906 return this->s_compare( addr + difference_type(pos1),
2907 addr + difference_type(pos1 + dtl::min_value(n1, this->size() - pos1)),
2908 s, s + difference_type(n2));
2909 }
2910
2911
2912
2913
2914
2915
2916 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2917 int compare(size_type pos1, size_type n1, const CharT* s) const
2918 { return this->compare(pos1, n1, s, Traits::length(s)); }
2919
2920 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2921 private:
2922 void priv_reserve(size_type res_arg, const bool null_terminate = true)
2923 {
2924 if (res_arg > this->max_size()){
2925 throw_length_error("basic_string::reserve max_size() exceeded");
2926 }
2927
2928 if (this->capacity() < res_arg){
2929 size_type n = dtl::max_value(res_arg, this->size()) + 1;
2930 size_type new_cap = this->next_capacity(n);
2931 pointer reuse = 0;
2932 pointer new_start = this->allocation_command(allocate_new, n, new_cap, reuse);
2933 size_type new_length = 0;
2934
2935 const pointer addr = this->priv_addr();
2936 new_length += priv_uninitialized_copy
2937 (addr, addr + difference_type(this->priv_size()), new_start);
2938 if(null_terminate){
2939 this->priv_construct_null(new_start + difference_type(new_length));
2940 }
2941 this->deallocate_block();
2942 this->assure_long();
2943 this->priv_long_addr(new_start);
2944 this->priv_long_size(new_length);
2945 this->priv_storage(new_cap);
2946 }
2947 }
2948
2949 template<class It1, class It2>
2950 static int s_compare(It1 f1, It1 l1, It2 f2, It2 l2)
2951 {
2952 const std::size_t n1 = std::size_t(l1 - f1);
2953 const std::size_t n2 = std::size_t(l2 - f2);
2954 const int cmp = Traits::compare(boost::movelib::to_raw_pointer(f1),
2955 boost::movelib::to_raw_pointer(f2),
2956 dtl::min_value(n1, n2));
2957 return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
2958 }
2959
2960 template<class AllocVersion>
2961 void priv_shrink_to_fit_dynamic_buffer
2962 ( AllocVersion
2963 , typename dtl::enable_if<dtl::is_same<AllocVersion, version_1> >::type* = 0)
2964 {
2965
2966 size_type real_cap = 0;
2967 const pointer long_addr = this->priv_long_addr();
2968 const size_type long_size = this->priv_long_size();
2969 const size_type long_storage = this->priv_long_storage();
2970
2971 BOOST_CONTAINER_TRY{
2972 pointer reuse = 0;
2973 real_cap = long_size+1;
2974 const pointer ret = this->allocation_command(allocate_new, long_size+1, real_cap, reuse);
2975
2976 Traits::copy( boost::movelib::to_raw_pointer(ret)
2977 , boost::movelib::to_raw_pointer(this->priv_long_addr())
2978 , long_size+1);
2979 this->priv_long_addr(ret);
2980 this->priv_storage(real_cap);
2981
2982 this->alloc().deallocate(long_addr, long_storage);
2983 }
2984 BOOST_CONTAINER_CATCH(...){
2985 return;
2986 }
2987 BOOST_CONTAINER_CATCH_END
2988 }
2989
2990 template<class AllocVersion>
2991 void priv_shrink_to_fit_dynamic_buffer
2992 ( AllocVersion
2993 , typename dtl::enable_if<dtl::is_same<AllocVersion, version_2> >::type* = 0)
2994 {
2995 size_type received_size = this->priv_long_size()+1;
2996 pointer hint = this->priv_long_addr();
2997 if(this->alloc().allocation_command
2998 ( shrink_in_place | nothrow_allocation, this->priv_long_storage(), received_size, hint)){
2999 this->priv_storage(received_size);
3000 }
3001 }
3002
3003 BOOST_CONTAINER_FORCEINLINE void priv_construct_null(pointer p)
3004 { this->construct(p, CharT(0)); }
3005
3006
3007
3008 BOOST_CONTAINER_FORCEINLINE void priv_terminate_string()
3009 { this->priv_construct_null(this->priv_end_addr()); }
3010
3011 template<class FwdIt, class Count> inline
3012 void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val)
3013 {
3014
3015 FwdIt init = first;
3016
3017 BOOST_CONTAINER_TRY{
3018
3019 for (; count--; ++first){
3020 this->construct(first, val);
3021 }
3022 }
3023 BOOST_CONTAINER_CATCH(...){
3024
3025 for (; init != first; ++init){
3026 this->destroy(init);
3027 }
3028 BOOST_CONTAINER_RETHROW
3029 }
3030 BOOST_CONTAINER_CATCH_END
3031 }
3032
3033 template<class InpIt, class FwdIt> inline
3034 size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest)
3035 {
3036
3037 FwdIt dest_init = dest;
3038 size_type constructed = 0;
3039
3040 BOOST_CONTAINER_TRY{
3041
3042 for (; first != last; ++dest, ++first, ++constructed){
3043 this->construct(dest, *first);
3044 }
3045 }
3046 BOOST_CONTAINER_CATCH(...){
3047
3048 for (; constructed--; ++dest_init){
3049 this->destroy(dest_init);
3050 }
3051 BOOST_CONTAINER_RETHROW
3052 }
3053 BOOST_CONTAINER_CATCH_END
3054 return (constructed);
3055 }
3056
3057 template <class InputIterator, class OutIterator>
3058 static void priv_copy(InputIterator first, InputIterator last, OutIterator result)
3059 {
3060 for ( ; first != last; ++first, ++result)
3061 Traits::assign(*result, *first);
3062 }
3063
3064 static BOOST_CONTAINER_FORCEINLINE void priv_copy(const CharT* first, const CharT* last, CharT* result)
3065 { Traits::copy(result, first, std::size_t(last - first)); }
3066
3067 template <class Integer>
3068 BOOST_CONTAINER_FORCEINLINE basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
3069 Integer n, Integer x,
3070 dtl::true_)
3071 { return this->replace(first, last, (size_type) n, (CharT) x); }
3072
3073 template <class InputIter>
3074 BOOST_CONTAINER_FORCEINLINE basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
3075 InputIter f, InputIter l,
3076 dtl::false_)
3077 {
3078 typedef typename boost::container::iterator_traits<InputIter>::iterator_category Category;
3079 return this->priv_replace(first, last, f, l, Category());
3080 }
3081
3082 #endif
3083 };
3084
3085 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3086
3087 template <typename InputIterator>
3088 basic_string(InputIterator, InputIterator) ->
3089 basic_string<typename iterator_traits<InputIterator>::value_type>;
3090
3091 template <typename InputIterator, typename Allocator>
3092 basic_string(InputIterator, InputIterator, Allocator const&) ->
3093 basic_string<typename iterator_traits<InputIterator>::value_type, Allocator>;
3094
3095 #endif
3096
3097 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
3098
3099
3100
3101 typedef basic_string
3102 <char
3103 ,std::char_traits<char>
3104 ,new_allocator<char> >
3105 string;
3106
3107
3108
3109 typedef basic_string
3110 <wchar_t
3111 ,std::char_traits<wchar_t>
3112 ,new_allocator<wchar_t> >
3113 wstring;
3114
3115 #else
3116
3117 template <class CharT, class Traits, class Allocator>
3118 const typename basic_string<CharT,Traits,Allocator>::size_type
3119 basic_string<CharT,Traits,Allocator>::npos;
3120
3121 template<class S>
3122 struct is_string
3123 {
3124 static const bool value = false;
3125 };
3126
3127 template<class C, class T, class A>
3128 struct is_string< basic_string<C, T, A> >
3129 {
3130 static const bool value = true;
3131 };
3132
3133 #endif
3134
3135
3136
3137
3138
3139
3140 template <class CharT, class Traits, class Allocator> inline
3141 basic_string<CharT,Traits,Allocator>
3142 operator+(const basic_string<CharT,Traits,Allocator>& x
3143 ,const basic_string<CharT,Traits,Allocator>& y)
3144 {
3145 typedef basic_string<CharT,Traits,Allocator> str_t;
3146 typedef typename str_t::reserve_t reserve_t;
3147 reserve_t reserve;
3148 str_t result(reserve, x.size() + y.size(), x.get_stored_allocator());
3149 result.append(x);
3150 result.append(y);
3151 return result;
3152 }
3153
3154 template <class CharT, class Traits, class Allocator> inline
3155 basic_string<CharT, Traits, Allocator> operator+
3156 ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
3157 , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
3158 {
3159 x += y;
3160 return boost::move(x);
3161 }
3162
3163 template <class CharT, class Traits, class Allocator> inline
3164 basic_string<CharT, Traits, Allocator> operator+
3165 ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
3166 , const basic_string<CharT,Traits,Allocator>& y)
3167 {
3168 x += y;
3169 return boost::move(x);
3170 }
3171
3172 template <class CharT, class Traits, class Allocator> inline
3173 basic_string<CharT, Traits, Allocator> operator+
3174 (const basic_string<CharT,Traits,Allocator>& x
3175 ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
3176 {
3177 y.insert(y.begin(), x.begin(), x.end());
3178 return boost::move(y);
3179 }
3180
3181 template <class CharT, class Traits, class Allocator> inline
3182 basic_string<CharT, Traits, Allocator> operator+
3183 (const CharT* s, basic_string<CharT, Traits, Allocator> y)
3184 {
3185 y.insert(y.begin(), s, s + Traits::length(s));
3186 return y;
3187 }
3188
3189 template <class CharT, class Traits, class Allocator> inline
3190 basic_string<CharT,Traits,Allocator> operator+
3191 (basic_string<CharT,Traits,Allocator> x, const CharT* s)
3192 {
3193 x += s;
3194 return x;
3195 }
3196
3197 template <class CharT, class Traits, class Allocator> inline
3198 basic_string<CharT,Traits,Allocator> operator+
3199 (CharT c, basic_string<CharT,Traits,Allocator> y)
3200 {
3201 y.insert(y.begin(), c);
3202 return y;
3203 }
3204
3205 template <class CharT, class Traits, class Allocator> inline
3206 basic_string<CharT,Traits,Allocator> operator+
3207 (basic_string<CharT,Traits,Allocator> x, const CharT c)
3208 {
3209 x += c;
3210 return x;
3211 }
3212
3213
3214
3215 template <class CharT, class Traits, class Allocator>
3216 inline bool
3217 operator==(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3218 {
3219 return x.size() == y.size() &&
3220 Traits::compare(x.data(), y.data(), x.size()) == 0;
3221 }
3222
3223 template <class CharT, class Traits, class Allocator>
3224 inline bool
3225 operator==(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3226 {
3227 typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
3228 return n == y.size() && Traits::compare(s, y.data(), n) == 0;
3229 }
3230
3231 template <class CharT, class Traits, class Allocator>
3232 inline bool
3233 operator==(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3234 {
3235 typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
3236 return x.size() == n && Traits::compare(x.data(), s, n) == 0;
3237 }
3238
3239 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3240 inline
3241 BOOST_CONTAINER_DOC1ST( bool,
3242 typename dtl::disable_if
3243 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3244 operator==( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3245 {
3246 return x.size() == y.size() &&
3247 Traits::compare(x.data(), y.data(), x.size()) == 0;
3248 }
3249
3250 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3251 inline
3252 BOOST_CONTAINER_DOC1ST( bool,
3253 typename dtl::disable_if
3254 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3255 operator==( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3256 {
3257 return x.size() == y.size() &&
3258 Traits::compare(x.data(), y.data(), x.size()) == 0;
3259 }
3260
3261 template <class CharT, class Traits, class Allocator>
3262 inline bool
3263 operator!=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3264 { return !(x == y); }
3265
3266 template <class CharT, class Traits, class Allocator>
3267 inline bool
3268 operator!=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3269 { return !(s == y); }
3270
3271 template <class CharT, class Traits, class Allocator>
3272 inline bool
3273 operator!=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3274 { return !(x == s); }
3275
3276
3277 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3278 inline
3279 BOOST_CONTAINER_DOC1ST( bool,
3280 typename dtl::disable_if
3281 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3282 operator!=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3283 { return !(x == y); }
3284
3285 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3286 inline
3287 BOOST_CONTAINER_DOC1ST( bool,
3288 typename dtl::disable_if
3289 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3290 operator!=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3291 { return !(x == y); }
3292
3293
3294 template <class CharT, class Traits, class Allocator>
3295 inline bool
3296 operator<(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3297 {
3298 return x.compare(y) < 0;
3299 }
3300
3301 template <class CharT, class Traits, class Allocator>
3302 inline bool
3303 operator<(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3304 {
3305 return y.compare(s) > 0;
3306 }
3307
3308 template <class CharT, class Traits, class Allocator>
3309 inline bool
3310 operator<(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3311 {
3312 return x.compare(s) < 0;
3313 }
3314
3315 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3316 inline
3317 BOOST_CONTAINER_DOC1ST( bool,
3318 typename dtl::disable_if
3319 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3320 operator<( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3321 { return y.compare(x) > 0; }
3322
3323 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3324 inline
3325 BOOST_CONTAINER_DOC1ST( bool,
3326 typename dtl::disable_if
3327 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3328 operator<( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3329 { return x.compare(y) < 0; }
3330
3331 template <class CharT, class Traits, class Allocator>
3332 inline bool
3333 operator>(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y) {
3334 return y < x;
3335 }
3336
3337 template <class CharT, class Traits, class Allocator>
3338 inline bool
3339 operator>(const CharT* s, const basic_string<CharT,Traits,Allocator>& y) {
3340 return y < s;
3341 }
3342
3343 template <class CharT, class Traits, class Allocator>
3344 inline bool
3345 operator>(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3346 {
3347 return s < x;
3348 }
3349
3350 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3351 inline
3352 BOOST_CONTAINER_DOC1ST( bool,
3353 typename dtl::disable_if
3354 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3355 operator>( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3356 { return y < x; }
3357
3358 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3359 inline
3360 BOOST_CONTAINER_DOC1ST( bool,
3361 typename dtl::disable_if
3362 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3363 operator>( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3364 { return y < x; }
3365
3366 template <class CharT, class Traits, class Allocator>
3367 inline bool
3368 operator<=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3369 {
3370 return !(y < x);
3371 }
3372
3373 template <class CharT, class Traits, class Allocator>
3374 inline bool
3375 operator<=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3376 { return !(y < s); }
3377
3378 template <class CharT, class Traits, class Allocator>
3379 inline bool
3380 operator<=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3381 { return !(s < x); }
3382
3383
3384 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3385 inline
3386 BOOST_CONTAINER_DOC1ST( bool,
3387 typename dtl::disable_if
3388 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3389 operator<=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3390 { return !(y < x); }
3391
3392 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3393 inline
3394 BOOST_CONTAINER_DOC1ST( bool,
3395 typename dtl::disable_if
3396 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3397 operator<=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3398 { return !(y < x); }
3399
3400 template <class CharT, class Traits, class Allocator>
3401 inline bool
3402 operator>=(const basic_string<CharT,Traits,Allocator>& x,
3403 const basic_string<CharT,Traits,Allocator>& y)
3404 { return !(x < y); }
3405
3406 template <class CharT, class Traits, class Allocator>
3407 inline bool
3408 operator>=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3409 { return !(s < y); }
3410
3411 template <class CharT, class Traits, class Allocator>
3412 inline bool
3413 operator>=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3414 { return !(x < s); }
3415
3416 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3417 inline
3418 BOOST_CONTAINER_DOC1ST( bool,
3419 typename dtl::disable_if
3420 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3421 operator>=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3422 { return !(x < y); }
3423
3424 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3425 inline
3426 BOOST_CONTAINER_DOC1ST( bool,
3427 typename dtl::disable_if
3428 <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3429 operator>=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3430 { return !(x < y); }
3431
3432
3433 template <class CharT, class Traits, class Allocator>
3434 inline void swap(basic_string<CharT,Traits,Allocator>& x, basic_string<CharT,Traits,Allocator>& y)
3435 BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
3436 { x.swap(y); }
3437
3438 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3439
3440 namespace dtl {
3441
3442 template <class CharT, class Traits>
3443 inline bool
3444 string_fill(std::basic_ostream<CharT, Traits>& os,
3445 std::basic_streambuf<CharT, Traits>* buf,
3446 std::size_t n)
3447 {
3448 CharT f = os.fill();
3449 std::size_t i;
3450 bool ok = true;
3451
3452 for (i = 0; i < n; i++)
3453 ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof());
3454 return ok;
3455 }
3456
3457 }
3458 #endif
3459
3460 template <class CharT, class Traits, class Allocator>
3461 std::basic_ostream<CharT, Traits>&
3462 operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Traits,Allocator>& s)
3463 {
3464 typename std::basic_ostream<CharT, Traits>::sentry sentry(os);
3465 bool ok = false;
3466
3467 if (sentry) {
3468 ok = true;
3469 typename basic_string<CharT,Traits,Allocator>::size_type n = s.size();
3470 typename basic_string<CharT,Traits,Allocator>::size_type pad_len = 0;
3471 const bool left = (os.flags() & std::ios::left) != 0;
3472 const std::size_t w = os.width(0);
3473 std::basic_streambuf<CharT, Traits>* buf = os.rdbuf();
3474
3475 if (w != 0 && n < w)
3476 pad_len = w - n;
3477
3478 if (!left)
3479 ok = dtl::string_fill(os, buf, pad_len);
3480
3481 ok = ok &&
3482 buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n);
3483
3484 if (left)
3485 ok = ok && dtl::string_fill(os, buf, pad_len);
3486 }
3487
3488 if (!ok)
3489 os.setstate(std::ios_base::failbit);
3490
3491 return os;
3492 }
3493
3494
3495 template <class CharT, class Traits, class Allocator>
3496 std::basic_istream<CharT, Traits>&
3497 operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
3498 {
3499 typename std::basic_istream<CharT, Traits>::sentry sentry(is);
3500
3501 if (sentry) {
3502 std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
3503 const std::ctype<CharT>& ctype = std::use_facet<std::ctype<CharT> >(is.getloc());
3504
3505 s.clear();
3506 std::size_t n = is.width(0);
3507 if (n == 0)
3508 n = static_cast<std::size_t>(-1);
3509 else
3510 s.reserve(n);
3511
3512 while (n-- > 0) {
3513 typename Traits::int_type c1 = buf->sbumpc();
3514
3515 if (Traits::eq_int_type(c1, Traits::eof())) {
3516 is.setstate(std::ios_base::eofbit);
3517 break;
3518 }
3519 else {
3520 CharT c = Traits::to_char_type(c1);
3521
3522 if (ctype.is(std::ctype<CharT>::space, c)) {
3523 if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof()))
3524 is.setstate(std::ios_base::failbit);
3525 break;
3526 }
3527 else
3528 s.push_back(c);
3529 }
3530 }
3531
3532
3533 if (s.size() == 0)
3534 is.setstate(std::ios_base::failbit);
3535 }
3536 else
3537 is.setstate(std::ios_base::failbit);
3538
3539 return is;
3540 }
3541
3542 template <class CharT, class Traits, class Allocator>
3543 std::basic_istream<CharT, Traits>&
3544 getline(std::istream& is, basic_string<CharT,Traits,Allocator>& s,CharT delim)
3545 {
3546 typename basic_string<CharT,Traits,Allocator>::size_type nread = 0;
3547 typename std::basic_istream<CharT, Traits>::sentry sentry(is, true);
3548 if (sentry) {
3549 std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
3550 s.clear();
3551
3552 while (nread < s.max_size()) {
3553 int c1 = buf->sbumpc();
3554 if (Traits::eq_int_type(c1, Traits::eof())) {
3555 is.setstate(std::ios_base::eofbit);
3556 break;
3557 }
3558 else {
3559 ++nread;
3560 CharT c = Traits::to_char_type(c1);
3561 if (!Traits::eq(c, delim))
3562 s.push_back(c);
3563 else
3564 break;
3565 }
3566 }
3567 }
3568 if (nread == 0 || nread >= s.max_size())
3569 is.setstate(std::ios_base::failbit);
3570
3571 return is;
3572 }
3573
3574 template <class CharT, class Traits, class Allocator>
3575 inline std::basic_istream<CharT, Traits>&
3576 getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
3577 {
3578 return getline(is, s, '\n');
3579 }
3580
3581 template <class Ch, class Allocator>
3582 inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, Allocator> const& v)
3583 {
3584 std::size_t seed = 0;
3585 const Ch *first = v.data();
3586
3587 for(std::size_t i = 0, i_max = v.size(); i != i_max; ++i)
3588 {
3589 boost::intrusive::detail::hash_combine_size_t(seed, static_cast<std::size_t>(*first));
3590 ++first;
3591 }
3592
3593 return seed;
3594 }
3595
3596 }}
3597
3598
3599 #if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
3600 #pragma GCC diagnostic pop
3601 #endif
3602
3603
3604 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3605
3606 namespace boost {
3607
3608
3609
3610 template <class C, class T, class Allocator>
3611 struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
3612 {
3613 typedef typename boost::container::basic_string<C, T, Allocator>::allocator_type allocator_type;
3614 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3615 static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3616 ::boost::has_trivial_destructor_after_move<pointer>::value;
3617 };
3618
3619 }
3620
3621 #endif
3622
3623 #include <boost/container/detail/config_end.hpp>
3624
3625 #endif