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