/* * Copyright (C) 2002,2003 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. * * $Id: array2.hh,v 1.6 2004/04/24 11:46:01 dheck Exp $ */ #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; // Construction / Copying explicit Array2(int ww=0, int hh=0, const T& val=T(), const A& a=A()); Array2(const Array2 &a); Array2 &operator=(Array2 a2); // call by value! // Destructor ~Array2() { destroy_elements(); } iterator begin() { return this->first; } iterator end() { return this->last; } const_iterator begin() const { return this->first; } const_iterator end() const { return this->last; } iterator row_begin(size_type y) { return this->first + y*w; } iterator row_end(size_type y) { return this->first + y*w + w; } const_iterator row_begin(size_type y) const { return this->first + y*w; } const_iterator row_end(size_type y) const { return this->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 this->first[y*w+x]; } const T& get(size_type x, size_type y) const { return this->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) { this->first[y*w+x] = val; } /*! Fill the array with some value or the default value. */ void fill (const T& val=T()); /*! Resize the array in place, but discard any old array entries */ void resize (int w, int h, const T& val=T()); private: void destroy_elements(); size_type w, h; }; template Array2::Array2(int ww, int hh, const T& val, const A& a) : Array2Base(a, ww*hh), w(ww), h(hh) { std::uninitialized_fill(this->first, this->last, val); } template Array2::Array2(const Array2 &a) : Array2Base(a.alloc, a.last-a.first) { std::uninitialized_copy(a.begin(), a.end(), this->first); } template void Array2::destroy_elements() { for (T* p=this->first; p!=this->last; ++p) p->~T(); } template void Array2::fill (const T& val) { destroy_elements(); std::uninitialized_fill(this->first, this->last, val); } /*! Resize the array in place, but discard any old array entries */ template void Array2::resize (int w_, int h_, const T& val) { destroy_elements(); Array2Base::resize(w_*h_); std::uninitialized_fill(this->first, this->last, val); w = w_; h = h_; } template void Array2::swap(Array2 &a2) { std::swap(this->first, a2.first); std::swap(this->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