00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00034
00035
00036 #ifndef _TSTATICARRAY_H_
00037 #define _TSTATICARRAY_H_
00038
00039 #include "Mbo.h"
00040
00041 #if defined(_MSC_VER)
00042 # pragma warning(push)
00043 # pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
00044 #endif
00045
00046 namespace mbo
00047 {
00048
00059 #ifndef MBO_TSA_VERIFY
00060 # define MBO_TSA_VERIFY 1
00061 #endif
00062
00071 #ifndef MBO_TSA_STL_ITERATOR
00072 # define MBO_TSA_STL_ITERATOR 1
00073 #endif
00074
00080 #if MBO_TSA_VERIFY
00081 # define mbo_tsa_throw_if_not(exception, condition) mbo_throw_if_not(exception, condition)
00082 #else
00083 # define mbo_tsa_throw_if_not(exception, condition)
00084 #endif
00085
00086
00087
00088
00089
00090 #ifndef __DEPRECATED
00091 # if !MBO_TSA_STL_ITERATOR && !defined(DOXYGEN) && _MSC_VER >= 1300
00092 # define __DEPRECATED __declspec(deprecated)
00093 # else
00094 # define __DEPRECATED
00095 # endif
00096 #endif
00097
00118 template<class __ValueType
00119 , size_t __MaxSize
00120 , class __Allocator = std::allocator<__ValueType>
00121 >
00122 class TStaticArray
00123 {
00124 public:
00125 typedef TStaticArray<__ValueType, __MaxSize> _MyType;
00126 typedef __Allocator allocator;
00127 typedef typename __Allocator::size_type size_type;
00128 typedef typename __Allocator::value_type value_type;
00129 typedef typename __Allocator::reference reference;
00130 typedef typename __Allocator::const_reference const_reference;
00131 typedef typename __Allocator::pointer pointer;
00132 typedef typename __Allocator::const_pointer const_pointer;
00133 typedef typename __Allocator::difference_type difference_type;
00135 class iterator;
00136
00139 class const_iterator
00140 #if MBO_TSA_STL_ITERATOR
00141 # if !defined(_MSC_VER) || _MSC_VER >= 1300 || defined(_STLPORT_VERSION)
00142 : public std::iterator<std::random_access_iterator_tag, value_type, difference_type, const_pointer, const_reference>
00143 # else
00144 : public std::_Ranit<value_type, difference_type>
00145 # endif
00146 #endif
00147 {
00148 public:
00152 inline const_iterator(const _MyType & array, size_type pos = 0)
00153 : m_array(array), m_pos(pos)
00154 {
00155 }
00156
00159 inline const_iterator(const const_iterator& oth)
00160 : m_array(oth.m_array), m_pos(oth.m_pos)
00161 {
00162 }
00163
00166 inline const_iterator(const iterator& oth)
00167 : m_array(oth.m_array), m_pos(oth.m_pos)
00168 {
00169 }
00170
00173 inline const_reference operator * () const
00174 {
00175 return m_array[m_pos];
00176 }
00177
00180 inline const_pointer operator -> () const
00181 {
00182 return &(operator*());
00183 }
00184
00188 inline const_iterator & operator ++ ()
00189 {
00190 ++m_pos;
00191 return *this;
00192 }
00193
00197 inline __DEPRECATED const_iterator operator ++ (int)
00198 {
00199
00200 return const_iterator(m_array, m_pos++);
00201 }
00202
00206 inline const_iterator & operator -- ()
00207 {
00208 --m_pos;
00209 return *this;
00210 }
00211
00215 inline __DEPRECATED const_iterator operator -- (int)
00216 {
00217
00218 return const_iterator(m_array, m_pos--);
00219 }
00220
00226 inline bool operator == (const const_iterator &rhs) const __THROWS(logic_error)
00227 {
00228 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00229 return &m_array == &rhs.m_array && m_pos == rhs.m_pos;
00230 }
00231
00236 inline bool operator != (const const_iterator &rhs) const
00237 {
00238 return !operator == (rhs);
00239 }
00240
00246 inline bool operator == (const iterator &rhs) const __THROWS(logic_error)
00247 {
00248 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00249 return &m_array == &rhs.m_array && m_pos == rhs.m_pos;
00250 }
00251
00256 inline bool operator != (const iterator &rhs) const
00257 {
00258 return !operator == (rhs);
00259 }
00260
00265 inline const_iterator & operator = (const const_iterator & rhs)
00266 {
00267 #if _MSC_VER >= 1300
00268 # pragma push_macro("new")
00269 # undef new
00270 #endif
00271 new (this) const_iterator(rhs.m_array, rhs.m_pos);
00272 #if _MSC_VER >= 1300
00273 # pragma pop_macro("new")
00274 #endif
00275 return *this;
00276 }
00277
00282 inline const_reference operator [] (size_type nPos) const __THROWS(out_of_range)
00283 {
00284 return m_array[nPos];
00285 }
00286
00292 inline difference_type operator - (const const_iterator & rhs) const __THROWS(logic_error)
00293 {
00294 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00295 return m_pos - rhs.m_pos;
00296 }
00297
00303 inline const_iterator & operator -= (difference_type diff) __THROWS(logic_error)
00304 {
00305 #if _MSC_VER >= 1300
00306 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00307 #endif
00308 mbo_tsa_throw_if_not(logic_error, m_pos >= diff);
00309 m_pos -= diff;
00310 #if _MSC_VER >= 1300
00311 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00312 #endif
00313 return *this;
00314 }
00315
00321 inline const_iterator & operator += (difference_type diff) __THROWS(logic_error)
00322 {
00323 #if _MSC_VER >= 1300
00324 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00325 #endif
00326 mbo_tsa_throw_if_not(logic_error, m_pos + diff >= m_pos && m_pos + diff >= diff && m_pos + diff <= m_array.size());
00327 m_pos += diff;
00328 #if _MSC_VER >= 1300
00329 # pragma warning(default: 4018)
00330 #endif
00331 return *this;
00332 }
00333
00339 inline const_iterator operator - (difference_type diff) const __THROWS(logic_error)
00340 {
00341 #if _MSC_VER >= 1300
00342 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00343 #endif
00344 mbo_tsa_throw_if_not(logic_error, m_pos >= diff);
00345 return const_iterator(m_array, m_pos - diff);
00346 #if _MSC_VER >= 1300
00347 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00348 #endif
00349 }
00350
00356 inline const_iterator operator + (difference_type diff) const __THROWS(logic_error)
00357 {
00358 #if _MSC_VER >= 1300
00359 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00360 #endif
00361 mbo_tsa_throw_if_not(logic_error, m_pos + diff >= m_pos && m_pos + diff >= diff && m_pos + diff <= m_array.size());
00362 return const_iterator(m_array, m_pos + diff);
00363 #if _MSC_VER >= 1300
00364 # pragma warning(default: 4018)
00365 #endif
00366 }
00367
00373 inline bool operator < (const const_iterator & rhs) const __THROWS(logic_error)
00374 {
00375 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00376 return m_pos < rhs.m_pos;
00377 }
00378
00384 inline bool operator > (const const_iterator & rhs) const __THROWS(logic_error)
00385 {
00386 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00387 return m_pos > rhs.m_pos;
00388 }
00389
00395 inline bool operator <= (const const_iterator & rhs) const __THROWS(logic_error)
00396 {
00397 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00398 return m_pos <= rhs.m_pos;
00399 }
00400
00406 inline bool operator >= (const const_iterator & rhs) const __THROWS(logic_error)
00407 {
00408 mbo_tsa_throw_if_not(logic_error, &m_array == &rhsrhs.m_array);
00409 return m_pos >= rhs.m_pos;
00410 }
00411
00412 protected:
00413 const _MyType & m_array;
00414 size_type m_pos;
00415 };
00416
00419 class iterator
00420 #if MBO_TSA_STL_ITERATOR
00421 # if !defined(_MSC_VER) || _MSC_VER >= 1300 || defined(_STLPORT_VERSION)
00422 : public std::iterator<std::random_access_iterator_tag, value_type, difference_type, pointer, reference>
00423 # else
00424 : public std::_Ranit<value_type, difference_type>
00425 # endif
00426 #endif
00427 {
00428 public:
00429 friend class const_iterator;
00430
00434 explicit inline iterator(_MyType & array, size_type pos = 0)
00435 : m_array(array), m_pos(pos)
00436 {
00437 }
00438
00441 inline iterator(const iterator& oth)
00442 : m_array(oth.m_array), m_pos(oth.m_pos)
00443 {
00444 }
00445
00448 operator const_iterator()
00449 {
00450 return const_iterator(m_array, m_pos);
00451 }
00452
00455 inline const_reference operator * () const
00456 {
00457 return m_array[m_pos];
00458 }
00459
00462 inline reference operator * ()
00463 {
00464 return m_array[m_pos];
00465 }
00466
00469 inline const_pointer operator -> () const
00470 {
00471 return &(operator*());
00472 }
00473
00476 inline pointer operator -> ()
00477 {
00478 return &(operator*());
00479 }
00480
00484 inline iterator & operator ++ ()
00485 {
00486 ++m_pos;
00487 return *this;
00488 }
00489
00493 inline __DEPRECATED iterator operator ++ (int)
00494 {
00495
00496 return iterator(m_array, m_pos++);
00497 }
00498
00502 inline iterator & operator -- ()
00503 {
00504 --m_pos;
00505 return *this;
00506 }
00507
00511 inline __DEPRECATED iterator operator -- (int)
00512 {
00513
00514 return iterator(m_array, m_pos--);
00515 }
00516
00522 inline bool operator == (const iterator &rhs) const
00523 {
00524 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00525 return m_pos == rhs.m_pos;
00526 }
00527
00533 inline bool operator != (const iterator &rhs) const __THROWS(logic_error)
00534 {
00535 return !operator == (rhs);
00536 }
00537
00542 inline iterator & operator = (const iterator & rhs)
00543 {
00544 new (this) iterator(rhs.m_array, rhs.m_pos);
00545 return *this;
00546 }
00547
00552 inline reference operator [] (size_type nPos) __THROWS(out_of_range)
00553 {
00554 return m_array[nPos];
00555 }
00556
00561 inline const_reference operator [] (size_type nPos) const __THROWS(out_of_range)
00562 {
00563 return m_array[nPos];
00564 }
00565
00571 inline difference_type operator - (const iterator & rhs) const __THROWS(logic_error)
00572 {
00573 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00574 return m_pos - rhs.m_pos;
00575 }
00576
00582 inline iterator & operator -= (difference_type diff) __THROWS(logic_error)
00583 {
00584 #if _MSC_VER >= 1300
00585 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00586 #endif
00587 mbo_ta_throw_if_not(logic_error, m_pos >= diff);
00588 m_pos -= diff;
00589 #if _MSC_VER >= 1300
00590 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00591 #endif
00592 return *this;
00593 }
00594
00600 inline iterator & operator += (difference_type diff) __THROWS(logic_error)
00601 {
00602 #if _MSC_VER >= 1300
00603 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00604 #endif
00605 mbo_tsa_throw_if_not(logic_error, m_pos + diff >= m_pos && m_pos + diff >= diff && m_pos + diff <= m_array.size());
00606 m_pos += diff;
00607 #if _MSC_VER >= 1300
00608 # pragma warning(default: 4018)
00609 #endif
00610 return *this;
00611 }
00612
00618 inline iterator operator - (difference_type diff) const __THROWS(logic_error)
00619 {
00620 #if _MSC_VER >= 1300
00621 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00622 #endif
00623 mbo_tsa_throw_if_not(logic_error, m_pos >= diff);
00624 return iterator(m_array, m_pos - diff);
00625 #if _MSC_VER >= 1300
00626 # pragma warning(default: 4018)
00627 #endif
00628 }
00629
00635 inline iterator operator + (difference_type diff) const __THROWS(logic_error)
00636 {
00637 #if _MSC_VER >= 1300
00638 # pragma warning(disable: 4018) // '>=' : signed/unsigned mismatch
00639 #endif
00640 mbo_tsa_throw_if_not(logic_error, m_pos + diff >= m_pos && m_pos + diff >= diff && m_pos + diff <= m_array.size());
00641 return iterator(m_array, m_pos + diff);
00642 #if _MSC_VER >= 1300
00643 # pragma warning(default: 4018)
00644 #endif
00645 }
00646
00652 inline bool operator < (const iterator & rhs) const __THROWS(logic_error)
00653 {
00654 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00655 return m_pos < rhs.m_pos;
00656 }
00657
00663 inline bool operator > (const iterator & rhs) const __THROWS(logic_error)
00664 {
00665 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00666 return m_pos > rhs.m_pos;
00667 }
00668
00674 inline bool operator <= (const iterator & rhs) const __THROWS(logic_error)
00675 {
00676 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00677 return m_pos <= rhs.m_pos;
00678 }
00679
00685 inline bool operator >= (const iterator & rhs) const __THROWS(logic_error)
00686 {
00687 mbo_tsa_throw_if_not(logic_error, &m_array == &rhs.m_array);
00688 return m_pos >= rhs.m_pos;
00689 }
00690
00691 protected:
00692 _MyType & m_array;
00693 size_type m_pos;
00694 };
00695
00696 #if MBO_TSA_STL_ITERATOR
00697
00700 # if !defined(_MSC_VER) || _MSC_VER >= 1300
00701 typedef std::reverse_iterator<iterator> reverse_iterator;
00702 # else
00703 typedef std::reverse_iterator<iterator, value_type, reference, pointer, difference_type> reverse_iterator;
00704 # endif
00705
00706
00710 # if !defined(_MSC_VER) || _MSC_VER >= 1300
00711 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00712 # else
00713 typedef std::reverse_iterator<const_iterator, value_type, const_reference, const_pointer, difference_type> const_reverse_iterator;
00714 # endif
00715 #endif
00716
00719 TStaticArray()
00720 : m_nSize(0)
00721 , m_acValues(reinterpret_cast<value_array_ref>(m_acData))
00722 , m_alloc()
00723 {
00724 }
00725
00728 explicit TStaticArray(_IN size_type initial_count)
00729 : m_nSize(0)
00730 , m_acValues(reinterpret_cast<value_array_ref>(m_acData))
00731 , m_alloc()
00732 {
00733 mbo_tsa_throw_if_not(out_of_range, initial_count <= __MaxSize);
00734 while(m_nSize < initial_count)
00735 {
00736 append_element();
00737 }
00738 }
00739
00742 TStaticArray(_IN size_type initial_count, _IN const value_type& val)
00743 : m_nSize(0)
00744 , m_acValues(reinterpret_cast<value_array_ref>(m_acData))
00745 , m_alloc()
00746 {
00747 mbo_tsa_throw_if_not(out_of_range, initial_count <= __MaxSize);
00748 while(m_nSize < initial_count)
00749 {
00750 append(val);
00751 }
00752 }
00753
00754 ~TStaticArray()
00755 {
00756 clear();
00757 }
00758
00759 enum { max_size = __MaxSize };
00760
00763 inline size_type capacity() const
00764 {
00765 return max_size;
00766 }
00767
00770 inline size_type size() const
00771 {
00772 return m_nSize;
00773 }
00774
00784 inline resize(size_type nNewSize) throw(overflow_error)
00785 {
00786 resize(nNewSize, value_type());
00787 }
00788
00799 inline void resize(size_type nNewSize, value_type value) throw(overflow_error)
00800 {
00801 if (nNewSize > max_size)
00802 {
00803 nNewSize = max_size;
00804 throw str::overflow_error("New size exceeds maximum size");
00805 }
00806 while(size() < nNewSize)
00807 {
00808 push_back(value);
00809 }
00810 while(size() > nNewSize)
00811 {
00812 pop_back();
00813 }
00814 }
00815
00820 inline void limit_size(size_type nNewSize)
00821 {
00822 while(size() > nNewSize)
00823 {
00824 pop_back();
00825 }
00826 }
00827
00833 inline void reserve(size_type nNewSize) throw(overflow_error)
00834 {
00835 mbo_tsa_throw_if_not(overflow_error, nNewSize <= max_size);
00836 }
00837
00840 inline bool empty() const
00841 {
00842 return size() == 0;
00843 }
00844
00847 inline bool full() const
00848 {
00849 return size() == max_size;
00850 }
00851
00856 inline const_reference at(_IN size_type index) const throw(out_of_range)
00857 {
00858 mbo_tsa_throw_if_not(out_of_range, index < m_nSize);
00859 return m_acValues[index];
00860 }
00861
00866 inline reference at(_IN size_type index) throw(out_of_range)
00867 {
00868 mbo_tsa_throw_if_not(out_of_range, index < m_nSize);
00869 return m_acValues[index];
00870 }
00871
00876 inline const_reference operator[] (_IN size_type index) const throw(out_of_range)
00877 {
00878 mbo_tsa_throw_if_not(out_of_range, index < m_nSize);
00879 return m_acValues[index];
00880 }
00881
00886 inline reference operator[] (_IN size_type index) throw(out_of_range)
00887 {
00888 mbo_tsa_throw_if_not(out_of_range, index < m_nSize);
00889 return m_acValues[index];
00890 }
00891
00895 inline const_reference front() const throw(out_of_range)
00896 {
00897 mbo_tsa_throw_if_not(out_of_range, m_nSize > 0);
00898 return m_acValues[0];
00899 }
00900
00904 inline reference front() throw(out_of_range)
00905 {
00906 mbo_tsa_throw_if_not(out_of_range, m_nSize > 0);
00907 return m_acValues[0];
00908 }
00909
00913 inline const_reference back() const throw(out_of_range)
00914 {
00915 mbo_tsa_throw_if_not(out_of_range, m_nSize > 0);
00916 return m_acValues[m_nSize-1];
00917 }
00918
00922 inline reference back() throw(out_of_range)
00923 {
00924 mbo_tsa_throw_if_not(out_of_range, m_nSize > 0);
00925 return m_acValues[m_nSize-1];
00926 }
00927
00933 inline void push_back(_IN const_reference value) throw(out_of_range)
00934 {
00935 mbo_tsa_throw_if_not(out_of_range, m_nSize < __MaxSize);
00936 m_alloc.construct(m_alloc.address(m_acValues[m_nSize++]), value);
00937 }
00938
00942 inline void pop_back() throw(out_of_range)
00943 {
00944 mbo_tsa_throw_if_not(out_of_range, m_nSize > 0);
00945 m_alloc.destroy(m_alloc.address(m_acValues[--m_nSize]));
00946 }
00947
00953 inline bool append(_IN const_reference value)
00954 {
00955 if (m_nSize < max_size)
00956 {
00957 m_alloc.construct(m_alloc.address(m_acValues[m_nSize++]), value);
00958 return true;
00959 }
00960 else
00961 {
00962 return false;
00963 }
00964 }
00965
00969 inline reference append_element() throw(out_of_range)
00970 {
00971 mbo_tsa_throw_if_not(out_of_range, m_nSize < __MaxSize);
00972 m_alloc.construct(m_alloc.address(m_acValues[m_nSize]), value_type());
00973 return m_acValues[m_nSize++];
00974 }
00975
00978 inline void clear()
00979 {
00980 while(m_nSize)
00981 {
00982 m_alloc.destroy(m_alloc.address(m_acValues[--m_nSize]));
00983 }
00984 }
00985
00988 inline const_iterator begin() const
00989 {
00990 return const_iterator(*this, 0);
00991 }
00992
00995 inline iterator begin()
00996 {
00997 return iterator(*this, 0);
00998 }
00999
01002 inline const_iterator end() const
01003 {
01004 return const_iterator(*this, m_nSize);
01005 }
01006
01009 inline iterator end()
01010 {
01011 return iterator(*this, m_nSize);
01012 }
01013
01017 inline const_iterator final() const
01018 {
01019 return const_iterator(*this, max_size);
01020 }
01021
01025 inline iterator final()
01026 {
01027 return iterator(*this, max_size);
01028 }
01029
01030 protected:
01031
01032 #if !defined(_MSC_VER) || _MSC_VER >= 1300
01033
01036 typedef value_type value_array[__MaxSize];
01037
01038 typedef value_array& value_array_ref;
01039 #else
01040 typedef value_type* value_array_ref;
01041 #endif
01042
01043 allocator m_alloc;
01044 size_type m_nSize;
01045 value_array_ref m_acValues;
01047 private:
01048
01055 struct value_memory
01056 {
01057 char m_cData[sizeof(value_type)];
01058 };
01059
01064 value_memory m_acData[__MaxSize];
01065 };
01066
01073 template<class __ValueType
01074 , size_t __MaxSize
01075 , class __Allocator = std::allocator<__ValueType>
01076 >
01077 class TStaticArrayEx
01078 : public TStaticArray<__ValueType, __MaxSize, __Allocator>
01079 {
01080 public:
01085 inline const_reference operator[] (_IN size_type index) const throw(out_of_range)
01086 {
01087 mbo_tsa_throw_if_not(out_of_range, index < __MaxSize);
01088 while(m_nSize <= index)
01089 {
01090 const_cast<TStaticArrayEx*>(this)->append_element();
01091 }
01092 return m_acValues[index];
01093 }
01094
01099 inline reference operator[] (_IN size_type index) throw(out_of_range)
01100 {
01101 mbo_tsa_throw_if_not(out_of_range, index < __MaxSize);
01102 while(m_nSize <= index)
01103 {
01104 append_element();
01105 }
01106 return m_acValues[index];
01107 }
01108 };
01109
01110 };
01111
01112 #if defined(_MSC_VER)
01113 # pragma warning(pop)
01114 #endif
01115
01116 #endif // _TSTATICARRAY_H_