libStatGen Software  1
ReusableVector.h
00001 /*
00002  *  Copyright (C) 2011  Regents of the University of Michigan,
00003  *                      Hyun Min Kang, Matthew Flickenger, Matthew Snyder,
00004  *                      and Goncalo Abecasis
00005  *
00006  *   This program is free software: you can redistribute it and/or modify
00007  *   it under the terms of the GNU General Public License as published by
00008  *   the Free Software Foundation, either version 3 of the License, or
00009  *   (at your option) any later version.
00010  *
00011  *   This program is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details.
00015  *
00016  *   You should have received a copy of the GNU General Public License
00017  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include <vector>
00021 #include <stdexcept>
00022 
00023 #ifndef __REUSABLE_VECTOR_H__
00024 #define __REUSABLE_VECTOR_H__
00025 
00026 /// Create a vector of DATA_TYPE that reuses created objects to save on
00027 /// memory reallocations.  DATA_TYPE must have a function called clear()
00028 /// that is used to reset it for reuse.
00029 template <class DATA_TYPE>
00030 class ReusableVector
00031 {
00032 public:
00033     ReusableVector(): myCont(), myNextEmpty(0) {}
00034     virtual ~ReusableVector();
00035 
00036     /// Clear the vector contents.
00037     void reset();
00038     /// Clear the vector contents.
00039     void clear() {reset();}
00040 
00041     /// Get a reference to a new entry to be populated so the user can
00042     /// directly populate it rather than having to copy into it.
00043     DATA_TYPE& getNextEmpty();
00044 
00045     /// Get a reference to the data at the specified index.
00046     /// Throws an exception if the index is out of range.
00047     DATA_TYPE& get(unsigned int index) const;
00048 
00049     /// Return the number of populated entries in the vector.
00050     // The next empty position is the same as the size.
00051     int size() const {return(myNextEmpty);}
00052 
00053     void rmLast();
00054 
00055 protected:
00056     std::vector<DATA_TYPE*> myCont;
00057     unsigned int myNextEmpty;
00058 private:
00059     ReusableVector& operator=(const ReusableVector& rv);
00060     ReusableVector(const ReusableVector& rv);
00061 };
00062 
00063 
00064 /////////////////////////////////////////////////////////////
00065 // ReusableVector
00066 template <class DATA_TYPE>
00067 ReusableVector<DATA_TYPE>::~ReusableVector()
00068 {
00069     for(unsigned int i = 0; i < myCont.size(); i++)
00070     {
00071         // Delete all the entries.
00072         delete myCont[i];
00073         myCont[i] = NULL;
00074     }
00075     myCont.clear();
00076     myNextEmpty = 0;
00077 }
00078 
00079 
00080 template <class DATA_TYPE>
00081 void ReusableVector<DATA_TYPE>::reset()
00082 {
00083     // Set the next empty element to be the first one on the list.
00084     // That means there are none used.
00085     myNextEmpty = 0;
00086 }
00087         
00088 
00089 template <class DATA_TYPE>
00090 DATA_TYPE& ReusableVector<DATA_TYPE>::getNextEmpty()
00091 {
00092     if(myNextEmpty == myCont.size())
00093     {
00094         // We are at the end of the available entries, so add a new one.
00095         myCont.resize(myCont.size() + 1);
00096 
00097         // Create a new entry.
00098         myCont[myNextEmpty] = new DATA_TYPE;
00099     }
00100     else
00101     {
00102         // myNextEmpty is an element, and not the end.
00103         // So, clear out the data.
00104         myCont[myNextEmpty]->clear();
00105     }
00106 
00107     DATA_TYPE* returnVal = myCont[myNextEmpty];
00108 
00109     // Increment next empty to the next element.
00110     ++myNextEmpty;
00111     // return the element to be used.
00112     return(*returnVal);
00113 }
00114 
00115 
00116 template <class DATA_TYPE>
00117 DATA_TYPE& ReusableVector<DATA_TYPE>::get(unsigned int index) const
00118 {
00119     if((index < myNextEmpty) && (index >= 0))
00120     {
00121         // index is a valid position, so return that data.
00122         if(myCont[index] == NULL)
00123         {
00124             throw(std::runtime_error("ReusableVector::get BUG, found a null pointer."));
00125         }
00126         return(*myCont[index]);
00127     }
00128 
00129     // Not set in the vector, so throw an exception.
00130     throw(std::runtime_error("ReusableVector::get called with out of range index."));
00131     // return(myCont[0]);
00132 }
00133 
00134 template <class DATA_TYPE>
00135 void ReusableVector<DATA_TYPE>::rmLast()
00136 {
00137     if(myNextEmpty > 0)
00138     {
00139         --myNextEmpty;
00140     }
00141 }
00142 
00143 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends