1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00
occt/src/NCollection/NCollection_BaseVector.cxx

203 lines
7.2 KiB
C++
Executable File

// File: NCollection_BaseVector.cxx
// Created: 24.04.02 10:07:15
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2002
#include <NCollection_BaseVector.hxx>
#include <Standard_RangeError.hxx>
#ifdef DEB
#include <Standard_OutOfRange.hxx>
#endif
#include <stdlib.h>
//=======================================================================
//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 = 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
//=======================================================================
NCollection_BaseVector::~NCollection_BaseVector()
{
for (Standard_Integer i = 0; i < myCapacity; i++)
myData[i].Reinit (0, 0);
myDataFree (* this, myData);
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void NCollection_BaseVector::Clear()
{
if (myLength > 0) {
for (Standard_Integer i = 0; i < myCapacity; i++)
myData[i].Reinit (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
//purpose : returns the pointer where the new data item is supposed to be put
//=======================================================================
void * NCollection_BaseVector::ExpandV (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");
const unsigned int 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);
}
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) {
// Reallocate the array myData
do myCapacity += GetCapacity(myIncrement); while (myCapacity <= nNewBlock);
MemBlock * aNewData = myDataInit (* this, myCapacity, myData, myNBlocks);
myDataFree (* this, myData);
myData = aNewData;
}
if (myNBlocks > 0) {
// Change length of old last block to myIncrement
MemBlock * aLastBlock = (MemBlock *) &myData[myNBlocks-1];
aLastBlock -> SetLength (myIncrement);
}
// Initialise new blocks
MemBlock * aNewBlock = (MemBlock *) &myData[myNBlocks++];
aNewBlock -> Reinit (myLength, myIncrement);
while (myNBlocks < nNewBlock) {
aNewBlock -> SetLength (myIncrement);
myLength += myIncrement;
aNewBlock = (MemBlock *) &myData[myNBlocks++];
aNewBlock -> Reinit (myLength, myIncrement);
}
aNewBlock -> SetLength (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);
}
#endif