0023284: Using 'memcpy' on class that contains a virtual method
[occt.git] / src / NCollection / NCollection_BaseVector.hxx
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 #ifndef NCollection_BaseVector_HeaderFile
21 #define NCollection_BaseVector_HeaderFile
22
23 #include <Standard_TypeDef.hxx>
24 #include <NCollection_BaseAllocator.hxx>
25 #include <stddef.h>
26
27 #include <Standard_OutOfRange.hxx>
28
29 #if defined(_MSC_VER)
30   #pragma warning(push, 1)
31   #pragma warning(disable:4355)
32 #endif
33
34 // this value defines the number of blocks that are reserved
35 // when the capacity of vector is increased
36 inline Standard_Integer GetCapacity (const Standard_Integer theIncrement)
37 {
38   return Max(theIncrement/8, 1);
39 }
40
41 //! Class NCollection_BaseVector - base for NCollection_Vector template
42 class NCollection_BaseVector
43 {
44
45 protected:
46
47   // Auxiliary structure for memory blocks
48   struct MemBlock
49   {
50
51   public:
52
53     //! @param theIndex    Item index in the block
54     //! @param theItemSize Element size in bytes
55     //! @return the address of specified item in this memory block
56     void* findV (const Standard_Integer theIndex,
57                  const size_t           theItemSize) const
58     {
59       return (char* )DataPtr + size_t(theIndex) * theItemSize;
60     }
61
62   public:
63
64     void*            DataPtr;    //!< block of elements
65     Standard_Integer FirstIndex; //!< index of the first element (among all memory blocks in collection)
66     Standard_Integer Length;
67     Standard_Integer Size;
68
69   };
70
71   //! Base class for Iterator implementation
72   class Iterator
73   {
74   protected:
75     Iterator()
76     : myICurBlock (0),
77       myIEndBlock (0),
78       myCurIndex  (0),
79       myEndIndex  (0) {}
80
81     Iterator (const NCollection_BaseVector& theVector)
82     {
83       initV (theVector);
84     }
85
86     Iterator (const Iterator& theVector)
87     {
88       copyV (theVector);
89     }
90
91     Standard_EXPORT void initV (const NCollection_BaseVector& theVector);
92
93     Standard_EXPORT void copyV (const Iterator&);
94
95     Standard_Boolean moreV() const
96     {
97       return (myICurBlock < myIEndBlock || myCurIndex < myEndIndex);
98     }
99
100     void nextV()
101     {
102       if (++myCurIndex >= myVector->myData[myICurBlock].Length
103        && myICurBlock < myIEndBlock)
104       {
105         ++myICurBlock;
106         myCurIndex = 0;
107       }
108     }
109
110     const MemBlock* curBlockV() const
111     {
112       return &myVector->myData[myICurBlock];
113     }
114
115     const NCollection_BaseVector* myVector;    //!< the Master vector
116     Standard_Integer              myICurBlock; //!< # of the current block
117     Standard_Integer              myIEndBlock;
118     Standard_Integer              myCurIndex;  //!< Index in the current block
119     Standard_Integer              myEndIndex;
120   };
121
122 protected: //! @name Block initializer
123
124   typedef void (*initMemBlocks_t) (NCollection_BaseVector& theVector,
125                                    MemBlock&               theBlock,
126                                    const Standard_Integer  theFirst,
127                                    const Standard_Integer  theSize);
128
129   //! Allocate memory for array of memory blocks.
130   //! @param theAllocator  Memory allocator to use
131   //! @param theCapacity   Number of memory blocks in array
132   //! @param theSource     Original array of memory blocks, will be automatically deallocated
133   //! @param theSourceSize Number of memory blocks in original array
134   Standard_EXPORT static MemBlock* allocMemBlocks (Handle(NCollection_BaseAllocator)& theAllocator,
135                                                    const Standard_Integer             theCapacity,
136                                                    MemBlock*                          theSource     = NULL,
137                                                    const Standard_Integer             theSourceSize = 0);
138
139 protected: //! @name protected methods
140
141   //! Empty constructor
142   NCollection_BaseVector (Handle(NCollection_BaseAllocator)& theAllocator,
143                           initMemBlocks_t                    theInitBlocks,
144                           const size_t                       theSize,
145                           const Standard_Integer             theInc)
146   : myItemSize   (theSize),
147     myIncrement  (theInc),
148     myLength     (0),
149     myCapacity   (GetCapacity (myIncrement)),
150     myNBlocks    (0),
151     myData       (allocMemBlocks (theAllocator, myCapacity)),
152     myInitBlocks (theInitBlocks) {}
153
154   //! Copy constructor
155   NCollection_BaseVector (Handle(NCollection_BaseAllocator)& theAllocator,
156                           initMemBlocks_t                    theInitBlocks,
157                           const NCollection_BaseVector&      theOther)
158   : myItemSize   (theOther.myItemSize),
159     myIncrement  (theOther.myIncrement),
160     myLength     (theOther.myLength),
161     myCapacity   (GetCapacity(myIncrement) + theOther.myLength / theOther.myIncrement),
162     myNBlocks    (1 + (theOther.myLength - 1)/theOther.myIncrement),
163     myData       (allocMemBlocks (theAllocator, myCapacity)),
164     myInitBlocks (theInitBlocks) {}
165
166   //! @return pointer to memory where to put the new item
167   Standard_EXPORT void* expandV (Handle(NCollection_BaseAllocator)& theAllocator,
168                                  const Standard_Integer             theIndex);
169
170   //! Locate the memory holding the desired value
171   inline void* findV (const Standard_Integer theIndex) const
172   {
173     Standard_OutOfRange_Raise_if (theIndex < 0 || theIndex >= myLength,
174                                   "NCollection_BaseVector::findV");
175     const Standard_Integer aBlock = theIndex / myIncrement;
176     return myData[aBlock].findV (theIndex - aBlock * myIncrement, myItemSize);
177   }
178
179 public: //! @name public API
180
181   //! Empty the vector of its objects
182   Standard_EXPORT void Clear();
183
184 protected: //! @name Private fields
185
186   size_t           myItemSize;
187   Standard_Integer myIncrement;
188   Standard_Integer myLength;
189   Standard_Integer myCapacity;
190   Standard_Integer myNBlocks;
191   MemBlock*        myData;
192   initMemBlocks_t  myInitBlocks;
193
194 protected:
195
196   friend class Iterator;
197
198 };
199
200 #if defined(_MSC_VER)
201   #pragma warning(pop)
202 #endif
203
204 #endif // NCollection_BaseVector_HeaderFile