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 #ifndef UTILITY_COLLECTION_FIXED_SIZE_BUFFER_H
00033 #define UTILITY_COLLECTION_FIXED_SIZE_BUFFER_H
00034
00035 namespace Onikiri
00036 {
00037 template < typename T, size_t SIZE, typename Tag = int >
00038 class fixed_sized_buffer : private boost::array< T, SIZE >
00039 {
00040 public:
00041 typedef typename boost::array< T, SIZE > base_type;
00042
00043 typedef typename base_type::iterator iterator;
00044 typedef typename base_type::const_iterator const_iterator;
00045 typedef typename base_type::reference reference;
00046 typedef typename base_type::const_reference const_reference;
00047 typedef typename base_type::size_type size_type;
00048
00049 fixed_sized_buffer() :
00050 m_end( base_type::begin() + 0 )
00051 {
00052
00053 }
00054
00055 fixed_sized_buffer( const fixed_sized_buffer& rhs )
00056 {
00057 std::copy( rhs.begin(), rhs.end(), begin() );
00058 m_end = begin() + rhs.size();
00059 }
00060
00061 fixed_sized_buffer& operator= ( const fixed_sized_buffer& rhs )
00062 {
00063 std::copy( rhs.begin(), rhs.end(), begin() );
00064 m_end = begin() + rhs.size();
00065 return *this;
00066 }
00067
00068
00069 reference at( size_type i )
00070 {
00071 return base_type::at( i );
00072 }
00073
00074 const_reference at( size_type i ) const
00075 {
00076 return base_type::at( i );
00077 }
00078
00079 reference operator[]( size_type i )
00080 {
00081 return (*static_cast<base_type*>(this))[i];
00082 }
00083
00084 const_reference operator[]( size_type i ) const
00085 {
00086 return (*static_cast<base_type*>(this))[i];
00087 }
00088
00089 const T* data() const
00090 {
00091 return base_type::data();
00092 }
00093
00094 T* data()
00095 {
00096 return base_type::data();
00097 }
00098
00099
00100 size_type size() const
00101 {
00102 return m_end - begin();
00103 }
00104
00105 void push_back( const T& value )
00106 {
00107 if( size() >= base_type::size() ){
00108 buffer_overflow();
00109 }
00110
00111 *m_end = value;
00112 m_end++;
00113 }
00114
00115 void pop_front()
00116 {
00117 erase( begin() );
00118 }
00119
00120 iterator begin()
00121 {
00122 return base_type::begin();
00123 }
00124
00125 iterator end()
00126 {
00127 return m_end;
00128 }
00129
00130 const_iterator begin() const
00131 {
00132 return base_type::begin();
00133 }
00134
00135 const_iterator end() const
00136 {
00137 return m_end;
00138 }
00139
00140 void clear()
00141 {
00142 m_end = begin();
00143 }
00144
00145 void resize( size_t size, const T& value = T() )
00146 {
00147 if( size >= base_type::size() ){
00148 buffer_overflow();
00149 }
00150 m_end = begin() + size;
00151 std::fill( begin(), end(), value );
00152 }
00153
00154 iterator erase( const_iterator where )
00155 {
00156 const_iterator s = where + 1;
00157 iterator d = iterator( where );
00158 while( s != end() ){
00159 *d = *s;
00160 s++;
00161 d++;
00162 }
00163
00164 m_end--;
00165 return iterator( where );
00166 }
00167
00168 protected:
00169 iterator m_end;
00170
00171 NOINLINE void buffer_overflow()
00172 {
00173 THROW_RUNTIME_ERROR(
00174 "A buffer is resized in excess of a max buffer size. "
00175 "The max buffer size (%d) is too small. "
00176 "Type tag: %s",
00177 (int)SIZE,
00178 typeid( Tag ).name()
00179 );
00180 }
00181 };
00182 }
00183
00184 #endif