0030478: Foundation Classes, NCollection_Array2 - provide Resize/Move methods consist...
[occt.git] / src / NCollection / NCollection_Array2.hxx
CommitLineData
b311480e 1// Created on: 2002-04-15
2// Created by: Alexander Kartomin (akm)
973c2be1 3// Copyright (c) 2002-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
16#ifndef NCollection_Array2_HeaderFile
17#define NCollection_Array2_HeaderFile
18
7fd59977 19#include <Standard_DimensionMismatch.hxx>
20#include <Standard_OutOfMemory.hxx>
21#include <Standard_OutOfRange.hxx>
7fd59977 22
ddf2fe8e 23#include <NCollection_DefineAlloc.hxx>
7fd59977 24
7fd59977 25// *********************************************** Template for Array2 class
26/**
27* Purpose: The class Array2 represents bi-dimensional arrays
28* of fixed size known at run time.
29* The ranges of indices are user defined.
92435cd0 30*
31* Class allocates one 1D array storing full data (all Rows and Columns)
32* and extra 1D array storing pointers to each Row.
33*
34* Warning: Programs clients of such class must be independent
7fd59977 35* of the range of the first element. Then, a C++ for
36* loop must be written like this
37*
38* for (i = A.LowerRow(); i <= A.UpperRow(); i++)
39* for (j = A.LowerCol(); j <= A.UpperCol(); j++)
40*/
ddf2fe8e 41template <class TheItemType>
42class NCollection_Array2
7fd59977 43{
79a35943 44public:
45 //! STL-compliant typedef for value type
46 typedef TheItemType value_type;
47
48public:
7fd59977 49 // **************** Implementation of the Iterator interface.
ddf2fe8e 50 class Iterator
7fd59977 51 {
52 public:
53 //! Empty constructor - for later Init
54 Iterator (void) :
55 myCurrent (0),
56 mySize (0),
57 myArray (NULL) {}
58 //! Constructor with initialisation
59 Iterator (const NCollection_Array2& theArray) :
60 myCurrent (0),
61 mySize (theArray.Length()),
62 myArray ((NCollection_Array2 *) &theArray) {}
63 //! Initialisation
64 void Init (const NCollection_Array2& theArray)
65 {
66 myCurrent = 0;
67 mySize = theArray.Length();
68 myArray = (NCollection_Array2 *) &theArray;
69 }
70 //! Check end
ddf2fe8e 71 Standard_Boolean More (void) const
7fd59977 72 { return (myCurrent < mySize); }
73 //! Make step
ddf2fe8e 74 void Next (void)
7fd59977 75 { myCurrent++; }
76 //! Constant value access
ddf2fe8e 77 const TheItemType& Value (void) const
7fd59977 78 { return myArray->myStart[myCurrent]; }
79 //! Variable value access
ddf2fe8e 80 TheItemType& ChangeValue (void) const
7fd59977 81 { return myArray->myStart[myCurrent]; }
7fd59977 82 private:
83 Standard_Integer myCurrent; //!< Index of the current item
84 Standard_Integer mySize; //!< Total amount of items
85 NCollection_Array2* myArray; //!< Pointer to the array being iterated
86 }; // End of nested class Iterator
87
88 public:
89 // ---------- PUBLIC METHODS ------------
90
92435cd0 91 //! Empty constructor; should be used with caution.
92 //! @sa methods Resize() and Move().
93 NCollection_Array2()
94 : myLowerRow (1),
95 myUpperRow (0),
96 myLowerCol (1),
97 myUpperCol (0),
98 myData (NULL),
99 myStart (NULL),
100 myDeletable(false)
101 {
102 //
103 }
104
7fd59977 105 //! Constructor
106 NCollection_Array2(const Standard_Integer theRowLower,
107 const Standard_Integer theRowUpper,
108 const Standard_Integer theColLower,
109 const Standard_Integer theColUpper) :
7fd59977 110 myLowerRow (theRowLower),
111 myUpperRow (theRowUpper),
112 myLowerCol (theColLower),
113 myUpperCol (theColUpper),
114 myDeletable (Standard_True)
115 { Allocate(); }
116
117 //! Copy constructor
118 NCollection_Array2 (const NCollection_Array2& theOther) :
7fd59977 119 myLowerRow (theOther.LowerRow()),
120 myUpperRow (theOther.UpperRow()),
121 myLowerCol (theOther.LowerCol()),
122 myUpperCol (theOther.UpperCol()),
123 myDeletable (Standard_True)
124 {
125 Allocate();
126 *this = theOther;
127 }
128
92435cd0 129#ifndef OCCT_NO_RVALUE_REFERENCE
130 //! Move constructor
131 NCollection_Array2 (NCollection_Array2&& theOther)
132 : myLowerRow (theOther.myLowerRow),
133 myUpperRow (theOther.myUpperRow),
134 myLowerCol (theOther.myLowerRow),
135 myUpperCol (theOther.myUpperCol),
136 myData (theOther.myData),
137 myStart (theOther.myStart),
138 myDeletable(theOther.myDeletable)
139 {
140 theOther.myStart = NULL;
141 theOther.myData = NULL;
142 theOther.myDeletable = false;
143 }
144#endif
145
7fd59977 146 //! C array-based constructor
147 NCollection_Array2(const TheItemType& theBegin,
148 const Standard_Integer theRowLower,
149 const Standard_Integer theRowUpper,
150 const Standard_Integer theColLower,
151 const Standard_Integer theColUpper) :
7fd59977 152 myLowerRow (theRowLower),
153 myUpperRow (theRowUpper),
154 myLowerCol (theColLower),
155 myUpperCol (theColUpper),
156 myDeletable (Standard_False)
157 {
158 myStart = (TheItemType *) &theBegin;
159 Allocate();
160 }
161
162 //! Initialise the values
163 void Init (const TheItemType& theValue)
164 {
165 TheItemType *pCur, *pEnd=myStart+Size();
166 for(pCur = myStart; pCur<pEnd; pCur++)
167 *pCur = theValue;
168 }
169
170 //! Size (number of items)
ddf2fe8e 171 Standard_Integer Size (void) const
7fd59977 172 { return Length(); }
173 //! Length (number of items)
174 Standard_Integer Length (void) const
92435cd0 175 { return NbRows() * NbColumns(); }
176
177 //! Returns number of rows
178 Standard_Integer NbRows() const { return myUpperRow - myLowerRow + 1; }
179
180 //! Returns number of columns
181 Standard_Integer NbColumns() const { return myUpperCol - myLowerCol + 1; }
7fd59977 182
9535c4be 183 //! Returns length of the row, i.e. number of columns
92435cd0 184 Standard_Integer RowLength() const { return NbColumns(); }
9535c4be 185
186 //! Returns length of the column, i.e. number of rows
92435cd0 187 Standard_Integer ColLength() const { return NbRows(); }
7fd59977 188
189 //! LowerRow
190 Standard_Integer LowerRow (void) const
191 { return myLowerRow; }
192 //! UpperRow
193 Standard_Integer UpperRow (void) const
194 { return myUpperRow; }
195 //! LowerCol
196 Standard_Integer LowerCol (void) const
197 { return myLowerCol; }
198 //! UpperCol
199 Standard_Integer UpperCol (void) const
200 { return myUpperCol; }
201
202 //! myDeletable flag
203 Standard_Boolean IsDeletable (void) const
204 { return myDeletable; }
205
ddf2fe8e 206 //! Assignment
207 NCollection_Array2& Assign (const NCollection_Array2& theOther)
7fd59977 208 {
209 if (&theOther == this)
210 return *this;
e3a6386d 211 Standard_DimensionMismatch_Raise_if (Length() != theOther.Length(), "NCollection_Array2::operator=");
7fd59977 212 TheItemType * pMyItem = myStart;
213 TheItemType * pItem = theOther.myStart;
214 const Standard_Integer iSize = Length();
215 for (Standard_Integer i=0; i < iSize; i++, pItem++, pMyItem++)
216 *pMyItem = *pItem;
217 return *this;
218 }
219
92435cd0 220 //! Move assignment.
221 //! This array will borrow all the data from theOther.
222 //! The moved object will be left unitialized and should not be used anymore.
223 NCollection_Array2& Move (NCollection_Array2& theOther)
224 {
225 if (&theOther == this)
226 {
227 return *this;
228 }
229
230 if (myDeletable)
231 {
232 delete[] myStart;
233 }
234 if (myData != NULL)
235 {
236 delete[] &(myData[myLowerRow]);
237 }
238
239 myLowerRow = theOther.myLowerRow;
240 myUpperRow = theOther.myUpperRow;
241 myLowerCol = theOther.myLowerRow;
242 myUpperCol = theOther.myUpperCol;
243 myData = theOther.myData;
244 myStart = theOther.myStart;
245 myDeletable = theOther.myDeletable;
246
247 theOther.myStart = NULL;
248 theOther.myData = NULL;
249 theOther.myDeletable = Standard_False;
250 return *this;
251 }
252
ddf2fe8e 253 //! Assignment operator
254 NCollection_Array2& operator= (const NCollection_Array2& theOther)
255 {
256 return Assign (theOther);
257 }
258
92435cd0 259#ifndef OCCT_NO_RVALUE_REFERENCE
260 //! Move assignment operator; @sa Move()
261 NCollection_Array2& operator= (NCollection_Array2&& theOther)
262 {
263 return Move (theOther);
264 }
265#endif
266
7fd59977 267 //! Constant value access
268 const TheItemType& Value (const Standard_Integer theRow,
269 const Standard_Integer theCol) const
270 {
e3a6386d 271 Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
272 theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::Value");
7fd59977 273 return myData[theRow][theCol];
274 }
275
276 //! operator() - alias to ChangeValue
277 const TheItemType& operator() (const Standard_Integer theRow,
278 const Standard_Integer theCol) const
279 { return Value (theRow,theCol); }
280
281 //! Variable value access
282 TheItemType& ChangeValue (const Standard_Integer theRow,
283 const Standard_Integer theCol)
284 {
e3a6386d 285 Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
286 theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::ChangeValue");
7fd59977 287 return myData[theRow][theCol];
288 }
289
290 //! operator() - alias to ChangeValue
291 TheItemType& operator() (const Standard_Integer theRow,
292 const Standard_Integer theCol)
293 { return ChangeValue (theRow,theCol); }
294
295 //! SetValue
296 void SetValue (const Standard_Integer theRow,
297 const Standard_Integer theCol,
298 const TheItemType& theItem)
299 {
e3a6386d 300 Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
301 theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::SetValue");
7fd59977 302 myData[theRow][theCol] = theItem;
303 }
92435cd0 304
305 //! Resizes the array to specified bounds.
306 //! No re-allocation will be done if length of array does not change,
307 //! but existing values will not be discarded if theToCopyData set to FALSE.
308 //! @param theRowLower new lower Row of array
309 //! @param theRowUpper new upper Row of array
310 //! @param theColLower new lower Column of array
311 //! @param theColUpper new upper Column of array
312 //! @param theToCopyData flag to copy existing data into new array
313 void Resize (Standard_Integer theRowLower,
314 Standard_Integer theRowUpper,
315 Standard_Integer theColLower,
316 Standard_Integer theColUpper,
317 Standard_Boolean theToCopyData)
318 {
319 Standard_RangeError_Raise_if (theRowUpper < theRowLower
320 || theColUpper < theColLower, "NCollection_Array2::Resize");
321 const Standard_Integer anOldNbRows = NbRows();
322 const Standard_Integer anOldNbCols = NbColumns();
323 const Standard_Integer aLowerRowOld = myLowerRow;
324 const Standard_Integer aLowerColOld = myLowerCol;
325 const Standard_Integer aNewNbRows = theRowUpper - theRowLower + 1;
326 const Standard_Integer aNewNbCols = theColUpper - theColLower + 1;
327
328 TheItemType* aStartOld = myStart;
329 TheItemType** aTableOld = myData != NULL ? myData + aLowerRowOld : NULL;
330 myLowerRow = theRowLower;
331 myUpperRow = theRowUpper;
332 myLowerCol = theColLower;
333 myUpperCol = theColUpper;
334 if (aNewNbRows == anOldNbRows
335 && aNewNbCols == anOldNbCols)
336 {
337 if (myLowerCol != aLowerColOld)
338 {
339 fillIndexTable (aTableOld);
340 }
341 myData = aTableOld - myLowerRow;
342 return;
343 }
344
345 if (myDeletable
346 && !theToCopyData)
347 {
348 delete[] aStartOld;
349 }
350 delete[] aTableOld;
351
352 Allocate();
353 if (!theToCopyData)
354 {
355 myDeletable = Standard_True;
356 return;
357 }
358
359 const Standard_Integer aNbRowsToCopy = Min (anOldNbRows, aNewNbRows);
360 const Standard_Integer aNbColsToCopy = Min (anOldNbCols, aNewNbCols);
361 for (Standard_Integer aRowIter = 0; aRowIter < aNbRowsToCopy; ++aRowIter)
362 {
363 for (Standard_Integer aColIter = 0; aColIter < aNbColsToCopy; ++aColIter)
364 {
365 myStart[size_t(aRowIter) * size_t(aNewNbCols) + size_t(aColIter)] = aStartOld[size_t(aRowIter) * size_t(anOldNbCols) + size_t(aColIter)];
366 }
367 }
368
369 if (myDeletable)
370 {
371 delete[] aStartOld;
372 }
373 myDeletable = Standard_True;
374 }
375
7fd59977 376 //! Destructor - releases the memory
377 ~NCollection_Array2 (void)
378 {
379 if (myDeletable) delete [] myStart;
92435cd0 380 if (myData != NULL)
381 {
382 delete[] &(myData[myLowerRow]);
383 }
7fd59977 384 }
385
386 private:
387 // ----------- PRIVATE METHODS -----------
388
389 //! Allocate memory for the array, set up indirection table
390 void Allocate (void)
391 {
92435cd0 392 const Standard_Integer aNbRows = NbRows();
393 const Standard_Integer aNbCols = NbColumns();
394 Standard_RangeError_Raise_if (aNbRows <= 0 || aNbCols <= 0, "NCollection_Array2::Allocate");
395 if (myDeletable)
396 {
7fd59977 397 // allocation of the data in the array
92435cd0 398 myStart = new TheItemType[size_t(aNbRows) * size_t(aNbCols)];
e3a6386d 399 Standard_OutOfMemory_Raise_if (!myStart, "NCollection_Array2 : Allocation failed");
7fd59977 400 }
401 // else myStart is set to the beginning of the given array
92435cd0 402
403 TheItemType** pTable = new TheItemType* [aNbRows];
e3a6386d 404 Standard_OutOfMemory_Raise_if (!pTable, "NCollection_Array2 : Allocation failed");
92435cd0 405 fillIndexTable (pTable);
406 }
7fd59977 407
92435cd0 408 //! Fill index table for accessing array elements.
409 void fillIndexTable (TheItemType** theTable)
410 {
411 // Items of table point to the 0th items in the rows of the array
412 TheItemType* aRow = myStart - myLowerCol;
413 const Standard_Integer aNbRows = NbRows();
414 const Standard_Size aNbCols = NbColumns();
415 for (Standard_Integer aRowIter = 0; aRowIter < aNbRows; ++aRowIter)
7fd59977 416 {
92435cd0 417 theTable[aRowIter] = aRow;
418 aRow += aNbCols;
7fd59977 419 }
420
92435cd0 421 // Set myData to the 0th row pointer of the table
422 myData = theTable - myLowerRow;
7fd59977 423 }
424
7fd59977 425 protected:
426 // ---------- PROTECTED FIELDS -----------
427 Standard_Integer myLowerRow;
428 Standard_Integer myUpperRow;
429 Standard_Integer myLowerCol;
430 Standard_Integer myUpperCol;
431
432 TheItemType** myData; //!< Pointer to the row pointers table
433 TheItemType* myStart; //!< Pointer to the memory array
434 Standard_Boolean myDeletable; //!< Flag showing who allocated the array
435
436 // ----------- FRIEND CLASSES ------------
437 friend class Iterator;
438
439};
440
7fd59977 441#endif