b311480e |
1 | // Created on: 2002-04-23 |
2 | // Created by: Alexander GRIGORIEV |
f4aad56f |
3 | // Copyright (c) 2002-2013 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
973c2be1 |
7 | // This library is free software; you can redistribute it and / or modify it |
8 | // under the terms of the GNU Lesser General Public 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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
b311480e |
15 | |
7fd59977 |
16 | #ifndef NCollection_Vector_HeaderFile |
17 | #define NCollection_Vector_HeaderFile |
18 | |
19 | #include <NCollection_BaseVector.hxx> |
20 | #include <NCollection_BaseCollection.hxx> |
21 | |
f4aad56f |
22 | //! Class NCollection_Vector (dynamic array of objects) |
23 | //! |
24 | //! This class is similar to NCollection_Array1 though the indices always start |
25 | //! at 0 (in Array1 the first index must be specified) |
26 | //! |
27 | //! The Vector is always created with 0 length. It can be enlarged by two means: |
28 | //! 1. Calling the method Append (val) - then "val" is added to the end of the |
29 | //! vector (the vector length is incremented) |
30 | //! 2. Calling the method SetValue (i, val) - if "i" is greater than or equal |
31 | //! to the current length of the vector, the vector is enlarged to accomo- |
32 | //! date this index |
33 | //! |
34 | //! The methods Append and SetValue return a non-const reference to the copied |
35 | //! object inside the vector. This reference is guaranteed to be valid until |
36 | //! the vector is destroyed. It can be used to access the vector member directly |
37 | //! or to pass its address to other data structures. |
38 | //! |
39 | //! The vector iterator remembers the length of the vector at the moment of the |
40 | //! creation or initialisation of the iterator. Therefore the iteration begins |
41 | //! at index 0 and stops at the index equal to (remembered_length-1). It is OK |
42 | //! to enlarge the vector during the iteration. |
7fd59977 |
43 | template <class TheItemType> class NCollection_Vector |
f4aad56f |
44 | : public NCollection_BaseCollection<TheItemType>, |
45 | public NCollection_BaseVector |
7fd59977 |
46 | { |
f4aad56f |
47 | public: |
48 | |
23be7421 |
49 | typedef TheItemType TheItemTypeD; |
7fd59977 |
50 | |
f4aad56f |
51 | //! Nested class Iterator |
7fd59977 |
52 | class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator, |
53 | public NCollection_BaseVector::Iterator |
54 | { |
55 | public: |
f4aad56f |
56 | |
7fd59977 |
57 | //! Empty constructor - for later Init |
f4aad56f |
58 | Iterator() {} |
59 | |
7fd59977 |
60 | //! Constructor with initialisation |
f4aad56f |
61 | Iterator (const NCollection_Vector& theVector) |
62 | : NCollection_BaseVector::Iterator (theVector) {} |
63 | |
7fd59977 |
64 | //! Copy constructor |
f4aad56f |
65 | Iterator (const Iterator& theOther) |
66 | : NCollection_BaseVector::Iterator (theOther) {} |
67 | |
7fd59977 |
68 | //! Initialisation |
f4aad56f |
69 | void Init (const NCollection_Vector& theVector) |
70 | { |
71 | initV (theVector); |
72 | } |
73 | |
7fd59977 |
74 | //! Assignment |
f4aad56f |
75 | Iterator& operator= (const Iterator& theOther) |
76 | { |
77 | copyV (theOther); |
78 | return *this; |
7fd59977 |
79 | } |
f4aad56f |
80 | |
7fd59977 |
81 | //! Check end |
f4aad56f |
82 | virtual Standard_Boolean More() const |
83 | { |
84 | return moreV(); |
85 | } |
86 | |
7fd59977 |
87 | //! Make step |
f4aad56f |
88 | virtual void Next() |
89 | { |
90 | nextV(); |
91 | } |
92 | |
7fd59977 |
93 | //! Constant value access |
f4aad56f |
94 | virtual const TheItemType& Value() const |
95 | { |
96 | return ((const TheItemType* )curBlockV()->DataPtr)[myCurIndex]; |
97 | } |
98 | |
7fd59977 |
99 | //! Variable value access |
f4aad56f |
100 | virtual TheItemType& ChangeValue() const |
101 | { |
102 | return ((TheItemType* )curBlockV()->DataPtr)[myCurIndex]; |
103 | } |
104 | |
105 | }; |
7fd59977 |
106 | |
f4aad56f |
107 | public: //! @name public methods |
7fd59977 |
108 | |
109 | //! Constructor |
110 | NCollection_Vector (const Standard_Integer theIncrement = 256, |
f4aad56f |
111 | const Handle_NCollection_BaseAllocator& theAlloc = NULL) |
112 | : NCollection_BaseCollection<TheItemType> (theAlloc), |
113 | NCollection_BaseVector (NCollection_BaseCollection<TheItemType>::myAllocator, initMemBlocks, sizeof(TheItemType), theIncrement) {} |
7fd59977 |
114 | |
115 | //! Copy constructor |
116 | NCollection_Vector (const NCollection_Vector& theOther) |
f4aad56f |
117 | : NCollection_BaseCollection<TheItemType> (theOther.myAllocator), |
118 | NCollection_BaseVector (NCollection_BaseCollection<TheItemType>::myAllocator, initMemBlocks, theOther) |
119 | { |
120 | copyData (theOther); |
121 | } |
122 | |
123 | //! Destructor |
124 | ~NCollection_Vector() |
125 | { |
126 | for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter) |
127 | { |
128 | initMemBlocks (*this, myData[anItemIter], 0, 0); |
7fd59977 |
129 | } |
f4aad56f |
130 | NCollection_BaseCollection<TheItemType>::myAllocator->Free (myData); |
131 | } |
132 | |
133 | //! Operator= |
134 | NCollection_Vector& operator= (const NCollection_Vector& theOther) |
135 | { |
136 | Assign (theOther, Standard_False); |
137 | return *this; |
138 | } |
139 | |
140 | //! Total number of items |
141 | Standard_Integer Length() const |
142 | { |
143 | return myLength; |
7fd59977 |
144 | } |
145 | |
146 | //! Total number of items in the vector |
f4aad56f |
147 | virtual Standard_Integer Size() const |
148 | { |
149 | return myLength; |
150 | } |
7fd59977 |
151 | |
a174a3c5 |
152 | //! Method for consistency with other collections. |
153 | //! @return Lower bound (inclusive) for iteration. |
154 | Standard_Integer Lower() const |
155 | { |
156 | return 0; |
157 | } |
158 | |
159 | //! Method for consistency with other collections. |
160 | //! @return Upper bound (inclusive) for iteration. |
161 | Standard_Integer Upper() const |
162 | { |
f4aad56f |
163 | return myLength - 1; |
a174a3c5 |
164 | } |
165 | |
166 | //! Empty query |
167 | Standard_Boolean IsEmpty() const |
168 | { |
f4aad56f |
169 | return (myLength == 0); |
a174a3c5 |
170 | } |
171 | |
7fd59977 |
172 | //! Virtual assignment (any collection to this array) |
173 | virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther) |
174 | { |
f4aad56f |
175 | if (this != &theOther) |
176 | { |
177 | TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = theOther.CreateIterator(); |
178 | while (anIter2.More()) |
179 | { |
7fd59977 |
180 | Append (anIter2.Value()); |
181 | anIter2.Next(); |
182 | } |
183 | } |
184 | } |
185 | |
186 | //! Assignment to the collection of the same type |
f4aad56f |
187 | inline void Assign (const NCollection_Vector& theOther, |
188 | const Standard_Boolean theOwnAllocator = Standard_True); |
7fd59977 |
189 | |
190 | //! Method to create iterators for base collections |
f4aad56f |
191 | virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& CreateIterator() const |
192 | { |
193 | return *(new (this->IterAllocator()) Iterator(*this)); |
194 | } |
7fd59977 |
195 | |
196 | //! Append |
f4aad56f |
197 | TheItemType& Append (const TheItemType& theValue) |
198 | { |
199 | TheItemType& anAppended = *(TheItemType* )expandV (NCollection_BaseCollection<TheItemType>::myAllocator, myLength); |
7fd59977 |
200 | anAppended = theValue; |
201 | return anAppended; |
202 | } |
203 | |
f4aad56f |
204 | //! Operator() - query the const value |
205 | const TheItemType& operator() (const Standard_Integer theIndex) const |
206 | { |
207 | return Value (theIndex); |
208 | } |
209 | |
210 | const TheItemType& Value (const Standard_Integer theIndex) const |
211 | { |
212 | return *(const TheItemType* )findV (theIndex); |
7fd59977 |
213 | } |
214 | |
a174a3c5 |
215 | //! @return first element |
216 | const TheItemType& First() const |
217 | { |
f4aad56f |
218 | return *(const TheItemType* )findV (Lower()); |
a174a3c5 |
219 | } |
220 | |
221 | //! @return first element |
222 | TheItemType& ChangeFirst() |
223 | { |
f4aad56f |
224 | return *(TheItemType* )findV (Lower()); |
a174a3c5 |
225 | } |
226 | |
227 | //! @return last element |
228 | const TheItemType& Last() const |
229 | { |
f4aad56f |
230 | return *(const TheItemType* )findV (Upper()); |
a174a3c5 |
231 | } |
232 | |
233 | //! @return last element |
234 | TheItemType& ChangeLast() |
235 | { |
f4aad56f |
236 | return *(TheItemType* )findV (Upper()); |
a174a3c5 |
237 | } |
238 | |
f4aad56f |
239 | //! Operator() - query the value |
240 | TheItemType& operator() (const Standard_Integer theIndex) |
241 | { |
242 | return ChangeValue (theIndex); |
243 | } |
244 | |
245 | TheItemType& ChangeValue (const Standard_Integer theIndex) |
246 | { |
247 | return *(TheItemType* )findV (theIndex); |
7fd59977 |
248 | } |
249 | |
250 | //! SetValue () - set or append a value |
f4aad56f |
251 | TheItemType& SetValue (const Standard_Integer theIndex, |
252 | const TheItemType& theValue) |
253 | { |
254 | Standard_OutOfRange_Raise_if (theIndex < 0, "NCollection_Vector::SetValue"); |
255 | TheItemType* const aVecValue = (TheItemType* )(theIndex < myLength ? findV (theIndex) : expandV (NCollection_BaseCollection<TheItemType>::myAllocator, theIndex)); |
256 | *aVecValue = theValue; |
257 | return *aVecValue; |
7fd59977 |
258 | } |
259 | |
f4aad56f |
260 | private: //! @name private methods |
261 | |
262 | void copyData (const NCollection_Vector& theOther) |
263 | { |
264 | Standard_Integer iBlock = 0; |
7fd59977 |
265 | /*NCollection_Vector::*/Iterator anIter (theOther); |
f4aad56f |
266 | for (Standard_Integer aLength = 0; aLength < myLength; aLength += myIncrement) |
267 | { |
268 | MemBlock& aBlock = myData[iBlock]; |
269 | initMemBlocks (*this, aBlock, aLength, myIncrement); |
270 | Standard_Integer anItemIter = 0; |
271 | for (; anItemIter < myIncrement; ++anItemIter) |
272 | { |
273 | if (!anIter.More()) |
274 | { |
275 | break; |
276 | } |
277 | |
278 | ((TheItemType* )aBlock.DataPtr)[anItemIter] = anIter.Value(); |
7fd59977 |
279 | anIter.Next(); |
280 | } |
f4aad56f |
281 | aBlock.Length = anItemIter; |
7fd59977 |
282 | iBlock++; |
283 | } |
284 | } |
285 | |
f4aad56f |
286 | //! Method to initialize memory block content |
287 | static void initMemBlocks (NCollection_BaseVector& theVector, |
288 | NCollection_BaseVector::MemBlock& theBlock, |
289 | const Standard_Integer theFirst, |
290 | const Standard_Integer theSize) |
7fd59977 |
291 | { |
f4aad56f |
292 | NCollection_Vector& aSelf = static_cast<NCollection_Vector&> (theVector); |
293 | Handle(NCollection_BaseAllocator)& anAllocator = aSelf.myAllocator; |
294 | |
295 | // release current content |
296 | if (theBlock.DataPtr != NULL) |
297 | { |
298 | for (Standard_Integer anItemIter = 0; anItemIter < theBlock.Size; ++anItemIter) |
299 | { |
300 | ((TheItemType* )theBlock.DataPtr)[anItemIter].~TheItemTypeD(); |
301 | } |
302 | anAllocator->Free (theBlock.DataPtr); |
303 | theBlock.DataPtr = NULL; |
7fd59977 |
304 | } |
7fd59977 |
305 | |
f4aad56f |
306 | // allocate new content if requested |
307 | if (theSize > 0) |
308 | { |
309 | theBlock.DataPtr = anAllocator->Allocate (theSize * sizeof(TheItemType)); |
310 | for (Standard_Integer anItemIter = 0; anItemIter < theSize; ++anItemIter) |
311 | { |
312 | new (&((TheItemType* )theBlock.DataPtr)[anItemIter]) TheItemType; |
313 | } |
314 | } |
315 | theBlock.FirstIndex = theFirst; |
316 | theBlock.Size = theSize; |
317 | theBlock.Length = 0; |
7fd59977 |
318 | } |
319 | |
320 | friend class Iterator; |
f4aad56f |
321 | |
7fd59977 |
322 | }; |
323 | |
f4aad56f |
324 | //! Assignment to the collection of the same type |
325 | template <class TheItemType> inline |
326 | void NCollection_Vector<TheItemType>::Assign (const NCollection_Vector& theOther, |
327 | const Standard_Boolean theOwnAllocator) |
328 | { |
329 | if (this == &theOther) |
330 | { |
331 | return; |
332 | } |
333 | |
334 | // destroy current data using current allocator |
335 | for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter) |
336 | { |
337 | initMemBlocks (*this, myData[anItemIter], 0, 0); |
338 | } |
339 | NCollection_BaseCollection<TheItemType>::myAllocator->Free (myData); |
340 | |
341 | // allocate memory blocks with new allocator |
342 | if (!theOwnAllocator) |
343 | { |
344 | NCollection_BaseCollection<TheItemType>::myAllocator = theOther.myAllocator; |
345 | } |
346 | myIncrement = theOther.myIncrement; |
347 | myLength = theOther.myLength; |
348 | myNBlocks = (myLength == 0) ? 0 : (1 + (myLength - 1)/myIncrement); |
349 | myCapacity = GetCapacity (myIncrement) + myLength / myIncrement; |
350 | myData = allocMemBlocks (NCollection_BaseCollection<TheItemType>::myAllocator, myCapacity); |
351 | |
352 | // copy data |
353 | copyData (theOther); |
354 | } |
355 | |
356 | #endif // NCollection_Vector_HeaderFile |