0031671: Coding Rules - eliminate warnings issued by clang 11
[occt.git] / src / NCollection / NCollection_Vector.hxx
1 // Created on: 2002-04-23
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2002-2013 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_Vector_HeaderFile
17 #define NCollection_Vector_HeaderFile
18
19 #include <NCollection_BaseVector.hxx>
20 #include <NCollection_StlIterator.hxx>
21
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.
43 template <class TheItemType>
44 class NCollection_Vector : public NCollection_BaseVector
45 {
46 public:
47   //! STL-compliant typedef for value type
48   typedef TheItemType value_type;
49
50 public:
51
52   //! Nested class Iterator
53   class Iterator : public NCollection_BaseVector::Iterator
54   {
55   public:
56
57     //! Empty constructor - for later Init
58     Iterator() {}
59
60     //! Constructor with initialisation
61     Iterator (const NCollection_Vector& theVector, Standard_Boolean theToEnd = Standard_False)
62     : NCollection_BaseVector::Iterator (theVector, theToEnd) {}
63
64     //! Initialisation
65     void Init (const NCollection_Vector& theVector)
66     {
67       initV (theVector);
68     }
69
70     //! Check end
71     Standard_Boolean More() const
72     {
73       return moreV();
74     }
75
76     //! Increment operator.
77     void Next()
78     {
79       nextV();
80     }
81
82     //! Decrement operator.
83     void Previous()
84     {
85       prevV();
86     }
87
88     //! Offset operator.
89     void Offset (ptrdiff_t theOffset)
90     {
91       offsetV (static_cast<int>(theOffset));
92     }
93
94     //! Difference operator.
95     ptrdiff_t Differ (const Iterator& theOther) const
96     {
97       return differV (theOther);
98     }
99
100     //! Constant value access
101     const TheItemType& Value() const
102     {
103       return ((const TheItemType* )curBlockV()->DataPtr)[myCurIndex];
104     }
105
106     //! Variable value access
107     TheItemType& ChangeValue() const
108     {
109       return ((TheItemType* )curBlockV()->DataPtr)[myCurIndex];
110     }
111
112     //! Performs comparison of two iterators.
113     Standard_Boolean IsEqual (const Iterator& theOther) const
114     {
115       return myVector    == theOther.myVector
116           && myCurIndex  == theOther.myCurIndex
117           && myEndIndex  == theOther.myEndIndex  
118           && myICurBlock == theOther.myICurBlock
119           && myIEndBlock == theOther.myIEndBlock;
120     }
121   };
122
123   //! Shorthand for a regular iterator type.
124   typedef NCollection_StlIterator<std::random_access_iterator_tag, Iterator, TheItemType, false> iterator;
125
126   //! Shorthand for a constant iterator type.
127   typedef NCollection_StlIterator<std::random_access_iterator_tag, Iterator, TheItemType, true> const_iterator;
128
129   //! Returns an iterator pointing to the first element in the vector.
130   iterator begin() const { return Iterator (*this, false); }
131
132   //! Returns an iterator referring to the past-the-end element in the vector.
133   iterator end() const { return Iterator (*this, true); }
134
135   //! Returns a const iterator pointing to the first element in the vector.
136   const_iterator cbegin() const { return Iterator (*this, false); }
137
138   //! Returns a const iterator referring to the past-the-end element in the vector.
139   const_iterator cend() const { return Iterator (*this, true); }
140
141 public: //! @name public methods
142
143   //! Constructor
144   explicit NCollection_Vector (const Standard_Integer theIncrement              = 256,
145                                const Handle(NCollection_BaseAllocator)& theAlloc = NULL) :
146     NCollection_BaseVector (theAlloc, initMemBlocks, sizeof(TheItemType), theIncrement)
147   {}
148
149   //! Copy constructor
150   NCollection_Vector (const NCollection_Vector& theOther) :
151     NCollection_BaseVector (theOther.myAllocator, initMemBlocks, theOther)
152   {
153     copyData (theOther);
154   }
155
156   //! Destructor
157   virtual ~NCollection_Vector()
158   {
159     for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
160     {
161       initMemBlocks (*this, myData[anItemIter], 0, 0);
162     }
163     this->myAllocator->Free (myData);
164   }
165
166   //! Total number of items
167   Standard_Integer Length() const
168   {
169     return myLength;
170   }
171
172   //! Total number of items in the vector
173   Standard_Integer Size() const
174   {
175     return myLength;
176   }
177
178   //! Method for consistency with other collections.
179   //! @return Lower bound (inclusive) for iteration.
180   Standard_Integer Lower() const
181   {
182     return 0;
183   }
184
185   //! Method for consistency with other collections.
186   //! @return Upper bound (inclusive) for iteration.
187   Standard_Integer Upper() const
188   {
189     return myLength - 1;
190   }
191
192   //! Empty query
193   Standard_Boolean IsEmpty() const
194   {
195     return (myLength == 0);
196   }
197
198   //! Assignment to the collection of the same type
199   inline void Assign (const NCollection_Vector& theOther,
200                       const Standard_Boolean theOwnAllocator = Standard_True);
201
202   //! Assignment operator
203   NCollection_Vector& operator= (const NCollection_Vector& theOther)
204   {
205     Assign (theOther, Standard_False);
206     return *this;
207   }
208
209   //! Append
210   TheItemType& Append (const TheItemType& theValue)
211   {
212     TheItemType& anAppended = *(TheItemType* )expandV (myLength);
213     anAppended = theValue;
214     return anAppended;
215   }
216
217   //! Appends an empty value and returns the reference to it
218   TheItemType& Appended ()
219   {
220     TheItemType& anAppended = *(TheItemType* )expandV (myLength);
221     return anAppended;
222   }
223
224   //! Operator() - query the const value
225   const TheItemType& operator() (const Standard_Integer theIndex) const
226   {
227     return Value (theIndex);
228   }
229
230   //! Operator[] - query the const value
231   const TheItemType& operator[] (Standard_Integer theIndex) const { return Value (theIndex); }
232
233   const TheItemType& Value (const Standard_Integer theIndex) const
234   {
235     return *(const TheItemType* )findV (theIndex);
236   }
237
238   //! @return first element
239   const TheItemType& First() const
240   {
241     return *(const TheItemType* )findV (Lower());
242   }
243
244   //! @return first element
245   TheItemType& ChangeFirst()
246   {
247     return *(TheItemType* )findV (Lower());
248   }
249
250   //! @return last element
251   const TheItemType& Last() const
252   {
253     return *(const TheItemType* )findV (Upper());
254   }
255
256   //! @return last element
257   TheItemType& ChangeLast()
258   {
259     return *(TheItemType* )findV (Upper());
260   }
261
262   //! Operator() - query the value
263   TheItemType& operator() (const Standard_Integer theIndex)
264   {
265     return ChangeValue (theIndex);
266   }
267
268   //! Operator[] - query the value
269   TheItemType& operator[] ( Standard_Integer theIndex) { return ChangeValue (theIndex); }
270
271   TheItemType& ChangeValue (const Standard_Integer theIndex)
272   {
273     return *(TheItemType* )findV (theIndex);
274   }
275
276   //! SetValue () - set or append a value
277   TheItemType& SetValue (const Standard_Integer theIndex,
278                          const TheItemType&     theValue)
279   {
280     Standard_OutOfRange_Raise_if (theIndex < 0, "NCollection_Vector::SetValue");
281     TheItemType* const aVecValue = (TheItemType* )(theIndex < myLength ? findV (theIndex) : expandV (theIndex));
282     *aVecValue = theValue;
283     return *aVecValue;
284   }
285
286 private: //! @name private methods
287
288   void copyData (const NCollection_Vector& theOther)
289   {
290     Standard_Integer iBlock = 0;
291     /*NCollection_Vector::*/Iterator anIter (theOther);
292     for (Standard_Integer aLength = 0; aLength < myLength; aLength += myIncrement)
293     {
294       MemBlock& aBlock = myData[iBlock];
295       initMemBlocks (*this, aBlock, aLength, myIncrement);
296       Standard_Integer anItemIter = 0;
297       for (; anItemIter < myIncrement; ++anItemIter)
298       {
299         if (!anIter.More())
300         {
301           break;
302         }
303
304         ((TheItemType* )aBlock.DataPtr)[anItemIter] = anIter.Value();
305         anIter.Next();
306       }
307       aBlock.Length = anItemIter;
308       iBlock++;
309     }
310   }
311
312   //! Method to initialize memory block content
313   static void initMemBlocks (NCollection_BaseVector&           theVector,
314                              NCollection_BaseVector::MemBlock& theBlock,
315                              const Standard_Integer            theFirst,
316                              const Standard_Integer            theSize)
317   {
318     NCollection_Vector& aSelf = static_cast<NCollection_Vector&> (theVector);
319     Handle(NCollection_BaseAllocator)& anAllocator = aSelf.myAllocator;
320
321     // release current content
322     if (theBlock.DataPtr != NULL)
323     {
324       for (Standard_Integer anItemIter = 0; anItemIter < theBlock.Size; ++anItemIter)
325       {
326         ((TheItemType* )theBlock.DataPtr)[anItemIter].~TheItemType();
327       }
328       anAllocator->Free (theBlock.DataPtr);
329       theBlock.DataPtr = NULL;
330     }
331
332     // allocate new content if requested
333     if (theSize > 0)
334     {
335       theBlock.DataPtr = anAllocator->Allocate (theSize * sizeof(TheItemType));
336       for (Standard_Integer anItemIter = 0; anItemIter < theSize; ++anItemIter)
337       {
338         new (&((TheItemType* )theBlock.DataPtr)[anItemIter]) TheItemType;
339       }
340     }
341     theBlock.FirstIndex = theFirst;
342     theBlock.Size       = theSize;
343     theBlock.Length     = 0;
344   }
345
346   friend class Iterator;
347
348 };
349
350 //! Assignment to the collection of the same type
351 template <class TheItemType> inline
352 void NCollection_Vector<TheItemType>::Assign (const NCollection_Vector& theOther,
353                                               const Standard_Boolean    theOwnAllocator)
354 {
355   if (this == &theOther)
356   {
357     return;
358   }
359
360   // destroy current data using current allocator
361   for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
362   {
363     initMemBlocks (*this, myData[anItemIter], 0, 0);
364   }
365   this->myAllocator->Free (myData);
366
367   // allocate memory blocks with new allocator
368   if (!theOwnAllocator)
369   {
370     this->myAllocator = theOther.myAllocator;
371   }
372   myIncrement = theOther.myIncrement;
373   myLength    = theOther.myLength;
374   myNBlocks   = (myLength == 0) ? 0 : (1 + (myLength - 1)/myIncrement);
375   myCapacity  = GetCapacity (myIncrement) + myLength / myIncrement;
376   myData      = allocMemBlocks (myCapacity);
377
378   // copy data
379   copyData (theOther);
380 }
381
382 #endif // NCollection_Vector_HeaderFile