0023284: Using 'memcpy' on class that contains a virtual method
authoromy <omy@opencascade.com>
Fri, 15 Mar 2013 09:04:26 +0000 (13:04 +0400)
committeromy <omy@opencascade.com>
Fri, 15 Mar 2013 09:04:26 +0000 (13:04 +0400)
NCollection_BaseVector::MemBlock class was converted to POD structure
Added fix for compilation of multiple inherited classes on gcc/Linux

src/NCollection/NCollection_BaseVector.cxx
src/NCollection/NCollection_BaseVector.hxx
src/NCollection/NCollection_Vector.hxx

index 783e86e..2750cf4 100755 (executable)
@@ -1,6 +1,6 @@
 // Created on: 2002-04-24
 // Created by: Alexander GRIGORIEV
-// Copyright (c) 2002-2012 OPEN CASCADE SAS
+// Copyright (c) 2002-2013 OPEN CASCADE SAS
 //
 // The content of this file is subject to the Open CASCADE Technology Public
 // License Version 6.5 (the "License"). You may not use the content of this file
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-
 #include <NCollection_BaseVector.hxx>
 #include <Standard_RangeError.hxx>
-#ifdef DEB
-#include <Standard_OutOfRange.hxx>
-#endif
-#include <stdlib.h>
+#include <cstdlib>
 
 //=======================================================================
-//function : GetIndexV
-//purpose  : 
-//=======================================================================
-
-Standard_Integer NCollection_BaseVector::MemBlock::GetIndexV
-                   (void * theItem, const size_t theItemSize) const
-{
-  const ptrdiff_t anOffset = (char *) theItem - (char *) myData;
-  const Standard_Integer anIndex = (Standard_Integer) (anOffset / theItemSize);
-#ifdef DEB
-  if (anOffset < 0 || anOffset != Standard_Integer (anIndex * theItemSize)
-      || anIndex > Standard_Integer (myLength))
-    Standard_OutOfRange::Raise ("NCollection_BaseVector: "
-                                "Wrong object passed to GetIndex");
-#endif
-  return anIndex + myFirstInd;
-}
-
-//=======================================================================
-//function : ~NCollection_BaseVector
-//purpose  : Destructor
+//function : NCollection_BaseVector::Iterator::copyV
+//purpose  : Copy from another iterator
 //=======================================================================
 
-NCollection_BaseVector::~NCollection_BaseVector()
+void NCollection_BaseVector::Iterator::copyV (const NCollection_BaseVector::Iterator& theOth)
 {
-  for (Standard_Integer i = 0; i < myCapacity; i++)
-    myData[i].Reinit (0, 0);
-  myDataFree (* this, myData);
+  myVector    = theOth.myVector;
+  myICurBlock = theOth.myICurBlock;
+  myIEndBlock = theOth.myIEndBlock;
+  myCurIndex  = theOth.myCurIndex;
+  myEndIndex  = theOth.myEndIndex;
 }
 
 //=======================================================================
-//function : Clear
-//purpose  : 
+//function : initV
+//purpose  : Initialisation of iterator by a vector
 //=======================================================================
 
