c8a13aa9b03630ed0e6dea10bb9a34637d69c4a6
[occt.git] / src / NCollection / NCollection_Array2.hxx
1 // Created on: 2002-04-15
2 // Created by: Alexander Kartomin (akm)
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef NCollection_Array2_HeaderFile
17 #define NCollection_Array2_HeaderFile
18
19 #ifndef No_Exception
20 #include <Standard_DimensionMismatch.hxx>
21 #include <Standard_OutOfMemory.hxx>
22 #include <Standard_OutOfRange.hxx>
23 #endif
24
25 #include <NCollection_BaseCollection.hxx>
26
27 // *********************************************** Template for Array2 class
28 /**
29 * Purpose:   The class Array2 represents bi-dimensional arrays 
30 *            of fixed size known at run time. 
31 *            The ranges of indices are user defined.
32 *            
33 * Warning:   Programs clients of such class must be independant
34 *            of the range of the first element. Then, a C++ for
35 *            loop must be written like this
36 *            
37 *            for (i = A.LowerRow(); i <= A.UpperRow(); i++)
38 *              for (j = A.LowerCol(); j <= A.UpperCol(); j++)
39 */            
40 template <class TheItemType> class NCollection_Array2
41   : public NCollection_BaseCollection<TheItemType>
42 {
43 public:
44   //! STL-compliant typedef for value type
45   typedef TheItemType value_type;
46
47 public:
48   // **************** Implementation of the Iterator interface.
49   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator
50   {
51   public:
52     //! Empty constructor - for later Init
53     Iterator (void) :
54       myCurrent (0),
55       mySize    (0),
56       myArray   (NULL) {}
57     //! Constructor with initialisation
58     Iterator  (const NCollection_Array2& theArray) :
59       myCurrent (0),
60       mySize    (theArray.Length()),
61       myArray   ((NCollection_Array2 *) &theArray) {}
62     //! Initialisation
63     void Init (const NCollection_Array2& theArray)
64     { 
65       myCurrent = 0;
66       mySize    = theArray.Length();
67       myArray   = (NCollection_Array2 *) &theArray; 
68     }
69     //! Check end
70     virtual Standard_Boolean More (void) const
71     { return (myCurrent < mySize); }
72     //! Make step
73     virtual void Next (void)
74     { myCurrent++; }
75     //! Constant value access
76     virtual const TheItemType& Value (void) const
77     { return myArray->myStart[myCurrent]; }
78     //! Variable value access
79     virtual TheItemType& ChangeValue (void) const
80     { return myArray->myStart[myCurrent]; }
81   private:
82     Standard_Integer    myCurrent;  //!< Index of the current item
83     Standard_Integer    mySize;     //!< Total amount of items
84     NCollection_Array2* myArray;    //!< Pointer to the array being iterated
85   }; // End of nested class Iterator
86
87  public:
88   // ---------- PUBLIC METHODS ------------
89
90   //! Constructor
91   NCollection_Array2(const Standard_Integer theRowLower,
92                      const Standard_Integer theRowUpper,
93                      const Standard_Integer theColLower,
94                      const Standard_Integer theColUpper) :
95     NCollection_BaseCollection<TheItemType>     (),
96     myLowerRow                                  (theRowLower),
97     myUpperRow                                  (theRowUpper),
98     myLowerCol                                  (theColLower),
99     myUpperCol                                  (theColUpper),
100     myDeletable                                 (Standard_True)
101   { Allocate(); }
102
103   //! Copy constructor 
104   NCollection_Array2 (const NCollection_Array2& theOther) :
105     NCollection_BaseCollection<TheItemType>     (),
106     myLowerRow                                  (theOther.LowerRow()),
107     myUpperRow                                  (theOther.UpperRow()),
108     myLowerCol                                  (theOther.LowerCol()),
109     myUpperCol                                  (theOther.UpperCol()),
110     myDeletable                                 (Standard_True)
111   {
112     Allocate();
113     *this = theOther;
114   }
115
116   //! C array-based constructor
117   NCollection_Array2(const TheItemType&     theBegin,
118                      const Standard_Integer theRowLower,
119                      const Standard_Integer theRowUpper,
120                      const Standard_Integer theColLower,
121                      const Standard_Integer theColUpper) :
122     NCollection_BaseCollection<TheItemType>     (),
123     myLowerRow                                  (theRowLower),
124     myUpperRow                                  (theRowUpper),
125     myLowerCol                                  (theColLower),
126     myUpperCol                                  (theColUpper),
127     myDeletable                                 (Standard_False)
128   {
129     myStart = (TheItemType *) &theBegin;
130     Allocate();
131   }
132
133   //! Initialise the values
134   void Init (const TheItemType& theValue) 
135   {
136     TheItemType *pCur, *pEnd=myStart+Size();
137     for(pCur = myStart; pCur<pEnd; pCur++)
138       *pCur = theValue;
139   }
140
141   //! Size (number of items)
142   virtual Standard_Integer Size (void) const
143   { return Length(); }
144   //! Length (number of items)
145   Standard_Integer Length (void) const
146   { return RowLength() * ColLength(); }
147
148   //! RowLength 
149   Standard_Integer RowLength (void) const
150   { return (myUpperCol-myLowerCol+1); }
151   //! ColLength 
152   Standard_Integer ColLength (void) const
153   { return (myUpperRow-myLowerRow+1); }
154
155   //! LowerRow
156   Standard_Integer LowerRow (void) const
157   { return myLowerRow; }
158   //! UpperRow
159   Standard_Integer UpperRow (void) const
160   { return myUpperRow; }
161   //! LowerCol
162   Standard_Integer LowerCol (void) const
163   { return myLowerCol; }
164   //! UpperCol
165   Standard_Integer UpperCol (void) const
166   { return myUpperCol; }
167
168   //! myDeletable flag
169   Standard_Boolean IsDeletable (void) const
170   { return myDeletable; }
171
172   //! Assign 
173   // Copies items from the other collection into the allocated
174   // storage. Raises an exception when sizes differ.
175   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
176   {
177     if (&theOther == this)
178       return;
179 #if !defined No_Exception && !defined No_Standard_DimensionMismatch
180     if (Length() != theOther.Size())
181       Standard_DimensionMismatch::Raise ("NCollection_Array2::Assign");
182 #endif
183     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = 
184       theOther.CreateIterator();
185     const TheItemType* pEnd = myStart+Length();
186     for (TheItemType* pItem=myStart;
187          pItem < pEnd;
188          pItem++, anIter2.Next())
189       *pItem = anIter2.Value();
190   }
191
192   //! operator= (array to array)
193   NCollection_Array2& operator= (const NCollection_Array2& theOther)
194   { 
195     if (&theOther == this)
196       return *this;
197 #if !defined No_Exception && !defined No_Standard_DimensionMismatch
198     if (Length() != theOther.Length())
199       Standard_DimensionMismatch::Raise ("NCollection_Array2::operator=");
200 #endif
201     TheItemType * pMyItem  = myStart;
202     TheItemType * pItem    = theOther.myStart;
203     const Standard_Integer iSize = Length();
204     for (Standard_Integer i=0; i < iSize; i++, pItem++, pMyItem++)
205       *pMyItem = *pItem;
206     return *this; 
207   }
208
209   //! Constant value access
210   const TheItemType& Value (const Standard_Integer theRow,
211                             const Standard_Integer theCol) const
212   {
213 #if !defined No_Exception && !defined No_Standard_OutOfRange
214     if (theRow < myLowerRow || theRow > myUpperRow ||
215         theCol < myLowerCol || theCol > myUpperCol)
216       Standard_OutOfRange::Raise ("NCollection_Array2::Value");
217 #endif
218     return myData[theRow][theCol];
219   }
220
221   //! operator() - alias to ChangeValue
222   const TheItemType& operator() (const Standard_Integer theRow,
223                                  const Standard_Integer theCol) const
224   { return Value (theRow,theCol); }
225
226   //! Variable value access
227   TheItemType& ChangeValue (const Standard_Integer theRow,
228                             const Standard_Integer theCol)
229   {
230 #if !defined No_Exception && !defined No_Standard_OutOfRange
231     if (theRow < myLowerRow || theRow > myUpperRow ||
232         theCol < myLowerCol || theCol > myUpperCol)
233       Standard_OutOfRange::Raise ("NCollection_Array2::ChangeValue");
234 #endif
235     return myData[theRow][theCol];
236   }
237
238   //! operator() - alias to ChangeValue
239   TheItemType& operator() (const Standard_Integer theRow,
240                            const Standard_Integer theCol)
241   { return ChangeValue (theRow,theCol); }
242
243   //! SetValue
244   void SetValue (const Standard_Integer theRow,
245                  const Standard_Integer theCol,
246                  const TheItemType&     theItem)
247   {
248 #if !defined No_Exception && !defined No_Standard_OutOfRange
249     if (theRow < myLowerRow || theRow > myUpperRow ||
250         theCol < myLowerCol || theCol > myUpperCol)
251       Standard_OutOfRange::Raise ("NCollection_Array2::SetValue");
252 #endif
253     myData[theRow][theCol] = theItem;
254   }
255   
256   //! Destructor - releases the memory
257   ~NCollection_Array2 (void)
258   { 
259     if (myDeletable) delete [] myStart;
260     delete [] &(myData[myLowerRow]);
261   }
262
263  private:
264   // ----------- PRIVATE METHODS -----------
265
266   //! Allocate memory for the array, set up indirection table
267   void Allocate (void)
268   {
269     const Standard_Integer iRowSize = myUpperCol - myLowerCol + 1;
270     const Standard_Integer iColSize = myUpperRow - myLowerRow + 1;
271 #if !defined No_Exception && !defined No_Standard_RangeError
272     if (iRowSize <= 0  || iColSize <= 0)
273       Standard_RangeError::Raise ("NCollection_Array2::Allocate");
274 #endif
275     if (myDeletable) {
276       // allocation of the data in the array
277       myStart = new TheItemType[iRowSize * iColSize];
278 #if !defined No_Exception && !defined No_Standard_OutOfMemory
279       if (!myStart)
280         Standard_OutOfMemory::Raise ("NCollection_Array2 : Allocation failed");
281 #endif
282     }
283     // else myStart is set to the beginning of the given array
284     TheItemType** pTable = new TheItemType* [iColSize];
285 #if !defined No_Exception && !defined No_Standard_OutOfMemory
286     if (!pTable)
287       Standard_OutOfMemory::Raise ("NCollection_Array2 : Allocation failed");
288 #endif
289
290     // Items of pTable point to the '0'th items in the rows of the array
291     TheItemType* pRow = myStart - myLowerCol;
292     for (Standard_Integer i = 0; i < iColSize; i++) 
293     {
294       pTable[i] = pRow;
295       pRow += iRowSize;
296     }
297
298     // Set myData to the '0'th row pointer of the pTable
299     myData = pTable - myLowerRow;
300   }
301
302   //! Creates Iterator for use on BaseCollection
303   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
304     CreateIterator(void) const
305   { return *(new (this->IterAllocator()) Iterator(*this)); }
306
307  protected:
308   // ---------- PROTECTED FIELDS -----------
309   Standard_Integer myLowerRow;
310   Standard_Integer myUpperRow;
311   Standard_Integer myLowerCol;
312   Standard_Integer myUpperCol;
313
314   TheItemType**    myData;      //!< Pointer to the row pointers table
315   TheItemType*     myStart;     //!< Pointer to the memory array
316   Standard_Boolean myDeletable; //!< Flag showing who allocated the array
317
318   // ----------- FRIEND CLASSES ------------
319  friend class Iterator;
320
321 };
322
323 #endif