Seg3D  2.4
Seg3D is a free volume segmentation and processing tool developed by the NIH Center for Integrative Biomedical Computing at the University of Utah Scientific Computing and Imaging (SCI) Institute.
the_dynamic_array.hxx
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2016 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27 */
28 
29 // File : the_dynamic_array.hxx
30 // Author : Pavel A. Koshevoy
31 // Created : Fri Oct 31 17:16:25 MDT 2003
32 // Copyright : (C) 2004-2008 University of Utah
33 // Description : Implementation of a dynamically resizable array
34 // that grows automatically.
35 
36 #ifndef THE_DYNAMIC_ARRAY_HXX_
37 #define THE_DYNAMIC_ARRAY_HXX_
38 
39 // system includes:
40 #include <algorithm>
41 #include <iostream>
42 #include <vector>
43 
44 // forward declarations:
45 template<class T> class the_dynamic_array_t;
46 
47 #undef min
48 #undef max
49 
50 
51 //----------------------------------------------------------------
52 // the_dynamic_array_ref_t
53 //
54 template<class T>
56 {
57 public:
59  size_t index = 0):
60  array_(array),
61  index_(index)
62  {}
63 
64  inline the_dynamic_array_ref_t<T> & operator << (const T & elem)
65  {
66  array_[index_++] = elem;
67  return *this;
68  }
69 
70 private:
71  // reference to the array:
72  the_dynamic_array_t<T> & array_;
73 
74  // current index into the array:
75  size_t index_;
76 };
77 
78 
79 //----------------------------------------------------------------
80 // the_dynamic_array_t
81 //
82 template<class T>
84 {
85 public:
87  array_(NULL),
88  page_size_(16),
89  size_(0),
90  init_value_()
91  {}
92 
93  the_dynamic_array_t(const size_t & init_size):
94  array_(NULL),
95  page_size_(init_size),
96  size_(0),
97  init_value_()
98  {}
99 
100  the_dynamic_array_t(const size_t & init_size,
101  const size_t & page_size,
102  const T & init_value):
103  array_(NULL),
104  page_size_(page_size),
105  size_(0),
106  init_value_(init_value)
107  {
108  resize(init_size);
109  }
110 
111  // copy constructor:
113  array_(NULL),
114  page_size_(0),
115  size_(0),
116  init_value_(a.init_value_)
117  {
118  (*this) = a;
119  }
120 
121  // destructor:
123  {
124  clear();
125  }
126 
127  // remove all contents of this array:
128  void clear()
129  {
130  size_t num = num_pages();
131  for (size_t i = 0; i < num; i++)
132  {
133  delete (*array_)[i];
134  }
135 
136  delete array_;
137  array_ = NULL;
138 
139  size_ = 0;
140  }
141 
142  // the assignment operator:
143  the_dynamic_array_t<T> & operator = (const the_dynamic_array_t<T> & array)
144  {
145  clear();
146 
147  page_size_ = array.page_size_;
148  init_value_ = array.init_value_;
149 
150  resize(array.size_);
151  for (size_t i = 0; i < size_; i++)
152  {
153  (*this)[i] = array[i];
154  }
155 
156  return *this;
157  }
158 
159  // resize the array, all contents will be preserved:
160  void resize(const size_t & new_size)
161  {
162  // bump the current size value:
163  size_ = new_size;
164 
165  // do nothing if resizing is unnecessary:
166  if (size_ <= max_size()) return;
167 
168  // we'll have to do something about the existing data:
169  size_t old_num_pages = num_pages();
170  size_t new_num_pages =
171  std::max((size_t)(2 * old_num_pages),
172  (size_t)(1 + size_ / page_size_));
173 
174  // create a new array:
175  std::vector< std::vector<T> * > * new_array =
176  new std::vector< std::vector<T> * >(new_num_pages);
177 
178  // shallow-copy the old content:
179  for (size_t i = 0; i < old_num_pages; i++)
180  {
181  (*new_array)[i] = (*array_)[i];
182  }
183 
184  // initialize the new pages:
185  for (size_t i = old_num_pages; i < new_num_pages; i++)
186  {
187  (*new_array)[i] = new std::vector<T>(page_size_);
188  for (size_t j = 0; j < page_size_; j++)
189  {
190  (*(*new_array)[i])[j] = init_value_;
191  }
192  }
193 
194  // get rid of the old array:
195  delete array_;
196 
197  // put the new array in place of the old array:
198  array_ = new_array;
199  }
200 
201  // the size of this array:
202  inline const size_t & size() const
203  { return size_; }
204 
205  inline const size_t & page_size() const
206  { return page_size_; }
207 
208  // maximum usable size of the array that does not require resizing the array:
209  inline size_t max_size() const
210  { return num_pages() * page_size_; }
211 
212  // number of pages currently allocated:
213  inline size_t num_pages() const
214  { return (array_ == NULL) ? 0 : array_->size(); }
215 
216  inline const T * page(const size_t & page_index) const
217  { return &((*(*array_)[page_index])[0]); }
218 
219  inline T * page(const size_t & page_index)
220  { return &((*(*array_)[page_index])[0]); }
221 
222  // return either first or last index into the array:
223  inline size_t end_index(bool last) const
224  {
225  if (last == false) return 0;
226  return size_ - 1;
227  }
228 
229  // return either first or last element in the array:
230  inline const T & end_elem(bool last) const
231  { return elem(end_index(last)); }
232 
233  inline T & end_elem(bool last)
234  { return elem(end_index(last)); }
235 
236  inline const T & front() const
237  { return end_elem(false); }
238 
239  inline T & front()
240  { return end_elem(false); }
241 
242  inline const T & back() const
243  { return end_elem(true); }
244 
245  inline T & back()
246  { return end_elem(true); }
247 
248  // non-const accessors:
249  inline T & elem(const size_t i)
250  {
251  if (i >= size_) resize(i + 1);
252  return (*(*array_)[i / page_size_])[i % page_size_];
253  }
254 
255  inline T & operator [] (const size_t & i)
256  { return elem(i); }
257 
258  // const accessors:
259  inline const T & elem(const size_t & i) const
260  { return (*((*array_)[i / page_size_]))[i % page_size_]; }
261 
262  inline const T & operator [] (const size_t & i) const
263  { return elem(i); }
264 
265  // this is usefull for filling-in the array:
266  the_dynamic_array_ref_t<T> operator << (const T & elem)
267  {
268  (*this)[0] = elem;
269  return the_dynamic_array_ref_t<T>(*this, 1);
270  }
271 
272  // grow the array by one and insert a new element at the tail:
273  inline void push_back(const T & elem)
274  { (*this)[size_] = elem; }
275 
276  inline void append(const T & elem)
277  { push_back(elem); }
278 
279  // return the index of the first occurrence of a given element in the array:
280  size_t index_of(const T & element) const
281  {
282  for (size_t i = 0; i < size_; i++)
283  {
284  if (!(elem(i) == element)) continue;
285  return i;
286  }
287 
288  return ~0u;
289  }
290 
291  // check whether this array contains a given element:
292  inline bool has(const T & element) const
293  { return index_of(element) != ~0u; }
294 
295  // remove an element from the array:
296  bool remove(const T & element)
297  {
298  size_t idx = index_of(element);
299  if (idx == ~0u) return false;
300 
301  for (size_t i = idx + 1; i < size_; i++)
302  {
303  elem(i - 1) = elem(i);
304  }
305 
306  size_--;
307  return true;
308  }
309 
310  void assign(const size_t & size, const T & element)
311  {
312  resize(size);
313  for (size_t i = 0; i < size; i++)
314  {
315  elem(i) = element;
316  }
317  }
318 
319  // for debugging, dumps this list into a stream:
320  void dump(std::ostream & strm) const
321  {
322  strm << "the_dynamic_array_t(" << (void *)this << ") {\n";
323  for (size_t i = 0; i < size_; i++)
324  {
325  strm << elem(i) << std::endl;
326  }
327  strm << '}';
328  }
329 
330 protected:
331  // an array of pointers to arrays (pages) of data:
332  std::vector< std::vector<T> *> * array_;
333 
334  // page size:
335  size_t page_size_;
336 
337  // current array size:
338  size_t size_;
339 
340  // init value used when resizing the array:
341  T init_value_;
342 };
343 
344 //----------------------------------------------------------------
345 // operator <<
346 //
347 template <class T>
348 std::ostream &
349 operator << (std::ostream & s, const the_dynamic_array_t<T> & a)
350 {
351  a.dump(s);
352  return s;
353 }
354 
355 
356 #endif // THE_DYNAMIC_ARRAY_HXX_
Definition: the_dynamic_array.hxx:45
Definition: the_dynamic_array.hxx:55