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