4e57c75e |
1 | // Created by: Peter KURNEV |
2 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
3 | // |
4 | // The content of this file is subject to the Open CASCADE Technology Public |
5 | // License Version 6.5 (the "License"). You may not use the content of this file |
6 | // except in compliance with the License. Please obtain a copy of the License |
7 | // at http://www.opencascade.org and read it completely before using this file. |
8 | // |
9 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
10 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
11 | // |
12 | // The Original Code and all software distributed under the License is |
13 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
14 | // Initial Developer hereby disclaims all such warranties, including without |
15 | // limitation, any warranties of merchantability, fitness for a particular |
16 | // purpose or non-infringement. Please see the License for the specific terms |
17 | // and conditions governing the rights and limitations under the License. |
18 | |
19 | #ifndef BOPCol_Array1_HeaderFile |
20 | #define BOPCol_Array1_HeaderFile |
21 | |
22 | #include <NCollection_List.hxx> |
23 | #include <Standard.hxx> |
24 | #include <NCollection_BaseAllocator.hxx> |
25 | |
26 | /** |
27 | * Class BOPCol_Array1 (dynamic array of objects) |
28 | * |
29 | * 1. The Array1 uses the allocator (in terms of NCollection_BaseAllocator) |
30 | * to allocate the memory. |
31 | * 2. The memory is allocated as a list of memory blocks. The size of the first |
32 | * block is myStartSize. The size of the other blocks is myIncrement |
33 | * 3 The Array1 is created with 0 length. |
34 | * 4. The Array1 must be initiated by invoke the method Init(). |
35 | * Init() allocates the memory block for initial myStartSize elements. |
36 | * 5. The elements can be added by the method Append(theElement). the method |
37 | * Append(theElement) arranges theElement in |
38 | * a) previously allocated memory block (if it is possible) |
39 | * b) new allocated memory block (otherwise). The size of new blocks to |
40 | * allocate can be set [once only] by the method SetIncrement(theSize). |
41 | * 6. The contents of the element with index "i" can be queried or modified |
42 | * by the methods |
43 | * SetValue(i, theElement), Value(i), ChangeValue(i), operator()(i) |
44 | */ |
45 | |
46 | //======================================================================= |
47 | //class : MemBlock |
48 | // |
49 | //======================================================================= |
50 | template <class Type> class BOPCol_MemBlock { |
51 | |
52 | public: |
53 | // Ctor |
54 | BOPCol_MemBlock(const Handle(NCollection_BaseAllocator)& theAllocator) { |
55 | myI1=0; |
56 | myI2=0; |
57 | mySize=0; |
58 | myData=NULL; |
59 | myAllocator=theAllocator; |
60 | myNext=NULL; |
61 | } |
62 | // ~ |
63 | ~BOPCol_MemBlock(){ |
64 | Clear(); |
65 | } |
66 | // Clear |
67 | void Clear() { |
68 | if (myData) { |
69 | //Standard_Integer i; |
70 | Standard_Size i; |
71 | // |
72 | for (i=0; i<mySize; ++i) { |
73 | myData[i].~Type(); |
74 | } |
75 | myAllocator->Free((Standard_Address&)myData); |
76 | // |
77 | myData=NULL; |
78 | mySize=0; |
79 | myNext=NULL; |
80 | } |
81 | } |
82 | // Allocate |
83 | void Allocate(const Standard_Size theSize) { |
84 | //Standard_Integer i; |
85 | Standard_Size i; |
86 | // |
87 | Clear(); |
88 | mySize=theSize; |
89 | myData=(Type*)myAllocator->Allocate(theSize*sizeof(Type)); |
90 | for (i=0; i<mySize; ++i) { |
91 | #ifdef BOPCol_Array1_Use_Allocator |
92 | new (myData+i) Type (myAllocator); |
93 | #else |
94 | new (myData+i) Type; |
95 | #endif |
96 | } |
97 | } |
98 | // SetRange |
99 | void SetRange(const Standard_Integer theI1, |
100 | const Standard_Integer theI2) { |
101 | myI1=theI1; |
102 | myI2=theI2; |
103 | } |
104 | // Range |
105 | void Range(Standard_Integer& theI1, |
106 | Standard_Integer& theI2) const { |
107 | theI1=myI1; |
108 | theI2=myI2; |
109 | } |
110 | // Contains |
111 | Standard_Boolean Contains(const Standard_Integer theIndex)const { |
112 | return (theIndex>=myI1 && theIndex<=myI2); |
113 | } |
114 | // SetValue |
115 | void SetValue(const Standard_Integer theIndex, |
116 | const Type& theValue) { |
117 | *(myData+theIndex-myI1)=theValue; |
118 | } |
119 | // Value |
120 | const Type& Value(const Standard_Integer theIndex)const { |
121 | return *(myData+theIndex-myI1); |
122 | } |
123 | // ChangeValue |
124 | Type& ChangeValue(const Standard_Integer theIndex) { |
125 | return *(myData+theIndex-myI1); |
126 | } |
127 | // SetNext |
128 | void SetNext(BOPCol_MemBlock<Type>* pNext) { |
129 | myNext=pNext; |
130 | } |
131 | // Next |
132 | BOPCol_MemBlock<Type>* Next() { |
133 | return myNext; |
134 | } |
135 | // |
136 | public: |
137 | BOPCol_MemBlock<Type>* myNext; |
138 | protected: |
139 | Standard_Integer myI1; |
140 | Standard_Integer myI2; |
141 | Standard_Size mySize; |
142 | Type *myData; |
143 | Handle(NCollection_BaseAllocator) myAllocator; |
144 | }; |
145 | |
146 | //======================================================================= |
147 | //class : BOPCol_Array1 |
148 | // |
149 | //======================================================================= |
150 | template <class Type> class BOPCol_Array1 { |
151 | |
152 | public: |
153 | typedef BOPCol_MemBlock<Type>* BOPCol_PMemBlock; |
154 | typedef BOPCol_MemBlock<Type> BOPCol_XMemBlock; |
155 | //========= |
156 | // Ctor |
157 | BOPCol_Array1(const Handle(NCollection_BaseAllocator)& theAllocator=0L) { |
158 | myStartSize=32; |
159 | myIncrement=8; |
160 | myExtent=0; |
161 | myPBlock=NULL; |
162 | myPBlock1=NULL; |
163 | // |
164 | if (theAllocator.IsNull()) { |
165 | myAllocator = NCollection_BaseAllocator::CommonBaseAllocator(); |
166 | } |
167 | else { |
168 | myAllocator=theAllocator; |
169 | } |
170 | } |
171 | // ~ |
172 | ~BOPCol_Array1() { |
173 | Clear(); |
174 | } |
175 | //=========== |
176 | // Clear |
177 | void Clear() { |
178 | BOPCol_PMemBlock pBlock, pNext; |
179 | // |
180 | pBlock=myPBlock1; |
181 | while(pBlock) { |
182 | pNext=pBlock->Next(); |
183 | // |
184 | //pBlock->~BOPCol_MemBlock<Type> (); |
185 | pBlock->~BOPCol_XMemBlock(); |
186 | //pBlock->Clear(); |
187 | myAllocator->Free((Standard_Address&)pBlock); |
188 | // |
189 | pBlock=pNext; |
190 | } |
191 | myPBlock1=NULL; |
192 | myPBlock=NULL; |
193 | myExtent=0; |
194 | } |
195 | // SetStartSize |
196 | void SetStartSize(const Standard_Size theSize) { |
197 | if (theSize>0) { |
198 | myStartSize=theSize; |
199 | } |
200 | } |
201 | // SetIncrement |
202 | void SetIncrement(const Standard_Size theSize){ |
203 | if (theSize>0) { |
204 | myIncrement=theSize; |
205 | } |
206 | } |
207 | // Increment |
208 | Standard_Size Increment()const { |
209 | return myIncrement; |
210 | } |
211 | // Extent |
212 | Standard_Size Extent()const { |
213 | return myExtent; |
214 | } |
215 | // Size |
216 | Standard_Size Size()const { |
217 | return myExtent; |
218 | } |
219 | // Size |
220 | Standard_Size Length()const { |
221 | return myExtent; |
222 | } |
223 | // Init |
224 | void Init(); |
225 | // Append(const Type& theValue) |
226 | Standard_Integer Append(const Type& theValue); |
227 | // Append() |
228 | Standard_Integer Append(); |
229 | // SetValue |
230 | void SetValue(const Standard_Integer theIndex, |
231 | const Type& theValue); |
232 | // Value |
233 | const Type& operator()(const Standard_Integer theIndex)const; |
234 | // |
235 | const Type& Value(const Standard_Integer theIndex)const; |
236 | // ChangeValue |
237 | Type& operator()(const Standard_Integer theIndex); |
238 | // |
239 | Type& ChangeValue(const Standard_Integer theIndex); |
240 | // |
241 | // protected |
242 | protected: |
243 | //=========== |
244 | //FindBlock |
245 | Standard_Boolean FindBlock(const Standard_Integer theIndex)const ; |
246 | //Copy ctor |
247 | BOPCol_Array1(const BOPCol_Array1&); |
248 | //Assign operator |
249 | BOPCol_Array1& operator =(const BOPCol_Array1& theOther); |
250 | //========== |
251 | // fields |
252 | protected: |
253 | Standard_Size myStartSize; |
254 | Standard_Size myIncrement; |
255 | Standard_Size myExtent; |
256 | Type myDfltItem; |
257 | BOPCol_MemBlock<Type> * myPBlock; |
258 | BOPCol_MemBlock<Type> * myPBlock1; |
259 | Handle(NCollection_BaseAllocator) myAllocator; |
260 | }; |
261 | // |
262 | //======================================================================= |
263 | //function : Init |
264 | //purpose : |
265 | //======================================================================= |
266 | template <class Type> |
267 | void BOPCol_Array1<Type>::Init() { |
268 | BOPCol_PMemBlock pBlock; |
269 | // |
270 | pBlock=(BOPCol_PMemBlock)myAllocator->Allocate(sizeof(BOPCol_MemBlock<Type>)); |
271 | new (pBlock) BOPCol_MemBlock<Type>(myAllocator); |
272 | // |
273 | pBlock->Allocate(myStartSize); |
274 | pBlock->SetRange(0, myStartSize-1); |
275 | myPBlock1=pBlock; |
276 | myPBlock=pBlock; |
277 | } |
278 | //======================================================================= |
279 | //function : Append |
280 | //purpose : |
281 | //======================================================================= |
282 | template <class Type> |
283 | Standard_Integer BOPCol_Array1<Type>::Append(const Type& theValue) { |
284 | BOPCol_PMemBlock pBlock, pNext; |
285 | // |
286 | pBlock=myPBlock1; |
287 | while(1) { |
288 | pNext=pBlock->myNext; |
289 | if(!pNext) { |
290 | myPBlock=pBlock; |
291 | break; |
292 | } |
293 | pBlock=pNext; |
294 | } |
295 | // |
296 | if (!myPBlock->Contains(myExtent)) { |
297 | // |
298 | pBlock=(BOPCol_PMemBlock)myAllocator->Allocate(sizeof(BOPCol_MemBlock<Type>)); |
299 | new (pBlock) BOPCol_MemBlock<Type>(myAllocator); |
300 | // |
301 | pBlock->Allocate(myIncrement); |
302 | pBlock->SetRange(myExtent, myExtent+myIncrement-1); |
303 | // |
304 | myPBlock->myNext=pBlock; |
305 | // |
306 | myPBlock=pBlock; |
307 | } |
308 | // |
309 | myPBlock->SetValue(myExtent, theValue); |
310 | // |
311 | ++myExtent; |
312 | // |
313 | return myExtent; |
314 | } |
315 | //======================================================================= |
316 | //function : Append |
317 | //purpose : |
318 | //======================================================================= |
319 | template <class Type> |
320 | Standard_Integer BOPCol_Array1<Type>::Append() { |
321 | BOPCol_PMemBlock pBlock, pNext; |
322 | // |
323 | pBlock=myPBlock1; |
324 | while(1) { |
325 | pNext=pBlock->myNext; |
326 | if(!pNext) { |
327 | myPBlock=pBlock; |
328 | break; |
329 | } |
330 | pBlock=pNext; |
331 | } |
332 | // |
333 | if (!myPBlock->Contains(myExtent)) { |
334 | // |
335 | pBlock=(BOPCol_PMemBlock)myAllocator->Allocate(sizeof(BOPCol_MemBlock<Type>)); |
336 | new (pBlock) BOPCol_MemBlock<Type>(myAllocator); |
337 | // |
338 | pBlock->Allocate(myIncrement); |
339 | pBlock->SetRange(myExtent, myExtent+myIncrement-1); |
340 | // |
341 | myPBlock->myNext=pBlock; |
342 | // |
343 | myPBlock=pBlock; |
344 | } |
345 | ++myExtent; |
346 | // |
347 | return myExtent; |
348 | } |
349 | //======================================================================= |
350 | //function : SetValue |
351 | //purpose : |
352 | //======================================================================= |
353 | template <class Type> |
354 | void BOPCol_Array1<Type>::SetValue(const Standard_Integer theIndex, |
355 | const Type& theValue) { |
356 | if (FindBlock(theIndex)) { |
357 | myPBlock->SetValue(theIndex, theValue); |
358 | } |
359 | } |
360 | //======================================================================= |
361 | //function : operator() |
362 | //purpose : |
363 | //======================================================================= |
364 | template <class Type> |
365 | const Type& BOPCol_Array1<Type>::operator()(const Standard_Integer theIndex)const { |
366 | if (FindBlock(theIndex)) { |
367 | return myPBlock->Value(theIndex); |
368 | } |
369 | return myDfltItem; |
370 | } |
371 | //======================================================================= |
372 | //function : Value |
373 | //purpose : |
374 | //======================================================================= |
375 | template <class Type> |
376 | const Type& BOPCol_Array1<Type>::Value(const Standard_Integer theIndex)const { |
377 | return operator()(theIndex); |
378 | } |
379 | //======================================================================= |
380 | //function : operator |
381 | //purpose : |
382 | //======================================================================= |
383 | template <class Type> |
384 | Type& BOPCol_Array1<Type>::operator()(const Standard_Integer theIndex) { |
385 | if (FindBlock(theIndex)) { |
386 | return myPBlock->ChangeValue(theIndex); |
387 | } |
388 | return myDfltItem; |
389 | } |
390 | //======================================================================= |
391 | //function : ChangeValue |
392 | //purpose : |
393 | //======================================================================= |
394 | template <class Type> |
395 | Type& BOPCol_Array1<Type>::ChangeValue(const Standard_Integer theIndex) { |
396 | return operator()(theIndex); |
397 | } |
398 | //======================================================================= |
399 | //function : FindBlock |
400 | //purpose : |
401 | //======================================================================= |
402 | template <class Type> |
403 | Standard_Boolean BOPCol_Array1<Type>::FindBlock(const Standard_Integer theIndex)const { |
404 | Standard_Boolean bRet; |
405 | // |
406 | bRet=myPBlock->Contains(theIndex); |
407 | if(bRet) { |
408 | return bRet; |
409 | } |
410 | // |
411 | Standard_Integer i1, i2; |
412 | BOPCol_PMemBlock pBlock, *xPBlock; |
413 | // |
414 | xPBlock=(BOPCol_PMemBlock*)&myPBlock; |
415 | pBlock=myPBlock1; |
416 | // |
417 | i1=0; |
418 | i2=myStartSize-1; |
419 | do { |
420 | if (theIndex>=i1 && theIndex<=i2) { |
421 | *xPBlock=pBlock; |
422 | return !bRet; |
423 | } |
424 | // |
425 | i1=i2+1; |
426 | i2=i1+myIncrement-1; |
427 | pBlock=pBlock->myNext; |
428 | } while(pBlock); |
429 | // |
430 | return bRet; |
431 | } |
432 | |
433 | #endif |