00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #ifndef STLSOFT_INCL_H_STLSOFT
00060 # include "stlsoft.h"
00061 #endif
00062 #ifdef _STLSOFT_AUTO_BUFFER_ALLOW_UDT
00063 # define _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
00064 # ifdef _STLSOFT_COMPILE_VERBOSE
00065 # pragma message("_STLSOFT_AUTO_BUFFER_ALLOW_UDT is deprecated. Use _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD instead")
00066 # endif
00067 #endif
00068 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00069 # ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00070 # include "stlsoft_iterator.h"
00071 # endif
00072 #endif
00073 #ifndef _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
00074 # ifndef STLSOFT_INCL_H_CONSTRAINTS
00075 # include "stlsoft_constraints.h"
00076 # endif
00077 #endif
00078 #ifndef STLSOFT_INCL_H_STLSOFT_SIMPLE_ALGORITHMS
00079 # include "stlsoft_simple_algorithms.h"
00080 #endif
00081 #ifdef STLSOFT_UNITTEST
00082 # ifndef STLSOFT_INCL_H_STLSOFT_NEW_ALLOCATOR
00083 # include "stlsoft_new_allocator.h"
00084 # endif
00085 # include <numeric>
00086 #endif
00087
00088
00089
00090
00091
00092 #ifndef _STLSOFT_NO_NAMESPACE
00093 namespace stlsoft
00094 {
00095 #endif
00096
00097
00098
00099
00100
00101
00102
00118
00119 template< ss_typename_param_k T
00120 , ss_typename_param_k A
00121 #ifdef __STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT
00122 # if !defined(__STLSOFT_COMPILER_IS_BORLAND) || \
00123 __BORLANDC__ < 0x0551
00124 , ss_size_t SPACE = 256
00125 # else
00126 , ss_size_t space = 256
00127 # endif
00128 #else
00129 # if !defined(__STLSOFT_COMPILER_IS_BORLAND) || \
00130 __BORLANDC__ < 0x0551
00131 , ss_size_t SPACE
00132 # else
00133 , ss_size_t space
00134 # endif
00135 #endif
00136 >
00137 class auto_buffer
00138 #if !defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
00139 : protected A
00140 #endif
00141 {
00143
00144 public:
00146 typedef T value_type;
00148 typedef A allocator_type;
00149 #if !defined(__STLSOFT_COMPILER_IS_BORLAND) || \
00150 __BORLANDC__ < 0x0551
00151 enum
00152 {
00154 space = SPACE
00155 };
00156 #endif
00157
00158 typedef auto_buffer<T, A, space> class_type;
00160 typedef ss_typename_type_k allocator_type::reference reference;
00162 typedef ss_typename_type_k allocator_type::const_reference const_reference;
00164 typedef ss_typename_type_k allocator_type::pointer pointer;
00166 typedef ss_typename_type_k allocator_type::const_pointer const_pointer;
00168 typedef ss_size_t size_type;
00170 typedef ss_ptrdiff_t difference_type;
00171 #if !defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00172
00173 typedef value_type *iterator;
00175 typedef value_type const *const_iterator;
00176 #else
00177
00178 typedef
00179 # if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00180 ss_typename_type_k
00181 # endif
00182 pointer_iterator < value_type
00183 , pointer
00184 , reference
00185 >::iterator_type iterator;
00187 typedef
00188 # if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00189 ss_typename_type_k
00190 # endif
00191 pointer_iterator < value_type const
00192 , const_pointer
00193 , const_reference
00194 >::iterator_type const_iterator;
00195
00197 typedef reverse_iterator_base < iterator
00198 , value_type
00199 , reference
00200 , pointer
00201 , difference_type
00202 > reverse_iterator;
00203
00205 typedef const_reverse_iterator_base < const_iterator
00206 , value_type const
00207 , const_reference
00208 , const_pointer
00209 , difference_type
00210 > const_reverse_iterator;
00211 #endif
00212
00213
00215
00216 private:
00217 pointer allocate_(size_type cItems, void *hint)
00218 {
00219 #ifdef __STLSOFT_CF_ALLOCATOR_ALLOCATE_HAS_HINT
00220 return get_allocator().allocate(cItems, hint);
00221 #else
00222 STLSOFT_SUPPRESS_UNUSED(hint);
00223
00224 return get_allocator().allocate(cItems);
00225 #endif
00226 }
00227
00228 pointer allocate_(size_type cItems)
00229 {
00230 #ifdef __STLSOFT_CF_ALLOCATOR_ALLOCATE_HAS_HINT
00231 return get_allocator().allocate(cItems, NULL);
00232 #else
00233 return get_allocator().allocate(cItems);
00234 #endif
00235 }
00236
00237 void deallocate_(pointer p, size_type cItems)
00238 {
00239 stlsoft_assert(NULL != p);
00240
00241 #ifdef __STLSOFT_CF_ALLOCATOR_DEALLOCATE_HAS_OBJECTCOUNT
00242 get_allocator().deallocate(p, cItems);
00243 #else
00244 STLSOFT_SUPPRESS_UNUSED(cItems);
00245
00246 get_allocator().deallocate(p);
00247 #endif
00248 }
00249
00250 pointer reallocate_(pointer p, size_type cItems, size_type cNewItems)
00251 {
00252 pointer new_p = allocate_(cNewItems, p);
00253
00254
00255
00256 if(NULL != new_p)
00257 {
00258 block_copy(new_p, p, cItems);
00259
00260 deallocate_(p, cItems);
00261 }
00262
00263 return new_p;
00264 }
00265 protected:
00266 static void block_copy(pointer dest, const_pointer src, size_type cItems)
00267 {
00268 pod_copy_n(dest, src, cItems);
00269 }
00270 static void block_set(pointer dest, size_type cItems, const_reference value)
00271 {
00272 pod_fill_n(dest, cItems, value);
00273 }
00275
00277
00278 public:
00289 ss_explicit_k auto_buffer(size_type cItems)
00290 : m_buffer((space < cItems) ? allocate_(cItems) : const_cast<pointer>(&m_internal[0]))
00291 , m_cItems((NULL != m_buffer) ? cItems : 0)
00292 {
00293
00294
00295
00296 stlsoft_static_assert(0 != space);
00297
00298
00299
00300
00301
00302 stlsoft_static_assert(stlsoft_raw_offsetof(class_type, m_buffer) < stlsoft_raw_offsetof(class_type, m_cItems));
00303 #if defined(__STLSOFT_COMPILER_IS_WATCOM)
00304 stlsoft_assert(stlsoft_raw_offsetof(class_type, m_buffer) < stlsoft_raw_offsetof(class_type, m_cItems));
00305 #else
00306 stlsoft_message_assert("m_buffer must be before m_cItems in the auto_buffer definition", stlsoft_raw_offsetof(class_type, m_buffer) < stlsoft_raw_offsetof(class_type, m_cItems));
00307 #endif
00308
00309 #ifndef _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
00310
00311
00312
00313
00314
00315
00316
00317 stlsoft_constraint_must_be_pod(value_type);
00318 #endif
00319 }
00325 #if defined(__STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT)
00326 ~auto_buffer()
00327 #else
00328 ~auto_buffer() stlsoft_throw_0()
00329 #endif
00330 {
00331 if(space < m_cItems)
00332 {
00333 stlsoft_assert(NULL != m_buffer);
00334
00335 deallocate_(m_buffer, m_cItems);
00336 }
00337 }
00339
00341
00342 public:
00355 ss_bool_t resize(size_type cItems)
00356 {
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 if(m_cItems < cItems)
00367 {
00368
00369
00370 if(space < m_cItems)
00371 {
00372
00373 pointer new_buffer = reallocate_(m_buffer, m_cItems, cItems);
00374
00375
00376
00377 if(NULL == new_buffer)
00378 {
00379 return false;
00380 }
00381
00382
00383 m_buffer = new_buffer;
00384 }
00385 else
00386 {
00387
00388
00389 if(space < cItems)
00390 {
00391
00392
00393 pointer new_buffer = allocate_(cItems);
00394
00395
00396
00397 if(NULL == new_buffer)
00398 {
00399 return false;
00400 }
00401
00402 if(0 != m_cItems)
00403 {
00404 block_copy(new_buffer, m_buffer, m_cItems);
00405 }
00406 m_buffer = new_buffer;
00407 }
00408 else
00409 {
00410
00411
00412
00413 stlsoft_assert(!(space < cItems));
00414 }
00415 }
00416 }
00417 else
00418 {
00419
00420
00421 if(space < m_cItems)
00422 {
00423
00424
00425 if(space < cItems)
00426 {
00427
00428
00429
00430 stlsoft_assert(space < cItems);
00431 }
00432 else
00433 {
00434
00435
00436 if(0 != cItems)
00437 {
00438 block_copy(const_cast<pointer>(&m_internal[0]), m_buffer, cItems);
00439 }
00440
00441 deallocate_(m_buffer, m_cItems);
00442
00443 m_buffer = const_cast<pointer>(&m_internal[0]);
00444 }
00445 }
00446 else
00447 {
00448
00449
00450
00451 stlsoft_assert(!(space < cItems));
00452 }
00453 }
00454
00455 m_cItems = cItems;
00456
00457 return true;
00458 }
00459
00465 void swap(class_type &rhs)
00466 {
00467 if( space < m_cItems &&
00468 space < rhs.m_cItems)
00469 {
00470
00471 swap_(m_buffer, rhs.m_buffer);
00472 }
00473 else if(space < m_cItems)
00474 {
00475
00476
00477
00478 block_copy(&m_internal[0], &rhs.m_internal[0], rhs.m_cItems);
00479
00480
00481 rhs.m_buffer = m_buffer;
00482
00483
00484 m_buffer = &m_internal[0];
00485 }
00486 else if(space < rhs.m_cItems)
00487 {
00488
00489 rhs.swap(*this);
00490
00491 return;
00492 }
00493 else
00494 {
00495
00496 value_type t[space];
00497
00498 block_copy(&t[0], &rhs.m_internal[0], rhs.m_cItems);
00499 block_copy(&rhs.m_internal[0], &m_internal[0], m_cItems);
00500 block_copy(&m_internal[0], &t[0], rhs.m_cItems);
00501 }
00502
00503 swap_(m_cItems, rhs.m_cItems);
00504 }
00506
00508
00509 public:
00510
00511
00512
00513
00514
00515
00517 operator pointer ()
00518 {
00519 return m_buffer;
00520 }
00521
00522 #ifdef _STLSOFT_AUTO_BUFFER_ALLOW_CONST_CONVERSION_OPERATOR
00523
00524 operator const_pointer () const
00525 {
00526 return m_buffer;
00527 }
00528 #endif
00529
00530
00533 public:
00535 pointer data()
00536 {
00537 return m_buffer;
00538 }
00540 const_pointer data() const
00541 {
00542 return m_buffer;
00543 }
00545
00547
00548 public:
00550 const_iterator begin() const
00551 {
00552 return m_buffer;
00553 }
00561 const_iterator end() const
00562 {
00563 return m_buffer + m_cItems;
00564 }
00565
00567 iterator begin()
00568 {
00569 return m_buffer;
00570 }
00578 iterator end()
00579 {
00580 return m_buffer + m_cItems;
00581 }
00582
00583 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00587 const_reverse_iterator rbegin() const
00588 {
00589 return const_reverse_iterator(end());
00590 }
00594 const_reverse_iterator rend() const
00595 {
00596 return const_reverse_iterator(begin());
00597 }
00601 reverse_iterator rbegin()
00602 {
00603 return reverse_iterator(end());
00604 }
00608 reverse_iterator rend()
00609 {
00610 return reverse_iterator(begin());
00611 }
00612 #endif
00613
00615
00617
00618 public:
00626 size_type size() const
00627 {
00628 return m_cItems;
00629 }
00630
00632 static size_type internal_size()
00633 {
00634 return space;
00635 }
00636
00641 ss_bool_t empty() const
00642 {
00643 return 0 == m_cItems;
00644 }
00645
00646 #if defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
00647 static allocator_type &get_allocator()
00648 {
00649 static allocator_type s_allocator;
00650
00651 return s_allocator;
00652 }
00653 #else
00654 allocator_type get_allocator() const
00655 {
00656 return *this;
00657 }
00658 #endif
00659
00661
00663
00664 private:
00665 pointer m_buffer;
00666 size_type m_cItems;
00667 value_type m_internal[space];
00669
00670
00671 private:
00672 auto_buffer(class_type const &rhs);
00673 auto_buffer const &operator =(class_type const &rhs);
00674 };
00675
00676
00677
00678
00679
00680 #ifndef __STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED
00681
00682 template< ss_typename_param_k T
00683 , ss_typename_param_k A
00684 , ss_size_t SPACE
00685 >
00686 inline ss_bool_t is_empty(auto_buffer<T, A, SPACE> const &b)
00687 {
00688 return b.empty();
00689 }
00690
00691 #endif
00692
00694
00695
00696 #ifdef STLSOFT_UNITTEST
00697
00698 namespace unittest
00699 {
00700 ss_bool_t test_stlsoft_auto_buffer(unittest_reporter *r)
00701 {
00702 ss_bool_t bSuccess = true;
00703
00704 unittest_initialiser init(r, "STLSoft", "auto_buffer", __FILE__);
00705
00706 typedef auto_buffer<int, new_allocator<int>, 16> buffer_t;
00707
00708 buffer_t buffer1(10);
00709 buffer_t buffer2(100);
00710
00711
00712
00713
00714 int *pi = buffer1.data();
00715
00716 for(ss_size_t c = 1; bSuccess && c < buffer1.internal_size(); ++c)
00717 {
00718 buffer1.resize(c);
00719
00720 if(pi != buffer1.data())
00721 {
00722 r->report("auto_buffer resize not allocated from internal buffer: failed ", __LINE__);
00723 bSuccess = false;
00724 }
00725 }
00726
00727 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00728
00729 int total_forward = stlsoft_ns_qual_std(accumulate)(buffer2.begin(), buffer2.end(), 0);
00730 int total_backward = stlsoft_ns_qual_std(accumulate)(buffer2.rbegin(), buffer2.rend(), 0);
00731
00732 if(total_forward != total_backward)
00733 {
00734 r->report("Forward and backward enumeration equivalence failed ", __LINE__);
00735 bSuccess = false;
00736 }
00737 #endif
00738
00739 return bSuccess;
00740 }
00741
00742 unittest_registrar unittest_stlsoft_auto_buffer(test_stlsoft_auto_buffer);
00743
00744 }
00745
00746 #endif
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758