a922b1fd3521ca4a9a327252aed002c084d1d522
[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   // **************** Implementation of the Iterator interface.
52  public:
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_BaseVector::MemBlock(0,0) {}
61     //! Constructor
62     MemBlock (const Standard_Integer theFirstInd,
63               const Standard_Integer theSize)
64       : NCollection_BaseVector::MemBlock (theFirstInd, theSize)
65       { myData = new TheItemType [theSize]; }
66     //! Copy constructor
67     MemBlock (const MemBlock& theOther)
68       : NCollection_BaseVector::MemBlock (theOther.FirstIndex(),theOther.Size())
69     {
70       myLength = theOther.Length();
71       myData = new TheItemType [Size()];
72       for (size_t i=0; i < Length(); i++)
73         ((TheItemType *) myData)[i] = theOther.Value(i);
74     }
75     //! Reinit
76     virtual void Reinit (const Standard_Integer theFirst,
77                          const size_t           theSize)
78     {
79       if (myData) delete [] (TheItemType *) myData;
80       myData = (theSize > 0) ? new TheItemType [theSize] : NULL;
81       myFirstInd = theFirst;
82       mySize     = theSize;
83       myLength   = 0;
84     }
85     //! Destructor
86     virtual ~MemBlock () { if (myData) delete [] (TheItemType *) myData; }
87     //! Operator () const
88     const TheItemType& Value (const Standard_Integer theIndex) const
89     { return ((TheItemType *) myData) [theIndex]; }
90     //! Operator ()
91     TheItemType& ChangeValue (const Standard_Integer theIndex)
92     { return ((TheItemType *) myData) [theIndex]; }
93     //! GetIndex
94     Standard_Integer GetIndex (const TheItemType& theItem) const {
95       return GetIndexV ((void *)&theItem, sizeof(TheItemType));
96     }
97   }; // End of the nested class MemBlock
98
99   // ----------------------------------------------------------------------
100   // ------------------------ Nested class Iterator -----------------------
101   // ----------------------------------------------------------------------
102   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator,
103                    public NCollection_BaseVector::Iterator
104   {
105   public:
106     //! Empty constructor - for later Init
107     Iterator  (void) {}
108     //! Constructor with initialisation
109     Iterator  (const NCollection_Vector& theVector) :
110       NCollection_BaseVector::Iterator (theVector) {}
111     //! Copy constructor
112     Iterator  (const Iterator& theOther) :
113       NCollection_BaseVector::Iterator (theOther) {}
114     //! Initialisation
115     void Init (const NCollection_Vector& theVector) { InitV (theVector); } 
116     //! Assignment
117     Iterator& operator =  (const Iterator& theOther) {
118       CopyV (theOther);
119       return * this;
120     }
121     //! Check end
122     virtual Standard_Boolean More (void) const          { return MoreV (); }
123     //! Make step
124     virtual void             Next (void)                { NextV(); }
125     //! Constant value access
126     virtual const TheItemType& Value (void) const       {
127       return ((const MemBlock *) CurBlockV()) -> Value(myCurIndex); }
128     //! Variable value access
129     virtual TheItemType& ChangeValue (void) const       {
130       return ((MemBlock *) CurBlockV()) -> ChangeValue(myCurIndex); }
131     //! Operator new for allocating iterators
132     void* operator new(size_t theSize,
133                        const Handle(NCollection_BaseAllocator)& theAllocator) 
134     { return theAllocator->Allocate(theSize); }
135   }; // End of the nested class Iterator
136
137   // ----------------------------------------------------------------------
138   // ------------------------ Class Vector itself -------------------------
139   // ----------------------------------------------------------------------
140  public:
141   // ---------- PUBLIC METHODS ----------
142
143   //! Constructor
144   NCollection_Vector (const Standard_Integer theIncrement              = 256,
145                       const Handle_NCollection_BaseAllocator& theAlloc = 0L)
146     : NCollection_BaseCollection<TheItemType>(theAlloc),
147       NCollection_BaseVector (sizeof(TheItemType), theIncrement,
148                               FuncDataInit, FuncDataFree) {}
149
150   //! Copy constructor
151   NCollection_Vector (const NCollection_Vector& theOther)
152     : NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
153       NCollection_BaseVector (theOther, FuncDataInit, FuncDataFree)
154     { CopyData (theOther); }
155
156   //! Operator =
157   NCollection_Vector& operator = (const NCollection_Vector& theOther) {
158     if (this != &theOther) {
159       this->myAllocator = theOther.myAllocator;
160       NCollection_BaseVector::operator = (theOther);
161       CopyData (theOther);
162     }
163     return * this;
164   }
165
166   //! Total number of items in the vector
167   virtual Standard_Integer Size () const        { return Length(); }
168
169   //! Virtual assignment (any collection to this array)
170   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
171   {
172     if (this != &theOther) {
173       TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = 
174         theOther.CreateIterator();
175       while (anIter2.More()) {
176         Append (anIter2.Value());
177         anIter2.Next();
178       }
179     }
180   }
181
182   //! Assignment to the collection of the same type
183   void Assign (const NCollection_Vector& theOther)
184   {
185     if (this != &theOther) {
186       NCollection_BaseVector::operator = (theOther);
187       CopyData (theOther);
188     }
189   }
190
191   //! Method to create iterators for base collections
192   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator&
193     CreateIterator(void) const
194   { return *(new (this->IterAllocator()) Iterator(*this)); }
195
196   //! Append
197   TheItemType& Append (const TheItemType& theValue) {
198     TheItemType& anAppended = * (TheItemType *) ExpandV (myLength);
199     anAppended = theValue;
200     return anAppended;
201   }
202
203   //! Operator () - query the const value
204   const TheItemType& operator () (const Standard_Integer theIndex) const
205                                         { return Value (theIndex); }
206   const TheItemType& Value (const Standard_Integer theIndex) const {
207 //    if (myNBlocks == 1) return ((MemBlock *) myData) -> Value(theIndex);
208     return * (const TheItemType *) Find (theIndex);
209   }
210
211   //! Operator () - query the value
212   TheItemType& operator () (const Standard_Integer theIndex)
213                                         { return ChangeValue (theIndex); }
214   TheItemType& ChangeValue (const Standard_Integer theIndex) {
215 //    if (myNBlocks == 1) return ((MemBlock *) myData) -> ChangeValue(theIndex);
216     return * (TheItemType *) Find (theIndex);
217   }
218
219   //! SetValue () - set or append a value
220   TheItemType& SetValue    (const Standard_Integer theIndex,
221                             const TheItemType&     theValue) {
222 #if !defined No_Exception && !defined No_Standard_OutOfRange
223     if (theIndex < 0)
224       Standard_OutOfRange::Raise ("NCollection_Vector::SetValue");
225 #endif
226     TheItemType * const aVecValue = 
227       (TheItemType *)(theIndex<myLength? Find(theIndex): ExpandV(theIndex));
228     * aVecValue = theValue;
229     return * aVecValue;
230   }
231
232  private:
233   // ---------- PRIVATE METHODS ----------
234   void CopyData (const NCollection_Vector& theOther) {
235     Standard_Integer i, iBlock = 0;
236     /*NCollection_Vector::*/Iterator anIter (theOther);
237     for (int aLength = 0; aLength < myLength; aLength += myIncrement) {
238       MemBlock& aBlock = (MemBlock&) myData[iBlock];
239       aBlock.Reinit (aLength, myIncrement);
240       for (i = 0; i < myIncrement; i++) {
241         if (!anIter.More()) break;
242         aBlock.ChangeValue(i) = anIter.Value();
243         anIter.Next();
244       }
245       aBlock.SetLength(i);
246       iBlock++;
247     }
248   }
249
250   static NCollection_BaseVector::MemBlock * FuncDataInit
251                                 (const NCollection_BaseVector&   theVector,
252                                  const Standard_Integer          aCapacity,
253                                  const void                      * aSource,
254                                  const Standard_Integer          aSize)
255   {
256     const NCollection_Vector& aSelf =
257       static_cast<const NCollection_Vector&> (theVector);
258     MemBlock * aData =
259       (MemBlock *) aSelf.myAllocator->Allocate(aCapacity * sizeof(MemBlock));
260     Standard_Integer i = 0;
261     if (aSource != NULL) {
262       memcpy (aData, aSource, aSize * sizeof(MemBlock));
263       i = aSize;
264     }
265     while (i < aCapacity)
266       new (&aData[i++]) MemBlock;
267     return aData;
268   }
269
270   static void FuncDataFree (const NCollection_BaseVector&      theVector,
271                             NCollection_BaseVector::MemBlock * aData)
272   {
273     const NCollection_Vector& aSelf =
274       static_cast<const NCollection_Vector&> (theVector);
275     aSelf.myAllocator->Free(aData);
276   }
277
278   friend class Iterator;
279 };
280
281 #ifdef WNT
282 #pragma warning (pop)
283 #endif
284
285 #endif