[260] | 1 | // Copyright (C) 2014 ChaosForge Ltd
|
---|
| 2 | // http://chaosforge.org/
|
---|
| 3 | //
|
---|
| 4 | // This file is part of NV Libraries.
|
---|
| 5 | // For conditions of distribution and use, see copyright notice in nv.hh
|
---|
| 6 |
|
---|
| 7 | /**
|
---|
| 8 | * @file array.hh
|
---|
| 9 | * @author Kornel Kisielewicz epyon@chaosforge.org
|
---|
| 10 | * @brief exception free array classes
|
---|
| 11 | */
|
---|
| 12 |
|
---|
[319] | 13 | #ifndef NV_CORE_ARRAY_HH
|
---|
| 14 | #define NV_CORE_ARRAY_HH
|
---|
[260] | 15 |
|
---|
[319] | 16 | #include <nv/core/common.hh>
|
---|
[368] | 17 | #include <nv/stl/memory.hh>
|
---|
[374] | 18 | #include <nv/stl/iterator.hh>
|
---|
| 19 | #include <nv/stl/utility.hh>
|
---|
[260] | 20 | #include <vector>
|
---|
[323] | 21 | #include <algorithm>
|
---|
[260] | 22 | #include <array>
|
---|
| 23 |
|
---|
| 24 | namespace nv
|
---|
| 25 | {
|
---|
| 26 | using std::vector;
|
---|
| 27 |
|
---|
[374] | 28 | template< typename T, size_t N >
|
---|
| 29 | class array : public detail::pointer_iterators < array< T, N >, T, false >
|
---|
[260] | 30 | {
|
---|
| 31 | public:
|
---|
[374] | 32 | typedef T value_type;
|
---|
| 33 | typedef size_t size_type;
|
---|
| 34 | typedef ptrdiff_t difference_type;
|
---|
| 35 | typedef T* pointer;
|
---|
| 36 | typedef const T* const_pointer;
|
---|
| 37 | typedef T* iterator;
|
---|
| 38 | typedef const T* const_iterator;
|
---|
| 39 | typedef T& reference;
|
---|
| 40 | typedef const T& const_reference;
|
---|
| 41 | typedef nv::reverse_iterator<iterator> reverse_iterator;
|
---|
| 42 | typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
|
---|
[323] | 43 |
|
---|
[374] | 44 | static const size_type SIZE = N;
|
---|
| 45 | static const size_type ELEMENT_SIZE = sizeof( value_type );
|
---|
[323] | 46 |
|
---|
[374] | 47 | inline const_pointer data() const { return m_data; }
|
---|
| 48 | inline pointer data() { return m_data; }
|
---|
| 49 | inline size_type size() const { return SIZE; }
|
---|
| 50 | inline bool empty() const { return false; }
|
---|
| 51 | inline size_type raw_size() const { return SIZE * sizeof( T ); }
|
---|
| 52 | inline const char* raw_data() const { return (const char*)m_data; }
|
---|
| 53 | inline char* raw_data() { return (char*)m_data; }
|
---|
[260] | 54 |
|
---|
[374] | 55 | inline reference front() { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[0]; }
|
---|
| 56 | inline const_reference front() const { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[0]; }
|
---|
| 57 | inline reference back() { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[SIZE - 1]; }
|
---|
| 58 | inline const_reference back() const { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[SIZE - 1]; }
|
---|
| 59 |
|
---|
[260] | 60 | reference operator[]( size_type i )
|
---|
| 61 | {
|
---|
| 62 | NV_ASSERT( i < N, "Out of range" );
|
---|
[368] | 63 | return this->m_data[i];
|
---|
[260] | 64 | }
|
---|
| 65 |
|
---|
| 66 | const_reference operator[]( size_type i ) const
|
---|
| 67 | {
|
---|
| 68 | NV_ASSERT( i < N, "Out of range" );
|
---|
[368] | 69 | return this->m_data[i];
|
---|
[260] | 70 | }
|
---|
| 71 |
|
---|
[374] | 72 | reference at( size_type i )
|
---|
| 73 | {
|
---|
| 74 | NV_ASSERT( i < N, "Out of range" );
|
---|
| 75 | return this->m_data[i];
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | const_reference at( size_type i ) const
|
---|
| 79 | {
|
---|
| 80 | NV_ASSERT( i < N, "Out of range" );
|
---|
| 81 | return this->m_data[i];
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 84 | void swap( array<value_type, N>& y )
|
---|
| 85 | {
|
---|
| 86 | for ( size_type i = 0; i < N; ++i )
|
---|
| 87 | nv::swap( m_data[i], y.m_data[i] );
|
---|
| 88 | }
|
---|
| 89 |
|
---|
| 90 | void assign( const value_type& value ) { fill( value ); }
|
---|
| 91 |
|
---|
| 92 | void fill( const value_type& value )
|
---|
| 93 | {
|
---|
| 94 | std::fill_n( this->begin(), this->size(), value );
|
---|
| 95 | }
|
---|
| 96 |
|
---|
| 97 | private:
|
---|
| 98 | value_type m_data[SIZE];
|
---|
| 99 | };
|
---|
| 100 |
|
---|
| 101 | template< typename T, size_t N >
|
---|
| 102 | inline void swap( array<T, N>& lhs, array<T, N>& rhs )
|
---|
| 103 | {
|
---|
| 104 | lhs.swap( rhs );
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 107 | // template < typename T, typename ContainerAllocator >
|
---|
| 108 | // class vector_base
|
---|
| 109 | // {
|
---|
| 110 | // public:
|
---|
| 111 | // typedef T value_type;
|
---|
| 112 | // typedef size_t size_type;
|
---|
| 113 | // typedef ptrdiff_t difference_type;
|
---|
| 114 | // typedef T* pointer;
|
---|
| 115 | // typedef const T* const_pointer;
|
---|
| 116 | // typedef T* iterator;
|
---|
| 117 | // typedef const T* const_iterator;
|
---|
| 118 | // typedef T& reference;
|
---|
| 119 | // typedef const T& const_reference;
|
---|
[368] | 120 | //
|
---|
[374] | 121 | // protected:
|
---|
| 122 | // ContainerAllocator m_storage;
|
---|
| 123 | // };
|
---|
| 124 |
|
---|
| 125 | // template< typename T, size_t N >
|
---|
| 126 | // class static_vector : public detail::pointer_iterators < static_vector< T, N >, T, false >
|
---|
| 127 | // {
|
---|
| 128 | // public:
|
---|
| 129 | // typedef T value_type;
|
---|
| 130 | // typedef size_t size_type;
|
---|
| 131 | // typedef ptrdiff_t difference_type;
|
---|
| 132 | // typedef T* pointer;
|
---|
| 133 | // typedef const T* const_pointer;
|
---|
| 134 | // typedef T* iterator;
|
---|
| 135 | // typedef const T* const_iterator;
|
---|
| 136 | // typedef T& reference;
|
---|
| 137 | // typedef const T& const_reference;
|
---|
| 138 | // typedef nv::reverse_iterator<iterator> reverse_iterator;
|
---|
| 139 | // typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
|
---|
[368] | 140 | //
|
---|
[374] | 141 | // static_vector() : m_size(0) {}
|
---|
[368] | 142 | //
|
---|
[374] | 143 | // inline const_pointer data() const { return m_data; }
|
---|
| 144 | // inline pointer data() { return m_data; }
|
---|
| 145 | // inline size_type size() const { return m_size; }
|
---|
| 146 | // inline bool empty() const { return !m_size; }
|
---|
| 147 | // inline size_type raw_size() const { return N * sizeof( T ); }
|
---|
| 148 | // inline const char* raw_data() const { return (const char*)m_data; }
|
---|
| 149 | // inline char* raw_data() { return (char*)m_data; }
|
---|
| 150 | //
|
---|
| 151 | // inline reference front() { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[0]; }
|
---|
| 152 | // inline const_reference front() const { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[0]; }
|
---|
| 153 | // inline reference back() { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[m_size - 1]; }
|
---|
| 154 | // inline const_reference back() const { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_data[m_size - 1]; }
|
---|
| 155 | // protected:
|
---|
| 156 | // value_type m_data[N];
|
---|
| 157 | // size_type m_size;
|
---|
| 158 | // };
|
---|
[260] | 159 |
|
---|
[374] | 160 | template < typename T, typename ContainerAllocator >
|
---|
| 161 | class array_base : public detail:: pointer_iterators < array_base< T, ContainerAllocator >, T, false >
|
---|
| 162 | {
|
---|
| 163 | public:
|
---|
| 164 | typedef T value_type;
|
---|
| 165 | typedef size_t size_type;
|
---|
| 166 | typedef ptrdiff_t difference_type;
|
---|
| 167 | typedef T* pointer;
|
---|
| 168 | typedef const T* const_pointer;
|
---|
| 169 | typedef T* iterator;
|
---|
| 170 | typedef const T* const_iterator;
|
---|
| 171 | typedef T& reference;
|
---|
| 172 | typedef const T& const_reference;
|
---|
| 173 | typedef nv::reverse_iterator<iterator> reverse_iterator;
|
---|
| 174 | typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
|
---|
[260] | 175 |
|
---|
[374] | 176 | inline array_base() : m_storage() {}
|
---|
| 177 | inline array_base( pointer a_data, size_t a_size )
|
---|
| 178 | {
|
---|
| 179 |
|
---|
| 180 | }
|
---|
| 181 | inline const_pointer data() const { return m_storage.data(); }
|
---|
| 182 | inline pointer data() { return m_storage.data(); }
|
---|
| 183 | inline size_t size() const { return m_storage.size(); }
|
---|
| 184 | inline bool empty() const { return m_storage.size() != 0; }
|
---|
| 185 | inline size_type raw_size() const { return sizeof( T ) * m_storage.size(); }
|
---|
| 186 | inline const char* raw_data() const { return (const char*)m_storage.data(); }
|
---|
| 187 | inline char* raw_data() { return (char*)m_storage.data(); }
|
---|
| 188 |
|
---|
| 189 | inline reference front() { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_storage.data()[0]; }
|
---|
| 190 | inline const_reference front() const { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_storage.data()[0]; }
|
---|
| 191 | inline reference back() { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_storage.data()[size() - 1]; }
|
---|
| 192 | inline const_reference back() const { NV_ASSERT( !empty(), "front() called on empty data!" ); return m_storage.data()[size() - 1]; }
|
---|
| 193 | protected:
|
---|
| 194 | void push_values( size_type n, const value_type& value )
|
---|
| 195 | {
|
---|
| 196 |
|
---|
| 197 | }
|
---|
| 198 | ContainerAllocator m_storage;
|
---|
[260] | 199 | };
|
---|
| 200 |
|
---|
| 201 | template< class T >
|
---|
[368] | 202 | class dynamic_array : public detail::data_base< T, false, 0 >
|
---|
[260] | 203 | {
|
---|
| 204 | public:
|
---|
[374] | 205 | typedef T value_type;
|
---|
| 206 | typedef T* iterator;
|
---|
| 207 | typedef const T* const_iterator;
|
---|
| 208 | typedef T& reference;
|
---|
| 209 | typedef const T& const_reference;
|
---|
| 210 | typedef size_t size_type;
|
---|
| 211 | typedef ptrdiff_t difference_type;
|
---|
[323] | 212 |
|
---|
[374] | 213 | typedef nv::reverse_iterator<iterator> reverse_iterator;
|
---|
| 214 | typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
|
---|
[323] | 215 |
|
---|
[368] | 216 | dynamic_array() : detail::data_base< T, false, 0 >() {}
|
---|
| 217 | // : m_data( nullptr ), m_size(0) {}
|
---|
| 218 | explicit dynamic_array( size_type new_size ) : detail::data_base< T, false, 0 >( new value_type[new_size], new_size ) {}
|
---|
| 219 | // : m_data( new value_type[ new_size ] ), m_size( new_size ) {}
|
---|
| 220 | dynamic_array( const value_type& value, size_type size ) : detail::data_base< T, false, 0 >()
|
---|
| 221 | // : m_data( nullptr ), m_size(0)
|
---|
| 222 | { assign( value, size ); }
|
---|
| 223 | dynamic_array( const_iterator values, size_type size ) : detail::data_base< T, false, 0 >()
|
---|
| 224 | // : m_data( nullptr ), m_size(0)
|
---|
| 225 | { assign( values, size ); }
|
---|
[260] | 226 |
|
---|
| 227 | void resize( size_type new_size )
|
---|
| 228 | {
|
---|
[368] | 229 | if ( new_size != this->m_size )
|
---|
[260] | 230 | {
|
---|
[368] | 231 | value_type* old_data = this->m_data;
|
---|
| 232 | this->m_data = new_size > 0 ? new value_type[new_size] : nullptr;
|
---|
| 233 | if ( old_data && this->m_data )
|
---|
[260] | 234 | {
|
---|
[368] | 235 | std::copy_n( old_data, new_size > this->m_size ? this->m_size : new_size, this->m_data );
|
---|
[260] | 236 | }
|
---|
| 237 | delete[] old_data;
|
---|
[368] | 238 | this->m_size = new_size;
|
---|
[260] | 239 | }
|
---|
| 240 | }
|
---|
| 241 |
|
---|
[368] | 242 | // iterator begin() { return m_data; }
|
---|
| 243 | // const_iterator begin() const { return m_data; }
|
---|
| 244 | // const_iterator cbegin() const { return m_data; }
|
---|
| 245 | //
|
---|
| 246 | // iterator end() { return m_data+m_size; }
|
---|
| 247 | // const_iterator end() const { return m_data+m_size; }
|
---|
| 248 | // const_iterator cend() const { return m_data+m_size; }
|
---|
| 249 | //
|
---|
| 250 | // reverse_iterator rbegin() { return reverse_iterator( end() ); }
|
---|
| 251 | // const_reverse_iterator rbegin() const { return const_reverse_iterator( end() ); }
|
---|
| 252 | // const_reverse_iterator crbegin() const { return const_reverse_iterator( end() ); }
|
---|
| 253 | //
|
---|
| 254 | // reverse_iterator rend() { return reverse_iterator( begin() ); }
|
---|
| 255 | // const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); }
|
---|
| 256 | // const_reverse_iterator crend() const { return const_reverse_iterator( begin() ); }
|
---|
[260] | 257 |
|
---|
| 258 | reference operator[]( size_type i )
|
---|
| 259 | {
|
---|
[368] | 260 | NV_ASSERT( i < this->m_size, "Out of range" );
|
---|
| 261 | return this->m_data[i];
|
---|
[260] | 262 | }
|
---|
| 263 |
|
---|
| 264 | const_reference operator[]( size_type i ) const
|
---|
| 265 | {
|
---|
[368] | 266 | NV_ASSERT( i < this->m_size, "Out of range" );
|
---|
| 267 | return this->m_data[i];
|
---|
[260] | 268 | }
|
---|
| 269 |
|
---|
[368] | 270 | // reference front() { return m_data[0]; }
|
---|
| 271 | // const_reference front() const { return m_data[0]; }
|
---|
| 272 | // reference back() { return m_data[m_size-1]; }
|
---|
| 273 | // const_reference back() const { return m_data[m_size-1]; }
|
---|
| 274 | //
|
---|
| 275 | // size_type size() const { return m_size; }
|
---|
| 276 | // bool empty() const { return m_size == 0; }
|
---|
[374] | 277 | // static size_type max_size() { return numeric_limits< size_type >::max(); }
|
---|
[368] | 278 | // const value_type* data() const { return m_data; }
|
---|
| 279 | // value_type* data() { return m_data; }
|
---|
| 280 | //
|
---|
| 281 | // size_type raw_size() const { return m_size * ELEMENT_SIZE; }
|
---|
| 282 | // const char* raw_data() const { return (const char*)m_data; }
|
---|
| 283 | // char* raw_data() { return (char*)m_data; }
|
---|
[260] | 284 |
|
---|
[368] | 285 | void assign( const value_type& value ) { std::fill_n( this->begin(), this->size(), value ); }
|
---|
[260] | 286 | void assign( const value_type& value, size_type new_size )
|
---|
| 287 | {
|
---|
| 288 | resize( new_size );
|
---|
[368] | 289 | std::fill_n( this->begin(), this->size(), value );
|
---|
[260] | 290 | }
|
---|
| 291 | void assign( const_iterator values, size_type new_size )
|
---|
| 292 | {
|
---|
| 293 | resize( new_size );
|
---|
[368] | 294 | std::copy_n( values, this->size(), this->m_data );
|
---|
[260] | 295 | }
|
---|
| 296 |
|
---|
[368] | 297 | ~dynamic_array() { delete[] this->m_data; }
|
---|
[260] | 298 |
|
---|
| 299 | static const size_type ELEMENT_SIZE = sizeof(T);
|
---|
| 300 | };
|
---|
| 301 |
|
---|
[374] | 302 |
|
---|
| 303 |
|
---|
[260] | 304 | }
|
---|
| 305 |
|
---|
[319] | 306 | #endif // NV_CORE_ARRAY_HH |
---|