From f4aad56f9762b867763f0bcddd9a01e1542d3e40 Mon Sep 17 00:00:00 2001 From: omy Date: Fri, 15 Mar 2013 13:04:26 +0400 Subject: [PATCH] 0023284: Using 'memcpy' on class that contains a virtual method 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 | 256 +++++------ src/NCollection/NCollection_BaseVector.hxx | 312 +++++++------- src/NCollection/NCollection_Vector.hxx | 473 +++++++++++---------- 3 files changed, 492 insertions(+), 549 deletions(-) diff --git a/src/NCollection/NCollection_BaseVector.cxx b/src/NCollection/NCollection_BaseVector.cxx index 783e86eb51..2750cf4cd7 100755 --- a/src/NCollection/NCollection_BaseVector.cxx +++ b/src/NCollection/NCollection_BaseVector.cxx @@ -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,201 +17,149 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. - #include #include -#ifdef DEB -#include -#endif -#include +#include //======================================================================= -//function : GetIndexV -//purpose : +//function : NCollection_BaseVector::Iterator::copyV +//purpose : Copy from another iterator //======================================================================= -Standard_Integer NCollection_BaseVector::MemBlock::GetIndexV - (void * theItem, const size_t theItemSize) const +void NCollection_BaseVector::Iterator::copyV (const NCollection_BaseVector::Iterator& theOth) { - 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; + myVector = theOth.myVector; + myICurBlock = theOth.myICurBlock; + myIEndBlock = theOth.myIEndBlock; + myCurIndex = theOth.myCurIndex; + myEndIndex = theOth.myEndIndex; } //======================================================================= -//function : ~NCollection_BaseVector -//purpose : Destructor +//function : initV +//purpose : Initialisation of iterator by a vector //======================================================================= -NCollection_BaseVector::~NCollection_BaseVector() +void NCollection_BaseVector::Iterator::initV (const NCollection_BaseVector& theVector) { - for (Standard_Integer i = 0; i < myCapacity; i++) - myData[i].Reinit (0, 0); - myDataFree (* this, myData); + 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 : allocMemBlocks +//purpose : +//======================================================================= + +NCollection_BaseVector::MemBlock* NCollection_BaseVector + ::allocMemBlocks (Handle(NCollection_BaseAllocator)& theAllocator, + const Standard_Integer theCapacity, + MemBlock* theSource, + const Standard_Integer theSourceSize) +{ + 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); + } + + // Nullify newly allocated blocks + if (aCapacity < theCapacity) + { + memset (&aData[aCapacity], 0, (theCapacity - aCapacity) * sizeof(MemBlock)); + } + return aData; } //======================================================================= //function : Clear -//purpose : +//purpose : //======================================================================= void NCollection_BaseVector::Clear() { - if (myLength > 0) { - for (Standard_Integer i = 0; i < myCapacity; i++) - myData[i].Reinit (0, 0); - myLength = 0; + if (myLength > 0) + { + for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter) + { + myInitBlocks (*this, myData[anItemIter], 0, 0); + } + myLength = 0; myNBlocks = 0; } } //======================================================================= -//function : NCollection_BaseVector::Iterator::CopyV -//purpose : Copy from another iterator -//======================================================================= - -void NCollection_BaseVector::Iterator::CopyV - (const NCollection_BaseVector::Iterator& theOth) -{ - myVector = theOth.myVector; - myICurBlock = theOth.myICurBlock; - myIEndBlock = theOth.myIEndBlock; - myCurIndex = theOth.myCurIndex; - myEndIndex = theOth.myEndIndex; -} - -//======================================================================= -//function : InitV -//purpose : Initialisation of iterator by a vector -//======================================================================= - -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(); - } -} - -//======================================================================= -//function : operator = -//purpose : assignment -//======================================================================= - -NCollection_BaseVector& NCollection_BaseVector::operator = - (const NCollection_BaseVector& theOther) -{ -// 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; -} - -//======================================================================= -//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); + return aNewBlock->findV (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); -} -#endif diff --git a/src/NCollection/NCollection_BaseVector.hxx b/src/NCollection/NCollection_BaseVector.hxx index 5506ec0912..08c4e60d3b 100755 --- a/src/NCollection/NCollection_BaseVector.hxx +++ b/src/NCollection/NCollection_BaseVector.hxx @@ -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 @@ -26,13 +24,11 @@ #include #include -#if !defined No_Exception && !defined No_Standard_OutOfRange #include -#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]; } + Iterator() + : myICurBlock (0), + myIEndBlock (0), + myCurIndex (0), + myEndIndex (0) {} - 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 (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 + + 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: //! @name protected methods + + //! Empty constructor + 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 + { + 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); + } + +public: //! @name public API + + //! Empty the vector of its objects + Standard_EXPORT void Clear(); + +protected: //! @name Private fields + + size_t myItemSize; + Standard_Integer myIncrement; + Standard_Integer myLength; + Standard_Integer myCapacity; + Standard_Integer myNBlocks; + MemBlock* myData; + initMemBlocks_t myInitBlocks; + +protected: friend class Iterator; - // ---------- 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) - { -// myData = (MemBlock *) new char [myCapacity * sizeof(MemBlock)]; -// for (Standard_Integer i = 0; i < myCapacity; i++) -// new (&myData[i]) MemBlock; - } - - //! 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; } - - //! 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; }; -//======================================================================= -//function : Find -//purpose : locate the memory holding the desired value -//======================================================================= - -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); -} - -#ifdef WNT -#pragma warning(pop) +#if defined(_MSC_VER) + #pragma warning(pop) #endif -#endif +#endif // NCollection_BaseVector_HeaderFile diff --git a/src/NCollection/NCollection_Vector.hxx b/src/NCollection/NCollection_Vector.hxx index 5e94b221b9..fee43272e2 100755 --- a/src/NCollection/NCollection_Vector.hxx +++ b/src/NCollection/NCollection_Vector.hxx @@ -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 @@ -23,180 +23,135 @@ #include #include -#if !defined No_Exception && !defined No_Standard_OutOfRange -#include -#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 NCollection_Vector - : public NCollection_BaseCollection, - public NCollection_BaseVector +: public NCollection_BaseCollection, + 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::Iterator, public NCollection_BaseVector::Iterator { public: - //! Empty constructor - for later Init - Iterator (void) {} - //! Constructor with initialisation - Iterator (const NCollection_Vector& theVector) : - NCollection_BaseVector::Iterator (theVector) {} - //! Copy constructor - Iterator (const Iterator& theOther) : - NCollection_BaseVector::Iterator (theOther) {} - //! Initialisation - void Init (const NCollection_Vector& theVector) { InitV (theVector); } - //! Assignment - Iterator& operator = (const Iterator& theOther) { - CopyV (theOther); - return * this; - } - //! Check end - virtual Standard_Boolean More (void) const { return MoreV (); } - //! Make step - virtual void Next (void) { NextV(); } - //! Constant value access - virtual const TheItemType& Value (void) const { - return ((const MemBlock *) CurBlockV()) -> Value(myCurIndex); } - //! Variable value access - virtual TheItemType& ChangeValue (void) const { - return ((MemBlock *) CurBlockV()) -> ChangeValue(myCurIndex); } - }; // End of the nested class Iterator - // ---------------------------------------------------------------------- - // ------------------------ Class Vector itself ------------------------- - // ---------------------------------------------------------------------- - public: - // ---------- PUBLIC METHODS ---------- + //! Empty constructor - for later Init + Iterator() {} + + //! Constructor with initialisation + Iterator (const NCollection_Vector& theVector) + : NCollection_BaseVector::Iterator (theVector) {} + + //! Copy constructor + Iterator (const Iterator& theOther) + : NCollection_BaseVector::Iterator (theOther) {} + + //! Initialisation + void Init (const NCollection_Vector& theVector) + { + initV (theVector); + } + + //! Assignment + Iterator& operator= (const Iterator& theOther) + { + copyV (theOther); + return *this; + } + + //! Check end + virtual Standard_Boolean More() const + { + return moreV(); + } + + //! Make step + virtual void Next() + { + nextV(); + } + + //! Constant value access + virtual const TheItemType& Value() const + { + return ((const TheItemType* )curBlockV()->DataPtr)[myCurIndex]; + } + + //! Variable value access + virtual TheItemType& ChangeValue() const + { + return ((TheItemType* )curBlockV()->DataPtr)[myCurIndex]; + } + + }; + +public: //! @name public methods //! Constructor NCollection_Vector (const Standard_Integer theIncrement = 256, - const Handle_NCollection_BaseAllocator& theAlloc = 0L) - : NCollection_BaseCollection(theAlloc), - NCollection_BaseVector (sizeof(TheItemType), theIncrement, - FuncDataInit, FuncDataFree) {} + const Handle_NCollection_BaseAllocator& theAlloc = NULL) + : NCollection_BaseCollection (theAlloc), + NCollection_BaseVector (NCollection_BaseCollection::myAllocator, initMemBlocks, sizeof(TheItemType), theIncrement) {} //! Copy constructor NCollection_Vector (const NCollection_Vector& theOther) - : NCollection_BaseCollection(theOther.myAllocator), - NCollection_BaseVector (theOther, FuncDataInit, FuncDataFree) - { CopyData (theOther); } + : NCollection_BaseCollection (theOther.myAllocator), + NCollection_BaseVector (NCollection_BaseCollection::myAllocator, initMemBlocks, theOther) + { + copyData (theOther); + } - //! Operator = - NCollection_Vector& operator = (const NCollection_Vector& theOther) { - if (this != &theOther) { - this->myAllocator = theOther.myAllocator; - NCollection_BaseVector::operator = (theOther); - CopyData (theOther); + //! Destructor + ~NCollection_Vector() + { + for (Standard_Integer anItemIter = 0; anItemIter < myCapacity; ++anItemIter) + { + initMemBlocks (*this, myData[anItemIter], 0, 0); } - return * this; + NCollection_BaseCollection::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 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& theOther) { - if (this != &theOther) { - TYPENAME NCollection_BaseCollection::Iterator& anIter2 = - theOther.CreateIterator(); - while (anIter2.More()) { + if (this != &theOther) + { + TYPENAME NCollection_BaseCollection::Iterator& anIter2 = theOther.CreateIterator(); + while (anIter2.More()) + { Append (anIter2.Value()); anIter2.Next(); } @@ -232,126 +188,173 @@ template 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::Iterator& - CreateIterator(void) const - { return *(new (this->IterAllocator()) Iterator(*this)); } + virtual TYPENAME NCollection_BaseCollection::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::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::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 (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; - } - while (i < aCapacity) - new (&aData[i++]) MemBlock(aSelf.myAllocator.operator->()); - return aData; - } + NCollection_Vector& aSelf = static_cast (theVector); + Handle(NCollection_BaseAllocator)& anAllocator = aSelf.myAllocator; - static void FuncDataFree (const NCollection_BaseVector& theVector, - NCollection_BaseVector::MemBlock * aData) - { - const NCollection_Vector& aSelf = - static_cast (theVector); - aSelf.myAllocator->Free(aData); + // 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; + } + + // 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 inline +void NCollection_Vector::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::myAllocator->Free (myData); + + // allocate memory blocks with new allocator + if (!theOwnAllocator) + { + NCollection_BaseCollection::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::myAllocator, myCapacity); + + // copy data + copyData (theOther); +} + +#endif // NCollection_Vector_HeaderFile