1 // Created on: 2002-04-15
2 // Created by: Alexander Kartomin (akm)
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef NCollection_Array2_HeaderFile
17 #define NCollection_Array2_HeaderFile
19 #include <Standard_DimensionMismatch.hxx>
20 #include <Standard_OutOfMemory.hxx>
21 #include <Standard_OutOfRange.hxx>
23 #include <NCollection_DefineAlloc.hxx>
25 // *********************************************** Template for Array2 class
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.
31 * Class allocates one 1D array storing full data (all Rows and Columns)
32 * and extra 1D array storing pointers to each Row.
34 * Warning: Programs clients of such class must be independent
35 * of the range of the first element. Then, a C++ for
36 * loop must be written like this
38 * for (i = A.LowerRow(); i <= A.UpperRow(); i++)
39 * for (j = A.LowerCol(); j <= A.UpperCol(); j++)
41 template <class TheItemType>
42 class NCollection_Array2
45 //! STL-compliant typedef for value type
46 typedef TheItemType value_type;
49 // **************** Implementation of the Iterator interface.
53 //! Empty constructor - for later Init
58 //! Constructor with initialisation
59 Iterator (const NCollection_Array2& theArray) :
61 mySize (theArray.Length()),
62 myArray ((NCollection_Array2 *) &theArray) {}
64 void Init (const NCollection_Array2& theArray)
67 mySize = theArray.Length();
68 myArray = (NCollection_Array2 *) &theArray;
71 Standard_Boolean More (void) const
72 { return (myCurrent < mySize); }
76 //! Constant value access
77 const TheItemType& Value (void) const
78 { return myArray->myStart[myCurrent]; }
79 //! Variable value access
80 TheItemType& ChangeValue (void) const
81 { return myArray->myStart[myCurrent]; }
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
89 // ---------- PUBLIC METHODS ------------
91 //! Empty constructor; should be used with caution.
92 //! @sa methods Resize() and Move().
106 NCollection_Array2(const Standard_Integer theRowLower,
107 const Standard_Integer theRowUpper,
108 const Standard_Integer theColLower,
109 const Standard_Integer theColUpper) :
110 myLowerRow (theRowLower),
111 myUpperRow (theRowUpper),
112 myLowerCol (theColLower),
113 myUpperCol (theColUpper),
114 myDeletable (Standard_True)
118 NCollection_Array2 (const NCollection_Array2& theOther) :
119 myLowerRow (theOther.LowerRow()),
120 myUpperRow (theOther.UpperRow()),
121 myLowerCol (theOther.LowerCol()),
122 myUpperCol (theOther.UpperCol()),
123 myDeletable (Standard_True)
129 #ifndef OCCT_NO_RVALUE_REFERENCE
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)
140 theOther.myStart = NULL;
141 theOther.myData = NULL;
142 theOther.myDeletable = false;
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) :
152 myLowerRow (theRowLower),
153 myUpperRow (theRowUpper),
154 myLowerCol (theColLower),
155 myUpperCol (theColUpper),
156 myDeletable (Standard_False)
158 myStart = (TheItemType *) &theBegin;
162 //! Initialise the values
163 void Init (const TheItemType& theValue)
165 TheItemType *pCur, *pEnd=myStart+Size();
166 for(pCur = myStart; pCur<pEnd; pCur++)
170 //! Size (number of items)
171 Standard_Integer Size (void) const
173 //! Length (number of items)
174 Standard_Integer Length (void) const
175 { return NbRows() * NbColumns(); }
177 //! Returns number of rows
178 Standard_Integer NbRows() const { return myUpperRow - myLowerRow + 1; }
180 //! Returns number of columns
181 Standard_Integer NbColumns() const { return myUpperCol - myLowerCol + 1; }
183 //! Returns length of the row, i.e. number of columns
184 Standard_Integer RowLength() const { return NbColumns(); }
186 //! Returns length of the column, i.e. number of rows
187 Standard_Integer ColLength() const { return NbRows(); }
190 Standard_Integer LowerRow (void) const
191 { return myLowerRow; }
193 Standard_Integer UpperRow (void) const
194 { return myUpperRow; }
196 Standard_Integer LowerCol (void) const
197 { return myLowerCol; }
199 Standard_Integer UpperCol (void) const
200 { return myUpperCol; }
203 Standard_Boolean IsDeletable (void) const
204 { return myDeletable; }
207 NCollection_Array2& Assign (const NCollection_Array2& theOther)
209 if (&theOther == this)
211 Standard_DimensionMismatch_Raise_if (Length() != theOther.Length(), "NCollection_Array2::operator=");
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++)
221 //! This array will borrow all the data from theOther.
222 //! The moved object will be left uninitialized and should not be used anymore.
223 NCollection_Array2& Move (NCollection_Array2& theOther)
225 if (&theOther == this)
236 delete[] &(myData[myLowerRow]);
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;
247 theOther.myStart = NULL;
248 theOther.myData = NULL;
249 theOther.myDeletable = Standard_False;
253 //! Assignment operator
254 NCollection_Array2& operator= (const NCollection_Array2& theOther)
256 return Assign (theOther);
259 #ifndef OCCT_NO_RVALUE_REFERENCE
260 //! Move assignment operator; @sa Move()
261 NCollection_Array2& operator= (NCollection_Array2&& theOther)
263 return Move (theOther);
267 //! Constant value access
268 const TheItemType& Value (const Standard_Integer theRow,
269 const Standard_Integer theCol) const
271 Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
272 theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::Value");
273 return myData[theRow][theCol];
276 //! operator() - alias to ChangeValue
277 const TheItemType& operator() (const Standard_Integer theRow,
278 const Standard_Integer theCol) const
279 { return Value (theRow,theCol); }
281 //! Variable value access
282 TheItemType& ChangeValue (const Standard_Integer theRow,
283 const Standard_Integer theCol)
285 Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
286 theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::ChangeValue");
287 return myData[theRow][theCol];
290 //! operator() - alias to ChangeValue
291 TheItemType& operator() (const Standard_Integer theRow,
292 const Standard_Integer theCol)
293 { return ChangeValue (theRow,theCol); }
296 void SetValue (const Standard_Integer theRow,
297 const Standard_Integer theCol,
298 const TheItemType& theItem)
300 Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
301 theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::SetValue");
302 myData[theRow][theCol] = theItem;
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)
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;
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)
337 if (myLowerCol != aLowerColOld)
339 fillIndexTable (aTableOld);
341 myData = aTableOld - myLowerRow;
352 const Standard_Boolean wasDeletable = myDeletable;
353 myDeletable = Standard_True;
360 const Standard_Integer aNbRowsToCopy = Min (anOldNbRows, aNewNbRows);
361 const Standard_Integer aNbColsToCopy = Min (anOldNbCols, aNewNbCols);
362 for (Standard_Integer aRowIter = 0; aRowIter < aNbRowsToCopy; ++aRowIter)
364 for (Standard_Integer aColIter = 0; aColIter < aNbColsToCopy; ++aColIter)
366 myStart[size_t(aRowIter) * size_t(aNewNbCols) + size_t(aColIter)] = aStartOld[size_t(aRowIter) * size_t(anOldNbCols) + size_t(aColIter)];
376 //! Destructor - releases the memory
377 ~NCollection_Array2 (void)
379 if (myDeletable) delete [] myStart;
382 delete[] &(myData[myLowerRow]);
387 // ----------- PRIVATE METHODS -----------
389 //! Allocate memory for the array, set up indirection table
392 const Standard_Integer aNbRows = NbRows();
393 const Standard_Integer aNbCols = NbColumns();
394 Standard_RangeError_Raise_if (aNbRows <= 0 || aNbCols <= 0, "NCollection_Array2::Allocate");
397 // allocation of the data in the array
398 myStart = new TheItemType[size_t(aNbRows) * size_t(aNbCols)];
399 Standard_OutOfMemory_Raise_if (!myStart, "NCollection_Array2 : Allocation failed");
401 // else myStart is set to the beginning of the given array
403 TheItemType** pTable = new TheItemType* [aNbRows];
404 Standard_OutOfMemory_Raise_if (!pTable, "NCollection_Array2 : Allocation failed");
405 fillIndexTable (pTable);
408 //! Fill index table for accessing array elements.
409 void fillIndexTable (TheItemType** theTable)
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)
417 theTable[aRowIter] = aRow;
421 // Set myData to the 0th row pointer of the table
422 myData = theTable - myLowerRow;
426 // ---------- PROTECTED FIELDS -----------
427 Standard_Integer myLowerRow;
428 Standard_Integer myUpperRow;
429 Standard_Integer myLowerCol;
430 Standard_Integer myUpperCol;
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
436 // ----------- FRIEND CLASSES ------------
437 friend class Iterator;