1 /* ///////////////////////////////////////////////////////////////////////
7 * Brief: Memory buffer base class
10 * Copyright (c) 2008-2020, Waruqi All rights reserved.
11 * //////////////////////////////////////////////////////////////////// */
13 #ifndef EXTL_MEMORY_BUFFER_BASE_H
14 #define EXTL_MEMORY_BUFFER_BASE_H
16 /*!\file buffer_base.h
17 * \brief Memory buffer base class
21 # error buffer_base.h need be supported by c++.
24 /* ///////////////////////////////////////////////////////////////////////
27 #include "../iterator/iterator.h"
28 #include "../algorithm/algorithm.h"
29 #include "../error/error.h"
30 #include "pod_memory_traits.h"
32 /* ///////////////////////////////////////////////////////////////////////
37 /*!\brief buffer base class
38 * \param B The buffer type
39 * \param A The buffer type
41 * \ingroup extl_group_memory
43 template< typename_param_k B
48 #ifdef EXTL_EBO_FORM_2_SUPPORT
49 : protected A
/* if EBO is supported */
55 typedef buffer_base
<B
, A
, M
> class_type
;
56 typedef A allocator_type
;
57 typedef B buffer_type
;
58 typedef M memory_traits_type
;
59 typedef typename_type_k
allocator_type::value_type value_type
;
60 typedef pod_memory_traits
<value_type
> pod_memory_traits_type
;
61 typedef typename_type_k
allocator_type::pointer pointer
;
62 typedef typename_type_k
allocator_type::const_pointer const_pointer
;
63 typedef typename_type_k
allocator_type::reference reference
;
64 typedef typename_type_k
allocator_type::const_reference const_reference
;
65 typedef typename_type_k
allocator_type::size_type size_type
;
66 typedef e_ptrdiff_t difference_type
;
67 typedef e_bool_t bool_type
;
68 typedef size_type index_type
;
69 typedef pointer_iterator
<value_type
> iterator
;
70 typedef const_pointer_iterator
<value_type
> const_iterator
;
71 typedef reverse_iterator_base
<const_iterator
> reverse_iterator
;
72 typedef const_reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
78 const_iterator
begin() const { return const_iterator(buffer().data()); }
79 iterator
begin() { return iterator(buffer().data()); }
81 const_iterator
end() const { return const_iterator(buffer().data() + buffer().size()); }
82 iterator
end() { return iterator(buffer().data() + buffer().size()); }
84 const_reverse_iterator
rbegin() const { return const_reverse_iterator(buffer().end()); }
85 reverse_iterator
rbegin() { return reverse_iterator(buffer().end()); }
87 const_reverse_iterator
rend() const { return const_reverse_iterator(buffer().begin()); }
88 reverse_iterator
rend() { return reverse_iterator(buffer().begin()); }
94 /// Returns reference at the given index
95 reference
operator[](index_type index
)
97 return const_cast<reference
>(static_cast<buffer_type
const&>(*this).operator[](index
));
99 /// Returns const reference at the given index
100 const_reference
operator[](index_type index
) const
102 EXTL_ASSERT(buffer().is_valid());
103 EXTL_ASSERT(NULL
!= buffer().data());
104 EXTL_ASSERT(index
< buffer().size());
105 return buffer().data()[index
];
107 /// Returns reference at the given index and throws index_error() if index >= size()
108 reference
at(index_type index
)
110 return const_cast<reference
>(static_cast<buffer_type
const&>(*this).at(index
));
112 /// Returns const reference at the given index and throws index_error() if index >= size()
113 const_reference
at(index_type index
) const
115 EXTL_ASSERT(buffer().is_valid());
116 EXTL_ASSERT(NULL
!= buffer().data());
117 EXTL_ASSERT(index
< buffer().size());
118 EXTL_ASSERT_THROW(index
< buffer().size(), index_error("out of range"));
119 return buffer().data()[index
];
122 // Returns the first element of the buffer
123 reference
front() { return buffer().at(0); }
124 // Returns the first element of the buffer
125 const_reference
front() const { return buffer().at(0); }
126 // Returns the last element of the buffer
127 reference
back() { return buffer().at(buffer().size() - 1); }
128 // Returns the last element of the buffer
129 const_reference
back() const { return buffer().at(buffer().size() - 1); }
135 /// Indicates whether the buffer is empty
136 bool_type
is_empty() const { return 0 == buffer().size(); }
137 /// Indicates whether the buffer is empty for comparability
138 bool_type
empty() const { return buffer().is_empty(); }
139 /// The maximum size of the buffer
140 size_type
max_size() const { return allocator().max_size(); }
141 /// Reserves at least newcap size memory storage
142 void reserve(size_type newcap
) { if (buffer().capacity() < newcap
) buffer().resize(newcap
, e_false_v
); }
143 /// Clears the memory of the buffer
144 void clear() { buffer().erase(0, buffer().size()); }
145 /// Fills zero in the whole buffer
146 void clean() { memory_traits_type::fill_0(buffer().data(), buffer().size()); }
148 /// Returns the allocator
149 allocator_type
allocator() const
151 #ifdef EXTL_EBO_FORM_2_SUPPORT
154 return allocator_type();
159 /// \name Replacements
162 /// Replaces the given range [pos, pos + old_n) with the given new buffer with new_n value
163 buffer_type
& replace(size_type pos
, size_type old_n
, const_pointer new_buf
, size_type new_n
);
164 /// Replaces the given range [pos, pos + old_n) with the given new buffer
165 buffer_type
& replace(size_type pos
, size_type old_n
, buffer_type
const& new_buf
) { return replace(pos
, old_n
, new_buf
.data(), new_buf
.size()); }
166 /// Replaces the given range [pos, pos + old_n) with the given new buffer with new_n value
167 buffer_type
& replace(size_type pos
, size_type old_n
, buffer_type
const& new_buf
, size_type new_n
) { return buffer().replace(pos
, old_n
, new_buf
.data(), new_n
); }
168 /// Replaces the given range [pos, pos + old_n) with the given new_n value with the value new_value
169 buffer_type
& replace(size_type pos
, size_type old_n
, const_reference new_value
, size_type new_n
= 1);
170 /// Replaces the given position [pos, pos + 1) with the given new_n value with the value new_value
171 buffer_type
& replace(size_type pos
, const_reference new_value
, size_type new_n
= 1) { return buffer().replace(pos
, 1, new_value
, new_n
); }
173 /// Replaces the given range [first, last) with the input const_iterator with the given new buffer with new_n value
174 buffer_type
& replace(const_iterator first
, const_iterator last
, const_pointer new_buf
, size_type new_n
) { return buffer().replace(ptr_diff(buffer().begin(), first
), ptr_diff(first
, last
), new_buf
, new_n
); }
175 /// Replaces the given range [first, last) with the input const_iterator with the given new buffer
176 buffer_type
& replace(const_iterator first
, const_iterator last
, buffer_type
const& new_buf
) { return buffer().replace(first
, last
, new_buf
.data(), new_buf
.size()); }
177 /// Replaces the given range [first, last) with the input const_iterator with the given new buffer with new_n value
178 buffer_type
& replace(const_iterator first
, const_iterator last
, buffer_type
const& new_buf
, size_type new_n
) { return buffer().replace(first
, last
, new_buf
.data(), new_n
); }
179 /// Replaces the given range [first, last) with the input const_iterator with the given new_n value with the value new_value
180 buffer_type
& replace(const_iterator first
, const_iterator last
, const_reference new_value
, size_type new_n
= 1) { return buffer().replace(ptr_diff(buffer().begin(), first
), ptr_diff(first
, last
), new_value
, new_n
); }
181 /// Replaces the given position [pos, pos + 1) with the input const_iterator with the given new buffer with new_n value
182 buffer_type
& replace(const_iterator pos
, const_reference new_value
, size_type new_n
= 1) { return buffer().replace(ptr_diff(buffer().begin(), pos
), 1, new_value
, new_n
); }
184 /// Replaces the given range [first, last) with the input iterator with the given range [first2, last2)
185 buffer_type
& replace(const_iterator first
, const_iterator last
, const_pointer first2
, const_pointer last2
) { return buffer().replace(ptr_diff(buffer().begin(), first
), ptr_diff(first
, last
), first2
, ptr_diff(first2
, last2
)); }
186 /// Replaces the given range [first, last) with the input iterator with the given range [first2, last2) with the input iterator
187 buffer_type
& replace(const_iterator first
, const_iterator last
, const_iterator first2
, const_iterator last2
) { return buffer().replace(first
, last
, get_ptr(first2
), get_ptr(last2
)); }
188 /// Replaces the given range [first, last) with the input iterator with the given range [first2, last2) with the input reverse iterator
189 buffer_type
& replace(const_iterator first
, const_iterator last
, const_reverse_iterator first2
, const_reverse_iterator last2
)
191 size_type n
= static_cast<size_type
>(ptr_diff(first2
, last2
));
193 if(0 == n
) return buffer();
195 #if 0 // Maybe the buffer type is not owner of memory storage
197 std_copy(first2
, last2
, buf
.data());
198 buffer().replace(first
, last
, buf
.data(), n
);
200 pointer buf
= allocator().allocate(n
);
201 EXTL_ASSERT(NULL
!= buf
);
203 std_copy(first2
, last2
, buf
);
204 buffer().replace(first
, last
, buf
, n
);
206 allocator().deallocate(buf
);
211 #if defined(EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT)
212 /// Replaces the given range [first, last) with the input iterator with the given new buffer with new_n values
213 template < typename_param_k _InIt
>
214 buffer_type
& replace(const_iterator first
, const_iterator last
, _InIt first2
, _InIt last2
)
216 size_type n
= static_cast<size_type
>(std_distance(first2
, last2
));
218 if(0 == n
) return buffer();
220 #if 0 // Maybe the buffer type is not owner of memory storage
222 std_copy(first2
, last2
, buf
.data());
223 buffer().replace(first
, last
, buf
.data(), n
);
225 pointer buf
= allocator().allocate(n
);
226 EXTL_ASSERT(NULL
!= buf
);
228 std_copy(first2
, last2
, buf
);
229 buffer().replace(first
, last
, buf
, n
);
231 allocator().deallocate(buf
);
235 #endif /* EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT */
239 /// \name Assignments
242 /// Assigns from the given buffer
243 buffer_type
& assign(buffer_type
const& buf
) { return buffer().assign(buf
.data(), buf
.size(), 0); }
244 /// Assigns with n values from the given buffer at the specified position
245 buffer_type
& assign(buffer_type
const& buf
, size_type n
, size_type pos
= 0) { return buffer().assign(buf
.data(), n
, pos
); }
246 /// Assigns with n values from the given buffer at the specified position
247 buffer_type
& assign(const_pointer buf
, size_type n
, size_type pos
= 0) { return buffer().replace(0, buffer().size(), buf
+ pos
, n
); }
248 /// Assigns with n values
249 buffer_type
& assign(const_reference v
, size_type n
= 1) { return buffer().replace(0, buffer().size(), v
, n
); }
251 /// Assigns from range [first, last) with the const pointer iterator
252 buffer_type
& assign(const_pointer first
, const_pointer last
) { return buffer().assign(first
, last
- first
); }
253 /// Assigns from range [first, last) with the const input iterator
254 buffer_type
& assign(const_iterator first
, const_iterator last
) { return buffer().assign(get_ptr(first
), get_ptr(last
)); }
255 /// Assigns from range [first, last) with the const reverse input iterator
256 buffer_type
& assign(const_reverse_iterator first
, const_reverse_iterator last
) { return buffer().replace(buffer().begin(), buffer().end(), first
, last
); }
258 #if defined(EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT)
259 /// Assigns from range [first, last) with the input iterator
260 template < typename_param_k _InIt
>
261 buffer_type
& assign(_InIt first
, _InIt last
)
263 return buffer().replace(begin(), end(), first
, last
);
265 #endif /* EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT */
267 buffer_type
& operator=(buffer_type
const& buf
) { return buffer().assign(buf
, buf
.size()); }
268 buffer_type
& operator=(const_reference v
) { return buffer().assign(v
, 1); }
274 /// Appends from the given buffer
275 buffer_type
& append(buffer_type
const& buf
) { return buffer().append(buf
.data(), buf
.size(), 0); }
276 /// Appends with n values from the given buffer at the specified position
277 buffer_type
& append(buffer_type
const& buf
, size_type n
, size_type pos
= 0) { return buffer().append(buf
.data(), n
, pos
); }
278 /// Appends with n values from the given buffer at the specified position
279 buffer_type
& append(const_pointer buf
, size_type n
, size_type pos
= 0) { return buffer().replace(buffer().size(), 0, buf
+ pos
, n
); }
280 /// Appends with n values with the value v
281 buffer_type
& append(const_reference v
, size_type n
= 1) { return buffer().replace(buffer().size(), 0, v
, n
); }
283 /// Appends from range [first, last) with the const pointer
284 buffer_type
& append(const_pointer first
, const_pointer last
) { return buffer().append(first
, last
- first
, 0); }
285 /// Appends from range [first, last) with the const input iterator
286 buffer_type
& append(const_iterator first
, const_iterator last
) { return buffer().append(get_ptr(first
), get_ptr(last
)); }
287 /// Appends from range [first, last) with the const reverse input iterator
288 buffer_type
& append(const_reverse_iterator first
, const_reverse_iterator last
)
290 std_copy(first
, last
, extl_back_inserter(buffer()));
294 #if defined(EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT)
295 template < typename_param_k _InIt
>
296 buffer_type
& append(_InIt first
, _InIt last
) /* optimization */
298 std_copy(first
, last
, extl_back_inserter(buffer()));
301 #endif /* defined(EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT) */
304 buffer_type
& operator+=(buffer_type
const& buf
) { return buffer().append(buf
, buf
.size()); }
305 buffer_type
& operator+=(const_reference v
) { return buffer().append(v
, size_type(1)); }
308 void push_back(const_reference v
) { buffer().append(v
); }
309 void pop_back() { buffer().resize(buffer().size() - 1); }
312 /// \name Insertments
315 /// Inserts the given new buffer with new_n values into the given position *this[pos]
316 buffer_type
& insert(size_type pos
, const_pointer new_buf
, size_type new_n
) { return buffer().replace(pos
, 0, new_buf
, new_n
); }
317 /// Inserts the given new buffer into the given position *this[pos]
318 buffer_type
& insert(size_type pos
, buffer_type
const& new_buf
) { return buffer().insert(pos
, new_buf
.data(), new_buf
.size()); }
319 /// Inserts the given new buffer with new_n values into the given position *this[pos]
320 buffer_type
& insert(size_type pos
, buffer_type
const& new_buf
, size_type new_n
) { return buffer().insert(pos
, new_buf
.data(), new_n
); }
321 /// Inserts the given new_n value with the value new_value into the given position *this[pos]
322 buffer_type
& insert(size_type pos
, const_reference new_value
, size_type new_n
= 1) { return buffer().replace(pos
, 0, new_value
, new_n
); }
324 /// Inserts the given new buffer with new_n values into the given position *pos with the input iterator
325 buffer_type
& insert(const_iterator pos
, const_pointer new_buf
, size_type new_n
) { return buffer().insert(ptr_diff(buffer().begin(), pos
), new_buf
, new_n
); }
326 /// Inserts the given new buffer into the given position *pos with the input const_iterator
327 buffer_type
& insert(const_iterator pos
, buffer_type
const& new_buf
) { return buffer().insert(ptr_diff(buffer().begin(), pos
), new_buf
, new_buf
.size()); }
328 /// Inserts the given new buffer with new_n values into the given position *pos with the input const_iterator
329 buffer_type
& insert(const_iterator pos
, buffer_type
const& new_buf
, size_type new_n
) { return buffer().insert(ptr_diff(buffer().begin(), pos
), new_buf
, new_n
); }
330 /// Inserts the given new_n value with the value new_value into the given position *pos with the input const_iterator
331 buffer_type
& insert(const_iterator pos
, const_reference new_value
, size_type new_n
= 1) { return buffer().insert(ptr_diff(buffer().begin(), pos
), new_value
, new_n
); }
337 /// Erases the given range [pos, pos + n) from this
338 buffer_type
& erase(size_type pos
, size_type n
= 1);
339 /// Erases the given position *pos with the input iterator from this
340 buffer_type
& erase(const_iterator pos
) { return buffer().erase(ptr_diff(buffer().begin(), pos
), 1); }
341 /// Erases the given range [first, last) with the input iterator from this
342 buffer_type
& erase(const_iterator first
, const_iterator last
) { return buffer().erase(ptr_diff(buffer().begin(), first
), ptr_diff(first
, last
)); }
345 /// \name Reversement
348 /// Reverses the given range [first, last] of the buffer
349 buffer_type
& reverse(const_iterator first
, const_iterator last
) { return buffer().replace(first
, last
, const_reverse_iterator(last
), const_reverse_iterator(first
)); }
350 /// Reverses the given range [pos, pos + n] of the buffer
351 buffer_type
& reverse(size_type pos
, size_type n
) { return buffer().reverse(buffer().begin() + pos
, buffer().begin() + pos
+ n
); }
352 /// Reverses the whole buffer
353 buffer_type
& reverse() { return reverse(0, buffer().size()); }
359 /// Returns the difference between two pointers, last >= first
360 size_type
ptr_diff(const_pointer first
, const_pointer last
) const { EXTL_ASSERT(first
<= last
); return last
- first
; }
361 /// Returns the difference between two iterators, last >= first
362 size_type
ptr_diff(const_iterator
const& first
, const_iterator
const& last
) const { EXTL_ASSERT(first
<= last
); return last
- first
; }
363 /// Returns the difference between two reverse iterators, rfirst >= rlast
364 size_type
ptr_diff(const_reverse_iterator
const& rfirst
, const_reverse_iterator
const& rlast
) const { EXTL_ASSERT(rfirst
<= rlast
); return rlast
- rfirst
; }
366 /// Returns the derived class
367 buffer_type
const& buffer() const { return reinterpret_cast<buffer_type
const&>(*this); }
368 /// Returns the derived class
369 buffer_type
& buffer() { return reinterpret_cast<buffer_type
&>(*this); }
371 /// Returns the const pointer of the given the const pointer iterator
372 const_pointer
get_ptr(const_iterator
const& it
) const { return it
.current(); }
376 /* ///////////////////////////////////////////////////////////////////////
380 /* Template declaration */
381 #ifdef EXTL_BUFFER_BASE_TEMPLATE_DECL
382 # undef EXTL_BUFFER_BASE_TEMPLATE_DECL
385 #define EXTL_BUFFER_BASE_TEMPLATE_DECL \
386 template< typename_param_k B \
387 , typename_param_k A \
388 , typename_param_k M \
391 /* Class qualification */
392 #ifdef EXTL_BUFFER_BASE_QUAL
393 # undef EXTL_BUFFER_BASE_QUAL
396 #define EXTL_BUFFER_BASE_QUAL buffer_base<B, A, M>
398 /* Class qualification */
399 #ifdef EXTL_BUFFER_BASE_RET_QUAL
400 # undef EXTL_BUFFER_BASE_RET_QUAL
403 #define EXTL_BUFFER_BASE_RET_QUAL(ret_type) \
404 typename_type_ret_k EXTL_BUFFER_BASE_QUAL::ret_type \
405 EXTL_BUFFER_BASE_QUAL
407 /* ///////////////////////////////////////////////////////////////////////
411 /* Replaces the given range [*this[pos], *this[pos + old_n]) to the given new c-style buffer with new_n characters */
412 EXTL_BUFFER_BASE_TEMPLATE_DECL
413 inline EXTL_BUFFER_BASE_RET_QUAL(buffer_type
&)::replace(size_type pos
, size_type old_n
, const_pointer new_buf
, size_type new_n
)
415 EXTL_ASSERT(buffer().is_valid());
416 if (NULL
== new_buf
) return buffer();
417 if (!(0 < new_n
|| 0 < old_n
)) return buffer();
419 size_type size
= buffer().size();
420 EXTL_MESSAGE_ASSERT(!(size
< pos
), "out of range");
421 EXTL_ASSERT_THROW(!(size
< pos
), index_error("out of range"));
423 if (size
- pos
< old_n
) old_n
= size
- pos
;
424 EXTL_MESSAGE_ASSERT(!(max_size() < size
- old_n
+ new_n
), "result buffer is too long");
425 EXTL_ASSERT_THROW(!(max_size() < size
- old_n
+ new_n
), std_length_error("result buffer is too long"));
428 * data: |-------------------------------|||||||||||||||||||
429 * old_buf: |------------------------|
430 * tail: |||||||||||||||||||
432 size_type tail_n
= size
- pos
- old_n
;
434 /* Calculates the new size of the replaced buffer */
435 size_type new_size
= size
+ (new_n
- old_n
);
436 EXTL_ASSERT(new_size
> 0);
437 if (new_size
<= 0) return buffer();
439 /* resize the size of buffer */
440 buffer().resize(new_size
);
442 /* resize() maybe change the pointer to the buffer and size */
443 pointer data
= buffer().data();
444 size
= buffer().size();
445 EXTL_ASSERT(NULL
!= data
);
447 /* new_buf has no overlap with the data */
448 if (new_buf
< data
|| data
+ size
<= new_buf
)
451 memory_traits_type::move(data
+ pos
+ new_n
, data
+ pos
+ old_n
, tail_n
);
454 memory_traits_type::copy(data
+ pos
, new_buf
, new_n
);
456 else /* new_buf is the subbuffer of this, replace carefully
457 * std::replace of VC 6.0 exist bugs
460 if (new_n
<= old_n
) /* The hole is not large, only copy in subbuffer */
462 /* data: |--------------------------------------||||||||||||
463 * old_buf: |-------------------------------|
464 * new_buf: |==========|
468 * data: |------==========----------------------||||||||||||
469 * old_buf: |-------------------------------|
470 * new_buf: |==========|
474 * data: |------==========||||||||||||
475 * old_buf: |-------------------------------|
476 * new_buf: |==========|
480 memory_traits_type::move(data
+ pos
, new_buf
, new_n
);
482 memory_traits_type::move(data
+ pos
+ new_n
, data
+ pos
+ old_n
, tail_n
);
484 else if (new_buf
<= data
+ pos
)
486 /*if (new_buf + new_n >= data + pos + old_n)
488 /* data: |------------------------|||||||||||||||||||||||||||
489 * old_buf: |--------|
490 * new_buf: |========//////////////////////|
494 * data: |------------------------ |||||||||||||||||||||||||||
495 * old_buf: |--------|
496 * old_new_buf: |========//////////////////////|
497 * new_new_buf: |========///////////// /////////|
501 * data: |--------------=========/////////////////////|||||||||||||||||||||||||||
502 * old_buf: |--------|
503 * old_new_buf: |========//////////////////////|
504 * new_new_buf: |========///////////// /////////|
508 /*memory_traits_type::move(data + pos + new_n, data + pos + old_n, tail_n);*/
510 /*size_type new_head_n = pos + old_n - (new_buf - data);*/ /* |========///////////// */
511 /*memory_traits_type::move(data + pos, new_buf, new_head_n);*/
512 /*memory_traits_type::move(data + pos + new_head_n, new_buf + new_head_n + new_n - old_n, new_n - new_head_n);*/
517 /* data: |------------------------|||||||||||||||||||||||||||
518 * old_buf: |--------|
519 * new_buf: |========////////|
523 * data: |------------------------ |||||||||||||||||||||||||||
524 * old_buf: |--------|
525 * old_new_buf: |========//////////////////////|
526 * new_new_buf: |========////////|
530 * data: |--------------=========/////////////|||||||||||||||||||||||||||
531 * old_buf: |--------|
532 * old_new_buf: |========//////////////////////|
533 * new_new_buf: |========////////|
537 memory_traits_type::move(data
+ pos
+ new_n
, data
+ pos
+ old_n
, tail_n
);
539 memory_traits_type::move(data
+ pos
, new_buf
, new_n
);
542 else if (data
+ pos
+ old_n
<= new_buf
)
544 /* data: |-----------|||||||||||||||||||||||||||||||||||||||
546 * new_buf: |========//////////////////////|
550 * data: |----------- |||||||||||||||||||||||||||||||||||||||
552 * old_new_buf: |========//////////////////////|
553 * new_new_buf: |========//////////////////////|
557 * data: |--========//////////////////////|||||||||||||||||||||||||||||||||||||||
559 * old_new_buf: |========//////////////////////|
560 * new_new_buf: |========//////////////////////|
564 memory_traits_type::move(data
+ pos
+ new_n
, data
+ pos
+ old_n
, tail_n
);
566 memory_traits_type::move(data
+ pos
, new_buf
+ (new_n
- old_n
), new_n
);
570 /* data: |-------------------|||||||||||||||||||||||||||||||
572 * new_buf: |=======//////////////////|
576 * data: |----------=========|||||||||||||||||||||||||||||||
578 * new_buf: |=======//////////////////|
582 * data: |----------========= ||||||||||||||||||||||||||||||||
584 * old_new_buf: |=======//////////////////|
585 * new_new_buf: |==== ===//////////////////|
588 /* fill rest of new hole
589 * data: |----------=========//////////////////||||||||||||||||||||||||||||||||
591 * old_new_buf: |=======//////////////////|
592 * new_new_buf: |==== ===//////////////////|
597 memory_traits_type::move(data
+ pos
, new_buf
, old_n
);
599 memory_traits_type::move(data
+ pos
+ new_n
, data
+ pos
+ old_n
, tail_n
);
600 /* fill rest of new hole */
601 memory_traits_type::move(data
+ pos
+ old_n
, new_buf
+ (new_n
) /* Note: not old_n */
606 EXTL_ASSERT(buffer().is_valid());
610 /* Replaces the given range [*this[pos], *this[pos + old_n]) to the given new_n value with the value new_value */
611 EXTL_BUFFER_BASE_TEMPLATE_DECL
612 inline EXTL_BUFFER_BASE_RET_QUAL(buffer_type
&)::replace(size_type pos
, size_type old_n
, const_reference new_value
, size_type new_n
)
614 EXTL_ASSERT(buffer().is_valid());
615 if (0 == new_n
) return buffer();
616 if (!(0 < new_n
|| 0 < old_n
)) return buffer();
618 size_type size
= buffer().size();
619 EXTL_MESSAGE_ASSERT(!(size
< pos
), "out of range");
620 EXTL_ASSERT_THROW(!(size
< pos
), index_error("out of range"));
622 if (size
- pos
< old_n
) old_n
= size
- pos
;
623 EXTL_MESSAGE_ASSERT(!(max_size() < size
- old_n
+ new_n
), "result buffer is too long");
624 EXTL_ASSERT_THROW(!(max_size() < size
- old_n
+ new_n
), std_length_error("result buffer is too long"));
626 /* the length of tail
627 * data: |-------------------------------|||||||||||||||||||
628 * old_str: |------------------------|
629 * tail: |||||||||||||||||||
631 size_type tail_n
= size
- pos
- old_n
;
633 /* Calculates the new size of the replaced buffer */
634 size_type new_size
= size
+ (new_n
- old_n
);
635 EXTL_ASSERT(new_size
> 0);
636 if (new_size
<= 0) return buffer();
638 /* resize the size of buffer */
639 buffer().resize(new_size
);
641 /* resize() maybe change the pointer to the buffer and size */
642 pointer data
= buffer().data();
643 size
= buffer().size();
644 EXTL_ASSERT(NULL
!= data
);
649 memory_traits_type::move(data
+ pos
+ new_n
, data
+ pos
+ old_n
, tail_n
);
653 memory_traits_type::fill(data
+ pos
, new_value
, new_n
);
655 EXTL_ASSERT(buffer().is_valid());
659 /* Erases the given range [*this[pos], *this[pos + n]) from this */
660 EXTL_BUFFER_BASE_TEMPLATE_DECL
661 inline EXTL_BUFFER_BASE_RET_QUAL(buffer_type
&)::erase(size_type pos
, size_type n
)
663 if (n
<= 0) return buffer();
664 EXTL_ASSERT(buffer().is_valid());
666 size_type size
= buffer().size();
667 pointer data
= buffer().data();
668 EXTL_ASSERT(NULL
!= data
);
669 if(NULL
== data
) return buffer();
671 if (size
- pos
< n
) n
= size
- pos
;
673 EXTL_MESSAGE_ASSERT(!(size
< pos
), "out of range");
674 EXTL_ASSERT_THROW(!(size
< pos
), index_error("out of range"));
676 memory_traits_type::move(data
+ pos
, data
+ pos
+ n
, size
- pos
- n
);
677 buffer().resize(size
- n
);
679 EXTL_ASSERT(buffer().is_valid());
682 /* /////////////////////////////////////////////////////////////////////////
685 EXTL_BUFFER_BASE_TEMPLATE_DECL
686 EXTL_INLINE
void swap(EXTL_BUFFER_BASE_QUAL
& lhs
, EXTL_BUFFER_BASE_QUAL
& rhs
)
688 static_cast<B
&>(lhs
).swap(static_cast<B
&>(rhs
));
690 /* /////////////////////////////////////////////////////////////////////////
693 EXTL_BUFFER_BASE_TEMPLATE_DECL
694 EXTL_INLINE typename_type_ret_k
EXTL_BUFFER_BASE_QUAL::
695 const_pointer
get_ptr(EXTL_BUFFER_BASE_QUAL
const& p
)
697 return static_cast<B
const&>(p
).data();
700 EXTL_BUFFER_BASE_TEMPLATE_DECL
701 EXTL_INLINE typename_type_ret_k
EXTL_BUFFER_BASE_QUAL::
702 size_type
get_size(EXTL_BUFFER_BASE_QUAL
const& p
)
704 return static_cast<B
const&>(p
).size();
706 /* //////////////////////////////////////////////////////////////////// */
707 #undef EXTL_BUFFER_BASE_TEMPLATE_DECL
708 #undef EXTL_BUFFER_BASE_QUAL
709 #undef EXTL_BUFFER_BASE_RET_QUAL
711 /* ///////////////////////////////////////////////////////////////////////
716 /* ///////////////////////////////////////////////////////////////////////
719 #if !defined(EXTL_NO_STL) && \
720 !defined(EXTL_NO_NAMESPACE)
721 /* ::std namespace */
722 EXTL_STD_BEGIN_NAMESPACE
724 template< typename_param_k B
728 EXTL_INLINE
void swap(EXTL_NS(buffer_base
)<B
, A
, M
>& lhs
,
729 EXTL_NS(buffer_base
)<B
, A
, M
>& rhs
)
731 static_cast<B
&>(lhs
).swap(static_cast<B
&>(rhs
));
733 /* ::std namespace */
734 EXTL_STD_END_NAMESPACE
737 /* //////////////////////////////////////////////////////////////////// */
738 #endif /* EXTL_MEMORY_BUFFER_BASE_H */
739 /* //////////////////////////////////////////////////////////////////// */