1 // Created on: 2002-04-23
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2002-2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef NCollection_Vector_HeaderFile
17 #define NCollection_Vector_HeaderFile
19 #include <NCollection_BaseVector.hxx>
20 #include <NCollection_BaseCollection.hxx>
22 //! Class NCollection_Vector (dynamic array of objects)
24 //! This class is similar to NCollection_Array1 though the indices always start
25 //! at 0 (in Array1 the first index must be specified)
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-
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.
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.
43 template <class TheItemType> class NCollection_Vector
44 : public NCollection_BaseCollection<TheItemType>,
45 public NCollection_BaseVector
49 typedef TheItemType TheItemTypeD;
51 //! Nested class Iterator
52 class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator,
53 public NCollection_BaseVector::Iterator
57 //! Empty constructor - for later Init
60 //! Constructor with initialisation
61 Iterator (const NCollection_Vector& theVector)
62 : NCollection_BaseVector::Iterator (theVector) {}
65 Iterator (const Iterator& theOther)
66 : NCollection_BaseVector::Iterator (theOther) {}
69 void Init (const NCollection_Vector& theVector)
75 Iterator& operator= (const Iterator& theOther)
82 virtual Standard_Boolean More() const
93 //! Constant value access
94 virtual const TheItemType& Value() const
96 return ((const TheItemType* )curBlockV()->DataPtr)[myCurIndex];
99 //! Variable value access
100 virtual TheItemType& ChangeValue() const
102 return ((TheItemType* )curBlockV()->DataPtr)[myCurIndex];
107 public: //! @name public methods
110 NCollection_Vector (const Standard_Integer theIncrement = 256,
111 const Handle(NCollection_BaseAllocator)& theAlloc = NULL)
112 : NCollection_BaseCollection<TheItemType> (theAlloc),
113 NCollection_BaseVector (NCollection_BaseCollection<TheItemType>::myAllocator, initMemBlocks, sizeof(TheItemType), theIncrement) {}
116 NCollection_Vector (const NCollection_Vector& theOther)
117 : NCollection_BaseCollection<TheItemType> (theOther.myAllocator),
118 NCollection_BaseVector (NCollection_BaseCollection<TheItemType>::myAllocator, initMemBlocks, theOther)
124 ~NCollection_Vector()
126 for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
128 initMemBlocks (*this, myData[anItemIter], 0, 0);
130 NCollection_BaseCollection<TheItemType>::myAllocator->Free (myData);
134 NCollection_Vector& operator= (const NCollection_Vector& theOther)
136 Assign (theOther, Standard_False);
140 //! Total number of items
141 Standard_Integer Length() const
146 //! Total number of items in the vector
147 virtual Standard_Integer Size() const
152 //! Method for consistency with other collections.
153 //! @return Lower bound (inclusive) for iteration.
154 Standard_Integer Lower() const
159 //! Method for consistency with other collections.
160 //! @return Upper bound (inclusive) for iteration.
161 Standard_Integer Upper() const
167 Standard_Boolean IsEmpty() const
169 return (myLength == 0);
172 //! Virtual assignment (any collection to this array)
173 virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
175 if (this != &theOther)
177 TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = theOther.CreateIterator();
178 while (anIter2.More())
180 Append (anIter2.Value());
186 //! Assignment to the collection of the same type
187 inline void Assign (const NCollection_Vector& theOther,
188 const Standard_Boolean theOwnAllocator = Standard_True);
190 //! Method to create iterators for base collections
191 virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& CreateIterator() const
193 return *(new (this->IterAllocator()) Iterator(*this));
197 TheItemType& Append (const TheItemType& theValue)
199 TheItemType& anAppended = *(TheItemType* )expandV (NCollection_BaseCollection<TheItemType>::myAllocator, myLength);
200 anAppended = theValue;
204 //! Operator() - query the const value
205 const TheItemType& operator() (const Standard_Integer theIndex) const
207 return Value (theIndex);
210 const TheItemType& Value (const Standard_Integer theIndex) const
212 return *(const TheItemType* )findV (theIndex);
215 //! @return first element
216 const TheItemType& First() const
218 return *(const TheItemType* )findV (Lower());
221 //! @return first element
222 TheItemType& ChangeFirst()
224 return *(TheItemType* )findV (Lower());
227 //! @return last element
228 const TheItemType& Last() const
230 return *(const TheItemType* )findV (Upper());
233 //! @return last element
234 TheItemType& ChangeLast()
236 return *(TheItemType* )findV (Upper());
239 //! Operator() - query the value
240 TheItemType& operator() (const Standard_Integer theIndex)
242 return ChangeValue (theIndex);
245 TheItemType& ChangeValue (const Standard_Integer theIndex)
247 return *(TheItemType* )findV (theIndex);
250 //! SetValue () - set or append a value
251 TheItemType& SetValue (const Standard_Integer theIndex,
252 const TheItemType& theValue)
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;
260 private: //! @name private methods
262 void copyData (const NCollection_Vector& theOther)
264 Standard_Integer iBlock = 0;
265 /*NCollection_Vector::*/Iterator anIter (theOther);
266 for (Standard_Integer aLength = 0; aLength < myLength; aLength += myIncrement)
268 MemBlock& aBlock = myData[iBlock];
269 initMemBlocks (*this, aBlock, aLength, myIncrement);
270 Standard_Integer anItemIter = 0;
271 for (; anItemIter < myIncrement; ++anItemIter)
278 ((TheItemType* )aBlock.DataPtr)[anItemIter] = anIter.Value();
281 aBlock.Length = anItemIter;
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)
292 NCollection_Vector& aSelf = static_cast<NCollection_Vector&> (theVector);
293 Handle(NCollection_BaseAllocator)& anAllocator = aSelf.myAllocator;
295 // release current content
296 if (theBlock.DataPtr != NULL)
298 for (Standard_Integer anItemIter = 0; anItemIter < theBlock.Size; ++anItemIter)
300 ((TheItemType* )theBlock.DataPtr)[anItemIter].~TheItemTypeD();
302 anAllocator->Free (theBlock.DataPtr);
303 theBlock.DataPtr = NULL;
306 // allocate new content if requested
309 theBlock.DataPtr = anAllocator->Allocate (theSize * sizeof(TheItemType));
310 for (Standard_Integer anItemIter = 0; anItemIter < theSize; ++anItemIter)
312 new (&((TheItemType* )theBlock.DataPtr)[anItemIter]) TheItemType;
315 theBlock.FirstIndex = theFirst;
316 theBlock.Size = theSize;
320 friend class Iterator;
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)
329 if (this == &theOther)
334 // destroy current data using current allocator
335 for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
337 initMemBlocks (*this, myData[anItemIter], 0, 0);
339 NCollection_BaseCollection<TheItemType>::myAllocator->Free (myData);
341 // allocate memory blocks with new allocator
342 if (!theOwnAllocator)
344 NCollection_BaseCollection<TheItemType>::myAllocator = theOther.myAllocator;
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);
356 #endif // NCollection_Vector_HeaderFile