Commit | Line | Data |
---|---|---|
7fd59977 | 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 | ||
7fd59977 | 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 | { | |
7fd59977 | 45 | public: |
23be7421 | 46 | typedef TheItemType TheItemTypeD; |
7fd59977 | 47 | // ---------------------------------------------------------------------- |
48 | //! Nested class MemBlock | |
49 | class MemBlock : public NCollection_BaseVector::MemBlock | |
50 | { | |
1c35b92f | 51 | public: |
52 | DEFINE_STANDARD_ALLOC | |
53 | ||
7fd59977 | 54 | //! Empty constructor |
23be7421 M |
55 | MemBlock (NCollection_BaseAllocator* theAlloc) |
56 | : NCollection_BaseVector::MemBlock(0,0,theAlloc) | |
57 | {} | |
7fd59977 | 58 | //! Constructor |
59 | MemBlock (const Standard_Integer theFirstInd, | |
23be7421 M |
60 | const Standard_Integer theSize, |
61 | NCollection_BaseAllocator* theAlloc) | |
62 | : NCollection_BaseVector::MemBlock (theFirstInd, theSize, theAlloc) | |
63 | { | |
64 | myData = myAlloc->Allocate(theSize * sizeof(TheItemType)); | |
0f633a22 | 65 | for (Standard_Integer i=0; i < theSize; i++) |
23be7421 M |
66 | new (&((TheItemType *) myData)[i]) TheItemType; |
67 | } | |
7fd59977 | 68 | //! Copy constructor |
69 | MemBlock (const MemBlock& theOther) | |
23be7421 M |
70 | : NCollection_BaseVector::MemBlock (theOther.FirstIndex(),theOther.Size(), |
71 | theOther.myAlloc) | |
7fd59977 | 72 | { |
73 | myLength = theOther.Length(); | |
23be7421 | 74 | myData = myAlloc->Allocate(Size() * sizeof(TheItemType)); |
0f633a22 | 75 | Standard_Integer i; |
23be7421 M |
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; | |
7fd59977 | 80 | } |
81 | //! Reinit | |
82 | virtual void Reinit (const Standard_Integer theFirst, | |
0f633a22 | 83 | const Standard_Integer theSize) |
7fd59977 | 84 | { |
23be7421 | 85 | if (myData) { |
0f633a22 | 86 | for (Standard_Integer i=0; i < mySize; i++) |
23be7421 M |
87 | ((TheItemType *) myData)[i].~TheItemTypeD(); |
88 | myAlloc->Free(myData); | |
89 | myData = NULL; | |
90 | } | |
91 | if (theSize > 0) { | |
92 | myData = myAlloc->Allocate(theSize * sizeof(TheItemType)); | |
0f633a22 | 93 | for (Standard_Integer i=0; i < theSize; i++) |
23be7421 M |
94 | new (&((TheItemType *) myData)[i]) TheItemType; |
95 | } | |
7fd59977 | 96 | myFirstInd = theFirst; |
97 | mySize = theSize; | |
98 | myLength = 0; | |
99 | } | |
100 | //! Destructor | |
23be7421 M |
101 | virtual ~MemBlock () |
102 | { | |
103 | if (myData) { | |
0f633a22 | 104 | for (Standard_Integer i=0; i < Size(); i++) |
23be7421 M |
105 | ((TheItemType *) myData)[i].~TheItemTypeD(); |
106 | myAlloc->Free(myData); | |
107 | myData = NULL; | |
108 | } | |
109 | } | |
7fd59977 | 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); } | |
7fd59977 | 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) | |
23be7421 | 285 | new (&aData[i++]) MemBlock(aSelf.myAllocator.operator->()); |
7fd59977 | 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 | ||
7fd59977 | 300 | #endif |