-void NCollection_BaseVector::Clear()
+void NCollection_BaseVector::Iterator::initV (const NCollection_BaseVector& theVector)
 {
-  if (myLength > 0) {
-    for (Standard_Integer i = 0; i < myCapacity; i++)
-      myData[i].Reinit (0, 0);
-    myLength = 0;
-    myNBlocks = 0;
+  myVector    = &theVector;
+  myICurBlock = 0;
+  myCurIndex  = 0;
+  if (theVector.myNBlocks == 0)
+  {
+    myIEndBlock = 0;
+    myEndIndex  = 0;
+  }
+  else
+  {
+    myIEndBlock = theVector.myNBlocks - 1;
+    myEndIndex  = theVector.myData[myIEndBlock].Length;
   }
 }
 
 //=======================================================================
-//function : NCollection_BaseVector::Iterator::CopyV
-//purpose  : Copy from another iterator
+//function : allocMemBlocks
+//purpose  :
 //=======================================================================
 
-void NCollection_BaseVector::Iterator::CopyV
-                                (const NCollection_BaseVector::Iterator& theOth)
+NCollection_BaseVector::MemBlock* NCollection_BaseVector
+  ::allocMemBlocks (Handle(NCollection_BaseAllocator)& theAllocator,
+                    const Standard_Integer             theCapacity,
+                    MemBlock*                          theSource,
+                    const Standard_Integer             theSourceSize)
 {
-  myVector      = theOth.myVector;
-  myICurBlock   = theOth.myICurBlock;
-  myIEndBlock   = theOth.myIEndBlock;
-  myCurIndex    = theOth.myCurIndex;
-  myEndIndex    = theOth.myEndIndex;
-}
-
-//=======================================================================
-//function : InitV
-//purpose  : Initialisation of iterator by a vector
-//=======================================================================
+  MemBlock* aData = (MemBlock* )theAllocator->Allocate (theCapacity * sizeof(MemBlock));
+
+  // copy content from source array
+  Standard_Integer aCapacity = 0;
+  if (theSource != NULL)
+  {
+    memcpy (aData, theSource, theSourceSize * sizeof(MemBlock));
+    aCapacity = theSourceSize;
+    theAllocator->Free (theSource);
+  }
 
-void NCollection_BaseVector::Iterator::InitV
-                                      (const NCollection_BaseVector& theVector)
-{
-  myVector      = &theVector;
-  myICurBlock   = 0;
-  myCurIndex    = 0;
-  if (theVector.myNBlocks == 0) {
-    myIEndBlock   = 0;
-    myEndIndex    = 0;
-  } else {
-    myIEndBlock   = theVector.myNBlocks - 1;
-    myEndIndex    = theVector.myData[myIEndBlock].Length();
+  // Nullify newly allocated blocks
+  if (aCapacity < theCapacity)
+  {
+    memset (&aData[aCapacity], 0, (theCapacity - aCapacity) * sizeof(MemBlock));
   }
+  return aData;
 }
 
 //=======================================================================
-//function : operator =
-//purpose  : assignment
+//function : Clear
+//purpose  :
 //=======================================================================
 
-NCollection_BaseVector& NCollection_BaseVector::operator =
-                                        (const NCollection_BaseVector& theOther)
+void NCollection_BaseVector::Clear()
 {
-//    if (this != &theOther) {
-  myIncrement = theOther.myIncrement;
-  myLength    = theOther.Length();
-  myNBlocks   = (myLength == 0) ? 0 : (1 + (myLength - 1)/myIncrement);
-  for (Standard_Integer i = 0; i < myCapacity; i++)
-    myData[i].Reinit (0, 0);
-  myDataFree (* this, myData);
-  myCapacity  = GetCapacity(myIncrement) + myLength / myIncrement;
-  myData = myDataInit (* this, myCapacity, NULL, 0);
-//    }
-  return * this;
+  if (myLength > 0)
+  {
+    for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
+    {
+      myInitBlocks (*this, myData[anItemIter], 0, 0);
+    }
+    myLength  = 0;
+    myNBlocks = 0;
+  }
 }
 
 //=======================================================================
-//function : ExpandV
+//function : expandV
 //purpose  : returns the pointer where the new data item is supposed to be put
 //=======================================================================
 
-void * NCollection_BaseVector::ExpandV (const Standard_Integer theIndex)
+void* NCollection_BaseVector::expandV (Handle(NCollection_BaseAllocator)& theAllocator,
+                                       const Standard_Integer             theIndex)
 {
   const Standard_Integer aNewLength = theIndex + 1;
-  if (myNBlocks) {
-    //  Take the last array in the vector of arrays
-    MemBlock& aLastBlock = myData [myNBlocks - 1];
-    Standard_RangeError_Raise_if (theIndex < aLastBlock.FirstIndex(),
-                                  "NColelction_BaseVector::ExpandV");
-    Standard_Integer anIndLastBlock = theIndex - aLastBlock.FirstIndex();
-    //  Is there still room for 1 item in the last array?
-    if (anIndLastBlock < aLastBlock.Size()) {
+  if (myNBlocks > 0)
+  {
+    // Take the last array in the vector of arrays
+    MemBlock& aLastBlock = myData[myNBlocks - 1];
+    Standard_RangeError_Raise_if (theIndex < aLastBlock.FirstIndex,
+                                  "NColelction_BaseVector::expandV");
+    Standard_Integer anIndLastBlock = theIndex - aLastBlock.FirstIndex;
+    // Is there still room for 1 item in the last array?
+    if (anIndLastBlock < aLastBlock.Size)
+    {
       myLength = aNewLength;
-      aLastBlock.SetLength (anIndLastBlock + 1);
-      return aLastBlock.Find (anIndLastBlock, myItemSize);
+      aLastBlock.Length = anIndLastBlock + 1;
+      return aLastBlock.findV (anIndLastBlock, myItemSize);
     }
-    myLength = aLastBlock.FirstIndex() + aLastBlock.Size();
+    myLength = aLastBlock.FirstIndex + aLastBlock.Size;
   }
 
-  //    There is no room in the last array or the whole vector
-  //    is not yet initialised. Initialise a new array, but before that
-  //    check whether it is available within myCapacity
-
-  const Standard_Integer nNewBlock =
-    myNBlocks + 1 + (theIndex - myLength) / myIncrement;
-  if (myCapacity < nNewBlock) {
+  // There is no room in the last array
+  // or the whole vector is not yet initialised.
+  // Initialise a new array, but before that check whether it is available within myCapacity.
+  const Standard_Integer nNewBlock = myNBlocks + 1 + (theIndex - myLength) / myIncrement;
+  if (myCapacity < nNewBlock)
+  {
     // Reallocate the array myData 
     do myCapacity += GetCapacity(myIncrement); while (myCapacity <= nNewBlock);
-    MemBlock * aNewData = myDataInit (* this, myCapacity, myData, myNBlocks);
-    myDataFree (* this, myData);
-    myData = aNewData;
+
+    myData = allocMemBlocks (theAllocator, myCapacity, myData, myNBlocks);
   }
-  if (myNBlocks > 0) {
+  if (myNBlocks > 0)
+  {
     // Change length of old last block to myIncrement
-    MemBlock * aLastBlock = (MemBlock *) &myData[myNBlocks-1];
-    aLastBlock -> SetLength (myIncrement);
+    MemBlock& aLastBlock = myData[myNBlocks - 1];
+    aLastBlock.Length = myIncrement;
   }
+
   // Initialise new blocks
-  MemBlock * aNewBlock = (MemBlock *) &myData[myNBlocks++];
-  aNewBlock -> Reinit (myLength, myIncrement);
-  while (myNBlocks < nNewBlock) {
-    aNewBlock -> SetLength (myIncrement);
+  MemBlock* aNewBlock = &myData[myNBlocks++];
+  myInitBlocks (*this, *aNewBlock, myLength, myIncrement);
+  while (myNBlocks < nNewBlock)
+  {
+    aNewBlock->Length = myIncrement;
     myLength += myIncrement;
-    aNewBlock = (MemBlock *) &myData[myNBlocks++];
-    aNewBlock -> Reinit (myLength, myIncrement);
+    aNewBlock = &myData[myNBlocks++];
+    myInitBlocks (*this, *aNewBlock, myLength, myIncrement);
   }
-  aNewBlock -> SetLength (aNewLength - myLength);
+  aNewBlock->Length = aNewLength - myLength;
   myLength = aNewLength;
-  return aNewBlock -> Find (theIndex - aNewBlock -> FirstIndex(), myItemSize);
-}
-
-//=======================================================================
-//function : Find
-//purpose  : locate the memory holding the desired value
-//remark   : This is only useful when the blocks can have holes (i.e., deletion
-//           is enabled at any location)
-//         : Currently this method is replaced by a direct one (inline)
-//=======================================================================
-#ifdef THIS_IS_NOW_DISABLED
-void * NCollection_BaseVector::Find (const Standard_Integer theIndex) const
-{
-#ifdef DEB
-  if (theIndex < 0 || theIndex >= myLength) Standard_OutOfRange::Raise (NULL);
-#endif
-  //    Binary search for the last memory block whose 'FirstIndex'
-  //    is not greater than 'theIndex'
-  const MemBlock * ptrArrays = myData;
-  Standard_Integer aLow = 0;
-  Standard_Integer anUp = myNBlocks-1;
-  if (theIndex >= ptrArrays[anUp].FirstIndex()) aLow = anUp;
-  else while (1) {
-    Standard_Integer aMid = (aLow + anUp)/2;
-    if (aMid == aLow) break;
-    if (ptrArrays[aMid].FirstIndex() > theIndex)
-      anUp = aMid;
-    else
-      aLow = aMid;
-  }
-
-  //    Find the item at the proper offset in the found MemBlock-type block
-  const Standard_Integer anOffset = theIndex - ptrArrays[aLow].FirstIndex();
-  return ptrArrays[aLow].Find (anOffset, myItemSize);
+  return aNewBlock->findV (theIndex - aNewBlock->FirstIndex, myItemSize);
 }
-#endif
index 5506ec0..08c4e60 100755 (executable)
@@ -1,6 +1,6 @@
 // Created on: 2002-04-24
 // Created by: Alexander GRIGORIEV
-// Copyright (c) 2002-2012 OPEN CASCADE SAS
+// Copyright (c) 2002-2013 OPEN CASCADE SAS
 //
 // The content of this file is subject to the Open CASCADE Technology Public
 // License Version 6.5 (the "License"). You may not use the content of this file
@@ -17,8 +17,6 @@
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-
-
 #ifndef NCollection_BaseVector_HeaderFile
 #define NCollection_BaseVector_HeaderFile
 
 #include <NCollection_BaseAllocator.hxx>
 #include <stddef.h>
 
-#if !defined No_Exception && !defined No_Standard_OutOfRange
 #include <Standard_OutOfRange.hxx>
-#endif
 
-#ifdef WNT
-#pragma warning(push, 1)
-#pragma warning(disable:4355)
+#if defined(_MSC_VER)
+  #pragma warning(push, 1)
+  #pragma warning(disable:4355)
 #endif
 
 // this value defines the number of blocks that are reserved
@@ -42,171 +38,167 @@ inline Standard_Integer GetCapacity (const Standard_Integer theIncrement)
   return Max(theIncrement/8, 1);
 }
 
-/**
- *  Class NCollection_BaseVector - base for generic vector
- */
+//! Class NCollection_BaseVector - base for NCollection_Vector template
 class NCollection_BaseVector
 {
- public:
-  // ------------ Class MemBlock ------------
-  class MemBlock {
-  protected:
-    MemBlock (NCollection_BaseAllocator* theAlloc)
-      : myAlloc(theAlloc),
-        myData(NULL),
-        myFirstInd(0),
-        myLength(0),
-        mySize(0) {}
-    MemBlock (const Standard_Integer theFirstInd,
-              const Standard_Integer theLength,
-              NCollection_BaseAllocator* theAlloc)
-      : myAlloc(theAlloc),
-        myData(NULL),
-        myFirstInd(theFirstInd),
-        myLength(0),
-        mySize(theLength) {}
-    virtual void        Reinit     (const Standard_Integer,
-                                    const Standard_Integer) {}
-    Standard_Integer    FirstIndex () const     { return myFirstInd; }
-    Standard_Integer    Size       () const     { return mySize; }
+
+protected:
+
+  // Auxiliary structure for memory blocks
+  struct MemBlock
+  {
+
   public:
-    virtual             ~MemBlock () {}
-    void                SetLength  (const Standard_Integer theLen)
-                                                { myLength = theLen; }
-    Standard_Integer    Length     () const     { return myLength; }
-    void *              Find       (const Standard_Integer theInd,
-                                    const size_t           theSize) const
-                                    { return ((char *) myData)+theInd*theSize;}
-    Standard_EXPORT Standard_Integer
-                        GetIndexV  (void * theItem, const size_t theSz) const;
-  protected:
-    NCollection_BaseAllocator*   myAlloc;
-    void*                        myData;
-    Standard_Integer             myFirstInd;
-    Standard_Integer             myLength;
-    Standard_Integer             mySize;
-    friend class NCollection_BaseVector;
+
+    //! @param theIndex    Item index in the block
+    //! @param theItemSize Element size in bytes
+    //! @return the address of specified item in this memory block
+    void* findV (const Standard_Integer theIndex,
+                 const size_t           theItemSize) const
+    {
+      return (char* )DataPtr + size_t(theIndex) * theItemSize;
+    }
+
+  public:
+
+    void*            DataPtr;    //!< block of elements
+    Standard_Integer FirstIndex; //!< index of the first element (among all memory blocks in collection)
+    Standard_Integer Length;
+    Standard_Integer Size;
+
   };
 
-  class Iterator {
+  //! Base class for Iterator implementation
+  class Iterator
+  {
   protected:
-    Iterator () :
-      myICurBlock (0), myIEndBlock (0), myCurIndex (0), myEndIndex (0) {}
-    Iterator (const NCollection_BaseVector& theVector) { InitV (theVector); }
-    Iterator (const Iterator& theVector)               { CopyV (theVector); }
-    Standard_EXPORT void InitV (const NCollection_BaseVector& theVector);
-    Standard_EXPORT void CopyV (const Iterator&);
-    Standard_Boolean     MoreV () const
-        { return (myICurBlock < myIEndBlock || myCurIndex < myEndIndex); }
-    void                 NextV ()
-        { if (++myCurIndex >= myVector -> myData[myICurBlock].Length() &&
-              myICurBlock < myIEndBlock)
-          { ++myICurBlock; myCurIndex = 0; } }
-    const MemBlock *     CurBlockV () const
-        { return &myVector -> myData[myICurBlock]; }
-
-    const NCollection_BaseVector * myVector;   // the Master vector
-    Standard_Integer             myICurBlock;  // # of the current block
-    Standard_Integer             myIEndBlock;
-    Standard_Integer             myCurIndex;   // Index in the current block
-    Standard_Integer             myEndIndex;
+    Iterator()
+    : myICurBlock (0),
+      myIEndBlock (0),
+      myCurIndex  (0),
+      myEndIndex  (0) {}
+
+    Iterator (const NCollection_BaseVector& theVector)
+    {
+      initV (theVector);
+    }
+
+    Iterator (const Iterator& theVector)
+    {
+      copyV (theVector);
+    }
+
+    Standard_EXPORT void initV (const NCollection_BaseVector& theVector);
+
+    Standard_EXPORT void copyV (const Iterator&);
+
+    Standard_Boolean moreV() const
+    {
+      return (myICurBlock < myIEndBlock || myCurIndex < myEndIndex);
+    }
+
+    void nextV()
+    {
+      if (++myCurIndex >= myVector->myData[myICurBlock].Length
+       && myICurBlock < myIEndBlock)
+      {
+        ++myICurBlock;
+        myCurIndex = 0;
+      }
+    }
+
+    const MemBlock* curBlockV() const
+    {
+      return &myVector->myData[myICurBlock];
+    }
+
+    const NCollection_BaseVector* myVector;    //!< the Master vector
+    Standard_Integer              myICurBlock; //!< # of the current block
+    Standard_Integer              myIEndBlock;
+    Standard_Integer              myCurIndex;  //!< Index in the current block
+    Standard_Integer              myEndIndex;
   };
 
- protected:
-  // ------------ Block initializer ---------
-  typedef MemBlock * (* FuncPtrDataInit) (const NCollection_BaseVector&,
-                                          const Standard_Integer aCapacity,
-                                          const void             * aSource,
-                                          const Standard_Integer aSize);
-  typedef void (* FuncPtrDataFree)       (const NCollection_BaseVector&,
-                                          MemBlock *);
+protected: //! @name Block initializer
 
-  friend class Iterator;
+  typedef void (*initMemBlocks_t) (NCollection_BaseVector& theVector,
+                                   MemBlock&               theBlock,
+                                   const Standard_Integer  theFirst,
+                                   const Standard_Integer  theSize);
+
+  //! Allocate memory for array of memory blocks.
+  //! @param theAllocator  Memory allocator to use
+  //! @param theCapacity   Number of memory blocks in array
+  //! @param theSource     Original array of memory blocks, will be automatically deallocated
+  //! @param theSourceSize Number of memory blocks in original array
+  Standard_EXPORT static MemBlock* allocMemBlocks (Handle(NCollection_BaseAllocator)& theAllocator,
+                                                   const Standard_Integer             theCapacity,
+                                                   MemBlock*                          theSource     = NULL,
+                                                   const Standard_Integer             theSourceSize = 0);
 
-  // ---------- PROTECTED METHODS ----------
+protected: //! @name protected methods
 
   //! Empty constructor
-  NCollection_BaseVector (const size_t           theSize,
-                          const Standard_Integer theInc,
-                          FuncPtrDataInit        theDataInit,
-                          FuncPtrDataFree        theDataFree)
-     : myItemSize  (theSize),
-       myIncrement (theInc),
-       myLength    (0),
-       myCapacity  (GetCapacity(myIncrement)),
-       myNBlocks   (0),
-       myData      (theDataInit (* this, myCapacity, NULL, 0)),
-       myDataInit  (theDataInit),
-       myDataFree  (theDataFree)
+  NCollection_BaseVector (Handle(NCollection_BaseAllocator)& theAllocator,
+                          initMemBlocks_t                    theInitBlocks,
+                          const size_t                       theSize,
+                          const Standard_Integer             theInc)
+  : myItemSize   (theSize),
+    myIncrement  (theInc),
+    myLength     (0),
+    myCapacity   (GetCapacity (myIncrement)),
+    myNBlocks    (0),
+    myData       (allocMemBlocks (theAllocator, myCapacity)),
+    myInitBlocks (theInitBlocks) {}
+
+  //! Copy constructor
+  NCollection_BaseVector (Handle(NCollection_BaseAllocator)& theAllocator,
+                          initMemBlocks_t                    theInitBlocks,
+                          const NCollection_BaseVector&      theOther)
+  : myItemSize   (theOther.myItemSize),
+    myIncrement  (theOther.myIncrement),
+    myLength     (theOther.myLength),
+    myCapacity   (GetCapacity(myIncrement) + theOther.myLength / theOther.myIncrement),
+    myNBlocks    (1 + (theOther.myLength - 1)/theOther.myIncrement),
+    myData       (allocMemBlocks (theAllocator, myCapacity)),
+    myInitBlocks (theInitBlocks) {}
+
+  //! @return pointer to memory where to put the new item
+  Standard_EXPORT void* expandV (Handle(NCollection_BaseAllocator)& theAllocator,
+                                 const Standard_Integer             theIndex);
+
+  //! Locate the memory holding the desired value
+  inline void* findV (const Standard_Integer theIndex) const
   {
-//    myData = (MemBlock *) new char [myCapacity * sizeof(MemBlock)];
-//    for (Standard_Integer i = 0; i < myCapacity; i++)
-//      new (&myData[i]) MemBlock;
+    Standard_OutOfRange_Raise_if (theIndex < 0 || theIndex >= myLength,
+                                  "NCollection_BaseVector::findV");
+    const Standard_Integer aBlock = theIndex / myIncrement;
+    return myData[aBlock].findV (theIndex - aBlock * myIncrement, myItemSize);
   }
 
-  //! Copy constructor
-  NCollection_BaseVector (const NCollection_BaseVector& theOther,
-                          FuncPtrDataInit               theDataInit,
-                          FuncPtrDataFree               theDataFree)
-    : myItemSize  (theOther.myItemSize),
-      myIncrement (theOther.myIncrement),
-      myLength    (theOther.Length()),
-      myCapacity  (GetCapacity(myIncrement)+theOther.Length()/theOther.myIncrement),
-      myNBlocks   (1 + (theOther.Length() - 1)/theOther.myIncrement),
-      myData      (theDataInit (* this, myCapacity, NULL, 0)),
-      myDataInit  (theDataInit),
-      myDataFree  (theDataFree)  {}
-
-  //! Destructor
-  Standard_EXPORT ~NCollection_BaseVector ();
-
-  //! Operator =
-  Standard_EXPORT NCollection_BaseVector& operator =
-                                 (const NCollection_BaseVector&);
-
-  //! ExpandV: returns pointer to memory where to put the new item
-  Standard_EXPORT void * ExpandV (const Standard_Integer theIndex);
-
-  //! Find: locate the memory holding the desired value
-  inline          void * Find    (const Standard_Integer theIndex) const;
-
- public:
-  //! Total number of items
-  Standard_Integer      Length  () const      { return myLength; }
+public: //! @name public API
 
   //! Empty the vector of its objects
-  Standard_EXPORT void  Clear   ();
-
- protected:
-  // ---------- PRIVATE FIELDS ----------
-  size_t                myItemSize;
-  Standard_Integer      myIncrement;
-  Standard_Integer      myLength;
-  Standard_Integer      myCapacity;
-  Standard_Integer      myNBlocks;
-  MemBlock              * myData;
-  FuncPtrDataInit       myDataInit;
-  FuncPtrDataFree       myDataFree;
-};
+  Standard_EXPORT void Clear();
 
-//=======================================================================
-//function : Find
-//purpose  : locate the memory holding the desired value
-//=======================================================================
+protected: //! @name Private fields
 
-inline void * NCollection_BaseVector::Find
-                                        (const Standard_Integer theIndex) const
-{
-#if !defined No_Exception && !defined No_Standard_OutOfRange
-  if (theIndex < 0 || theIndex >= myLength)
-    Standard_OutOfRange::Raise ("NCollection_BaseVector::Find");
-#endif
-  const Standard_Integer aBlock = theIndex / myIncrement;
-  return myData[aBlock].Find (theIndex - aBlock * myIncrement, myItemSize);
-}
+  size_t           myItemSize;
+  Standard_Integer myIncrement;
+  Standard_Integer myLength;
+  Standard_Integer myCapacity;
+  Standard_Integer myNBlocks;
+  MemBlock*        myData;
+  initMemBlocks_t  myInitBlocks;
 
-#ifdef WNT
-#pragma warning(pop)
-#endif
+protected:
+
+  friend class Iterator;
 
+};
+
+#if defined(_MSC_VER)
+  #pragma warning(pop)
 #endif
+
+#endif // NCollection_BaseVector_HeaderFile
index 5e94b22..fee4327 100755 (executable)
@@ -1,6 +1,6 @@
 // Created on: 2002-04-23
 // Created by: Alexander GRIGORIEV
-// Copyright (c) 2002-2012 OPEN CASCADE SAS
+// Copyright (c) 2002-2013 OPEN CASCADE SAS
 //
 // The content of this file is subject to the Open CASCADE Technology Public
 // License Version 6.5 (the "License"). You may not use the content of this file
 #include <NCollection_BaseVector.hxx>
 #include <NCollection_BaseCollection.hxx>
 
-#if !defined No_Exception && !defined No_Standard_OutOfRange
-#include <Standard_OutOfRange.hxx>
-#endif
-
-/**
-* Class NCollection_Vector (dynamic array of objects)
-*
-* This class is similar to NCollection_Array1  though the indices always start
-* at 0 (in Array1 the first index must be specified)
-*
-* The Vector is always created with 0 length. It can be enlarged by two means:
-*   1. Calling the method Append (val) - then "val" is added to the end of the
-*      vector (the vector length is incremented)
-*   2. Calling the method SetValue (i, val)  - if "i" is greater than or equal
-*      to the current length of the vector,  the vector is enlarged to accomo-
-*      date this index
-*
-* The methods Append and SetValue return  a non-const reference  to the copied
-* object  inside  the vector.  This reference  is guaranteed to be valid until
-* the vector is destroyed. It can be used to access the vector member directly
-* or to pass its address to other data structures.
-*
-* The vector iterator remembers the length of the vector  at the moment of the
-* creation or initialisation of the iterator.   Therefore the iteration begins
-* at index 0  and stops at the index equal to (remembered_length-1).  It is OK
-* to enlarge the vector during the iteration.
-*/
-
+//! Class NCollection_Vector (dynamic array of objects)
+//!
+//! This class is similar to NCollection_Array1  though the indices always start
+//! at 0 (in Array1 the first index must be specified)
+//!
+//! The Vector is always created with 0 length. It can be enlarged by two means:
+//!  1. Calling the method Append (val) - then "val" is added to the end of the
+//!     vector (the vector length is incremented)
+//!  2. Calling the method SetValue (i, val)  - if "i" is greater than or equal
+//!     to the current length of the vector,  the vector is enlarged to accomo-
+//!     date this index
+//!
+//! The methods Append and SetValue return  a non-const reference  to the copied
+//! object  inside  the vector.  This reference  is guaranteed to be valid until
+//! the vector is destroyed. It can be used to access the vector member directly
+//! or to pass its address to other data structures.
+//!
+//! The vector iterator remembers the length of the vector  at the moment of the
+//! creation or initialisation of the iterator.   Therefore the iteration begins
+//! at index 0  and stops at the index equal to (remembered_length-1).  It is OK
+//! to enlarge the vector during the iteration.
 template <class TheItemType> class NCollection_Vector
-                            : public NCollection_BaseCollection<TheItemType>,
-                              public NCollection_BaseVector
+: public NCollection_BaseCollection<TheItemType>,
+  public NCollection_BaseVector
 {
- public:
+public:
+
   typedef TheItemType TheItemTypeD;
-  // ----------------------------------------------------------------------
-  //! Nested class MemBlock
-  class MemBlock : public NCollection_BaseVector::MemBlock
-  {
-   public:
-    DEFINE_STANDARD_ALLOC
-
-    //! Empty constructor
-    MemBlock (NCollection_BaseAllocator* theAlloc)
-      : NCollection_BaseVector::MemBlock(0,0,theAlloc)
-    {}
-    //! Constructor
-    MemBlock (const Standard_Integer theFirstInd,
-              const Standard_Integer theSize,
-              NCollection_BaseAllocator* theAlloc)
-      : NCollection_BaseVector::MemBlock (theFirstInd, theSize, theAlloc)
-    {
-      myData = myAlloc->Allocate(theSize * sizeof(TheItemType));
-      for (Standard_Integer i=0; i < theSize; i++)
-        new (&((TheItemType *) myData)[i]) TheItemType;
-    }
-    //! Copy constructor
-    MemBlock (const MemBlock& theOther)
-      : NCollection_BaseVector::MemBlock (theOther.FirstIndex(),theOther.Size(),
-                                          theOther.myAlloc)
-    {
-      myLength = theOther.Length();
-      myData = myAlloc->Allocate(Size() * sizeof(TheItemType));
-      Standard_Integer i;
-      for (i=0; i < Length(); i++)
-        new (&((TheItemType *) myData)[i]) TheItemType(theOther.Value(i));
-      for (; i < Size(); i++)
-        new (&((TheItemType *) myData)[i]) TheItemType;
-    }
-    //! Reinit
-    virtual void Reinit (const Standard_Integer theFirst,
-                         const Standard_Integer theSize)
-    {
-      if (myData) {
-        for (Standard_Integer i=0; i < mySize; i++)
-          ((TheItemType *) myData)[i].~TheItemTypeD();
-        myAlloc->Free(myData);
-        myData = NULL;
-      }
-      if (theSize > 0) {
-        myData = myAlloc->Allocate(theSize * sizeof(TheItemType));
-        for (Standard_Integer i=0; i < theSize; i++)
-          new (&((TheItemType *) myData)[i]) TheItemType;
-      }
-      myFirstInd = theFirst;
-      mySize     = theSize;
-      myLength   = 0;
-    }
-    //! Destructor
-    virtual ~MemBlock ()
-    {
-      if (myData) {
-        for (Standard_Integer i=0; i < Size(); i++)
-          ((TheItemType *) myData)[i].~TheItemTypeD();
-        myAlloc->Free(myData);
-        myData = NULL;
-      }
-    }
-    //! Operator () const
-    const TheItemType& Value (const Standard_Integer theIndex) const
-    { return ((TheItemType *) myData) [theIndex]; }
-    //! Operator ()
-    TheItemType& ChangeValue (const Standard_Integer theIndex)
-    { return ((TheItemType *) myData) [theIndex]; }
-    //! GetIndex
-    Standard_Integer GetIndex (const TheItemType& theItem) const {
-      return GetIndexV ((void *)&theItem, sizeof(TheItemType));
-    }
-  }; // End of the nested class MemBlock
 
-  // ----------------------------------------------------------------------
-  // ------------------------ Nested class Iterator -----------------------
-  // ----------------------------------------------------------------------
+  //! Nested class Iterator
   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator,
                    public NCollection_BaseVector::Iterator
   {
   public:
+
     //! Empty constructor - for later Init
-    Iterator  (void) {}
+    Iterator() {}
+
     //! Constructor with initialisation
-    Iterator  (const NCollection_Vector& theVector) :
-      NCollection_BaseVector::Iterator (theVector) {}
+    Iterator (const NCollection_Vector& theVector)
+    : NCollection_BaseVector::Iterator (theVector) {}
+
     //! Copy constructor
-    Iterator  (const Iterator& theOther) :
-      NCollection_BaseVector::Iterator (theOther) {}
+    Iterator (const Iterator& theOther)
+    : NCollection_BaseVector::Iterator (theOther) {}
+
     //! Initialisation
-    void Init (const NCollection_Vector& theVector) { InitV (theVector); } 
+    void Init (const NCollection_Vector& theVector)
+    {
+      initV (theVector);
+    }
+
     //! Assignment
-    Iterator& operator =  (const Iterator& theOther) {
-      CopyV (theOther);
-      return * this;
+    Iterator& operator= (const Iterator& theOther)
+    {
+      copyV (theOther);
+      return *this;
     }
+
     //! Check end
-    virtual Standard_Boolean More (void) const          { return MoreV (); }
+    virtual Standard_Boolean More() const
+    {
+      return moreV();
+    }
+
     //! Make step
-    virtual void             Next (void)                { NextV(); }
+    virtual void Next()
+    {
+      nextV();
+    }
+
     //! Constant value access
-    virtual const TheItemType& Value (void) const       {
-      return ((const MemBlock *) CurBlockV()) -> Value(myCurIndex); }
+    virtual const TheItemType& Value() const
+    {
+      return ((const TheItemType* )curBlockV()->DataPtr)[myCurIndex];
+    }
+
     //! Variable value access
-    virtual TheItemType& ChangeValue (void) const       {
-      return ((MemBlock *) CurBlockV()) -> ChangeValue(myCurIndex); }
-  }; // End of the nested class Iterator
+    virtual TheItemType& ChangeValue() const
+    {
+      return ((TheItemType* )curBlockV()->DataPtr)[myCurIndex];
+    }
+
+  };
 
-  // ----------------------------------------------------------------------
-  // ------------------------ Class Vector itself -------------------------
-  // ----------------------------------------------------------------------
- public:
-  // ---------- PUBLIC METHODS ----------
+public: //! @name public methods
 
   //! Constructor
   NCollection_Vector (const Standard_Integer theIncrement              = 256,
-                      const Handle_NCollection_BaseAllocator& theAlloc = 0L)
-    : NCollection_BaseCollection<TheItemType>(theAlloc),
-      NCollection_BaseVector (sizeof(TheItemType), theIncrement,
-                              FuncDataInit, FuncDataFree) {}
+                      const Handle_NCollection_BaseAllocator& theAlloc = NULL)
+  : NCollection_BaseCollection<TheItemType> (theAlloc),
+    NCollection_BaseVector (NCollection_BaseCollection<TheItemType>::myAllocator, initMemBlocks, sizeof(TheItemType), theIncrement) {}
 
   //! Copy constructor
   NCollection_Vector (const NCollection_Vector& theOther)
-    : NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
-      NCollection_BaseVector (theOther, FuncDataInit, FuncDataFree)
-    { CopyData (theOther); }
-
-  //! Operator =
-  NCollection_Vector& operator = (const NCollection_Vector& theOther) {
-    if (this != &theOther) {
-      this->myAllocator = theOther.myAllocator;
-      NCollection_BaseVector::operator = (theOther);
-      CopyData (theOther);
+  : NCollection_BaseCollection<TheItemType> (theOther.myAllocator),
+    NCollection_BaseVector (NCollection_BaseCollection<TheItemType>::myAllocator, initMemBlocks, theOther)
+  {
+    copyData (theOther);
+  }
+
+  //! Destructor
+  ~NCollection_Vector()
+  {
+    for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
+    {
+      initMemBlocks (*this, myData[anItemIter], 0, 0);
     }
-    return * this;
+    NCollection_BaseCollection<TheItemType>::myAllocator->Free (myData);
+  }
+
+  //! Operator=
+  NCollection_Vector& operator= (const NCollection_Vector& theOther)
+  {
+    Assign (theOther, Standard_False);
+    return *this;
+  }
+
+  //! Total number of items
+  Standard_Integer Length() const
+  {
+    return myLength;
   }
 
   //! Total number of items in the vector
-  virtual Standard_Integer Size () const        { return Length(); }
+  virtual Standard_Integer Size() const
+  {
+    return myLength;
+  }
 
   //! Method for consistency with other collections.
   //! @return Lower bound (inclusive) for iteration.
@@ -209,22 +164,23 @@ template <class TheItemType> class NCollection_Vector
   //! @return Upper bound (inclusive) for iteration.
   Standard_Integer Upper() const
   {
-    return Length() - 1;
+    return myLength - 1;
   }
 
   //! Empty query
   Standard_Boolean IsEmpty() const
   {
-    return (Length() == 0);
+    return (myLength == 0);
   }
 
   //! Virtual assignment (any collection to this array)
   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
   {
-    if (this != &theOther) {
-      TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = 
-        theOther.CreateIterator();
-      while (anIter2.More()) {
+    if (this != &theOther)
+    {
+      TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = theOther.CreateIterator();
+      while (anIter2.More())
+      {
         Append (anIter2.Value());
         anIter2.Next();
       }
@@ -232,126 +188,173 @@ template <class TheItemType> class NCollection_Vector
   }
 
   //! Assignment to the collection of the same type
-  void Assign (const NCollection_Vector& theOther)
-  {
-    if (this != &theOther) {
-      NCollection_BaseVector::operator = (theOther);
-      CopyData (theOther);
-    }
-  }
+  inline void Assign (const NCollection_Vector& theOther,
+                      const Standard_Boolean    theOwnAllocator = Standard_True);
 
   //! Method to create iterators for base collections
-  virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator&
-    CreateIterator(void) const
-  { return *(new (this->IterAllocator()) Iterator(*this)); }
+  virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& CreateIterator() const
+  {
+    return *(new (this->IterAllocator()) Iterator(*this));
+  }
 
   //! Append
-  TheItemType& Append (const TheItemType& theValue) {
-    TheItemType& anAppended = * (TheItemType *) ExpandV (myLength);
+  TheItemType& Append (const TheItemType& theValue)
+  {
+    TheItemType& anAppended = *(TheItemType* )expandV (NCollection_BaseCollection<TheItemType>::myAllocator, myLength);
     anAppended = theValue;
     return anAppended;
   }
 
-  //! Operator () - query the const value
-  const TheItemType& operator () (const Standard_Integer theIndex) const
-                                        { return Value (theIndex); }
-  const TheItemType& Value (const Standard_Integer theIndex) const {
-//    if (myNBlocks == 1) return ((MemBlock *) myData) -> Value(theIndex);
-    return * (const TheItemType *) Find (theIndex);
+  //! Operator() - query the const value
+  const TheItemType& operator() (const Standard_Integer theIndex) const
+  {
+    return Value (theIndex);
+  }
+
+  const TheItemType& Value (const Standard_Integer theIndex) const
+  {
+    return *(const TheItemType* )findV (theIndex);
   }
 
   //! @return first element
   const TheItemType& First() const
   {
-    return *(const TheItemType* )Find (Lower());
+    return *(const TheItemType* )findV (Lower());
   }
 
   //! @return first element
   TheItemType& ChangeFirst()
   {
-    return *(TheItemType* )Find (Lower());
+    return *(TheItemType* )findV (Lower());
   }
 
   //! @return last element
   const TheItemType& Last() const
   {
-    return *(const TheItemType* )Find (Upper());
+    return *(const TheItemType* )findV (Upper());
   }
 
   //! @return last element
   TheItemType& ChangeLast()
   {
-    return *(TheItemType* )Find (Upper());
+    return *(TheItemType* )findV (Upper());
   }
 
-  //! Operator () - query the value
-  TheItemType& operator () (const Standard_Integer theIndex)
-                                        { return ChangeValue (theIndex); }
-  TheItemType& ChangeValue (const Standard_Integer theIndex) {
-//    if (myNBlocks == 1) return ((MemBlock *) myData) -> ChangeValue(theIndex);
-    return * (TheItemType *) Find (theIndex);
+  //! Operator() - query the value
+  TheItemType& operator() (const Standard_Integer theIndex)
+  {
+    return ChangeValue (theIndex);
+  }
+
+  TheItemType& ChangeValue (const Standard_Integer theIndex)
+  {
+    return *(TheItemType* )findV (theIndex);
   }
 
   //! SetValue () - set or append a value
-  TheItemType& SetValue    (const Standard_Integer theIndex,
-                            const TheItemType&     theValue) {
-#if !defined No_Exception && !defined No_Standard_OutOfRange
-    if (theIndex < 0)
-      Standard_OutOfRange::Raise ("NCollection_Vector::SetValue");
-#endif
-    TheItemType * const aVecValue = 
-      (TheItemType *)(theIndex<myLength? Find(theIndex): ExpandV(theIndex));
-    * aVecValue = theValue;
-    return * aVecValue;
+  TheItemType& SetValue (const Standard_Integer theIndex,
+                         const TheItemType&     theValue)
+  {
+    Standard_OutOfRange_Raise_if (theIndex < 0, "NCollection_Vector::SetValue");
+    TheItemType* const aVecValue = (TheItemType* )(theIndex < myLength ? findV (theIndex) : expandV (NCollection_BaseCollection<TheItemType>::myAllocator, theIndex));
+    *aVecValue = theValue;
+    return *aVecValue;
   }
 
- private:
-  // ---------- PRIVATE METHODS ----------
-  void CopyData (const NCollection_Vector& theOther) {
-    Standard_Integer i, iBlock = 0;
+private: //! @name private methods
+
+  void copyData (const NCollection_Vector& theOther)
+  {
+    Standard_Integer iBlock = 0;
     /*NCollection_Vector::*/Iterator anIter (theOther);
-    for (int aLength = 0; aLength < myLength; aLength += myIncrement) {
-      MemBlock& aBlock = (MemBlock&) myData[iBlock];
-      aBlock.Reinit (aLength, myIncrement);
-      for (i = 0; i < myIncrement; i++) {
-        if (!anIter.More()) break;
-        aBlock.ChangeValue(i) = anIter.Value();
+    for (Standard_Integer aLength = 0; aLength < myLength; aLength += myIncrement)
+    {
+      MemBlock& aBlock = myData[iBlock];
+      initMemBlocks (*this, aBlock, aLength, myIncrement);
+      Standard_Integer anItemIter = 0;
+      for (; anItemIter < myIncrement; ++anItemIter)
+      {
+        if (!anIter.More())
+        {
+          break;
+        }
+
+        ((TheItemType* )aBlock.DataPtr)[anItemIter] = anIter.Value();
         anIter.Next();
       }
-      aBlock.SetLength(i);
+      aBlock.Length = anItemIter;
       iBlock++;
     }
   }
 
-  static NCollection_BaseVector::MemBlock * FuncDataInit
-                                (const NCollection_BaseVector&   theVector,
-                                 const Standard_Integer          aCapacity,
-                                 const void                      * aSource,
-                                 const Standard_Integer          aSize)
+  //! Method to initialize memory block content
+  static void initMemBlocks (NCollection_BaseVector&           theVector,
+                             NCollection_BaseVector::MemBlock& theBlock,
+                             const Standard_Integer            theFirst,
+                             const Standard_Integer            theSize)
   {
-    const NCollection_Vector& aSelf =
-      static_cast<const NCollection_Vector&> (theVector);
-    MemBlock * aData =
-      (MemBlock *) aSelf.myAllocator->Allocate(aCapacity * sizeof(MemBlock));
-    Standard_Integer i = 0;
-    if (aSource != NULL) {
-      memcpy (aData, aSource, aSize * sizeof(MemBlock));
-      i = aSize;
+    NCollection_Vector& aSelf = static_cast<NCollection_Vector&> (theVector);
+    Handle(NCollection_BaseAllocator)& anAllocator = aSelf.myAllocator;
+
+    // release current content
+    if (theBlock.DataPtr != NULL)
+    {
+      for (Standard_Integer anItemIter = 0; anItemIter < theBlock.Size; ++anItemIter)
+      {
+        ((TheItemType* )theBlock.DataPtr)[anItemIter].~TheItemTypeD();
+      }
+      anAllocator->Free (theBlock.DataPtr);
+      theBlock.DataPtr = NULL;
     }
-    while (i < aCapacity)
-      new (&aData[i++]) MemBlock(aSelf.myAllocator.operator->());
-    return aData;
-  }
 
-  static void FuncDataFree (const NCollection_BaseVector&      theVector,
-                            NCollection_BaseVector::MemBlock * aData)
-  {
-    const NCollection_Vector& aSelf =
-      static_cast<const NCollection_Vector&> (theVector);
-    aSelf.myAllocator->Free(aData);
+    // allocate new content if requested
+    if (theSize > 0)
+    {
+      theBlock.DataPtr = anAllocator->Allocate (theSize * sizeof(TheItemType));
+      for (Standard_Integer anItemIter = 0; anItemIter < theSize; ++anItemIter)
+      {
+        new (&((TheItemType* )theBlock.DataPtr)[anItemIter]) TheItemType;
+      }
+    }
+    theBlock.FirstIndex = theFirst;
+    theBlock.Size       = theSize;
+    theBlock.Length     = 0;
   }
 
   friend class Iterator;
+
 };
 
-#endif
+//! Assignment to the collection of the same type
+template <class TheItemType> inline
+void NCollection_Vector<TheItemType>::Assign (const NCollection_Vector& theOther,
+                                              const Standard_Boolean    theOwnAllocator)
+{
+  if (this == &theOther)
+  {
+    return;
+  }
+
+  // destroy current data using current allocator
+  for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter)
+  {
+    initMemBlocks (*this, myData[anItemIter], 0, 0);
+  }
+  NCollection_BaseCollection<TheItemType>::myAllocator->Free (myData);
+
+  // allocate memory blocks with new allocator
+  if (!theOwnAllocator)
+  {
+    NCollection_BaseCollection<TheItemType>::myAllocator = theOther.myAllocator;
+  }
+  myIncrement = theOther.myIncrement;
+  myLength    = theOther.myLength;
+  myNBlocks   = (myLength == 0) ? 0 : (1 + (myLength - 1)/myIncrement);
+  myCapacity  = GetCapacity (myIncrement) + myLength / myIncrement;
+  myData      = allocMemBlocks (NCollection_BaseCollection<TheItemType>::myAllocator, myCapacity);
+
+  // copy data
+  copyData (theOther);
+}
+
+#endif // NCollection_Vector_HeaderFile