#ifndef _INCLUDED_L3_ARR2D_H #define _INCLUDED_L3_ARR2D_H // *Automatic Safe Array 2D* Copyright (C) Krzysztof Bosak, 1999-07-22...2000-12-23 // All rights reserved. // kbosak@box43.pl // http://www.kbosak.prv.pl // autoarray2D has (x,y) and [x][y] indexing. // (0,0) and [0][0] are first elements. (x,y) indexing is faster. // autoarray2D_iterated is autoarray2D with extensive subset of STL-style iterators. #include "l3_array.h" #include "l3_ptr.h" #ifndef NDEBUG #include #endif template class autoarray2D_rowindex; template class autoarray2D_rowindex_const; ///////////////////////////////////////////////////////////////////////////// template class autoarray2D { // For short specification look at autoarray<> class comments. // Row-major storage. // NOTE: C has inherent column-major storage: // beware when using pointers directly. // Is EXCEPTION NEUTRAL. private: int _sizex; int _sizey; autoarray _data; basearray _rowindex; public: autoarray2D(); // NOTHROW autoarray2D(int requested_sizex, int requested_sizey); void swap(autoarray2D& other); // NOTHROW autoarray2D& operator=(const autoarray2D& other); // EXCEPTION NEUTRAL virtual ~autoarray2D() { } inline type& operator()(int indx, int indy) // EXCEPTION NEUTRAL { // Returns object contained in array by reference, changes are possible // (0,0) is first element. // (x,y) indexing is preferred over [x][y] indexing because of code efficiency. assert(indx>=0); assert(indx<_sizex); assert(indy>=0); assert(indy<_sizey); return _data[indx+_rowindex[indy]]; } inline const type& operator()(int indexx, int indexy) const // EXCEPTION NEUTRAL { // Returns object contained in array by reference, no changes allowed // (0,0) is first element. // (x,y) indexing is preferred over [x][y] indexing because of code efficiency. assert(indexx>=0); assert(indexx<_sizex); assert(indexy>=0); assert(indexy<_sizey); return _data[indexx+_rowindex[indexy]]; } inline autoarray2D_rowindex operator[](int indexx) // EXCEPTION NEUTRAL { // Returns object contained in array by reference. // [0][0] is first element. // (x,y) indexing is preferred over [x][y] indexing because of code efficiency. assert(indexx>=0); assert(indexx<_sizex); return autoarray2D_rowindex(*this, indexx); } inline autoarray2D_rowindex_const operator[](int indexx) const // EXCEPTION NEUTRAL { // Returns object contained in array by reference. // [0][0] is first element. // (x,y) indexing is preferred over [x][y] indexing because of code efficiency. assert(indexx>=0); assert(indexx<_sizex); return autoarray2D_rowindex_const(*this, indexx); } inline int sizex() const // NOTHROW { // Returns current x size of array return _sizex; } inline int sizey() const // NOTHROW { // Returns current y size of array return _sizey; } inline int surface() const // NOTHROW { // Returns current surface of array return _sizex*_sizey; } inline int memory() const // NOTHROW { // Returns memory usage of array in bytes return sizeof(*this)+_data.memory()+_rowindex.memory(); } inline void free() // NOTHROW { // Sets array to minimum memory usage _data.free(); _rowindex.free(); _sizex=0; _sizey=0; } void setsize(int new_sizex, int new_sizey); inline void fill(const type& fill_value)// not STL { // Fills the whole array with given value _data.fill(fill_value); } void assign_column(int indx, const basearray& column); }; ///////////////////////////////////////////////////////////////////////////// template autoarray2D::autoarray2D() // NOTHROW : _sizex(0), _sizey(0), _data(), _rowindex() { // Quick default constructor } ///////////////////////////////////////////////////////////////////////////// template autoarray2D::autoarray2D(int requested_sizex, int requested_sizey) // EXCEPTION NEUTRAL : _sizex(requested_sizex), _sizey(requested_sizey), _data(requested_sizex*requested_sizey), _rowindex(requested_sizey) { // Constructor for desired size, content is garbage assert(_sizex < ceil(_data.max_size()/static_cast(_sizey)) ); assert(_sizey < ceil(_data.max_size()/static_cast(_sizex)) ); int i=0; int ii=0; const int sizey_m3=_sizey-3; while(i void autoarray2D::setsize(int new_sizex, int new_sizey) // EXCEPTION NEUTRAL { // Does not prevents content of array. // Order of instructions if crucial for exception safety level. assert(new_sizex>=0); assert(new_sizey>=0); assert(new_sizex < ceil(_data.max_size()/static_cast(new_sizey)) ); assert(new_sizey < ceil(_data.max_size()/static_cast(new_sizex)) ); if(new_sizey>_sizey) { _rowindex.resize(new_sizey); } _data.setsize(new_sizex*new_sizey); if(new_sizex!=_sizex) { for(int i=0, ii=0; i void autoarray2D::swap(autoarray2D& other) // NOTHROW { // Swaps whole content of 2 arrays int itemp=other._sizex; other._sizex=_sizex; _sizex=itemp; itemp=other._sizey; other._sizey=_sizey; _sizey=itemp; _data.swap(other._data); _rowindex.swap(other._rowindex); } ///////////////////////////////////////////////////////////////////////////// template autoarray2D& autoarray2D::operator=(const autoarray2D& other) // EXCEPTION NEUTRAL { // Note: to make container exception neutral you must define this operator. assert(this!=&other);// This line can be safely ommitted. autoarray2D temp(other); swap(temp); return *this; } ///////////////////////////////////////////////////////////////////////////// template void autoarray2D::assign_column(int indx, const basearray& column) { // Returns object contained in array by reference, changes are possible // (0,0) is first element. // (x,y) indexing is preferred over [x][y] indexing because of code efficiency. assert(indx>=0); assert(indx<_sizex); assert(column.size()==_sizey); for(int y=0; y<_sizey; y++) { _data[indx+_rowindex[y]]=column[y]; } } ///////////////////////////////////////////////////////////////////////////// template class autoarray2D_rowindex { autoarray2D& _ref; int _indexx; public: inline autoarray2D_rowindex( autoarray2D& ref, int indexx ) // NOTHROW : _ref(ref), _indexx(indexx) { assert(indexx>0); } inline type& operator[](int indexy) // EXEPTION NEUTRAL { // Returns object contained in array by reference. assert(indexy>=0); return _ref.operator()(_indexx, indexy); } private: //autoarray2D_rowindex(const autoarray2D_rowindex&);// Allowed, but compiler-generated version works just fine. autoarray2D_rowindex& operator=(const autoarray2D_rowindex&);// Forbidden. }; ///////////////////////////////////////////////////////////////////////////// template class autoarray2D_rowindex_const { const autoarray2D& _ref; int _indexx; public: inline autoarray2D_rowindex_const( const autoarray2D& ref, int indexx ) // NOTHROW : _ref(ref), _indexx(indexx) { assert(indexx>0); } inline const type& operator[](int indexy) const // EXCEPTION NEUTRAL { // Returns object contained in array by reference. assert(indexy>0); return _ref.operator()(_indexx, indexy); } private: //autoarray2D_rowindex_const(const autoarray2D_rowindex_const&);// Allowed, but compiler-generated version works just fine. autoarray2D_rowindex_const& operator=(const autoarray2D_rowindex_const&);// Forbidden. }; ///////////////////////////////////////////////////////////////////////////// template class autoarray2D_iterated: public autoarray2D { // autoarray2D with added extensive subset of STL-style iterators // NOTE: C has inherent column-major storage: beware when using iterators. public: inline autoarray2D_iterated() : autoarray2D() // NOTHROW {// Quick default constructor } inline autoarray2D_iterated(int requested_sizex, int requested_sizey) // NOTHROW : autoarray2D(requested_sizex, requested_sizey) {// Constructor } type * begin() // NOTHROW { return &_data[0]; } const type * begin() const // NOTHROW { return &_data[0]; } type * end() // NOTHROW { return &_data[0]+_data.size(); } const type * end() const // NOTHROW { return &_data[0]+_data.size(); } class iterator: public SmartPtr { public: inline iterator(type * const ptr) :SmartPtr(ptr, ptr, INT_MAX) { } friend inline bool operator<(const iterator& iter, const type * const ptr) { return iter._ptr < ptr; } friend inline bool operator>(const iterator& iter, const type * const ptr) { return iter._ptr > ptr; } friend inline bool operator<=(const iterator& iter, const type * const ptr) { return iter._ptr <= ptr; } friend inline bool operator>=(const iterator& iter, const type * const ptr) { return iter._ptr >= ptr; } friend inline bool operator==(const iterator& iter, const type * const ptr) { return iter._ptr == ptr; } friend inline bool operator!=(const iterator& iter, const type * const ptr) { return iter._ptr != ptr; } }; class const_iterator: public SmartPtrReadOnly { public: inline const_iterator(const type * const ptr) :SmartPtrReadOnly(ptr, ptr, INT_MAX) { } friend inline bool operator<(const const_iterator& iter, const type * const ptr) { return iter._ptr < ptr; } friend inline bool operator>(const const_iterator& iter, const type * const ptr) { return iter._ptr > ptr; } friend inline bool operator<=(const const_iterator& iter, const type * const ptr) { return iter._ptr <= ptr; } friend inline bool operator>=(const const_iterator& iter, const type * const ptr) { return iter._ptr >= ptr; } friend inline bool operator==(const const_iterator& iter, const type * const ptr) { return iter._ptr == ptr; } friend inline bool operator!=(const const_iterator& iter, const type * const ptr) { return iter._ptr != ptr; } }; }; ///////////////////////////////////////////////////////////////////////////// #endif //_INCLUDED_L3_ARR2D_H