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