1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/NCollection/NCollection_SparseArrayBase.cxx
Pawel d93f7683c9 0023373: MSVC++ warnings issued during compilation for 64bits, 'Sparse Arrays'
Replaced 'Standard_Integer' with 'Standard_Size' to avoid compiler warning.
Removed redundant casting to 'Standard_Size'.
Removed code checking if a 'Standard_Size' variable is negative.
2012-08-24 14:18:55 +04:00

357 lines
10 KiB
C++
Executable File

// Created on: 2007-02-06
// Created by: Andrey BETENEV
// Copyright (c) 2007-2012 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
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#include <NCollection_SparseArrayBase.hxx>
#include <Standard_ProgramError.hxx>
//=======================================================================
//function : allocData
//purpose :
//=======================================================================
void NCollection_SparseArrayBase::allocData (const Standard_Size iBlock)
{
if ( iBlock < myNbBlocks )
return;
// the allocation of blocks starts from myBlockSize items
// and then is multiplied by 2 every time reallocation is needed
Standard_Size newNbBlocks = ( myNbBlocks ? myNbBlocks * 2 : myBlockSize );
while (iBlock >= newNbBlocks) newNbBlocks *= 2;
Standard_Address* newData =
(Standard_Address*)malloc(newNbBlocks*sizeof(Standard_Address));
if ( myNbBlocks >0 )
memcpy (newData, myData, myNbBlocks*sizeof(Standard_Address));
memset (newData+myNbBlocks, 0, (newNbBlocks-myNbBlocks)*sizeof(Standard_Address));
free (myData);
myData = newData;
myNbBlocks = newNbBlocks;
}
//=======================================================================
//function : freeBlock
//purpose :
//=======================================================================
void NCollection_SparseArrayBase::freeBlock (const Standard_Size iBlock)
{
Standard_Address & anAddr = myData[iBlock];
Block aBlock = getBlock(anAddr);
for (Standard_Size anInd=0; anInd < myBlockSize; anInd++)
if ( aBlock.IsSet(anInd) )
{
destroyItem (getItem (aBlock, anInd));
mySize--;
}
free (anAddr);
anAddr = 0;
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void NCollection_SparseArrayBase::Clear ()
{
// free block data
for (Standard_Size iBlock=0; iBlock < myNbBlocks; iBlock++)
if ( myData[iBlock] )
freeBlock (iBlock);
// free blocks and reset counters
free (myData);
myData = 0;
myNbBlocks = 0;
// consistency check
Standard_ProgramError_Raise_if (mySize!=0,"NCollection_SparseArrayBase: Implementation error: inconsistent items count")
}
//=======================================================================
//function : assign
//purpose :
//=======================================================================
void NCollection_SparseArrayBase::assign (const NCollection_SparseArrayBase& theOther)
{
if (this == &theOther)
return;
// if block size is different, clear all data
if ( myBlockSize != theOther.myBlockSize )
Clear();
myBlockSize = theOther.myBlockSize;
// iterate by blocks in theOther
Standard_Size iBlock=0;
for (; iBlock < theOther.myNbBlocks; iBlock++)
{
if ( ! theOther.myData[iBlock] )
{
// if other block is empty, just make sure to empty that block in "this"
if ( iBlock < myNbBlocks && myData[iBlock] )
freeBlock (iBlock);
continue;
}
if ( iBlock >= myNbBlocks )
allocData(iBlock);
Block anOtherBlock = getBlock(theOther.myData[iBlock]);
// if block not yet allocated, just allocate and fill
Standard_Address & anAddr = myData[iBlock];
if ( ! anAddr )
{
anAddr = calloc (Block::Size(myBlockSize, myItemSize), sizeof(char));
Block aBlock ( getBlock(anAddr) );
for (Standard_Size anInd=0; anInd < myBlockSize; anInd++)
if ( anOtherBlock.IsSet(anInd) )
{
Standard_Address anItem = getItem (aBlock, anInd);
aBlock.Set(anInd);
(*aBlock.Count)++;
mySize++;
createItem (anItem, getItem(anOtherBlock, anInd));
}
}
// else perform copying item-by-item
else
{
Block aBlock ( getBlock(anAddr) );
for (Standard_Size anInd=0; anInd < myBlockSize; anInd++)
{
Standard_Address anItem = getItem (aBlock, anInd);
if ( anOtherBlock.IsSet(anInd) )
{
Standard_Address anOtherItem = getItem (anOtherBlock, anInd);
if ( aBlock.IsSet(anInd) ) // copy
{
copyItem (anItem, anOtherItem);
}
else // create
{
aBlock.Set(anInd);
(*aBlock.Count)++;
mySize++;
createItem (anItem, getItem(anOtherBlock, anInd));
}
}
else if ( aBlock.IsSet(anInd) ) // delete
{
aBlock.Set(anInd);
(*aBlock.Count)--;
mySize--;
destroyItem (anItem);
}
}
}
}
// clear any remaining blocks in this
for (; iBlock < myNbBlocks; iBlock++)
if ( myData[iBlock] )
freeBlock (iBlock);
// consistency check
Standard_ProgramError_Raise_if (mySize!=theOther.mySize,
"NCollection_SparseArrayBase: Implementation error: inconsistent items count")
}
//=======================================================================
//function : exchange
//purpose :
//=======================================================================
template<class T> static inline void sswap (T &a, T &b) { T c = a; a = b; b = c; }
void NCollection_SparseArrayBase::exchange (NCollection_SparseArrayBase& theOther)
{
if (this == &theOther)
return;
// swap fields of this and theOther
sswap (myItemSize, theOther.myItemSize);
sswap (myBlockSize,theOther.myBlockSize);
sswap (myNbBlocks, theOther.myNbBlocks);
sswap (mySize, theOther.mySize);
sswap (myData, theOther.myData);
}
//=======================================================================
//function : setValue
//purpose :
//=======================================================================
Standard_Address NCollection_SparseArrayBase::setValue (const Standard_Size theIndex,
const Standard_Address theValue)
{
Standard_Size iBlock = theIndex / myBlockSize;
// resize blocks array if necessary
if ( iBlock >= myNbBlocks )
allocData (iBlock);
// allocate block if necessary
Standard_Address & anAddr = myData[iBlock];
if ( ! anAddr )
anAddr = calloc (Block::Size(myBlockSize, myItemSize), sizeof(char));
// get a block
Block aBlock (getBlock (anAddr));
// mark item as defined
Standard_Size anInd = theIndex % myBlockSize;
Standard_Address anItem = getItem (aBlock, anInd);
// either create an item by copy constructor if it is new, or assign it
if ( aBlock.Set(anInd) )
{
(*aBlock.Count)++;
mySize++;
createItem (anItem, theValue);
}
else
copyItem (anItem, theValue);
return anItem;
}
//=======================================================================
//function : HasValue
//purpose :
//=======================================================================
Standard_Boolean NCollection_SparseArrayBase::HasValue (const Standard_Size theIndex) const
{
Standard_Size iBlock = theIndex / myBlockSize;
if ( iBlock >= myNbBlocks ||
! myData[iBlock] )
return Standard_False;
return getBlock(myData[iBlock]).IsSet(theIndex % myBlockSize) ? Standard_True : Standard_False;
}
//=======================================================================
//function : UnsetValue
//purpose :
//=======================================================================
Standard_Boolean NCollection_SparseArrayBase::UnsetValue (const Standard_Size theIndex)
{
// check that the item is defined
Standard_Size iBlock = theIndex / myBlockSize;
if ( iBlock >= myNbBlocks || ! myData[iBlock] )
return Standard_False;
Block aBlock (getBlock(myData[iBlock]));
Standard_Size anInd = theIndex % myBlockSize;
if ( ! aBlock.Unset(anInd) )
return Standard_False;
// destroy the item
destroyItem (getItem (aBlock, anInd));
(*aBlock.Count)--;
mySize--;
// free block if it becomes empty
if ( ! (*aBlock.Count) )
freeBlock (iBlock);
return Standard_True;
}
//=======================================================================
//function : Iterator::Iterator
//purpose :
//=======================================================================
NCollection_SparseArrayBase::Iterator::Iterator (const NCollection_SparseArrayBase* theArray)
: myArr((NCollection_SparseArrayBase*)theArray),
myHasMore(Standard_False), myIBlock(0), myInd(0),
myBlock(0,0,0)
{
init(theArray);
}
//=======================================================================
//function : Iterator::Next
//purpose :
//=======================================================================
void NCollection_SparseArrayBase::Iterator::Next ()
{
if ( ! myArr || ! myHasMore )
return;
// iterate by items and blocks
for ( myInd++; ; myInd++ ) {
// if index is over the block size, advance to the next non-empty block
if ( myInd >= myArr->myBlockSize )
{
for ( myIBlock++; ; myIBlock++ ) {
if ( myIBlock >= myArr->myNbBlocks ) // end
{
myHasMore = Standard_False;
return;
}
if ( myArr->myData[myIBlock] )
{
myInd = 0;
myBlock = Block (myArr->myData[myIBlock], myArr->myBlockSize, myArr->myItemSize );
break;
}
}
}
// check if item is defined
if ( myBlock.IsSet (myInd) )
return;
}
}
//=======================================================================
//function : Iterator::init
//purpose :
//=======================================================================
void NCollection_SparseArrayBase::Iterator::init (const NCollection_SparseArrayBase* theArray)
{
myArr = (NCollection_SparseArrayBase*)theArray;
myHasMore = Standard_False;
if ( myArr )
{
myInd = 0;
// find first non-empty block
for ( myIBlock=0; myIBlock < myArr->myNbBlocks; myIBlock++ )
{
if ( ! myArr->myData[myIBlock] )
continue;
myHasMore = Standard_True;
myBlock = Block (myArr->myData[myIBlock], myArr->myBlockSize, myArr->myItemSize );
// if first item in the block is not set, advance to the next defined item
if ( ! myBlock.IsSet(myInd) )
Next();
return;
}
}
}