//====================================================================== // Copyright (C) 2002 Daniel Heck // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. //====================================================================== #ifndef PX_ARRAY2_HH #define PX_ARRAY2_HH /* * This file implements templated two-dimensional arrays. */ #include namespace px { template > struct Array2Base { A alloc; // allocator T *first, *last; // start/end of allocated space Array2Base(const A &a, typename A::size_type n) : alloc(a), first(alloc.allocate(n)), last(first+n) {} ~Array2Base() { // allocate(0) returns 0 on GCC 2.95 -- standard? if(first) alloc.deallocate(first, last-first); } void resize (typename A::size_type n) { if (first) alloc.deallocate(first, last-first); first = alloc.allocate(n); last = first+n; } }; template > class Array2 : private Array2Base { A alloc; public: typedef T value_type; typedef T* iterator; typedef const T * const_iterator; typedef T & reference; typedef const T & const_reference; typedef typename A::size_type size_type; Array2(int ww=0, int hh=0, const T& val=T(), const A& a=A()) : Array2Base(a, ww*hh), w(ww), h(hh) { std::uninitialized_fill(first, last, val); } Array2(const Array2 &a) : Array2Base(a.alloc, a.last-a.first) { std::uninitialized_copy(a.begin(), a.end(), first); } Array2 &operator=(Array2 a2); // call by value! // Destructor ~Array2() { destroy_elements(); } iterator begin() { return first; } iterator end() { return last; } const_iterator begin() const { return first; } const_iterator end() const { return last; } iterator row_begin(size_type y) { return first + y*w; } iterator row_end(size_type y) { return first + y*w + w; } const_iterator row_begin(size_type y) const { return first + y*w; } const_iterator row_end(size_type y) const { return first + y*w + w; } void swap(Array2 &a2); size_type width() const { return w; } size_type height()const { return h; } T& get(size_type x, size_type y) { return first[y*w+x]; } const T& get(size_type x, size_type y) const { return first[y*w+x]; } T& operator()(size_type x, size_type y) { return get(x,y); } const T& operator()(size_type x, size_type y) const { return get(x,y); } void set(size_type x, size_type y, const T& val) { first[y*w+x] = val; } void clear (const T& val=T()) { destroy_elements(); std::uninitialized_fill(first, last, val); } void resize (int w, int h, const T& val=T()) { destroy_elements(); Array2Base::resize(w*h); std::uninitialized_fill(first, last, val); this->w=w; this->h=h; } private: size_type w, h; void destroy_elements() { for (T* p=first; p!=last; ++p) p->~T(); } }; template void Array2::swap(Array2 &a2) { std::swap(first, a2.first); std::swap(last, a2.last); std::swap(w, a2.w); std::swap(h, a2.h); } template void swap (Array2 &a, Array2 &b) { a.swap(b); } template Array2& Array2::operator= (Array2 a2) { px::swap(*this, a2); return *this; } } #endif