0026799: NCollection_Array2's RowLength and ColLength return wrong value.
[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 #include <Standard_DimensionMismatch.hxx>
20 #include <Standard_OutOfMemory.hxx>
21 #include <Standard_OutOfRange.hxx>
22
23 #include <NCollection_DefineAlloc.hxx>
24
25 // *********************************************** Template for Array2 class
26 /**
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.
30 *            
31 * Warning:   Programs clients of such class must be independant
32 *            of the range of the first element. Then, a C++ for
33 *            loop must be written like this
34 *            
35 *            for (i = A.LowerRow(); i <= A.UpperRow(); i++)
36 *              for (j = A.LowerCol(); j <= A.UpperCol(); j++)
37 */            
38 template <class TheItemType>
39 class NCollection_Array2
40 {
41 public:
42   //! STL-compliant typedef for value type
43   typedef TheItemType value_type;
44
45 public:
46   // **************** Implementation of the Iterator interface.
47   class Iterator
48   {
49   public:
50     //! Empty constructor - for later Init
51     Iterator (void) :
52       myCurrent (0),
53       mySize    (0),
54       myArray   (NULL) {}
55     //! Constructor with initialisation
56     Iterator  (const NCollection_Array2& theArray) :
57       myCurrent (0),
58       mySize    (theArray.Length()),
59       myArray   ((NCollection_Array2 *) &theArray) {}
60     //! Initialisation
61     void Init (const NCollection_Array2& theArray)
62     { 
63       myCurrent = 0;
64       mySize    = theArray.Length();
65       myArray   = (NCollection_Array2 *) &theArray; 
66     }
67     //! Check end
68     Standard_Boolean More (void) const
69     { return (myCurrent < mySize); }
70     //! Make step
71     void Next (void)
72     { myCurrent++; }
73     //! Constant value access
74     const TheItemType& Value (void) const
75     { return myArray->myStart[myCurrent]; }
76     //! Variable value access
77     TheItemType& ChangeValue (void) const
78     { return myArray->myStart[myCurrent]; }
79   private:
80     Standard_Integer    myCurrent;  //!< Index of the current item
81     Standard_Integer    mySize;     //!< Total amount of items
82     NCollection_Array2* myArray;    //!< Pointer to the array being iterated
83   }; // End of nested class Iterator
84
85  public:
86   // ---------- PUBLIC METHODS ------------
87
88   //! Constructor
89   NCollection_Array2(const Standard_Integer theRowLower,
90                      const Standard_Integer theRowUpper,
91                      const Standard_Integer theColLower,
92                      const Standard_Integer theColUpper) :
93     myLowerRow                                  (theRowLower),
94     myUpperRow                                  (theRowUpper),
95     myLowerCol                                  (theColLower),
96     myUpperCol                                  (theColUpper),
97     myDeletable                                 (Standard_True)
98   { Allocate(); }
99
100   //! Copy constructor 
101   NCollection_Array2 (const NCollection_Array2& theOther) :
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     myLowerRow                                  (theRowLower),
119     myUpperRow                                  (theRowUpper),
120     myLowerCol                                  (theColLower),
121     myUpperCol                                  (theColUpper),
122     myDeletable                                 (Standard_False)
123   {
124     myStart = (TheItemType *) &theBegin;
125     Allocate();
126   }
127
128   //! Initialise the values
129   void Init (const TheItemType& theValue) 
130   {
131     TheItemType *pCur, *pEnd=myStart+Size();
132     for(pCur = myStart; pCur<pEnd; pCur++)
133       *pCur = theValue;
134   }
135
136   //! Size (number of items)
137   Standard_Integer Size (void) const
138   { return Length(); }
139   //! Length (number of items)
140   Standard_Integer Length (void) const
141   { return RowLength() * ColLength(); }
142
143   //! Returns length of the row, i.e. number of columns
144   Standard_Integer RowLength (void) const
145   { return (myUpperCol-myLowerCol+1); }
146
147   //! Returns length of the column, i.e. number of rows
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   //! Assignment
169   NCollection_Array2& Assign (const NCollection_Array2& theOther)
170   { 
171     if (&theOther == this)
172       return *this;
173     Standard_DimensionMismatch_Raise_if (Length() != theOther.Length(), "NCollection_Array2::operator=");
174     TheItemType * pMyItem  = myStart;
175     TheItemType * pItem    = theOther.myStart;
176     const Standard_Integer iSize = Length();
177     for (Standard_Integer i=0; i < iSize; i++, pItem++, pMyItem++)
178       *pMyItem = *pItem;
179     return *this; 
180   }
181
182   //! Assignment operator
183   NCollection_Array2& operator= (const NCollection_Array2& theOther)
184   { 
185     return Assign (theOther);
186   }
187
188   //! Constant value access
189   const TheItemType& Value (const Standard_Integer theRow,
190                             const Standard_Integer theCol) const
191   {
192     Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
193                                   theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::Value");
194     return myData[theRow][theCol];
195   }
196
197   //! operator() - alias to ChangeValue
198   const TheItemType& operator() (const Standard_Integer theRow,
199                                  const Standard_Integer theCol) const
200   { return Value (theRow,theCol); }
201
202   //! Variable value access
203   TheItemType& ChangeValue (const Standard_Integer theRow,
204                             const Standard_Integer theCol)
205   {
206     Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
207                                   theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::ChangeValue");
208     return myData[theRow][theCol];
209   }
210
211   //! operator() - alias to ChangeValue
212   TheItemType& operator() (const Standard_Integer theRow,
213                            const Standard_Integer theCol)
214   { return ChangeValue (theRow,theCol); }
215
216   //! SetValue
217   void SetValue (const Standard_Integer theRow,
218                  const Standard_Integer theCol,
219                  const TheItemType&     theItem)
220   {
221     Standard_OutOfRange_Raise_if (theRow < myLowerRow || theRow > myUpperRow ||
222                                   theCol < myLowerCol || theCol > myUpperCol, "NCollection_Array2::SetValue");
223     myData[theRow][theCol] = theItem;
224   }
225   
226   //! Destructor - releases the memory
227   ~NCollection_Array2 (void)
228   { 
229     if (myDeletable) delete [] myStart;
230     delete [] &(myData[myLowerRow]);
231   }
232
233  private:
234   // ----------- PRIVATE METHODS -----------
235
236   //! Allocate memory for the array, set up indirection table
237   void Allocate (void)
238   {
239     const Standard_Integer iRowSize = myUpperCol - myLowerCol + 1;
240     const Standard_Integer iColSize = myUpperRow - myLowerRow + 1;
241     Standard_RangeError_Raise_if (iRowSize <= 0  || iColSize <= 0, "NCollection_Array2::Allocate");
242     if (myDeletable) {
243       // allocation of the data in the array
244       myStart = new TheItemType[iRowSize * iColSize];
245       Standard_OutOfMemory_Raise_if (!myStart, "NCollection_Array2 : Allocation failed");
246     }
247     // else myStart is set to the beginning of the given array
248     TheItemType** pTable = new TheItemType* [iColSize];
249     Standard_OutOfMemory_Raise_if (!pTable, "NCollection_Array2 : Allocation failed");
250
251     // Items of pTable point to the '0'th items in the rows of the array
252     TheItemType* pRow = myStart - myLowerCol;
253     for (Standard_Integer i = 0; i < iColSize; i++) 
254     {
255       pTable[i] = pRow;
256       pRow += iRowSize;
257     }
258
259     // Set myData to the '0'th row pointer of the pTable
260     myData = pTable - myLowerRow;
261   }
262
263  protected:
264   // ---------- PROTECTED FIELDS -----------
265   Standard_Integer myLowerRow;
266   Standard_Integer myUpperRow;
267   Standard_Integer myLowerCol;
268   Standard_Integer myUpperCol;
269
270   TheItemType**    myData;      //!< Pointer to the row pointers table
271   TheItemType*     myStart;     //!< Pointer to the memory array
272   Standard_Boolean myDeletable; //!< Flag showing who allocated the array
273
274   // ----------- FRIEND CLASSES ------------
275  friend class Iterator;
276
277 };
278
279 #endif