Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/array

Go to the documentation of this file.
00001 /* **-*-c++-*-**************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: array 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.7 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #ifndef _BASE_ARRAY_
00026 #define _BASE_ARRAY_
00027 
00028 #include <iterator>
00029 #include <stdexcept>
00030 
00031 
00032 namespace base {
00033 
00034 template<typename T>
00035 class array 
00036 {
00037 public:
00038   typedef T value_type;
00039   typedef value_type* pointer;
00040   typedef const value_type* const_pointer;
00041   typedef value_type* iterator;
00042   typedef const value_type* const_iterator;
00043   typedef value_type& reference;
00044   typedef const value_type& const_reference;
00045   typedef Int size_type;
00046   typedef SInt difference_type;
00047 
00048   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00049   typedef std::reverse_iterator<iterator> reverse_iterator;
00050 
00051   array() { init(0,1); }
00052   array(size_type n) { init(n,n); }
00053   array(size_type n, size_type initial_capacity) { init(n,initial_capacity); }
00054 
00055   array(size_type n, T a[], bool by_reference=true) {
00056     if (!by_reference) {
00057       init(n,n);
00058       for(size_type e=0; e<n; ++e) _a[e] = a[e];
00059     }
00060     else {
00061       _size = _capacity = n;
00062       _a = a;
00063       _owner = false;
00064     }
00065   }
00066   
00067   array(const array& a) { 
00068     init(a._size,a._size);
00069     copy(a);
00070   }
00071   
00072   ~array() {
00073     if (_owner) delete[] _a;
00074   }
00075   
00076   
00077   array& operator=(const array& a)
00078   {
00079     copy(a);
00080     return *this;
00081   }
00082 
00083   bool operator==(const array& a) const
00084   {
00085     if (_size != a._size) return false;
00086     for(size_type e=0; e<_size; ++e)
00087       if (!(_a[e] == a._a[e])) return false;
00088     return true;
00089   }
00090 
00091   bool operator!=(const array& a) const
00092   {
00093     if (_size != a._size) return true;
00094     for(size_type e=0; e<_size; ++e)
00095       if (_a[e] != a._a[e]) return true;
00096     return false;
00097   }
00098 
00099 
00100   // 0-based indexing
00101   reference operator[](difference_type i) {
00102 #ifdef DEBUG
00103     if ((size_type(i) >= _size) || (i<0)) {
00104       Assertm( false, "array index within bounds (debug only check)");
00105     }
00106 #endif
00107     return _a[i];
00108   }
00109   
00110   const_reference operator[](difference_type i) const {
00111 #ifdef DEBUG
00112     if ((size_type(i) >= _size) || (i<0)) {
00113       Assertm( false, "array index within bounds (debug only check)");
00114     }
00115 #endif
00116     return _a[i];
00117   }
00118 
00119   // 1-based indexing
00120   reference operator()(difference_type i) {
00121 #ifdef DEBUG
00122     if ((size_type(i) > _size) || (i<1)) {
00123       Assertm( false, "array index within bounds (debug only check)");
00124     }
00125 #endif
00126     return _a[i-1];
00127   }
00128   const_reference operator()(difference_type i) const {
00129 #ifdef DEBUG
00130     if ((size_type(i) > _size) || (i<1)) {
00131       Assertm( false, "array index within bounds (debug only check)");
00132     }
00133 #endif    
00134     return _a[i-1];
00135   }
00136 
00137   // auto resize to index (0-based)
00138   reference at(difference_type i) throw(std::out_of_range) {
00139     if (size_type(i) >= _size) {
00140       if (_owner) 
00141         resize(i+1);
00142       else
00143         throw std::out_of_range(Exception("array index out of bounds"));
00144     }
00145     return _a[i];
00146   }
00147   
00148   size_type size() const { return _size; }
00149   size_type capacity() const { return _capacity; }
00150   
00151   array& clear() 
00152   {
00153     if (_owner) delete[] _a;
00154     init(0,1);
00155     return *this;
00156   }
00157   
00158   bool empty() { return _size == size_type(0); }
00159 
00160   
00161   // swap content of this with a
00162   void swap(array& a) {
00163     T* tmp_a = _a;
00164     size_type tmp_size = _size;
00165     size_type tmp_capacity = _capacity;
00166     bool tmp_owner = _owner;
00167     
00168     _a = a._a;
00169     _size = a._size;
00170     _capacity = a._capacity;
00171     _owner = a._owner;
00172 
00173     a._a = tmp_a;
00174     a._size = tmp_size;
00175     a._capacity = tmp_capacity;
00176     a._owner = tmp_owner;
00177   }
00178 
00179   
00180   // stack operations
00181   reference front() throw(std::out_of_range) {
00182     if (_size>0)
00183       return _a[0];
00184     else
00185       throw std::out_of_range((Exception("array has no elements (no front)")));
00186   }
00187   
00188   const_reference front() const throw(std::out_of_range) {
00189     if (_size>0)
00190       return _a[0];
00191     else
00192       throw std::out_of_range((Exception("array has no elements (no front)")));
00193   }
00194   
00195   reference back() throw(std::out_of_range) {
00196     if (_size>0)
00197       return _a[_size-1];
00198     else
00199       throw std::out_of_range((Exception("array has no elements (no back)")));
00200   }
00201 
00202   const_reference back() const throw(std::out_of_range) {
00203     if (_size>0)
00204       return _a[_size-1];
00205     else
00206       throw std::out_of_range((Exception("array has no elements (no back)")));
00207   }
00208 
00209   void push_back(const T& e) {
00210     resize(_size+1);
00211     _a[_size-1] = e;
00212   }
00213   
00214   void pop_back() throw(std::out_of_range) {
00215     if (_size>0)
00216       resize(_size-1);
00217     else
00218       throw std::out_of_range((Exception("array has no elements (nothing to pop)")));
00219   }
00220 
00221 
00222   iterator begin() { return _a; }
00223   const_iterator begin() const { return _a; }
00224   
00225   iterator end() { return _a + _size; }
00226   const_iterator end() const { return _a + _size; }
00227 
00228   pointer c_array() { return _a; }
00229   const_pointer c_array() const { return _a; }
00230   
00231   //  operator T*() { return _a; }
00232 
00233 
00234   void extend(size_type new_min_capacity)
00235   {
00236     size_type newcapacity = _capacity;
00237     while (newcapacity < new_min_capacity)
00238       newcapacity = size_type((Real(newcapacity) * 1.5) +1);
00239     
00240     if (newcapacity > _capacity) {
00241       T *_olda = _a;
00242       _a = new T[newcapacity];
00243       for(size_type e=0; e<_size; ++e)
00244         _a[e] = _olda[e];
00245       
00246       if (_owner) delete[] _olda;
00247       _capacity = newcapacity;
00248       _owner=true;
00249     }
00250   }
00251 
00252 
00253   array& trim()
00254   {
00255     if (!_owner) return *this;
00256     size_type newcapacity = _size;
00257     if (newcapacity==0) newcapacity=1;
00258     T *_olda = _a;
00259     _a = new T[newcapacity];
00260     for(size_type e=0; e<_size; ++e)
00261       _a[e] = _olda[e];
00262     delete[] _olda;
00263     _capacity = newcapacity;
00264     return *this;
00265   }
00266 
00267   
00268   array& resize(size_type newsize)
00269   {
00270     if (newsize > _capacity) extend(newsize);
00271     _size = newsize;
00272     return *this;
00273   }
00274 
00275 
00276   array& destructive_resize(size_type newsize)
00277   {
00278     if (_owner) delete[] _a;
00279     _size = _capacity = newsize;
00280     _a = new T[_capacity];
00281     _owner = true;
00282     return *this;
00283   }
00284 
00285   
00286 private:
00287   T *_a;
00288   size_type _size;
00289   size_type _capacity;
00290   bool      _owner;  // true if we alloc'd _a, false is it was provided
00291 
00292   void init(size_type size, size_type cap) {
00293     if (cap<size) cap = size;
00294     if (cap<=0) cap=1;
00295     _size=size; _capacity=cap;
00296     _a = new T[_capacity];
00297     _owner = true;
00298   }
00299   
00300   void copy(const array& a)
00301   {
00302     if (_owner)
00303       resize(a._size);
00304     size_type minsize = (_size<a._size)?_size:a._size;
00305     for(size_type e=0; e<minsize; ++e)
00306       _a[e] = a._a[e];
00307   }
00308 
00309 };
00310 
00311 } // base
00312 
00313 #endif

Generated on Thu Jul 29 15:56:03 2004 for OpenSim by doxygen 1.3.6