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