1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the class library */ 4 /* SoPlex --- the Sequential object-oriented simPlex. */ 5 /* */ 6 /* Copyright (c) 1996-2023 Zuse Institute Berlin (ZIB) */ 7 /* */ 8 /* Licensed under the Apache License, Version 2.0 (the "License"); */ 9 /* you may not use this file except in compliance with the License. */ 10 /* You may obtain a copy of the License at */ 11 /* */ 12 /* http://www.apache.org/licenses/LICENSE-2.0 */ 13 /* */ 14 /* Unless required by applicable law or agreed to in writing, software */ 15 /* distributed under the License is distributed on an "AS IS" BASIS, */ 16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ 17 /* See the License for the specific language governing permissions and */ 18 /* limitations under the License. */ 19 /* */ 20 /* You should have received a copy of the Apache-2.0 license */ 21 /* along with SoPlex; see the file LICENSE. If not email to soplex@zib.de. */ 22 /* */ 23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 24 25 /**@file array.h 26 * @brief Save arrays of arbitrary types. 27 */ 28 #ifndef _ARRAY_H_ 29 #define _ARRAY_H_ 30 31 #include <assert.h> 32 #include <string.h> 33 #include <vector> 34 #include "soplex/spxalloc.h" 35 36 namespace soplex 37 { 38 /**@brief Safe arrays of arbitrary types. 39 @ingroup Elementary 40 41 Class Array provides safe arrays of arbitrary type. Array elements are 42 accessed just like ordinary C++ array elements by means of the index 43 operator[](). Safety is provided by 44 45 - automatic memory management in constructor and destructor 46 preventing memory leaks 47 - checking of array bound when accessing elements with the 48 indexing operator[]() (only when compiled without \c -DNDEBUG). 49 50 Moreover, #Array%s may easily be extended by #insert%ing or 51 #append%ing elements to the Array or shrunken by 52 \ref remove() "removing" 53 elements. Method reSize(int n) resets the Array's length to \p n, 54 thereby appending elements or truncating the Array to the 55 required size. 56 57 An Array is implemented in a C++-compliant way with respect to 58 how memory is managed: Only operators new and delete are 59 used for allocating memory. This involves some overhead for all 60 methods effecting the length of an Array, i.e., all methods 61 insert(), append(), remove() and reSize(). This involves 62 allocating a new C++ array of the new size and copying all 63 elements with the template parameters operator=(). 64 65 For this reason, it is not convenient to use class Array if its elements 66 are \ref DataObjects "Data Objects". In this case use class DataArray 67 instead. 68 69 @see DataArray, \ref DataObjects "Data Objects" 70 */ 71 template < class T > 72 class Array 73 { 74 static_assert(!std::is_same<T, bool>::value, 75 "Since Array wraps std::vector, bool is not allowed to avoid unallowed behavior"); 76 protected: 77 78 //---------------------------------------- 79 /**@name Data */ 80 ///@{ 81 std::vector<T> data; 82 ///@} 83 84 public: 85 86 //---------------------------------------- 87 /**@name Access / modification */ 88 ///@{ 89 /// reference \p n 'th element. 90 T& operator[](int n) 91 { 92 assert(n >= 0 && n < int(data.capacity())); 93 return data[n]; 94 } 95 /// reference \p n 'th element. 96 const T& operator[](int n) const 97 { 98 assert(n >= 0 && n < int(data.capacity())); 99 return data[n]; 100 } 101 102 /** This function serves for using a Vector in an C-style 103 * function. It returns a pointer to the first value of the array. 104 */ 105 T* get_ptr() 106 { 107 return data.data(); 108 } 109 /// get a const C pointer to the data. 110 const T* get_const_ptr() const 111 { 112 return data.data(); 113 } 114 115 /// append 1 elements with value \p t. 116 void append(const T& t) 117 { 118 data.push_back(t); 119 } 120 /// append \p n uninitialized elements. 121 void append(int n) 122 { 123 T newt = T(); 124 this->append(n, newt); 125 } 126 /// append \p n elements with value \p t. 127 void append(int n, const T& t) 128 { 129 data.insert(data.end(), n, t); 130 } 131 /// append \p n elements from \p t. 132 void append(int n, const T t[]) 133 { 134 data.insert(data.end(), t, t + n); 135 } 136 /// append all elements from \p p_array. 137 void append(const Array<T>& t) 138 { 139 data.insert(data.end(), t.data.begin(), t.data.end()); 140 } 141 142 /// insert \p n uninitialized elements before \p i 'th element. 143 void insert(int i, int n) 144 { 145 T newt = T(); 146 147 if(n > 0) 148 data.insert(data.begin() + i - 1, n, newt); 149 } 150 151 /// insert \p n elements with value \p t before \p i 'the element. 152 void insert(int i, int n, const T& t) 153 { 154 if(n > 0) 155 { 156 data.insert(data.begin() + i - 1, n, t); 157 } 158 } 159 160 /// insert \p n elements from \p p_array before \p i 'th element. 161 void insert(int i, int n, const T t[]) 162 { 163 if(n > 0) 164 { 165 data.insert(data.begin() + i - 1, t, t + n); 166 } 167 } 168 169 /// insert all elements from \p p_array before \p i 'th element. 170 void insert(int i, const Array<T>& t) 171 { 172 if(t.size()) 173 { 174 data.insert(data.begin() + i - 1, t.data.begin(), t.data.end()); 175 } 176 } 177 178 /// remove \p m elements starting at \p n. 179 void remove(int n = 0, int m = 1) 180 { 181 assert(n < size() && n >= 0); 182 183 if(n + m < size()) 184 { 185 data.erase(data.begin() + n, data.begin() + n + m); 186 } 187 else 188 { 189 data.erase(data.begin() + n, data.end()); 190 } 191 } 192 193 /// remove all elements. 194 void clear() 195 { 196 data.clear(); 197 } 198 199 /// return the number of elements. 200 int size() const 201 { 202 return int(data.size()); 203 } 204 205 /// reset the number of elements. 206 void reSize(int newsize) 207 { 208 data.resize(newsize); 209 } 210 211 ///@} 212 213 //---------------------------------------- 214 /**@name Construction / destruction */ 215 ///@{ 216 /// assignment operator. 217 Array<T>& operator=(const Array<T>& rhs) 218 { 219 if(this != &rhs) 220 { 221 reSize(rhs.size()); 222 data = rhs.data; 223 } 224 225 return *this; 226 } 227 228 // Move assignment for Array 229 Array& operator=(const Array&& rhs) 230 { 231 data = std::move(rhs.data); 232 return *this; 233 } 234 235 /// default constructor. 236 /** The constructor allocates an Array of \p n uninitialized elements. 237 */ 238 explicit 239 Array(int n = 0) 240 { 241 data.resize(n); 242 } 243 244 /// copy constructor 245 Array(const Array& old) 246 { 247 data = old.data; 248 } 249 250 /// destructor 251 ~Array() 252 { 253 ; 254 } 255 256 void push_back(const T& val) 257 { 258 data.push_back(val); 259 } 260 261 void push_back(T&& val) 262 { 263 data.push_back(val); 264 } 265 266 /// Consistency check. 267 bool isConsistent() const 268 { 269 return true; 270 } 271 272 ///@} 273 }; 274 } // namespace soplex 275 #endif // _ARRAY_H_ 276