e95fa6922c282c52b1ce116e62aaef61b756c362
[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   // **************** Implementation of the Iterator interface.
45   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator
46   {
47   public:
48     //! Empty constructor - for later Init
49     Iterator (void) :
50       myCurrent (0),
51       mySize    (0),
52       myArray   (NULL) {}
53     //! Constructor with initialisation
54     Iterator  (const NCollection_Array2& theArray) :
55       myCurrent (0),
56       mySize    (theArray.Length()),
57       myArray   ((NCollection_Array2 *) &theArray) {}
58     //! Initialisation
59     void Init (const NCollection_Array2& theArray)
60     { 
61       myCurrent = 0;
62       mySize    = theArray.Length();
63       myArray   = (NCollection_Array2 *) &theArray; 
64     }
65     //! Check end
66     virtual Standard_Boolean More (void) const
67     { return (myCurrent < mySize); }
68     //! Make step
69     virtual void Next (void)
70     { myCurrent++; }
71     //! Constant value access
72     virtual const TheItemType& Value (void) const
73     { return myArray->myStart[myCurrent]; }
74     //! Variable value access
75     virtual TheItemType& ChangeValue (void) const
76     { return myArray->myStart[myCurrent]; }
77   private:
78     Standard_Integer    myCurrent;  //!< Index of the current item
79     Standard_Integer    mySize;     //!< Total amount of items
80     NCollection_Array2* myArray;    //!< Pointer to the array being iterated
81   }; // End of nested class Iterator
82
83  public:
84   // ---------- PUBLIC METHODS ------------
85
86   //! Constructor
87   NCollection_Array2(const Standard_Integer theRowLower,
88                      const Standard_Integer theRowUpper,
89                      const Standard_Integer theColLower,
90                      const Standard_Integer theColUpper) :
91     NCollection_BaseCollection<TheItemType>     (),
92     myLowerRow                                  (theRowLower),
93     myUpperRow                                  (theRowUpper),
94     myLowerCol                                  (theColLower),
95     myUpperCol                                  (theColUpper),
96     myDeletable                                 (Standard_True)
97   { Allocate(); }
98
99   //! Copy constructor 
100   NCollection_Array2 (const NCollection_Array2& theOther) :
101     NCollection_BaseCollection<TheItemType>     (),
102     myLowerRow                                  (theOther.LowerRow()),
103     myUpperRow                                  (theOther.UpperRow()),
104     myLowerCol                                  (theOther.LowerCol()),
105     myUpperCol                                  (theOther.UpperCol()),
106     myDeletable                                 (Standard_True)
107   {
108     Allocate();
109     *this = theOther;
110   }
111
112   //! C array-based constructor
113   NCollection_Array2(const TheItemType&     theBegin,
114                      const Standard_Integer theRowLower,
115                      const Standard_Integer theRowUpper,
116                      const Standard_Integer theColLower,
117                      const Standard_Integer theColUpper) :
118     NCollection_BaseCollection<TheItemType>     (),
119     myLowerRow                                  (theRowLower),
120     myUpperRow                                  (theRowUpper),
121     myLowerCol                                  (theColLower),
122     myUpperCol                                  (theColUpper),
123     myDeletable                                 (Standard_False)
124   {
125     myStart = (TheItemType *) &theBegin;
126     Allocate();
127   }
128
129   //! Initialise the values
130   void Init (const TheItemType& theValue) 
131   {
132     TheItemType *pCur, *pEnd=myStart+Size();
133     for(pCur = myStart; pCur<pEnd; pCur++)
134       *pCur = theValue;
135   }
136
137   //! Size (number of items)
138   virtual Standard_Integer Size (void) const
139   { return Length(); }
140   //! Length (number of items)
141   Standard_Integer Length (void) const
142   { return RowLength() * ColLength(); }
143
144   //! RowLength 
145   Standard_Integer RowLength (void) const
146   { return (myUpperCol-myLowerCol+1); }
147   //! ColLength 
148   Standard_Integer ColLength (void) const
149   { return (myUpperRow-myLowerRow+1); }
150
151   //! LowerRow
152   Standard_Integer LowerRow (void) const
153   { return myLowerRow; }
154   //! UpperRow
155   Standard_Integer UpperRow (void) const
156   { return myUpperRow; }
157   //! LowerCol
158   Standard_Integer LowerCol (void) const
159   { return myLowerCol; }
160   //! UpperCol
161   Standard_Integer UpperCol (void) const
162   { return myUpperCol; }
163
164   //! myDeletable flag
165   Standard_Boolean IsDeletable (void) const
166   { return myDeletable; }
167
168   //! Assign 
169   // Copies items from the other collection into the allocated
170   // storage. Raises an exception when sizes differ.
171   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
172   {
173     if (&theOther == this)
174       return;
175 #if !defined No_Exception && !defined No_Standard_DimensionMismatch
176     if (Length() != theOther.Size())
177       Standard_DimensionMismatch::Raise ("NCollection_Array2::Assign");
178 #endif
179     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = 
180       theOther.CreateIterator();
181     const TheItemType* pEnd = myStart+Length();
182     for (TheItemType* pItem=myStart;
183          pItem < pEnd;
184          pItem++, anIter2.Next())
185       *pItem = anIter2.Value();
186   }
187
188   //! operator= (array to array)
189   NCollection_Array2& operator= (const NCollection_Array2& theOther)
190   { 
191     if (&theOther == this)
192       return *this;
193 #if !defined No_Exception && !defined No_Standard_DimensionMismatch
194     if (Length() != theOther.Length())
195       Standard_DimensionMismatch::Raise ("NCollection_Array2::operator=");
196 #endif
197     TheItemType * pMyItem  = myStart;
198     TheItemType * pItem    = theOther.myStart;
199     const Standard_Integer iSize = Length();
200     for (Standard_Integer i=0; i < iSize; i++, pItem++, pMyItem++)
201       *pMyItem = *pItem;
202     return *this; 
203   }
204
205   //! Constant value access
206   const TheItemType& Value (const Standard_Integer theRow,
207                             const Standard_Integer theCol) const
208   {
209 #if !defined No_Exception && !defined No_Standard_OutOfRange
210     if (theRow < myLowerRow || theRow > myUpperRow ||
211         theCol < myLowerCol || theCol > myUpperCol)
212       Standard_OutOfRange::Raise ("NCollection_Array2::Value");
213 #endif
214     return myData[theRow][theCol];
215   }
216
217   //! operator() - alias to ChangeValue
218   const TheItemType& operator() (const Standard_Integer theRow,
219                                  const Standard_Integer theCol) const
220   { return Value (theRow,theCol); }
221
222   //! Variable value access
223   TheItemType& ChangeValue (const Standard_Integer theRow,
224                             const Standard_Integer theCol)
225   {
226 #if !defined No_Exception && !defined No_Standard_OutOfRange
227     if (theRow < myLowerRow || theRow > myUpperRow ||
228         theCol < myLowerCol || theCol > myUpperCol)
229       Standard_OutOfRange::Raise ("NCollection_Array2::ChangeValue");
230 #endif
231     return myData[theRow][theCol];
232   }
233
234   //! operator() - alias to ChangeValue
235   TheItemType& operator() (const Standard_Integer theRow,
236                            const Standard_Integer theCol)
237   { return ChangeValue (theRow,theCol); }
238
239   //! SetValue
240   void SetValue (const Standard_Integer theRow,
241                  const Standard_Integer theCol,
242                  const TheItemType&     theItem)
243   {
244 #if !defined No_Exception && !defined No_Standard_OutOfRange
245     if (theRow < myLowerRow || theRow > myUpperRow ||
246         theCol < myLowerCol || theCol > myUpperCol)
247       Standard_OutOfRange::Raise ("NCollection_Array2::SetValue");
248 #endif
249     myData[theRow][theCol] = theItem;
250   }
251   
252   //! Destructor - releases the memory
253   ~NCollection_Array2 (void)
254   { 
255     if (myDeletable) delete [] myStart;
256     delete [] &(myData[myLowerRow]);
257   }
258
259  private:
260   // ----------- PRIVATE METHODS -----------
261
262   //! Allocate memory for the array, set up indirection table
263   void Allocate (void)
264   {
265     const Standard_Integer iRowSize = myUpperCol - myLowerCol + 1;
266     const Standard_Integer iColSize = myUpperRow - myLowerRow + 1;
267 #if !defined No_Exception && !defined No_Standard_RangeError
268     if (iRowSize <= 0  || iColSize <= 0)
269       Standard_RangeError::Raise ("NCollection_Array2::Allocate");
270 #endif
271     if (myDeletable) {
272       // allocation of the data in the array
273       myStart = new TheItemType[iRowSize * iColSize];
274 #if !defined No_Exception && !defined No_Standard_OutOfMemory
275       if (!myStart)
276         Standard_OutOfMemory::Raise ("NCollection_Array2 : Allocation failed");
277 #endif
278     }
279     // else myStart is set to the beginning of the given array
280     TheItemType** pTable = new TheItemType* [iColSize];
281 #if !defined No_Exception && !defined No_Standard_OutOfMemory
282     if (!pTable)
283       Standard_OutOfMemory::Raise ("NCollection_Array2 : Allocation failed");
284 #endif
285
286     // Items of pTable point to the '0'th items in the rows of the array
287     TheItemType* pRow = myStart - myLowerCol;
288     for (Standard_Integer i = 0; i < iColSize; i++) 
289     {
290       pTable[i] = pRow;
291       pRow += iRowSize;
292     }
293
294     // Set myData to the '0'th row pointer of the pTable
295     myData = pTable - myLowerRow;
296   }
297
298   //! Creates Iterator for use on BaseCollection
299   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
300     CreateIterator(void) const
301   { return *(new (this->IterAllocator()) Iterator(*this)); }
302
303  protected:
304   // ---------- PROTECTED FIELDS -----------
305   Standard_Integer myLowerRow;
306   Standard_Integer myUpperRow;
307   Standard_Integer myLowerCol;
308   Standard_Integer myUpperCol;
309
310   TheItemType**    myData;      //!< Pointer to the row pointers table
311   TheItemType*     myStart;     //!< Pointer to the memory array
312   Standard_Boolean myDeletable; //!< Flag showing who allocated the array
313
314   // ----------- FRIEND CLASSES ------------
315  friend class Iterator;
316
317 };
318
319 #endif