1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-21 10:13:43 +03:00
occt/src/NCollection/NCollection_DoubleMap.hxx
abv d5f74e42d6 0024624: Lost word in license statement in source files
License statement text corrected; compiler warnings caused by Bison 2.41 disabled for MSVC; a few other compiler warnings on 54-bit Windows eliminated by appropriate type cast
Wrong license statements corrected in several files.
Copyright and license statements added in XSD and GLSL files.
Copyright year updated in some files.
Obsolete documentation files removed from DrawResources.
2014-02-20 16:15:17 +04:00

482 lines
15 KiB
C++

// Created on: 2002-04-24
// Created by: Alexander KARTOMIN (akm)
// Copyright (c) 2002-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef NCollection_DoubleMap_HeaderFile
#define NCollection_DoubleMap_HeaderFile
#include <NCollection_TypeDef.hxx>
#include <NCollection_BaseCollection.hxx>
#include <NCollection_BaseMap.hxx>
#include <NCollection_TListNode.hxx>
#include <Standard_TypeMismatch.hxx>
#include <Standard_MultiplyDefined.hxx>
#include <Standard_ImmutableObject.hxx>
#include <Standard_NoSuchObject.hxx>
#include <NCollection_DefaultHasher.hxx>
/**
* Purpose: The DoubleMap is used to bind pairs (Key1,Key2)
* and retrieve them in linear time.
*
* See Map from NCollection for a discussion about the number
* of buckets
*/
template < class TheKey1Type,
class TheKey2Type,
class Hasher1 = NCollection_DefaultHasher<TheKey1Type>,
class Hasher2 = NCollection_DefaultHasher<TheKey2Type> > class NCollection_DoubleMap
: public NCollection_BaseCollection<TheKey2Type>,
public NCollection_BaseMap
{
// **************** Adaptation of the TListNode to the DOUBLEmap
public:
class DoubleMapNode : public NCollection_TListNode<TheKey2Type>
{
public:
//! Constructor with 'Next'
DoubleMapNode (const TheKey1Type& theKey1,
const TheKey2Type& theKey2,
NCollection_ListNode* theNext1,
NCollection_ListNode* theNext2) :
NCollection_TListNode<TheKey2Type> (theKey2, theNext1)
{
myKey1 = theKey1;
myNext2 = (DoubleMapNode *) theNext2;
}
//! Key1
const TheKey1Type& Key1 (void)
{ return myKey1; }
//! Key2
const TheKey2Type& Key2 (void)
{ return this->myValue; }
//! Next2
DoubleMapNode*& Next2 (void)
{ return myNext2; }
//! Static deleter to be passed to BaseList
static void delNode (NCollection_ListNode * theNode,
Handle(NCollection_BaseAllocator)& theAl)
{
((DoubleMapNode *) theNode)->~DoubleMapNode();
theAl->Free(theNode);
}
private:
TheKey1Type myKey1;
DoubleMapNode *myNext2;
};
public:
// **************** Implementation of the Iterator interface.
class Iterator
: public NCollection_BaseCollection<TheKey2Type>::Iterator,
public NCollection_BaseMap::Iterator
{
public:
//! Empty constructor
Iterator (void) :
NCollection_BaseMap::Iterator() {}
//! Constructor
Iterator (const NCollection_DoubleMap& theMap) :
NCollection_BaseMap::Iterator(theMap) {}
//! Query if the end of collection is reached by iterator
virtual Standard_Boolean More(void) const
{ return PMore(); }
//! Make a step along the collection
virtual void Next(void)
{ PNext(); }
//! Key1 inquiry
const TheKey1Type& Key1(void) const
{
#if !defined No_Exception && !defined No_Standard_NoSuchObject
if (!More())
Standard_NoSuchObject::Raise ("NCollection_DoubleMap::Iterator::Key1");
#endif
return ((DoubleMapNode *) myNode)->Key1();
}
//! Key2 inquiry
const TheKey2Type& Key2(void) const
{
#if !defined No_Exception && !defined No_Standard_NoSuchObject
if (!More())
Standard_NoSuchObject::Raise ("NCollection_DoubleMap::Iterator::Key2");
#endif
return ((DoubleMapNode *) myNode)->Key2();
}
//! Value access
virtual const TheKey2Type& Value(void) const
{
#if !defined No_Exception && !defined No_Standard_NoSuchObject
if (!More())
Standard_NoSuchObject::Raise ("NCollection_DoubleMap::Iterator::Value");
#endif
return ((DoubleMapNode *) myNode)->Value();
}
//! Value change access - denied
virtual TheKey2Type& ChangeValue(void) const
{
Standard_ImmutableObject::Raise("NCollection_DoubleMap::Iterator::ChangeValue");
return * (TheKey2Type *) NULL; // For compiler
}
};
public:
// ---------- PUBLIC METHODS ------------
//! Constructor
NCollection_DoubleMap (const Standard_Integer NbBuckets=1,
const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
: NCollection_BaseCollection<TheKey2Type>(theAllocator),
NCollection_BaseMap (NbBuckets, Standard_False) {}
//! Copy constructor
NCollection_DoubleMap (const NCollection_DoubleMap& theOther)
: NCollection_BaseCollection<TheKey2Type>(theOther.myAllocator),
NCollection_BaseMap (theOther.NbBuckets(), Standard_False)
{ *this = theOther; }
//! Assign another collection
virtual void Assign(const NCollection_BaseCollection<TheKey2Type>& theOther)
{
if (this == &theOther)
return;
Standard_TypeMismatch::Raise ("NCollection_DoubleMap::Assign impossible");
}
//! Exchange the content of two maps without re-allocations.
//! Notice that allocators will be swapped as well!
void Exchange (NCollection_DoubleMap& theOther)
{
this->exchangeAllocators (theOther);
this->exchangeMapsData (theOther);
}
//! = another map
NCollection_DoubleMap& operator=(const NCollection_DoubleMap& theOther)
{
if (this == &theOther)
return *this;
Clear(theOther.myAllocator);
ReSize (theOther.Extent()-1);
Iterator anIter(theOther);
for (; anIter.More(); anIter.Next())
{
TheKey1Type aKey1 = anIter.Key1();
TheKey2Type aKey2 = anIter.Key2();
Standard_Integer iK1 = Hasher1::HashCode (aKey1, NbBuckets());
Standard_Integer iK2 = Hasher2::HashCode (aKey2, NbBuckets());
DoubleMapNode * pNode = new (this->myAllocator) DoubleMapNode (aKey1, aKey2,
myData1[iK1],
myData2[iK2]);
myData1[iK1] = pNode;
myData2[iK2] = pNode;
Increment();
}
return *this;
}
//! ReSize
void ReSize (const Standard_Integer N)
{
NCollection_ListNode** ppNewData1 = NULL;
NCollection_ListNode** ppNewData2 = NULL;
Standard_Integer newBuck;
if (BeginResize (N, newBuck, ppNewData1, ppNewData2, this->myAllocator))
{
if (myData1)
{
DoubleMapNode *p, *q;
Standard_Integer i, iK1, iK2;
for (i = 0; i <= NbBuckets(); i++)
{
if (myData1[i])
{
p = (DoubleMapNode *) myData1[i];
while (p)
{
iK1 = Hasher1::HashCode (p->Key1(), newBuck);
iK2 = Hasher2::HashCode (p->Key2(), newBuck);
q = (DoubleMapNode*) p->Next();
p->Next() = ppNewData1[iK1];
p->Next2() = (DoubleMapNode*)ppNewData2[iK2];
ppNewData1[iK1] = p;
ppNewData2[iK2] = p;
p = q;
}
}
}
}
EndResize (N, newBuck, ppNewData1, ppNewData2, this->myAllocator);
}
}
//! Bind
void Bind (const TheKey1Type& theKey1, const TheKey2Type& theKey2)
{
if (Resizable())
ReSize(Extent());
Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
DoubleMapNode * pNode;
pNode = (DoubleMapNode *) myData1[iK1];
while (pNode)
{
if (Hasher1::IsEqual (pNode->Key1(), theKey1))
Standard_MultiplyDefined::Raise("NCollection_DoubleMap:Bind");
pNode = (DoubleMapNode *) pNode->Next();
}
pNode = (DoubleMapNode *) myData2[iK2];
while (pNode)
{
if (Hasher2::IsEqual (pNode->Key2(), theKey2))
Standard_MultiplyDefined::Raise("NCollection_DoubleMap:Bind");
pNode = (DoubleMapNode *) pNode->Next();
}
pNode = new (this->myAllocator) DoubleMapNode (theKey1, theKey2,
myData1[iK1], myData2[iK2]);
myData1[iK1] = pNode;
myData2[iK2] = pNode;
Increment();
}
//!* AreBound
Standard_Boolean AreBound (const TheKey1Type& theKey1,
const TheKey2Type& theKey2) const
{
if (IsEmpty())
return Standard_False;
Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
DoubleMapNode * pNode1, * pNode2;
pNode1 = (DoubleMapNode *) myData1[iK1];
while (pNode1)
{
if (Hasher1::IsEqual(pNode1->Key1(), theKey1))
break;
pNode1 = (DoubleMapNode *) pNode1->Next();
}
if (pNode1 == NULL)
return Standard_False;
pNode2 = (DoubleMapNode *) myData2[iK2];
while (pNode2)
{
if (Hasher2::IsEqual(pNode2->Key2(), theKey2))
break;
pNode2 = (DoubleMapNode *) pNode2->Next();
}
if (pNode2 == NULL)
return Standard_False;
return (pNode1 == pNode2);
}
//! IsBound1
Standard_Boolean IsBound1 (const TheKey1Type& theKey1) const
{
if (IsEmpty())
return Standard_False;
Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
DoubleMapNode * pNode1;
pNode1 = (DoubleMapNode *) myData1[iK1];
while (pNode1)
{
if (Hasher1::IsEqual(pNode1->Key1(), theKey1))
return Standard_True;
pNode1 = (DoubleMapNode *) pNode1->Next();
}
return Standard_False;
}
//! IsBound2
Standard_Boolean IsBound2 (const TheKey2Type& theKey2) const
{
if (IsEmpty())
return Standard_False;
Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
DoubleMapNode * pNode2;
pNode2 = (DoubleMapNode *) myData2[iK2];
while (pNode2)
{
if (Hasher2::IsEqual(pNode2->Key2(), theKey2))
return Standard_True;
pNode2 = (DoubleMapNode *) pNode2->Next2();
}
return Standard_False;
}
//! UnBind1
Standard_Boolean UnBind1 (const TheKey1Type& theKey1)
{
if (IsEmpty())
return Standard_False;
Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
DoubleMapNode * p1, * p2, * q1, *q2;
q1 = q2 = NULL;
p1 = (DoubleMapNode *) myData1[iK1];
while (p1)
{
if (Hasher1::IsEqual (p1->Key1(), theKey1))
{
// remove from the data1
if (q1)
q1->Next() = p1->Next();
else
myData1[iK1] = (DoubleMapNode*) p1->Next();
Standard_Integer iK2 = Hasher2::HashCode (p1->Key2(), NbBuckets());
p2 = (DoubleMapNode *) myData2[iK2];
while (p2)
{
if (p2 == p1)
{
// remove from the data2
if (q2)
q2->Next2() = p2->Next2();
else
myData2[iK2] = (DoubleMapNode*) p2->Next2();
break;
}
q2 = p2;
p2 = (DoubleMapNode*) p2->Next2();
}
p1->~DoubleMapNode();
this->myAllocator->Free(p1);
Decrement();
return Standard_True;
}
q1 = p1;
p1 = (DoubleMapNode*) p1->Next();
}
return Standard_False;
}
//! UnBind2
Standard_Boolean UnBind2 (const TheKey2Type& theKey2)
{
if (IsEmpty())
return Standard_False;
Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
DoubleMapNode * p1, * p2, * q1, *q2;
q1 = q2 = NULL;
p2 = (DoubleMapNode *) myData2[iK2];
while (p2)
{
if (Hasher2::IsEqual (p2->Key2(), theKey2))
{
// remove from the data2
if (q2)
q2->Next() = p2->Next();
else
myData2[iK2] = (DoubleMapNode*) p2->Next2();
Standard_Integer iK1 = Hasher1::HashCode (p2->Key1(), NbBuckets());
p1 = (DoubleMapNode *) myData1[iK1];
while (p1)
{
if (p1 == p2)
{
// remove from the data1
if (q1)
q1->Next() = p1->Next();
else
myData1[iK1] = (DoubleMapNode*) p1->Next();
break;
}
q1 = p1;
p1 = (DoubleMapNode*) p1->Next();
}
p2->~DoubleMapNode();
this->myAllocator->Free(p2);
Decrement();
return Standard_True;
}
q2 = p2;
p2 = (DoubleMapNode*) p2->Next2();
}
return Standard_False;
}
//! Find1
const TheKey2Type& Find1(const TheKey1Type& theKey1) const
{
#if !defined No_Exception && !defined No_Standard_NoSuchObject
if (IsEmpty())
Standard_NoSuchObject::Raise ("NCollection_DoubleMap::Find1");
#endif
DoubleMapNode * pNode1 =
(DoubleMapNode *) myData1[Hasher1::HashCode(theKey1,NbBuckets())];
while (pNode1)
{
if (Hasher1::IsEqual (pNode1->Key1(), theKey1))
return pNode1->Key2();
pNode1 = (DoubleMapNode*) pNode1->Next();
}
Standard_NoSuchObject::Raise("NCollection_DoubleMap::Find1");
return pNode1->Key2(); // This for compiler
}
//! Find2
const TheKey1Type& Find2(const TheKey2Type& theKey2) const
{
#if !defined No_Exception && !defined No_Standard_NoSuchObject
if (IsEmpty())
Standard_NoSuchObject::Raise ("NCollection_DoubleMap::Find2");
#endif
DoubleMapNode * pNode2 =
(DoubleMapNode *) myData2[Hasher2::HashCode(theKey2,NbBuckets())];
while (pNode2)
{
if (Hasher2::IsEqual (pNode2->Key2(), theKey2))
return pNode2->Key1();
pNode2 = (DoubleMapNode*) pNode2->Next2();
}
Standard_NoSuchObject::Raise("NCollection_DoubleMap::Find2");
return pNode2->Key1(); // This for compiler
}
//! Clear data. If doReleaseMemory is false then the table of
//! buckets is not released and will be reused.
void Clear(const Standard_Boolean doReleaseMemory = Standard_True)
{ Destroy (DoubleMapNode::delNode, this->myAllocator, doReleaseMemory); }
//! Clear data and reset allocator
void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
{
Clear();
this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
NCollection_BaseAllocator::CommonBaseAllocator() );
}
//! Destructor
~NCollection_DoubleMap (void)
{ Clear(); }
//! Size
virtual Standard_Integer Size(void) const
{ return Extent(); }
private:
// ----------- PRIVATE METHODS -----------
//! Creates Iterator for use on BaseCollection
virtual TYPENAME NCollection_BaseCollection<TheKey2Type>::Iterator&
CreateIterator(void) const
{ return *(new (this->IterAllocator()) Iterator(*this)); }
};
#endif