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