0023284: Using 'memcpy' on class that contains a virtual method
[occt.git] / src / NCollection / NCollection_Vector.hxx
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