libStatGen Software
1
|
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