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