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