Increment OCCT version up to 7.4.0
[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 // 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 #ifndef NCollection_BaseVector_HeaderFile
17 #define NCollection_BaseVector_HeaderFile
18
19 #include <Standard_TypeDef.hxx>
20 #include <Standard_OutOfRange.hxx>
21 #include <NCollection_BaseAllocator.hxx>
22 #include <NCollection_DefineAlloc.hxx>
23
24 #include <stddef.h>
25
26 // this value defines the number of blocks that are reserved
27 // when the capacity of vector is increased
28 inline Standard_Integer GetCapacity (const Standard_Integer theIncrement)
29 {
30   return Max(theIncrement/8, 1);
31 }
32
33 //! Class NCollection_BaseVector - base for NCollection_Vector template
34 class NCollection_BaseVector
35 {
36 public:
37   //! Memory allocation
38   DEFINE_STANDARD_ALLOC
39   DEFINE_NCOLLECTION_ALLOC
40
41 protected:
42
43   // Auxiliary structure for memory blocks
44   struct MemBlock
45   {
46
47   public:
48
49     //! @param theIndex    Item index in the block
50     //! @param theItemSize Element size in bytes
51     //! @return the address of specified item in this memory block
52     void* findV (const Standard_Integer theIndex,
53                  const size_t           theItemSize) const
54     {
55       return (char* )DataPtr + size_t(theIndex) * theItemSize;
56     }
57
58   public:
59
60     void*            DataPtr;    //!< block of elements
61     Standard_Integer FirstIndex; //!< index of the first element (among all memory blocks in collection)
62     Standard_Integer Length;
63     Standard_Integer Size;
64
65   };
66
67   //! Base class for Iterator implementation
68   class Iterator
69   {
70   protected:
71     Iterator()
72     : myICurBlock (0),
73       myIEndBlock (0),
74       myCurIndex  (0),
75       myEndIndex  (0) {}
76
77     Iterator (const NCollection_BaseVector& theVector, Standard_Boolean theToEnd = Standard_False)
78     {
79       initV (theVector, theToEnd);
80     }
81
82     Iterator (const Iterator& theVector)
83     {
84       copyV (theVector);
85     }
86
87     Standard_EXPORT void initV (const NCollection_BaseVector& theVector, Standard_Boolean theToEnd = Standard_False);
88
89     Standard_EXPORT void copyV (const Iterator&);
90
91     Standard_Boolean moreV() const
92     {
93       return (myICurBlock < myIEndBlock || myCurIndex < myEndIndex);
94     }
95
96     void nextV()
97     {
98       if (++myCurIndex >= myVector->myData[myICurBlock].Length
99        && myICurBlock < myIEndBlock)
100       {
101         ++myICurBlock;
102         myCurIndex = 0;
103       }
104     }
105
106     void prevV()
107     {
108       if (--myCurIndex < 0 && myICurBlock > 0)
109       {
110         --myICurBlock;
111         myCurIndex = myVector->myData[myICurBlock].Length - 1;
112       }
113     }
114
115     void offsetV (Standard_Integer theOffset)
116     {
117       const Standard_Integer anIndex = myCurIndex + myICurBlock * myVector->myIncrement + theOffset;
118       myICurBlock = anIndex / myVector->myIncrement;
119       myCurIndex = anIndex % myVector->myIncrement;
120       if (myICurBlock > myIEndBlock)
121       {
122         // make sure that iterator produced by Offset()
123         // is equal to the end() iterator
124         --myICurBlock;
125         myCurIndex += myVector->myIncrement;
126       }
127     }
128
129     Standard_Integer differV (const Iterator& theOther) const
130     {
131       return (myCurIndex - theOther.myCurIndex) + (myICurBlock - theOther.myICurBlock) * myVector->myIncrement;
132     }
133
134     const MemBlock* curBlockV() const
135     {
136       return &myVector->myData[myICurBlock];
137     }
138
139     const NCollection_BaseVector* myVector;    //!< the Master vector
140     Standard_Integer              myICurBlock; //!< # of the current block
141     Standard_Integer              myIEndBlock;
142     Standard_Integer              myCurIndex;  //!< Index in the current block
143     Standard_Integer              myEndIndex;
144   };
145
146 protected: //! @name Block initializer
147
148   typedef void (*initMemBlocks_t) (NCollection_BaseVector& theVector,
149                                    MemBlock&               theBlock,
150                                    const Standard_Integer  theFirst,
151                                    const Standard_Integer  theSize);
152
153   //! Allocate memory for array of memory blocks.
154   //! @param theCapacity   Number of memory blocks in array
155   //! @param theSource     Original array of memory blocks, will be automatically deallocated
156   //! @param theSourceSize Number of memory blocks in original array
157   Standard_EXPORT MemBlock* allocMemBlocks (const Standard_Integer theCapacity,
158                                             MemBlock*              theSource     = NULL,
159                                             const Standard_Integer theSourceSize = 0);
160
161 protected: //! @name protected methods
162
163   //! Empty constructor
164   NCollection_BaseVector (const Handle(NCollection_BaseAllocator)& theAllocator,
165                           initMemBlocks_t                    theInitBlocks,
166                           const size_t                       theSize,
167                           const Standard_Integer             theInc)
168   : myItemSize   (theSize),
169     myIncrement  (theInc),
170     myLength     (0),
171     myCapacity   (GetCapacity (myIncrement)),
172     myNBlocks    (0),
173     myInitBlocks (theInitBlocks)
174   {
175     myAllocator = (theAllocator.IsNull() ? NCollection_BaseAllocator::CommonBaseAllocator() : theAllocator);
176     myData = allocMemBlocks (myCapacity);
177   }
178
179   //! Copy constructor
180   NCollection_BaseVector (const Handle(NCollection_BaseAllocator)& theAllocator,
181                           initMemBlocks_t                    theInitBlocks,
182                           const NCollection_BaseVector&      theOther)
183   : myItemSize   (theOther.myItemSize),
184     myIncrement  (theOther.myIncrement),
185     myLength     (theOther.myLength),
186     myCapacity   (GetCapacity(myIncrement) + theOther.myLength / theOther.myIncrement),
187     myNBlocks    (theOther.myLength == 0 ? 0 : 1 + (theOther.myLength - 1)/theOther.myIncrement),
188     myInitBlocks (theInitBlocks)
189   {
190     myAllocator = (theAllocator.IsNull() ? NCollection_BaseAllocator::CommonBaseAllocator() : theAllocator);
191     myData = allocMemBlocks (myCapacity);
192   }
193
194   //! Destructor
195   virtual ~NCollection_BaseVector() {}
196
197   //! @return pointer to memory where to put the new item
198   Standard_EXPORT void* expandV (const Standard_Integer theIndex);
199
200   //! Locate the memory holding the desired value
201   inline void* findV (const Standard_Integer theIndex) const
202   {
203     Standard_OutOfRange_Raise_if (theIndex < 0 || theIndex >= myLength,
204                                   "NCollection_BaseVector::findV");
205     const Standard_Integer aBlock = theIndex / myIncrement;
206     return myData[aBlock].findV (theIndex - aBlock * myIncrement, myItemSize);
207   }
208
209 public: //! @name public API
210
211   //! Empty the vector of its objects
212   Standard_EXPORT void Clear();
213   // to set the size of increment dynamically
214   void SetIncrement(const Standard_Integer aIncrement) {
215     if (aIncrement > 0) {
216       if (!myIncrement) {
217         myIncrement=aIncrement;
218       }
219     }
220   }
221
222   //! Returns attached allocator
223   const Handle(NCollection_BaseAllocator)& Allocator() const
224   {
225     return myAllocator;
226   }
227
228 protected: //! @name Protected fields
229
230   Handle(NCollection_BaseAllocator) myAllocator;
231   size_t           myItemSize;
232   Standard_Integer myIncrement;
233   Standard_Integer myLength;
234   Standard_Integer myCapacity;
235   Standard_Integer myNBlocks;
236   MemBlock*        myData;
237   initMemBlocks_t  myInitBlocks;
238
239 protected:
240
241   friend class Iterator;
242 };
243
244 #endif // NCollection_BaseVector_HeaderFile