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 | |
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 |