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