0022815: Missing delete operator for placement new
[occt.git] / src / NCollection / NCollection_Vector.hxx
1 // File:      NCollection_Vector.hxx
2 // Created:   23.04.02 19:24:33
3 // Author:    Alexander GRIGORIEV
4 // Copyright: Open Cascade 2002
5
6
7 #ifndef NCollection_Vector_HeaderFile
8 #define NCollection_Vector_HeaderFile
9
10 #include <NCollection_BaseVector.hxx>
11 #include <NCollection_BaseCollection.hxx>
12
13 #if !defined No_Exception && !defined No_Standard_OutOfRange
14 #include <Standard_OutOfRange.hxx>
15 #endif
16
17 /**
18 * Class NCollection_Vector (dynamic array of objects)
19 *
20 * This class is similar to NCollection_Array1  though the indices always start
21 * at 0 (in Array1 the first index must be specified)
22 *
23 * The Vector is always created with 0 length. It can be enlarged by two means:
24 *   1. Calling the method Append (val) - then "val" is added to the end of the
25 *      vector (the vector length is incremented)
26 *   2. Calling the method SetValue (i, val)  - if "i" is greater than or equal
27 *      to the current length of the vector,  the vector is enlarged to accomo-
28 *      date this index
29 *
30 * The methods Append and SetValue return  a non-const reference  to the copied
31 * object  inside  the vector.  This reference  is guaranteed to be valid until
32 * the vector is destroyed. It can be used to access the vector member directly
33 * or to pass its address to other data structures.
34 *
35 * The vector iterator remembers the length of the vector  at the moment of the
36 * creation or initialisation of the iterator.   Therefore the iteration begins
37 * at index 0  and stops at the index equal to (remembered_length-1).  It is OK
38 * to enlarge the vector during the iteration.
39 */
40
41 template <class TheItemType> class NCollection_Vector
42                             : public NCollection_BaseCollection<TheItemType>,
43                               public NCollection_BaseVector
44 {
45  public:
46   typedef TheItemType TheItemTypeD;
47   // ----------------------------------------------------------------------
48   //! Nested class MemBlock
49   class MemBlock : public NCollection_BaseVector::MemBlock
50   {
51    public:
52     DEFINE_STANDARD_ALLOC
53
54     //! Empty constructor
55     MemBlock (NCollection_BaseAllocator* theAlloc)
56       : NCollection_BaseVector::MemBlock(0,0,theAlloc)
57     {}
58     //! Constructor
59     MemBlock (const Standard_Integer theFirstInd,
60               const Standard_Integer theSize,
61               NCollection_BaseAllocator* theAlloc)
62       : NCollection_BaseVector::MemBlock (theFirstInd, theSize, theAlloc)
63     {
64       myData = myAlloc->Allocate(theSize * sizeof(TheItemType));
65       for (Standard_Integer i=0; i < theSize; i++)
66         new (&((TheItemType *) myData)[i]) TheItemType;
67     }
68     //! Copy constructor
69     MemBlock (const MemBlock& theOther)
70       : NCollection_BaseVector::MemBlock (theOther.FirstIndex(),theOther.Size(),
71                                           theOther.myAlloc)
72     {
73       myLength = theOther.Length();
74       myData = myAlloc->Allocate(Size() * sizeof(TheItemType));
75       Standard_Integer i;
76       for (i=0; i < Length(); i++)
77         new (&((TheItemType *) myData)[i]) TheItemType(theOther.Value(i));
78       for (; i < Size(); i++)
79         new (&((TheItemType *) myData)[i]) TheItemType;
80     }
81     //! Reinit
82     virtual void Reinit (const Standard_Integer theFirst,
83                          const Standard_Integer theSize)
84     {
85       if (myData) {
86         for (Standard_Integer i=0; i < mySize; i++)
87           ((TheItemType *) myData)[i].~TheItemTypeD();
88         myAlloc->Free(myData);
89         myData = NULL;
90       }
91       if (theSize > 0) {
92         myData = myAlloc->Allocate(theSize * sizeof(TheItemType));
93         for (Standard_Integer i=0; i < theSize; i++)
94           new (&((TheItemType *) myData)[i]) TheItemType;
95       }
96       myFirstInd = theFirst;
97       mySize     = theSize;
98       myLength   = 0;
99     }
100     //! Destructor
101     virtual ~MemBlock ()
102     {
103       if (myData) {
104         for (Standard_Integer i=0; i < Size(); i++)
105           ((TheItemType *) myData)[i].~TheItemTypeD();
106         myAlloc->Free(myData);
107         myData = NULL;
108       }
109     }
110     //! Operator () const
111     const TheItemType& Value (const Standard_Integer theIndex) const
112     { return ((TheItemType *) myData) [theIndex]; }
113     //! Operator ()
114     TheItemType& ChangeValue (const Standard_Integer theIndex)
115     { return ((TheItemType *) myData) [theIndex]; }
116     //! GetIndex
117     Standard_Integer GetIndex (const TheItemType& theItem) const {
118       return GetIndexV ((void *)&theItem, sizeof(TheItemType));
119     }
120   }; // End of the nested class MemBlock
121
122   // ----------------------------------------------------------------------
123   // ------------------------ Nested class Iterator -----------------------
124   // ----------------------------------------------------------------------
125   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator,
126                    public NCollection_BaseVector::Iterator
127   {
128   public:
129     //! Empty constructor - for later Init
130     Iterator  (void) {}
131     //! Constructor with initialisation
132     Iterator  (const NCollection_Vector& theVector) :
133       NCollection_BaseVector::Iterator (theVector) {}
134     //! Copy constructor
135     Iterator  (const Iterator& theOther) :
136       NCollection_BaseVector::Iterator (theOther) {}
137     //! Initialisation
138     void Init (const NCollection_Vector& theVector) { InitV (theVector); } 
139     //! Assignment
140     Iterator& operator =  (const Iterator& theOther) {
141       CopyV (theOther);
142       return * this;
143     }
144     //! Check end
145     virtual Standard_Boolean More (void) const          { return MoreV (); }
146     //! Make step
147     virtual void             Next (void)                { NextV(); }
148     //! Constant value access
149     virtual const TheItemType& Value (void) const       {
150       return ((const MemBlock *) CurBlockV()) -> Value(myCurIndex); }
151     //! Variable value access
152     virtual TheItemType& ChangeValue (void) const       {
153       return ((MemBlock *) CurBlockV()) -> ChangeValue(myCurIndex); }
154   }; // End of the nested class Iterator
155
156   // ----------------------------------------------------------------------
157   // ------------------------ Class Vector itself -------------------------
158   // ----------------------------------------------------------------------
159  public:
160   // ---------- PUBLIC METHODS ----------
161
162   //! Constructor
163   NCollection_Vector (const Standard_Integer theIncrement              = 256,
164                       const Handle_NCollection_BaseAllocator& theAlloc = 0L)
165     : NCollection_BaseCollection<TheItemType>(theAlloc),
166       NCollection_BaseVector (sizeof(TheItemType), theIncrement,
167                               FuncDataInit, FuncDataFree) {}
168
169   //! Copy constructor
170   NCollection_Vector (const NCollection_Vector& theOther)
171     : NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
172       NCollection_BaseVector (theOther, FuncDataInit, FuncDataFree)
173     { CopyData (theOther); }
174
175   //! Operator =
176   NCollection_Vector& operator = (const NCollection_Vector& theOther) {
177     if (this != &theOther) {
178       this->myAllocator = theOther.myAllocator;
179       NCollection_BaseVector::operator = (theOther);
180       CopyData (theOther);
181     }
182     return * this;
183   }
184
185   //! Total number of items in the vector
186   virtual Standard_Integer Size () const        { return Length(); }
187
188   //! Virtual assignment (any collection to this array)
189   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
190   {
191     if (this != &theOther) {
192       TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = 
193         theOther.CreateIterator();
194       while (anIter2.More()) {
195         Append (anIter2.Value());
196         anIter2.Next();
197       }
198     }
199   }
200
201   //! Assignment to the collection of the same type
202   void Assign (const NCollection_Vector& theOther)
203   {
204     if (this != &theOther) {
205       NCollection_BaseVector::operator = (theOther);
206       CopyData (theOther);
207     }
208   }
209
210   //! Method to create iterators for base collections
211   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator&
212     CreateIterator(void) const
213   { return *(new (this->IterAllocator()) Iterator(*this)); }
214
215   //! Append
216   TheItemType& Append (const TheItemType& theValue) {
217     TheItemType& anAppended = * (TheItemType *) ExpandV (myLength);
218     anAppended = theValue;
219     return anAppended;
220   }
221
222   //! Operator () - query the const value
223   const TheItemType& operator () (const Standard_Integer theIndex) const
224                                         { return Value (theIndex); }
225   const TheItemType& Value (const Standard_Integer theIndex) const {
226 //    if (myNBlocks == 1) return ((MemBlock *) myData) -> Value(theIndex);
227     return * (const TheItemType *) Find (theIndex);
228   }
229
230   //! Operator () - query the value
231   TheItemType& operator () (const Standard_Integer theIndex)
232                                         { return ChangeValue (theIndex); }
233   TheItemType& ChangeValue (const Standard_Integer theIndex) {
234 //    if (myNBlocks == 1) return ((MemBlock *) myData) -> ChangeValue(theIndex);
235     return * (TheItemType *) Find (theIndex);
236   }
237
238   //! SetValue () - set or append a value
239   TheItemType& SetValue    (const Standard_Integer theIndex,
240                             const TheItemType&     theValue) {
241 #if !defined No_Exception && !defined No_Standard_OutOfRange
242     if (theIndex < 0)
243       Standard_OutOfRange::Raise ("NCollection_Vector::SetValue");
244 #endif
245     TheItemType * const aVecValue = 
246       (TheItemType *)(theIndex<myLength? Find(theIndex): ExpandV(theIndex));
247     * aVecValue = theValue;
248     return * aVecValue;
249   }
250
251  private:
252   // ---------- PRIVATE METHODS ----------
253   void CopyData (const NCollection_Vector& theOther) {
254     Standard_Integer i, iBlock = 0;
255     /*NCollection_Vector::*/Iterator anIter (theOther);
256     for (int aLength = 0; aLength < myLength; aLength += myIncrement) {
257       MemBlock& aBlock = (MemBlock&) myData[iBlock];
258       aBlock.Reinit (aLength, myIncrement);
259       for (i = 0; i < myIncrement; i++) {
260         if (!anIter.More()) break;
261         aBlock.ChangeValue(i) = anIter.Value();
262         anIter.Next();
263       }
264       aBlock.SetLength(i);
265       iBlock++;
266     }
267   }
268
269   static NCollection_BaseVector::MemBlock * FuncDataInit
270                                 (const NCollection_BaseVector&   theVector,
271                                  const Standard_Integer          aCapacity,
272                                  const void                      * aSource,
273                                  const Standard_Integer          aSize)
274   {
275     const NCollection_Vector& aSelf =
276       static_cast<const NCollection_Vector&> (theVector);
277     MemBlock * aData =
278       (MemBlock *) aSelf.myAllocator->Allocate(aCapacity * sizeof(MemBlock));
279     Standard_Integer i = 0;
280     if (aSource != NULL) {
281       memcpy (aData, aSource, aSize * sizeof(MemBlock));
282       i = aSize;
283     }
284     while (i < aCapacity)
285       new (&aData[i++]) MemBlock(aSelf.myAllocator.operator->());
286     return aData;
287   }
288
289   static void FuncDataFree (const NCollection_BaseVector&      theVector,
290                             NCollection_BaseVector::MemBlock * aData)
291   {
292     const NCollection_Vector& aSelf =
293       static_cast<const NCollection_Vector&> (theVector);
294     aSelf.myAllocator->Free(aData);
295   }
296
297   friend class Iterator;
298 };
299
300 #endif