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