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