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