remove \r
[extl.git] / extl / memory / buffer_base.h
blobc42e98bb1ac34680e5dd1cce3d0a56632474f2ae
1 /* ///////////////////////////////////////////////////////////////////////
2 * File: buffer_base.h
4 * Created: 08.05.26
5 * Updated: 08.05.27
7 * Brief: Memory buffer base class
9 * [<Home>]
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
20 #ifndef __cplusplus
21 # error buffer_base.h need be supported by c++.
22 #endif
24 /* ///////////////////////////////////////////////////////////////////////
25 * Includes
27 #include "../iterator/iterator.h"
28 #include "../algorithm/algorithm.h"
29 #include "../error/error.h"
30 #include "pod_memory_traits.h"
32 /* ///////////////////////////////////////////////////////////////////////
33 * ::extl namespace
35 EXTL_BEGIN_NAMESPACE
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
44 , typename_param_k A
45 , typename_param_k M
47 class buffer_base
48 #ifdef EXTL_EBO_FORM_2_SUPPORT
49 : protected A /* if EBO is supported */
50 #endif
52 /// \name Types
53 /// @{
54 public:
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;
73 /// @}
75 /// \name Iterators
76 /// @{
77 public:
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()); }
89 /// @}
91 /// \name Accessors
92 /// @{
93 public:
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); }
130 /// @}
132 /// \name Others
133 /// @{
134 public:
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()); }
147 public:
148 /// Returns the allocator
149 allocator_type allocator() const
151 #ifdef EXTL_EBO_FORM_2_SUPPORT
152 return *this;
153 #else
154 return allocator_type();
155 #endif
157 /// @}
159 /// \name Replacements
160 /// @{
161 public:
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));
192 EXTL_ASSERT(0 != n);
193 if(0 == n) return buffer();
195 #if 0 // Maybe the buffer type is not owner of memory storage
196 buffer_type buf(n);
197 std_copy(first2, last2, buf.data());
198 buffer().replace(first, last, buf.data(), n);
199 #else
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);
207 #endif
208 return buffer();
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));
217 EXTL_ASSERT(0 != n);
218 if(0 == n) return buffer();
220 #if 0 // Maybe the buffer type is not owner of memory storage
221 buffer_type buf(n);
222 std_copy(first2, last2, buf.data());
223 buffer().replace(first, last, buf.data(), n);
224 #else
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);
232 #endif
233 return buffer();
235 #endif /* EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT */
237 /// @}
239 /// \name Assignments
240 /// @{
241 public:
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); }
269 /// @}
271 /// \name Appending
272 /// @{
273 public:
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()));
291 return 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()));
299 return buffer();
301 #endif /* defined(EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT) */
303 public:
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)); }
307 public:
308 void push_back(const_reference v) { buffer().append(v); }
309 void pop_back() { buffer().resize(buffer().size() - 1); }
310 /// @}
312 /// \name Insertments
313 /// @{
314 public:
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); }
332 /// @}
334 /// \name Erasements
335 /// @{
336 public:
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)); }
343 /// @}
345 /// \name Reversement
346 /// @{
347 public:
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()); }
354 /// @}
356 /// \name Helpers
357 /// @{
358 private:
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(); }
373 /// @}
376 /* ///////////////////////////////////////////////////////////////////////
377 * Macro
380 /* Template declaration */
381 #ifdef EXTL_BUFFER_BASE_TEMPLATE_DECL
382 # undef EXTL_BUFFER_BASE_TEMPLATE_DECL
383 #endif
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
394 #endif
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
401 #endif
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 /* ///////////////////////////////////////////////////////////////////////
408 * Class implemention
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"));
427 /* the size of tail
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)
450 /* move tail */
451 memory_traits_type::move(data + pos + new_n, data + pos + old_n, tail_n);
453 /* fill hole */
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: |==========|
467 /* fill hole
468 * data: |------==========----------------------||||||||||||
469 * old_buf: |-------------------------------|
470 * new_buf: |==========|
473 /* move tail
474 * data: |------==========||||||||||||
475 * old_buf: |-------------------------------|
476 * new_buf: |==========|
479 /* fill hole */
480 memory_traits_type::move(data + pos, new_buf, new_n);
481 /* move tail */
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: |========//////////////////////|
493 /* move tail
494 * data: |------------------------ |||||||||||||||||||||||||||
495 * old_buf: |--------|
496 * old_new_buf: |========//////////////////////|
497 * new_new_buf: |========///////////// /////////|
500 /* fill hole
501 * data: |--------------=========/////////////////////|||||||||||||||||||||||||||
502 * old_buf: |--------|
503 * old_new_buf: |========//////////////////////|
504 * new_new_buf: |========///////////// /////////|
507 /* move tail */
508 /*memory_traits_type::move(data + pos + new_n, data + pos + old_n, tail_n);*/
509 /* fill hole */
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);*/
515 else
517 /* data: |------------------------|||||||||||||||||||||||||||
518 * old_buf: |--------|
519 * new_buf: |========////////|
522 /* move tail
523 * data: |------------------------ |||||||||||||||||||||||||||
524 * old_buf: |--------|
525 * old_new_buf: |========//////////////////////|
526 * new_new_buf: |========////////|
529 /* fill hole
530 * data: |--------------=========/////////////|||||||||||||||||||||||||||
531 * old_buf: |--------|
532 * old_new_buf: |========//////////////////////|
533 * new_new_buf: |========////////|
536 /* move tail */
537 memory_traits_type::move(data + pos + new_n, data + pos + old_n, tail_n);
538 /* fill hole */
539 memory_traits_type::move(data + pos, new_buf, new_n);
540 /*}*/
542 else if (data + pos + old_n <= new_buf)
544 /* data: |-----------|||||||||||||||||||||||||||||||||||||||
545 * old_buf: |-------|
546 * new_buf: |========//////////////////////|
549 /* move tail
550 * data: |----------- |||||||||||||||||||||||||||||||||||||||
551 * old_buf: |-------|
552 * old_new_buf: |========//////////////////////|
553 * new_new_buf: |========//////////////////////|
556 /* fill hole
557 * data: |--========//////////////////////|||||||||||||||||||||||||||||||||||||||
558 * old_buf: |-------|
559 * old_new_buf: |========//////////////////////|
560 * new_new_buf: |========//////////////////////|
563 /* move tail */
564 memory_traits_type::move(data + pos + new_n, data + pos + old_n, tail_n);
565 /* fill hole */
566 memory_traits_type::move(data + pos, new_buf + (new_n - old_n), new_n);
568 else
570 /* data: |-------------------|||||||||||||||||||||||||||||||
571 * old_buf: |-------|
572 * new_buf: |=======//////////////////|
575 /* fill old hole
576 * data: |----------=========|||||||||||||||||||||||||||||||
577 * old_buf: |-------|
578 * new_buf: |=======//////////////////|
581 /* move tail
582 * data: |----------========= ||||||||||||||||||||||||||||||||
583 * old_buf: |-------|
584 * old_new_buf: |=======//////////////////|
585 * new_new_buf: |==== ===//////////////////|
588 /* fill rest of new hole
589 * data: |----------=========//////////////////||||||||||||||||||||||||||||||||
590 * old_buf: |-------|
591 * old_new_buf: |=======//////////////////|
592 * new_new_buf: |==== ===//////////////////|
596 /* fill old hole */
597 memory_traits_type::move(data + pos, new_buf, old_n);
598 /* move tail */
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 */
602 , new_n - old_n);
606 EXTL_ASSERT(buffer().is_valid());
608 return buffer();
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);
646 if (old_n < new_n)
648 /* move tail */
649 memory_traits_type::move(data + pos + new_n, data + pos + old_n, tail_n);
652 /* fill hole */
653 memory_traits_type::fill(data + pos, new_value, new_n);
655 EXTL_ASSERT(buffer().is_valid());
656 return buffer();
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());
680 return buffer();
682 /* /////////////////////////////////////////////////////////////////////////
683 * swapping
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 /* /////////////////////////////////////////////////////////////////////////
691 * shims
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 /* ///////////////////////////////////////////////////////////////////////
712 * ::extl namespace
714 EXTL_END_NAMESPACE
716 /* ///////////////////////////////////////////////////////////////////////
717 * std::swap
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
725 , typename_param_k A
726 , typename_param_k M
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
735 #endif
737 /* //////////////////////////////////////////////////////////////////// */
738 #endif /* EXTL_MEMORY_BUFFER_BASE_H */
739 /* //////////////////////////////////////////////////////////////////// */