Array.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_ARRAY_H_
00002 #define SimTK_SimTKCOMMON_ARRAY_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTKcommon                               *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-7 Stanford University and the Authors.         *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00035 #include "SimTKcommon/internal/common.h"
00036 
00037 #include <cstddef>
00038 #include <cassert>
00039 #include <ostream>
00040 
00041 
00042 namespace SimTKimpl {
00043     
00044 class ArrayHelperImpl;
00045 
00050 class SimTK_SimTKCOMMON_EXPORT ArrayHelper {
00051 public:     
00052     // no default constructor
00053     explicit ArrayHelper(const TypeManipulatorT&, int n=0);
00054     ArrayHelper(const TypeManipulatorT&, int n, const void* ival, bool repeat);
00055     ArrayHelper(const ArrayHelper&);
00056 
00057     // Sub-array constructors, read only and writable
00058     ArrayHelper(const ArrayHelper&, int offset, int length);
00059     ArrayHelper(ArrayHelper&,       int offset, int length);    
00060     
00061     ~ArrayHelper();
00062     ArrayHelper& operator=(const ArrayHelper&);
00063 
00064     void reverse(); // reverse the order of all elements
00065     
00066     // use signed integers to avoid signed/unsigned mismatch misery
00067     int capacity() const;
00068     int size() const;   
00069         
00070     const void* operator[](int i) const; 
00071     void* operator[](int i);
00072     
00073     void push_back(const void*);
00074     void pop_back();
00075     void clear();
00076     void resize(int n, const void* x=0);
00077     void reserve(int n);
00078     
00079 private:
00080     ArrayHelperImpl* impl;
00081     
00082     ArrayHelperImpl&        updImpl()       {assert(impl); return *impl;}
00083     const ArrayHelperImpl&  getImpl() const {assert(impl); return *impl;}
00084 };
00085 
00086 } //namespace SimTKimpl
00087 
00088 namespace SimTK {
00089 template <class T> class Array;
00090 template <class T> class ArrayView;
00091 
00092 template <class T> class ArrayBase {
00093 public:
00094     ArrayBase() : ah(type()) { }
00095     explicit ArrayBase(int n) : ah(type(),n) { }
00096     ArrayBase(int n, const T& ival)  : ah(type(),n,&ival,true) { }
00097     ArrayBase(int n, const T* ivals) : ah(type(),n,ivals,false) { }
00098         
00099     // Sub-array constructors, read only and writable, and their operator equivalents
00100     ArrayBase(const ArrayBase& a, int offset, int length) : ah(a.ah,offset,length) { }
00101     ArrayBase(ArrayBase&       a, int offset, int length) : ah(a.ah,offset,length) { }
00102 
00103     // Default copy, assignment, destructor made explicit here for convenient debugging.
00104     // These are "deep" copies.
00105     ArrayBase(const ArrayBase& src) : ah(src.ah) { }
00106     ~ArrayBase() { }
00107     ArrayBase& operator=(const ArrayBase& src) {
00108         if (this != &src)
00109             ah = src.ah;
00110         return *this;
00111     }
00112 
00113     // Assign the same value to every element.
00114     ArrayBase& operator=(const T& x) {
00115         for (int i=0; i < size(); ++i)
00116             (*this)[i] = x;
00117         return *this;
00118     }
00119 
00120     typedef T*       iterator;
00121     typedef const T* const_iterator;
00122     typedef T&       reference;
00123     typedef const T& const_reference;
00124 
00125     reference       front()       {assert(size()); return (*this)[0];}
00126     const_reference front() const {assert(size()); return (*this)[0];}
00127     reference       back()        {assert(size()); return (*this)[size()-1];}
00128     const_reference back()  const {assert(size()); return (*this)[size()-1];}
00129 
00130     // If the Array is empty, begin() and end() both return null so 
00131     // begin()==end() will return true.
00132     iterator       begin()       {return size() ? &front() : 0;}
00133     const_iterator begin() const {return size() ? &front() : 0;}
00134     iterator       end()         {return size() ? &back() + 1 : 0;}
00135     const_iterator end()   const {return size() ? &back() + 1 : 0;}
00136 
00137     void reverse() {ah.reverse();}
00138 
00139     int capacity() const { return ah.capacity(); }
00140     int size()     const { return ah.size(); }
00141 
00142     const T& operator[](int i) const {return getAs(ah[i]);}
00143     T&       operator[](int i)       {return updAs(ah[i]);}
00144     
00145     // Append to end of array.
00146     ArrayBase& operator+=(const T& x) { push_back(x); return *this; }
00147         
00148     void push_back(const T& x)           {ah.push_back(&x);}
00149     void pop_back()                      {ah.pop_back();}
00150     void clear()                         {ah.clear();}
00151     void resize(int n)                   {ah.resize(n);}
00152     void resize(int n, const T& x)       {ah.resize(n,&x);}
00153     void reserve(int n)                  {ah.reserve(n);}
00154     
00155 private:
00156     SimTKimpl::ArrayHelper  ah;
00157     
00158     static const SimTKimpl::TypeManipulatorT& type() {
00159         return SimTKimpl::MakeTypeManipulator<T>::getTypeManipulatorT();
00160     }
00161     static const T& getAs(const void* p) {return SimTKimpl::MakeTypeManipulator<T>::getAs(p);}
00162     static T&       updAs(void* p)       {return SimTKimpl::MakeTypeManipulator<T>::updAs(p);}    
00163 };  
00164 
00181 template <class T> class ArrayView : public ArrayBase<T> {
00182     typedef ArrayBase<T> Base;
00183 public:   
00184     // no default constructor
00185     ArrayView(const ArrayView& v) : Base(v, 0, v.size()) { } // an identical view
00186     explicit ArrayView(const Base& l) : Base(l, 0, l.size()) { }  // a view of the whole thing
00187     ~ArrayView() { } // convenient for debugging
00188        
00189     // Sub-array constructors, read only and writable, and their operator equivalents
00190     ArrayView(const ArrayView& a, int offset, int length) : Base(a,offset,length) { }
00191     ArrayView(ArrayView&       a, int offset, int length) : Base(a,offset,length) { }
00192     ArrayView operator()(int offset, int length) const { return ArrayView(*this, offset, length); }
00193     ArrayView operator()(int offset, int length)       { return ArrayView(*this, offset, length); } 
00194     
00195     // Shallow assignment only (ArrayBase understands)
00196     ArrayView& operator=(const ArrayView& v) { Base::operator=(v); return *this; }
00197     ArrayView& operator=(const Base& b) { Base::operator=(b); return *this; }
00198     
00199     // Conversions
00200     operator const Array<T>&() const { return *reinterpret_cast<const Array<T>*>(this); }
00201     operator Array<T>&()             { return *reinterpret_cast<Array<T>*>(this); }         
00202 private:
00203     // NO DATA MEMBERS ALLOWED
00204     ArrayView() { assert(false); } // default construction not allowed     
00205 };
00206 
00215 template <class T> class Array : public ArrayBase<T> {
00216     typedef ArrayBase<T> Base;
00217 public:
00218     Array() : Base() { }
00219     explicit Array(int n) : Base(n) { }
00220       
00221     // Default copy, assignment, destructor made explicit here for convenient debugging.
00222     // These are "deep" copies.
00223     Array(const Array& src) : Base(src) { }
00224     ~Array() { }
00225     Array& operator=(const Array& src) {Base::operator=(src); return *this;}
00226     // Assign to every element.
00227     Array& operator=(const T& x)       {Base::operator=(x); return *this;}
00228 
00229     // These allocate new space and fill it with copies of the supplied object(s)
00230     Array(int n, const T& ival)  : Base(n,ival) { }
00231     Array(int n, const T* ivals) : Base(n,ivals) { }
00232         
00233     // Sub-array constructors, read only and writable, and their operator equivalents
00234     Array(const Array& a, int offset, int length) : Base(a,offset,length) { }
00235     Array(Array&       a, int offset, int length) : Base(a,offset,length) { }
00236     
00237     const ArrayView<T> operator()(int offset, int length) const 
00238       { return ArrayView<T>(*this, offset, length); }
00239     ArrayView<T>       operator()(int offset, int length)       
00240       { return ArrayView<T>(*this, offset, length); }   
00241     
00242     // Append an element to the end of the Array. TODO: is this confusing?
00243     Array& operator+=(const T& x) { Base::operator+=(x); return *this; }
00244         
00245     // Conversions
00246     operator const ArrayView<T>&() const 
00247       { return *reinterpret_cast<const ArrayView<T>*>(this); }
00248     operator ArrayView<T>&()             
00249       { return *reinterpret_cast<ArrayView<T>*>(this); }
00250 private:
00251     // NO DATA MEMBERS ALLOWED   
00252 };  
00253 
00257 template <class T> inline int
00258 findFirstOf(const Array<T>& a, const T& test) {
00259     for (int i=0; i<a.size(); ++i)
00260         if (a[i] == test) return i;
00261     return -1;
00262 } 
00263 template <class T> inline int
00264 findFirstOf(const ArrayView<T>& a, const T& test) 
00265   { return findFirstOf((const Array<T>&)a,test); }
00266 
00271 
00272 template <class T> inline Array<int>
00273 findAllOf(const Array<T>& a, const T& test) {
00274     Array<int> matches;
00275     for (int i=0; i<a.size(); ++i)
00276         if (a[i] == test) matches.push_back(i);
00277     return matches;
00278 } 
00279 
00280 template <class T> inline Array<int>
00281 findAllOf(const ArrayView<T>& a, const T& test) { 
00282     return findAllOf((const Array<T>&)a,test); 
00283 }
00284 
00288 template <class T> inline bool
00289 contains(const Array<T>& a, const T& test) {
00290     return findFirstOf(a,test) != -1;
00291 }
00292 template <class T> inline bool
00293 contains(const ArrayView<T>& a, const T& test) {
00294     return findFirstOf(a,test) != -1;
00295 }
00296 
00297 template <class T> inline std::ostream&
00298 operator<<(std::ostream& s, const Array<T>& a) {
00299     for (int i=0; i<a.size(); ++i)
00300         s << a[i] << std::endl;
00301     return s;
00302 } 
00303 template <class T> inline std::ostream&
00304 operator<<(std::ostream& s, const ArrayView<T>& a) {
00305     return s << (const Array<T>&)a;
00306 }
00307 
00308 } // namespace SimTK
00309   
00310 #endif // SimTK_SimTKCOMMON_ARRAY_H_

Generated on Fri Sep 26 07:44:07 2008 for SimTKcore by  doxygen 1.5.6