0024911: Avoid using virtual functions in NCollection classes
[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_DefineAlloc.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>
41 class NCollection_Array2
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
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     Standard_Boolean More (void) const
71     { return (myCurrent < mySize); }
72     //! Make step
73     void Next (void)
74     { myCurrent++; }
75     //! Constant value access
76     const TheItemType& Value (void) const
77     { return myArray->myStart[myCurrent]; }
78     //! Variable value access
79     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     myLowerRow                                  (theRowLower),
96     myUpperRow                                  (theRowUpper),
97     myLowerCol                                  (theColLower),
98     myUpperCol                                  (theColUpper),
99     myDeletable                                 (Standard_True)
100   { Allocate(); }
101
102   //! Copy constructor 
103   NCollection_Array2 (const NCollection_Array2& theOther) :
104     myLowerRow                                  (theOther.LowerRow()),
105     myUpperRow                                  (theOther.UpperRow()),
106     myLowerCol                                  (theOther.LowerCol()),
107     myUpperCol                                  (theOther.UpperCol()),
108     myDeletable                                 (Standard_True)
109   {
110     Allocate();
111     *this = theOther;
112   }
113
114   //! C array-based constructor
115   NCollection_Array2(const TheItemType&     theBegin,
116                      const Standard_Integer theRowLower,
117                      const Standard_Integer theRowUpper,
118                      const Standard_Integer theColLower,
119                      const Standard_Integer theColUpper) :
120     myLowerRow                                  (theRowLower),
121     myUpperRow                                  (theRowUpper),
122     myLowerCol                                  (theColLower),
123     myUpperCol                                  (theColUpper),
124     myDeletable                                 (Standard_False)
125   {
126     myStart = (TheItemType *) &theBegin;
127     Allocate();
128   }
129
130   //! Initialise the values
131   void Init (const TheItemType& theValue) 
132   {
133     TheItemType *pCur, *pEnd=myStart+Size();
134     for(pCur = myStart; pCur<pEnd; pCur++)
135       *pCur = theValue;
136   }
137
138   //! Size (number of items)
139   Standard_Integer Size (void) const
140   { return Length(); }
141   //! Length (number of items)
142   Standard_Integer Length (void) const
143   { return RowLength() * ColLength(); }
144
145   //! RowLength 
146   Standard_Integer RowLength (void) const
147   { return (myUpperCol-myLowerCol+1); }
148   //! ColLength 
149   Standard_Integer ColLength (void) const
150   { return (myUpperRow-myLowerRow+1); }
151
152   //! LowerRow
153   Standard_Integer LowerRow (void) const
154   { return myLowerRow; }
155   //! UpperRow
156   Standard_Integer UpperRow (void) const
157   { return myUpperRow; }
158   //! LowerCol
159   Standard_Integer LowerCol (void) const
160   { return myLowerCol; }
161   //! UpperCol
162   Standard_Integer UpperCol (void) const
163   { return myUpperCol; }
164
165   //! myDeletable flag
166   Standard_Boolean IsDeletable (void) const
167   { return myDeletable; }
168
169   //! Assignment
170   NCollection_Array2& Assign (const NCollection_Array2& theOther)
171   { 
172     if (&theOther == this)
173       return *this;
174 #if !defined No_Exception && !defined No_Standard_DimensionMismatch
175     if (Length() != theOther.Length())
176       Standard_DimensionMismatch::Raise ("NCollection_Array2::operator=");
177 #endif
178     TheItemType * pMyItem  = myStart;
179     TheItemType * pItem    = theOther.myStart;
180     const Standard_Integer iSize = Length();
181     for (Standard_Integer i=0; i < iSize; i++, pItem++, pMyItem++)
182       *pMyItem = *pItem;
183     return *this; 
184   }
185
186   //! Assignment operator
187   NCollection_Array2& operator= (const NCollection_Array2& theOther)
188   { 
189     return Assign (theOther);
190   }
191
192   //! Constant value access
193   const TheItemType& Value (const Standard_Integer theRow,
194                             const Standard_Integer theCol) const
195   {
196 #if !defined No_Exception && !defined No_Standard_OutOfRange
197     if (theRow < myLowerRow || theRow > myUpperRow ||
198         theCol < myLowerCol || theCol > myUpperCol)
199       Standard_OutOfRange::Raise ("NCollection_Array2::Value");
200 #endif
201     return myData[theRow][theCol];
202   }
203
204   //! operator() - alias to ChangeValue
205   const TheItemType& operator() (const Standard_Integer theRow,
206                                  const Standard_Integer theCol) const
207   { return Value (theRow,theCol); }
208
209   //! Variable value access
210   TheItemType& ChangeValue (const Standard_Integer theRow,
211                             const Standard_Integer theCol)
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::ChangeValue");
217 #endif
218     return myData[theRow][theCol];
219   }
220
221   //! operator() - alias to ChangeValue
222   TheItemType& operator() (const Standard_Integer theRow,
223                            const Standard_Integer theCol)
224   { return ChangeValue (theRow,theCol); }
225
226   //! SetValue
227   void SetValue (const Standard_Integer theRow,
228                  const Standard_Integer theCol,
229                  const TheItemType&     theItem)
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::SetValue");
235 #endif
236     myData[theRow][theCol] = theItem;
237   }
238   
239   //! Destructor - releases the memory
240   ~NCollection_Array2 (void)
241   { 
242     if (myDeletable) delete [] myStart;
243     delete [] &(myData[myLowerRow]);
244   }
245
246  private:
247   // ----------- PRIVATE METHODS -----------
248
249   //! Allocate memory for the array, set up indirection table
250   void Allocate (void)
251   {
252     const Standard_Integer iRowSize = myUpperCol - myLowerCol + 1;
253     const Standard_Integer iColSize = myUpperRow - myLowerRow + 1;
254 #if !defined No_Exception && !defined No_Standard_RangeError
255     if (iRowSize <= 0  || iColSize <= 0)
256       Standard_RangeError::Raise ("NCollection_Array2::Allocate");
257 #endif
258     if (myDeletable) {
259       // allocation of the data in the array
260       myStart = new TheItemType[iRowSize * iColSize];
261 #if !defined No_Exception && !defined No_Standard_OutOfMemory
262       if (!myStart)
263         Standard_OutOfMemory::Raise ("NCollection_Array2 : Allocation failed");
264 #endif
265     }
266     // else myStart is set to the beginning of the given array
267     TheItemType** pTable = new TheItemType* [iColSize];
268 #if !defined No_Exception && !defined No_Standard_OutOfMemory
269     if (!pTable)
270       Standard_OutOfMemory::Raise ("NCollection_Array2 : Allocation failed");
271 #endif
272
273     // Items of pTable point to the '0'th items in the rows of the array
274     TheItemType* pRow = myStart - myLowerCol;
275     for (Standard_Integer i = 0; i < iColSize; i++) 
276     {
277       pTable[i] = pRow;
278       pRow += iRowSize;
279     }
280
281     // Set myData to the '0'th row pointer of the pTable
282     myData = pTable - myLowerRow;
283   }
284
285  protected:
286   // ---------- PROTECTED FIELDS -----------
287   Standard_Integer myLowerRow;
288   Standard_Integer myUpperRow;
289   Standard_Integer myLowerCol;
290   Standard_Integer myUpperCol;
291
292   TheItemType**    myData;      //!< Pointer to the row pointers table
293   TheItemType*     myStart;     //!< Pointer to the memory array
294   Standard_Boolean myDeletable; //!< Flag showing who allocated the array
295
296   // ----------- FRIEND CLASSES ------------
297  friend class Iterator;
298
299 };
300
301 #endif