X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2Fcml%2Fcore%2Fdynamic_2D.h;h=374c53942745f72c7d1541380b84579e25cd3e9e;hp=c6ea38693f5b6152ee21c349f3ee16d8e2c6c067;hb=40755d4c6251206c18ce4784967d3a910cee096f;hpb=d08114d4e7315636ff62127845150273e0cbf66f diff --git a/src/Moof/cml/core/dynamic_2D.h b/src/Moof/cml/core/dynamic_2D.h index c6ea386..374c539 100644 --- a/src/Moof/cml/core/dynamic_2D.h +++ b/src/Moof/cml/core/dynamic_2D.h @@ -13,7 +13,7 @@ Boost Software License, v1.0 (see cml/LICENSE for details). #ifndef dynamic_2D_h #define dynamic_2D_h -#include +#include #include #include #include @@ -40,15 +40,12 @@ class dynamic_2D /* Record the generator: */ typedef dynamic generator_type; - /* Array implementation: */ - typedef std::vector array_impl; - /* Standard: */ - typedef typename array_impl::value_type value_type; - typedef typename array_impl::pointer pointer; - typedef typename array_impl::reference reference; - typedef typename array_impl::const_reference const_reference; - typedef typename array_impl::const_pointer const_pointer; + typedef typename allocator_type::value_type value_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::const_pointer const_pointer; /* For matching by memory layout: */ typedef Layout layout; @@ -66,7 +63,8 @@ class dynamic_2D typedef twod_tag dimension_tag; /* To simplify the matrix transpose operator: */ - typedef dynamic_2D transposed_type; + typedef dynamic_2D::type, + Layout,Alloc> transposed_type; /* To simplify the matrix row and column operators: */ typedef dynamic_1D row_array_type; @@ -76,19 +74,25 @@ class dynamic_2D protected: /** Construct a dynamic array with no size. */ - dynamic_2D() {} + dynamic_2D() : m_rows(0), m_cols(0), m_data(0), m_alloc() {} - /** Construct a dynamic matrix given the dimensions. - * - * This constructor is guaranteed to throw only if the allocator throws. - * If the array implementation guarantees that the array data structure is - * not modified after an exception, then this constructor is - * exception-safe. - * - * @throws only if the allocator throws during an allocation. - */ + /** Construct a dynamic matrix given the dimensions. */ explicit dynamic_2D(size_t rows, size_t cols) - : m_rows(rows), m_cols(cols), m_data(rows*cols) {} + : m_rows(0), m_cols(0), m_data(0), m_alloc() + { + this->resize(rows, cols); + } + + /** Copy construct a dynamic matrix. */ + dynamic_2D(const dynamic_2D& other) + : m_rows(0), m_cols(0), m_data(0), m_alloc() + { + this->copy(other); + } + + ~dynamic_2D() { + this->destroy(); + } public: @@ -114,7 +118,7 @@ class dynamic_2D * @returns mutable reference. */ reference operator()(size_t row, size_t col) { - return get_element(row, col, layout()); + return this->get_element(row, col, layout()); } /** Access the given element of the matrix. @@ -124,7 +128,7 @@ class dynamic_2D * @returns const reference. */ const_reference operator()(size_t row, size_t col) const { - return get_element(row, col, layout()); + return this->get_element(row, col, layout()); } /** Return access to the data as a raw pointer. */ @@ -136,12 +140,58 @@ class dynamic_2D public: - /** Resize the array. + /** Set the array dimensions. The previous contents are destroyed + * before reallocating the array. If the number of rows and columns + * isn't changing, nothing happens. Also, if either rows or cols is 0, + * the array is cleared. * * @warning This is not guaranteed to preserve the original data. */ void resize(size_t rows, size_t cols) { - m_data.resize(rows*cols); m_rows = rows; m_cols = cols; + + /* Nothing to do if the size isn't changing: */ + if(rows == m_rows && cols == m_cols) return; + + /* Destroy the current array contents: */ + this->destroy(); + + /* Set the new size if non-zero: */ + if(rows*cols > 0) { + value_type* data = m_alloc.allocate(rows*cols); + for(size_t i = 0; i < rows*cols; ++ i) + m_alloc.construct(&data[i], value_type()); + + /* Success, so save the new array and the dimensions: */ + m_rows = rows; + m_cols = cols; + m_data = data; + } + } + + /** Copy the other array. The previous contents are destroyed before + * reallocating the array. If other == *this, nothing happens. Also, + * if either other.rows() or other.cols() is 0, the array is cleared. + */ + void copy(const dynamic_2D& other) { + + /* Nothing to do if it's the same array: */ + if(&other == this) return; + + /* Destroy the current array contents: */ + this->destroy(); + + /* Set the new size if non-zero: */ + size_t rows = other.rows(), cols = other.cols(); + if(rows*cols > 0) { + value_type* data = m_alloc.allocate(rows*cols); + for(size_t i = 0; i < rows*cols; ++ i) + m_alloc.construct(&data[i], other[i]); + + /* Success, so save the new array and the dimensions: */ + m_rows = rows; + m_cols = cols; + m_data = data; + } } @@ -166,8 +216,28 @@ class dynamic_2D protected: + /** Destroy the current contents of the array. */ + void destroy() { + if(m_data) { + for(size_t i = 0; i < m_rows*m_cols; ++ i) + m_alloc.destroy(&m_data[i]); + m_alloc.deallocate(m_data, m_rows*m_cols); + m_rows = m_cols = 0; + m_data = 0; + } + } + + + protected: + + /** Current array dimensions (may be 0,0). */ size_t m_rows, m_cols; - array_impl m_data; + + /** Array data (may be NULL). */ + value_type* m_data; + + /** Allocator for the array. */ + allocator_type m_alloc; }; } // namespace cml