Scippy

SoPlex

Sequential object-oriented simPlex

array.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2019 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file array.h
17  * @brief Save arrays of arbitrary types.
18  */
19 #ifndef _ARRAY_H_
20 #define _ARRAY_H_
21 
22 #include <assert.h>
23 #include <string.h>
24 #include "soplex/spxalloc.h"
25 
26 namespace soplex
27 {
28 /**@brief Safe arrays of arbitrary types.
29  @ingroup Elementary
30 
31  Class Array provides safe arrays of arbitrary type. Array elements are
32  accessed just like ordinary C++ array elements by means of the index
33  operator[](). Safety is provided by
34 
35  - automatic memory management in constructor and destructure
36  preventing memory leaks
37  - checking of array bound when accessing elements with the
38  indexing operator[]() (only when compiled without \c -DNDEBUG).
39 
40  Moreover, #Array%s may easily be extended by #insert%ing or
41  #append%ing elements to the Array or shrunken by
42  \ref remove() "removing"
43  elements. Method reSize(int n) resets the Array's length to \p n,
44  thereby appending elements or truncating the Array to the
45  required size.
46 
47  An Array is implemented in a C++-compliant way with respect to
48  how memory is managed: Only operators new and delete are
49  used for allocating memory. This involves some overhead for all
50  methods effecting the length of an Array, i.e., all methods
51  insert(), append(), remove() and reSize(). This involves
52  allocating a new C++ array of the new size and copying all
53  elements with the template parameters operator=().
54 
55  For this reason, it is not convenient to use class Array if its elements
56  are \ref DataObjects "Data Objects". In this case use class DataArray
57  instead.
58 
59  @see DataArray, \ref DataObjects "Data Objects"
60 */
61 template < class T >
62 class Array
63 {
64 protected:
65 
66  //----------------------------------------
67  /**@name Data */
68  //@{
69  int num; ///< the length of array data
70  T* data; ///< the array of elements
71  //@}
72 
73 public:
74 
75  //----------------------------------------
76  /**@name Access / modification */
77  //@{
78  /// reference \p n 'th element.
79  T& operator[](int n)
80  {
81  assert(n >= 0 && n < num);
82  return data[n];
83  }
84  /// reference \p n 'th element.
85  const T& operator[](int n) const
86  {
87  assert(n >= 0 && n < num);
88  return data[n];
89  }
90 
91  /** This function serves for using a Vector in an C-style
92  * function. It returns a pointer to the first value of the array.
93  */
94  T* get_ptr()
95  {
96  return data;
97  }
98 
99  /// append \p n uninitialized elements.
100  void append(int n)
101  {
102  insert(num, n);
103  }
104  /// append \p n elements from \p p_array.
105  void append(int n, const T* p_array)
106  {
107  insert(num, n, p_array);
108  }
109  /// append all elements from \p p_array.
110  void append(const Array<T>& p_array)
111  {
112  insert(num, p_array);
113  }
114 
115  /** insert \p n uninitialized elements before \p i 'th element.
116  *
117  * You must not! use realloc, memcpy or memmove, because some data element points inside itself, and therefore you
118  * always need to copy all elements by hand.
119  */
120  void insert(int i, int n)
121  {
122  assert(i <= num);
123  assert(num >= 0);
124 
125  if(n > 0)
126  {
127  T* newdata = 0;
128  int k;
129 
130  spx_alloc(newdata, num + n);
131  assert(newdata != 0);
132 
133  // copy front segment to new array
134  for(k = 0; k < i; ++k)
135  {
136  new(&(newdata[k])) T();
137  newdata[k] = data[k];
138  data[k].~T();
139  }
140 
141  // call constructor for new elements
142  for(; k < i + n; ++k)
143  new(&(newdata[k])) T();
144 
145  // copy rear segment to new array
146  for(k = i; k < num; ++k)
147  {
148  new(&(newdata[n + k])) T();
149  newdata[n + k] = data[k];
150  data[k].~T();
151  }
152 
153  if(data)
154  spx_free(data);
155 
156  data = newdata;
157  num += n;
158  }
159  }
160 
161  /// insert \p n elements from \p p_array before \p i 'th element.
162  void insert(int i, int n, const T* p_array)
163  {
164  insert(i, n);
165 
166  for(n--; n >= 0; --n)
167  data[n + i] = p_array[n];
168  }
169 
170  /// insert all elements from \p p_array before \p i 'th element.
171  void insert(int i, const Array<T>& p_array)
172  {
173  int n = p_array.size();
174  insert(i, n);
175 
176  for(n--; n >= 0; --n)
177  data[n + i] = p_array.data[n];
178  }
179 
180  /** remove \p m elements starting at \p n.
181  *
182  * You must not! use realloc, memcpy or memmove, because some data element points inside itself, and therefore you
183  * always need to copy all elements by hand.
184  */
185  void remove(int n = 0, int m = 1)
186  {
187  assert(n >= 0 && m >= 0);
188 
189  if(m > 0 && n < num)
190  {
191  T* newdata = 0;
192  int k;
193 
194  assert(num == size());
195  m -= (n + m <= num) ? 0 : n + m - num;
196 
197  if(num > m)
198  {
199  spx_alloc(newdata, num - m);
200  assert(newdata != 0);
201 
202  // copy rear segment to new array
203  for(k = num - 1; k >= n + m; --k)
204  {
205  new(&(newdata[k - m])) T();
206  newdata[k - m] = data[k];
207  data[k].~T();
208  }
209 
210  // call destructor for old elements
211  for(; k >= n; --k)
212  data[k].~T();
213 
214  // copy front segment to new array
215  for(; k >= 0; --k)
216  {
217  new(&(newdata[k])) T();
218  newdata[k] = data[k];
219  data[k].~T();
220  }
221  }
222  else
223  {
224  assert(num == m);
225  assert(n == 0);
226 
227  // call destructor for old elements
228  for(k = m - 1; k >= 0; --k)
229  data[k].~T();
230  }
231 
232  assert(data != 0);
233  spx_free(data);
234  data = newdata;
235 
236  num -= m;
237  assert((data == 0) == (num == 0));
238  }
239  }
240 
241  /// remove all elements.
242  void clear()
243  {
244  // call destructors of all elements
245  while(num > 0)
246  {
247  --num;
248  data[num].~T();
249  }
250 
251  if(data)
252  spx_free(data);
253 
254  assert(num == 0);
255  }
256 
257  /// return the number of elements.
258  int size() const
259  {
260  return num;
261  }
262 
263  /// reset the number of elements.
264  void reSize(int newsize)
265  {
266  if(newsize < num)
267  remove(newsize, num - newsize);
268  else if(newsize > num)
269  append(newsize - num);
270  }
271  //@}
272 
273  //----------------------------------------
274  /**@name Construction / destruction */
275  //@{
276  /// assignment operator.
277  /** Assigning an rvalue Array to an lvalue Array involves resizing
278  * the lvalue to the rvalues size() and copying all elements via
279  * the Array element's assignment operator=().
280  */
282  {
283  if(this != &rhs)
284  {
285  reSize(rhs.size());
286 
287  for(int i = 0; i < num; ++i)
288  data[i] = rhs.data[i];
289 
290  assert(Array::isConsistent());
291  }
292 
293  return *this;
294  }
295 
296  /// default constructor.
297  /** The constructor allocates an Array of \p n uninitialized elements.
298  */
299  explicit
300  Array(int n = 0)
301  : data(0)
302  {
303  assert(n >= 0);
304  num = n;
305 
306  if(num > 0)
307  {
308  int k;
309 
310  spx_alloc(data, num);
311  assert(data != 0);
312 
313  for(k = 0; k < num; ++k)
314  new(&(data[k])) T();
315  }
316 
317  assert(Array::isConsistent());
318  }
319 
320  /// copy constructor
321  Array(const Array<T>& old)
322  : num(old.num)
323  {
324  if(num > 0)
325  {
326  int k;
327 
328  data = 0;
329  spx_alloc(data, num);
330  assert(data != 0);
331 
332  for(k = 0; k < num; ++k)
333  {
334  new(&(data[k])) T();
335  data[k] = old.data[k];
336  }
337  }
338  else
339  data = 0;
340 
341  assert(Array::isConsistent());
342  }
343 
344  /// destructor
346  {
347  while(num > 0)
348  {
349  --num;
350  data[num].~T();
351  }
352 
353  if(data)
354  spx_free(data);
355  }
356 
357  /// consistency check
358  bool isConsistent() const
359  {
360 #ifdef ENABLE_CONSISTENCY_CHECKS
361 
362  if(num < 0 || (num > 0 && data == 0))
363  return MSGinconsistent("Array");
364 
365 #endif
366 
367  return true;
368  }
369  //@}
370 };
371 } // namespace soplex
372 #endif // _ARRAY_H_
Memory allocation routines.
int size() const
return the number of elements.
Definition: array.h:258
bool isConsistent() const
consistency check
Definition: array.h:358
const T & operator[](int n) const
reference n &#39;th element.
Definition: array.h:85
Safe arrays of arbitrary types.Class Array provides safe arrays of arbitrary type. Array elements are accessed just like ordinary C++ array elements by means of the index operator[](). Safety is provided by.
Definition: array.h:62
void insert(int i, int n, const T *p_array)
insert n elements from p_array before i &#39;th element.
Definition: array.h:162
T * data
the array of elements
Definition: array.h:70
void clear()
remove all elements.
Definition: array.h:242
void append(const Array< T > &p_array)
append all elements from p_array.
Definition: array.h:110
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
Array< T > & operator=(const Array< T > &rhs)
assignment operator.
Definition: array.h:281
void insert(int i, const Array< T > &p_array)
insert all elements from p_array before i &#39;th element.
Definition: array.h:171
T & operator[](int n)
reference n &#39;th element.
Definition: array.h:79
~Array()
destructor
Definition: array.h:345
T * get_ptr()
Definition: array.h:94
Everything should be within this namespace.
void reSize(int newsize)
reset the number of elements.
Definition: array.h:264
void append(int n, const T *p_array)
append n elements from p_array.
Definition: array.h:105
Array(const Array< T > &old)
copy constructor
Definition: array.h:321
Array(int n=0)
default constructor.
Definition: array.h:300
void append(int n)
append n uninitialized elements.
Definition: array.h:100
#define MSGinconsistent(name)
Definition: spxdefines.h:126
void insert(int i, int n)
Definition: array.h:120
int num
the length of array data
Definition: array.h:69
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:110