annotate DEPENDENCIES/generic/include/boost/container/string.hpp @ 133:4acb5d8d80b6 tip

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