0023284: Using 'memcpy' on class that contains a virtual method
[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 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #include <NCollection_BaseVector.hxx>
21 #include <Standard_RangeError.hxx>
22 #include <cstdlib>
23
24 //=======================================================================
25 //function : NCollection_BaseVector::Iterator::copyV
26 //purpose  : Copy from another iterator
27 //=======================================================================
28
29 void NCollection_BaseVector::Iterator::copyV (const NCollection_BaseVector::Iterator& theOth)
30 {
31   myVector    = theOth.myVector;
32   myICurBlock = theOth.myICurBlock;
33   myIEndBlock = theOth.myIEndBlock;
34   myCurIndex  = theOth.myCurIndex;
35   myEndIndex  = theOth.myEndIndex;
36 }
37
38 //=======================================================================
39 //function : initV
40 //purpose  : Initialisation of iterator by a vector
41 //=======================================================================
42
43 void NCollection_BaseVector::Iterator::initV (const NCollection_BaseVector& theVector)
44 {
45   myVector    = &theVector;
46   myICurBlock = 0;
47   myCurIndex  = 0;
48   if (theVector.myNBlocks == 0)
49   {
50     myIEndBlock = 0;
51     myEndIndex  = 0;
52   }
53   else
54   {
55     myIEndBlock = theVector.myNBlocks - 1;
56     myEndIndex  = theVector.myData[myIEndBlock].Length;
57   }
58 }
59
60 //=======================================================================
61 //function : allocMemBlocks
62 //purpose  :
63 //=======================================================================
64
65 NCollection_BaseVector::MemBlock* NCollection_BaseVector
66   ::allocMemBlocks (Handle(NCollection_BaseAllocator)& theAllocator,
67                     const Standard_Integer             theCapacity,
68                     MemBlock*                          theSource,
69                     const Standard_Integer             theSourceSize)
70 {
71   MemBlock* aData = (MemBlock* )theAllocator->Allocate (theCapacity * sizeof(MemBlock));
72
73   // copy content from source array
74   Standard_Integer aCapacity = 0;
75   if (theSource != NULL)
76   {
77     memcpy (aData, theSource, theSourceSize * sizeof(MemBlock));
78     aCapacity = theSourceSize;
79     theAllocator->Free (theSource);
80   }
81
82   // Nullify newly allocated blocks
83   if (aCapacity < theCapacity)
84   {
85     memset (&aData[aCapacity], 0, (theCapacity - aCapacity) * sizeof(MemBlock));
86   }
87   return aData;
88 }
89
90 //=======================================================================
91 //function : Clear
92 //purpose  :
93 //=======================================================================
94
95 void NCollection_BaseVector::Clear()
96 {
97   if (myLength > 0)
98   {
99     for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
100     {
101       myInitBlocks (*this, myData[anItemIter], 0, 0);
102     }
103     myLength  = 0;
104     myNBlocks = 0;
105   }
106 }
107
108 //=======================================================================
109 //function : expandV
110 //purpose  : returns the pointer where the new data item is supposed to be put
111 //=======================================================================
112
113 void* NCollection_BaseVector::expandV (Handle(NCollection_BaseAllocator)& theAllocator,
114                                        const Standard_Integer             theIndex)
115 {
116   const Standard_Integer aNewLength = theIndex + 1;
117   if (myNBlocks > 0)
118   {
119     // Take the last array in the vector of arrays
120     MemBlock& aLastBlock = myData[myNBlocks - 1];
121     Standard_RangeError_Raise_if (theIndex < aLastBlock.FirstIndex,
122                                   "NColelction_BaseVector::expandV");
123     Standard_Integer anIndLastBlock = theIndex - aLastBlock.FirstIndex;
124     // Is there still room for 1 item in the last array?
125     if (anIndLastBlock < aLastBlock.Size)
126     {
127       myLength = aNewLength;
128       aLastBlock.Length = anIndLastBlock + 1;
129       return aLastBlock.findV (anIndLastBlock, myItemSize);
130     }
131     myLength = aLastBlock.FirstIndex + aLastBlock.Size;
132   }
133
134   // There is no room in the last array
135   // or the whole vector is not yet initialised.
136   // Initialise a new array, but before that check whether it is available within myCapacity.
137   const Standard_Integer nNewBlock = myNBlocks + 1 + (theIndex - myLength) / myIncrement;
138   if (myCapacity < nNewBlock)
139   {
140     // Reallocate the array myData 
141     do myCapacity += GetCapacity(myIncrement); while (myCapacity <= nNewBlock);
142
143     myData = allocMemBlocks (theAllocator, myCapacity, myData, myNBlocks);
144   }
145   if (myNBlocks > 0)
146   {
147     // Change length of old last block to myIncrement
148     MemBlock& aLastBlock = myData[myNBlocks - 1];
149     aLastBlock.Length = myIncrement;
150   }
151
152   // Initialise new blocks
153   MemBlock* aNewBlock = &myData[myNBlocks++];
154   myInitBlocks (*this, *aNewBlock, myLength, myIncrement);
155   while (myNBlocks < nNewBlock)
156   {
157     aNewBlock->Length = myIncrement;
158     myLength += myIncrement;
159     aNewBlock = &myData[myNBlocks++];
160     myInitBlocks (*this, *aNewBlock, myLength, myIncrement);
161   }
162   aNewBlock->Length = aNewLength - myLength;
163   myLength = aNewLength;
164   return aNewBlock->findV (theIndex - aNewBlock->FirstIndex, myItemSize);
165 }