961fd633e77d76e7e0f36202a5ffe587d6e4dd3a
[occt.git] / src / NCollection / NCollection_BaseVector.cxx
1 // Created on: 2002-04-24
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2002-2013 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <NCollection_BaseVector.hxx>
17 #include <Standard_RangeError.hxx>
18 #include <cstdlib>
19
20 //=======================================================================
21 //function : NCollection_BaseVector::Iterator::copyV
22 //purpose  : Copy from another iterator
23 //=======================================================================
24
25 void NCollection_BaseVector::Iterator::copyV (const NCollection_BaseVector::Iterator& theOth)
26 {
27   myVector    = theOth.myVector;
28   myICurBlock = theOth.myICurBlock;
29   myIEndBlock = theOth.myIEndBlock;
30   myCurIndex  = theOth.myCurIndex;
31   myEndIndex  = theOth.myEndIndex;
32 }
33
34 //=======================================================================
35 //function : initV
36 //purpose  : Initialisation of iterator by a vector
37 //=======================================================================
38
39 void NCollection_BaseVector::Iterator::initV (const NCollection_BaseVector& theVector, Standard_Boolean theToEnd)
40 {
41   myVector = &theVector;
42
43   if (theVector.myNBlocks == 0)
44   {
45     myCurIndex  = 0;
46     myEndIndex  = 0;
47     myICurBlock = 0;
48     myIEndBlock = 0;
49   }
50   else
51   {
52     myIEndBlock = theVector.myNBlocks - 1;
53     myEndIndex  = theVector.myData[myIEndBlock].Length;
54
55     myICurBlock = !theToEnd ? 0 : myIEndBlock;
56     myCurIndex  = !theToEnd ? 0 : myEndIndex;
57   }
58 }
59
60 //=======================================================================
61 //function : allocMemBlocks
62 //purpose  :
63 //=======================================================================
64
65 NCollection_BaseVector::MemBlock* NCollection_BaseVector
66   ::allocMemBlocks (const Standard_Integer             theCapacity,
67                     MemBlock*                          theSource,
68                     const Standard_Integer             theSourceSize)
69 {
70   MemBlock* aData = (MemBlock* )myAllocator->Allocate (theCapacity * sizeof(MemBlock));
71
72   // copy content from source array
73   Standard_Integer aCapacity = 0;
74   if (theSource != NULL)
75   {
76     memcpy (aData, theSource, theSourceSize * sizeof(MemBlock));
77     aCapacity = theSourceSize;
78     myAllocator->Free (theSource);
79   }
80
81   // Nullify newly allocated blocks
82   if (aCapacity < theCapacity)
83   {
84     memset (&aData[aCapacity], 0, (theCapacity - aCapacity) * sizeof(MemBlock));
85   }
86   return aData;
87 }
88
89 //=======================================================================
90 //function : Clear
91 //purpose  :
92 //=======================================================================
93
94 void NCollection_BaseVector::Clear()
95 {
96   if (myLength > 0)
97   {
98     for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
99     {
100       myInitBlocks (*this, myData[anItemIter], 0, 0);
101     }
102     myLength  = 0;
103     myNBlocks = 0;
104   }
105 }
106
107 //=======================================================================
108 //function : expandV
109 //purpose  : returns the pointer where the new data item is supposed to be put
110 //=======================================================================
111
112 void* NCollection_BaseVector::expandV (const Standard_Integer theIndex)
113 {
114   const Standard_Integer aNewLength = theIndex + 1;
115   if (myNBlocks > 0)
116   {
117     // Take the last array in the vector of arrays
118     MemBlock& aLastBlock = myData[myNBlocks - 1];
119     Standard_RangeError_Raise_if (theIndex < aLastBlock.FirstIndex,
120                                   "NColelction_BaseVector::expandV");
121     Standard_Integer anIndLastBlock = theIndex - aLastBlock.FirstIndex;
122     // Is there still room for 1 item in the last array?
123     if (anIndLastBlock < aLastBlock.Size)
124     {
125       myLength = aNewLength;
126       aLastBlock.Length = anIndLastBlock + 1;
127       return aLastBlock.findV (anIndLastBlock, myItemSize);
128     }
129     myLength = aLastBlock.FirstIndex + aLastBlock.Size;
130   }
131
132   // There is no room in the last array
133   // or the whole vector is not yet initialised.
134   // Initialise a new array, but before that check whether it is available within myCapacity.
135   const Standard_Integer nNewBlock = myNBlocks + 1 + (theIndex - myLength) / myIncrement;
136   if (myCapacity < nNewBlock)
137   {
138     // Reallocate the array myData 
139     do myCapacity += GetCapacity(myIncrement); while (myCapacity <= nNewBlock);
140
141     myData = allocMemBlocks (myCapacity, myData, myNBlocks);
142   }
143   if (myNBlocks > 0)
144   {
145     // Change length of old last block to myIncrement
146     MemBlock& aLastBlock = myData[myNBlocks - 1];
147     aLastBlock.Length = myIncrement;
148   }
149
150   // Initialise new blocks
151   MemBlock* aNewBlock = &myData[myNBlocks++];
152   myInitBlocks (*this, *aNewBlock, myLength, myIncrement);
153   while (myNBlocks < nNewBlock)
154   {
155     aNewBlock->Length = myIncrement;
156     myLength += myIncrement;
157     aNewBlock = &myData[myNBlocks++];
158     myInitBlocks (*this, *aNewBlock, myLength, myIncrement);
159   }
160   aNewBlock->Length = aNewLength - myLength;
161   myLength = aNewLength;
162   return aNewBlock->findV (theIndex - aNewBlock->FirstIndex, myItemSize);
163 }