1 /* 2 * tSmartArray.h 3 * Avida 4 * 5 * Created by David on 3/26/06. 6 * Copyright 1999-2011 Michigan State University. All rights reserved. 7 * 8 * 9 * This file is part of Avida. 10 * 11 * Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License 12 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 13 * 14 * Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License along with Avida. 18 * If not, see <http://www.gnu.org/licenses/>. 19 * 20 */ 21 22 #ifndef tSmartArray_h 23 #define tSmartArray_h 24 25 #include "tArray.h" 26 27 #include <cassert> 28 29 // "I am so smart..." 30 static const int SMRT_INCREASE_MINIMUM = 10; 31 static const int SMRT_INCREASE_FACTOR = 2; 32 static const int SMRT_SHRINK_TEST_FACTOR = 4; 33 34 template <class T> class tSmartArray 35 { 36 private: 37 38 T* m_data; // Data Array 39 int m_size; // Raw Array Size 40 int m_active; // Active Size 41 int m_reserve; 42 43 public: 44 explicit tSmartArray(int size = 0, int reserve = 0) m_data(NULL)45 : m_data(NULL), m_size(0), m_active(0), m_reserve(reserve) { ResizeClear(size); } tSmartArray(const tSmartArray & rhs)46 tSmartArray(const tSmartArray& rhs) : m_data(NULL), m_size(0), m_active(0), m_reserve(0) { this->operator=(rhs); } tSmartArray(const tArray<T> & rhs)47 tSmartArray(const tArray<T>& rhs) : m_data(NULL), m_size(0), m_active(0), m_reserve(0) { this->operator=(rhs); } 48 ~tSmartArray()49 ~tSmartArray() { delete [] m_data; } 50 51 tSmartArray& operator=(const tSmartArray& rhs) 52 { 53 if (m_active != rhs.GetSize()) Resize(rhs.GetSize()); 54 for(int i = 0; i < m_active; i++) m_data[i] = rhs[i]; 55 return *this; 56 } 57 tSmartArray& operator=(const tArray<T>& rhs) 58 { 59 if (m_active != rhs.GetSize()) Resize(rhs.GetSize()); 60 for(int i = 0; i < m_active; i++) m_data[i] = rhs[i]; 61 return *this; 62 } 63 GetReserve()64 int GetReserve() const { return m_reserve; } SetReserve(int reserve)65 void SetReserve(int reserve) { m_reserve = reserve; } 66 GetSize()67 int GetSize() const { return m_active; } 68 ResizeClear(const int in_size)69 void ResizeClear(const int in_size) 70 { 71 assert(m_size >= 0); 72 73 m_active = in_size; 74 m_size = (in_size >= m_reserve) ? in_size : m_reserve; 75 76 if (m_data != NULL) delete [] m_data; 77 78 if (m_size > 0) { 79 m_data = new T[m_size]; // Allocate block for data 80 assert(m_data != NULL); // Memory allocation error: Out of Memory? 81 } 82 else m_data = NULL; 83 } 84 Resize(int new_size)85 void Resize(int new_size) 86 { 87 assert(new_size >= 0); 88 89 // If we're already at the size we want, don't bother doing anything. 90 if (new_size == m_active) return; 91 92 // If new size is 0, clean up and go! 93 if (new_size == 0) { 94 if (m_data != NULL) delete [] m_data; 95 m_data = NULL; 96 m_size = 0; 97 m_active = 0; 98 return; 99 } 100 101 // Determine if we need to adjust the allocated array sizes... 102 int shrink_test = new_size * SMRT_SHRINK_TEST_FACTOR; 103 if (new_size > m_size || (shrink_test < m_size && shrink_test >= m_reserve)) { 104 int new_array_size = new_size * SMRT_INCREASE_FACTOR; 105 const int new_array_min = new_size + SMRT_INCREASE_MINIMUM; 106 if (new_array_min > new_array_size) new_array_size = new_array_min; 107 108 T* new_data = new T[new_array_size]; 109 assert(new_data != NULL); // Memory Allocation Error: Out of Memory? 110 111 // Copy over old data... 112 for (int i = 0; i < m_active && i < new_size; i++) { 113 new_data[i] = m_data[i]; 114 } 115 if (m_data != NULL) delete [] m_data; // remove old data if exists 116 m_data = new_data; 117 118 m_size = new_array_size; 119 } 120 121 m_active = new_size; 122 } 123 Resize(int new_size,const T & empty_value)124 void Resize(int new_size, const T& empty_value) 125 { 126 int old_size = m_active; 127 Resize(new_size); 128 for (int i = old_size; i < new_size; i++) m_data[i] = empty_value; 129 } 130 131 T& operator[](const int index) 132 { 133 assert(index >= 0); // Lower Bounds Error 134 assert(index < m_active); // Upper Bounds Error 135 return m_data[index]; 136 } 137 const T& operator[](const int index) const 138 { 139 assert(index >= 0); // Lower Bounds Error 140 assert(index < m_active); // Upper Bounds Error 141 return m_data[index]; 142 } 143 144 145 // Stack-like Methods... Push(const T & value)146 void Push(const T& value) 147 { 148 Resize(m_active + 1); 149 m_data[m_active - 1] = value; 150 } 151 Pop()152 T Pop() 153 { 154 T value = m_data[m_active - 1]; 155 Resize(m_active - 1); 156 return value; 157 } 158 159 Swap(int idx1,int idx2)160 void Swap(int idx1, int idx2) 161 { 162 assert(idx1 >= 0); // Lower Bounds Error 163 assert(idx1 < m_active); // Upper Bounds Error 164 assert(idx2 >= 0); // Lower Bounds Error 165 assert(idx2 < m_active); // Upper Bounds Error 166 167 T v = m_data[idx1]; 168 m_data[idx1] = m_data[idx2]; 169 m_data[idx2] = v; 170 } 171 172 SetAll(const T & value)173 void SetAll(const T& value) 174 { 175 for (int i = 0; i < m_active; i++) m_data[i] = value; 176 } 177 }; 178 179 #endif 180