Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:19

0001 // Created on: 2002-04-24
0002 // Created by: Alexander KARTOMIN (akm)
0003 // Copyright (c) 2002-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef NCollection_IndexedDataMap_HeaderFile
0017 #define NCollection_IndexedDataMap_HeaderFile
0018 
0019 #include <NCollection_BaseMap.hxx>
0020 #include <NCollection_TListNode.hxx>
0021 #include <Standard_TypeMismatch.hxx>
0022 #include <Standard_NoSuchObject.hxx>
0023 #include <NCollection_StlIterator.hxx>
0024 #include <NCollection_DefaultHasher.hxx>
0025 
0026 #include <Standard_OutOfRange.hxx>
0027 #include <utility>
0028 
0029 /**
0030  * Purpose:     An indexed map is used  to store keys and to  bind
0031  *              an index to them.  Each  new key stored in the map
0032  *              gets an index.  Index are  incremented as keys are
0033  *              stored in the map. A key can be found by the index
0034  *              and an index by the key.  No  key but the last can
0035  *              be  removed so the  indices   are in the range 1..
0036  *              Extent.  An Item is stored with each key.
0037  *              
0038  *              This   class is   similar  to  IndexedMap     from
0039  *              NCollection  with the Item as  a new feature. Note
0040  *              the important difference on  the operator  ().  In
0041  *              the IndexedMap this operator returns  the Key.  In
0042  *              the IndexedDataMap this operator returns the Item.
0043  *               
0044  *              See  the  class   Map   from NCollection   for   a
0045  *              discussion about the number of buckets.
0046  */            
0047 
0048 template < class TheKeyType, 
0049            class TheItemType, 
0050            class Hasher = NCollection_DefaultHasher<TheKeyType> > 
0051 class NCollection_IndexedDataMap : public NCollection_BaseMap
0052 {
0053 public:
0054   //! STL-compliant typedef for key type
0055   typedef TheKeyType key_type;
0056   //! STL-compliant typedef for value type
0057   typedef TheItemType value_type;
0058   typedef Hasher hasher;
0059 
0060 private:
0061   //!    Adaptation of the TListNode to the INDEXEDDatamap
0062   class IndexedDataMapNode : public NCollection_TListNode<TheItemType>
0063   {
0064   public:
0065     //! Constructor with 'Next'
0066     IndexedDataMapNode (const TheKeyType&      theKey1, 
0067                         const Standard_Integer theIndex,
0068                         const TheItemType&     theItem,
0069                         NCollection_ListNode*  theNext1)
0070     : NCollection_TListNode<TheItemType>(theItem,theNext1),
0071       myKey1  (theKey1),
0072       myIndex (theIndex)
0073     {}
0074     //! Constructor with 'Next'
0075     IndexedDataMapNode (TheKeyType&&           theKey1,
0076                         const Standard_Integer theIndex,
0077                         const TheItemType&     theItem,
0078                         NCollection_ListNode*  theNext1)
0079     : NCollection_TListNode<TheItemType>(theItem,theNext1),
0080       myKey1  (std::forward<TheKeyType>(theKey1)),
0081       myIndex (theIndex)
0082     {}
0083     //! Constructor with 'Next'
0084     IndexedDataMapNode (const TheKeyType&      theKey1,
0085                         const Standard_Integer theIndex,
0086                         TheItemType&&          theItem,
0087                         NCollection_ListNode*  theNext1)
0088     : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem),theNext1),
0089       myKey1  (theKey1),
0090       myIndex (theIndex)
0091     {}
0092     //! Constructor with 'Next'
0093     IndexedDataMapNode (TheKeyType&&           theKey1,
0094                         const Standard_Integer theIndex,
0095                         TheItemType&&          theItem,
0096                         NCollection_ListNode*  theNext1)
0097     : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem),theNext1),
0098       myKey1  (std::forward<TheKeyType>(theKey1)),
0099       myIndex (theIndex)
0100     {}
0101     //! Key1
0102     TheKeyType& Key1() { return myKey1; }
0103     //! Index
0104     Standard_Integer& Index() { return myIndex; }
0105 
0106     //! Static deleter to be passed to BaseList
0107     static void delNode (NCollection_ListNode * theNode, 
0108                          Handle(NCollection_BaseAllocator)& theAl)
0109     {
0110       ((IndexedDataMapNode *) theNode)->~IndexedDataMapNode();
0111       theAl->Free(theNode);
0112     }
0113   private:
0114     TheKeyType       myKey1;
0115     Standard_Integer myIndex;
0116   };
0117 
0118  public:
0119   //!   Implementation of the Iterator interface.
0120   class Iterator
0121   {
0122   public:
0123     //! Empty constructor
0124     Iterator()
0125     : myMap (NULL),
0126       myIndex (0) {}
0127 
0128     //! Constructor
0129     Iterator (const NCollection_IndexedDataMap& theMap)
0130     : myMap ((NCollection_IndexedDataMap*)&theMap),
0131       myIndex (1) {}
0132 
0133     //! Query if the end of collection is reached by iterator
0134     Standard_Boolean More(void) const
0135     { return (myMap != NULL) && (myIndex <= myMap->Extent()); }
0136 
0137     //! Make a step along the collection
0138     void Next(void)
0139     { ++myIndex; }
0140 
0141     //! Value access
0142     const TheItemType& Value(void) const
0143     {  
0144       Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::Value");
0145       return myMap->FindFromIndex(myIndex);
0146     }
0147 
0148     //! ChangeValue access
0149     TheItemType& ChangeValue(void) const
0150     {  
0151       Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::ChangeValue");
0152       return myMap->ChangeFromIndex(myIndex);
0153     }
0154 
0155     //! Key
0156     const TheKeyType& Key() const
0157     {
0158       Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::Key");
0159       return myMap->FindKey(myIndex);
0160     }
0161 
0162     //! Performs comparison of two iterators.
0163     Standard_Boolean IsEqual (const Iterator& theOther) const
0164     {
0165       return myMap == theOther.myMap &&
0166              myIndex == theOther.myIndex;
0167     }
0168 
0169   private:
0170     NCollection_IndexedDataMap* myMap;   //!< Pointer to current node
0171     Standard_Integer            myIndex; //!< Current index
0172   };
0173   
0174   //! Shorthand for a regular iterator type.
0175   typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
0176 
0177   //! Shorthand for a constant iterator type.
0178   typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true> const_iterator;
0179 
0180   //! Returns an iterator pointing to the first element in the map.
0181   iterator begin() const { return Iterator (*this); }
0182 
0183   //! Returns an iterator referring to the past-the-end element in the map.
0184   iterator end() const { return Iterator(); }
0185 
0186   //! Returns a const iterator pointing to the first element in the map.
0187   const_iterator cbegin() const { return Iterator (*this); }
0188 
0189   //! Returns a const iterator referring to the past-the-end element in the map.
0190   const_iterator cend() const { return Iterator(); }
0191   
0192  public:
0193   // ---------- PUBLIC METHODS ------------
0194 
0195   //! Empty constructor.
0196   NCollection_IndexedDataMap() : NCollection_BaseMap (1, true, Handle(NCollection_BaseAllocator)()) {}
0197 
0198   //! Constructor
0199   explicit NCollection_IndexedDataMap (const Standard_Integer theNbBuckets,
0200                                        const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
0201   : NCollection_BaseMap (theNbBuckets, true, theAllocator) {}
0202 
0203   //! Copy constructor
0204   NCollection_IndexedDataMap (const NCollection_IndexedDataMap& theOther) 
0205     : NCollection_BaseMap (theOther.NbBuckets(), true, theOther.myAllocator) 
0206   { *this = theOther; }
0207 
0208   //! Move constructor
0209   NCollection_IndexedDataMap(NCollection_IndexedDataMap&& theOther) noexcept :
0210     NCollection_BaseMap(std::forward<NCollection_BaseMap>(theOther))
0211   {}
0212 
0213   //! Exchange the content of two maps without re-allocations.
0214   //! Notice that allocators will be swapped as well!
0215   void Exchange (NCollection_IndexedDataMap& theOther)
0216   {
0217     this->exchangeMapsData (theOther);
0218   }
0219 
0220   //! Assignment.
0221   //! This method does not change the internal allocator.
0222   NCollection_IndexedDataMap& Assign (const NCollection_IndexedDataMap& theOther)
0223   { 
0224     if (this == &theOther)
0225       return *this;
0226 
0227     Clear();
0228     Standard_Integer anExt = theOther.Extent();
0229     if (anExt)
0230     {
0231       ReSize (anExt-1); //mySize is same after resize
0232       for (Standard_Integer anIndexIter = 1; anIndexIter <= anExt; ++anIndexIter)
0233       {
0234         const TheKeyType&  aKey1  = theOther.FindKey      (anIndexIter);
0235         const TheItemType& anItem = theOther.FindFromIndex(anIndexIter);
0236         const size_t iK1 = HashCode (aKey1, NbBuckets());
0237         IndexedDataMapNode* pNode = new (this->myAllocator) IndexedDataMapNode (aKey1, anIndexIter, anItem, myData1[iK1]);
0238         myData1[iK1]             = pNode;
0239         myData2[anIndexIter - 1] = pNode;
0240         Increment();
0241       }
0242     }
0243     return *this;
0244   }
0245 
0246   //! Assignment operator
0247   NCollection_IndexedDataMap& operator= (const NCollection_IndexedDataMap& theOther)
0248   {
0249     return Assign (theOther);
0250   }
0251 
0252   //! Move operator
0253   NCollection_IndexedDataMap& operator= (NCollection_IndexedDataMap&& theOther) noexcept
0254   {
0255     if (this == &theOther)
0256       return *this;
0257     exchangeMapsData(theOther);
0258     return *this;
0259   }
0260 
0261   //! ReSize
0262   void ReSize (const Standard_Integer N)
0263   {
0264     NCollection_ListNode** ppNewData1 = NULL;
0265     NCollection_ListNode** ppNewData2 = NULL;
0266     Standard_Integer newBuck;
0267     if (BeginResize (N, newBuck, ppNewData1, ppNewData2))
0268     {
0269       if (myData1) 
0270       {
0271         for (Standard_Integer aBucketIter = 0; aBucketIter <= NbBuckets(); ++aBucketIter)
0272         {
0273           if (myData1[aBucketIter])
0274           {
0275             IndexedDataMapNode* p = (IndexedDataMapNode *) myData1[aBucketIter];
0276             while (p) 
0277             {
0278               const size_t iK1 = HashCode (p->Key1(), newBuck);
0279               IndexedDataMapNode* q = (IndexedDataMapNode* )p->Next();
0280               p->Next() = ppNewData1[iK1];
0281               ppNewData1[iK1] = p;
0282               p = q;
0283             }
0284           }
0285         }
0286       }
0287       EndResize (N, newBuck, ppNewData1, (NCollection_ListNode**)
0288         Standard::Reallocate(myData2, (newBuck + 1) * sizeof(NCollection_ListNode*)));
0289     }
0290   }
0291 
0292   //! Returns the Index of already bound Key or appends new Key with specified Item value.
0293   //! @param theKey1 Key to search (and to bind, if it was not bound already)
0294   //! @param theItem Item value to set for newly bound Key; ignored if Key was already bound
0295   //! @return index of Key
0296   Standard_Integer Add (const TheKeyType& theKey1, const TheItemType& theItem)
0297   {
0298     if (Resizable())
0299     {
0300       ReSize(Extent());
0301     }
0302     IndexedDataMapNode* aNode;
0303     size_t aHash;
0304     if (lookup(theKey1, aNode, aHash))
0305     {
0306       return aNode->Index();
0307     }
0308     const Standard_Integer aNewIndex = Increment();
0309     aNode = new (this->myAllocator) IndexedDataMapNode (theKey1, aNewIndex, theItem, myData1[aHash]);
0310     myData1[aHash]         = aNode;
0311     myData2[aNewIndex - 1] = aNode;
0312     return aNewIndex;
0313   }
0314 
0315   //! Returns the Index of already bound Key or appends new Key with specified Item value.
0316   //! @param theKey1 Key to search (and to bind, if it was not bound already)
0317   //! @param theItem Item value to set for newly bound Key; ignored if Key was already bound
0318   //! @return index of Key
0319   Standard_Integer Add (TheKeyType&& theKey1, const TheItemType& theItem)
0320   {
0321     if (Resizable())
0322     {
0323       ReSize(Extent());
0324     }
0325     IndexedDataMapNode* aNode;
0326     size_t aHash;
0327     if (lookup(theKey1, aNode, aHash))
0328     {
0329       return aNode->Index();
0330     }
0331     const Standard_Integer aNewIndex = Increment();
0332     aNode = new (this->myAllocator) IndexedDataMapNode (std::forward<TheKeyType>(theKey1), aNewIndex, theItem, myData1[aHash]);
0333     myData1[aHash]         = aNode;
0334     myData2[aNewIndex - 1] = aNode;
0335     return aNewIndex;
0336   }
0337 
0338   //! Returns the Index of already bound Key or appends new Key with specified Item value.
0339   //! @param theKey1 Key to search (and to bind, if it was not bound already)
0340   //! @param theItem Item value to set for newly bound Key; ignored if Key was already bound
0341   //! @return index of Key
0342   Standard_Integer Add (const TheKeyType& theKey1, TheItemType&& theItem)
0343   {
0344     if (Resizable())
0345     {
0346       ReSize(Extent());
0347     }
0348     IndexedDataMapNode* aNode;
0349     size_t aHash;
0350     if (lookup(theKey1, aNode, aHash))
0351     {
0352       return aNode->Index();
0353     }
0354     const Standard_Integer aNewIndex = Increment();
0355     aNode = new (this->myAllocator) IndexedDataMapNode (theKey1, aNewIndex, std::forward<TheItemType>(theItem), myData1[aHash]);
0356     myData1[aHash]         = aNode;
0357     myData2[aNewIndex - 1] = aNode;
0358     return aNewIndex;
0359   }
0360 
0361   //! Returns the Index of already bound Key or appends new Key with specified Item value.
0362   //! @param theKey1 Key to search (and to bind, if it was not bound already)
0363   //! @param theItem Item value to set for newly bound Key; ignored if Key was already bound
0364   //! @return index of Key
0365   Standard_Integer Add (TheKeyType&& theKey1, TheItemType&& theItem)
0366   {
0367     if (Resizable())
0368     {
0369       ReSize(Extent());
0370     }
0371     IndexedDataMapNode* aNode;
0372     size_t aHash;
0373     if (lookup(theKey1, aNode, aHash))
0374     {
0375       return aNode->Index();
0376     }
0377     const Standard_Integer aNewIndex = Increment();
0378     aNode = new (this->myAllocator) IndexedDataMapNode (std::forward<TheKeyType>(theKey1), aNewIndex,
0379                                                         std::forward<TheItemType>(theItem), myData1[aHash]);
0380     myData1[aHash]         = aNode;
0381     myData2[aNewIndex - 1] = aNode;
0382     return aNewIndex;
0383   }
0384 
0385   //! Contains
0386   Standard_Boolean Contains (const TheKeyType& theKey1) const
0387   {
0388     IndexedDataMapNode* aNode;
0389     if (lookup(theKey1, aNode))
0390     {
0391       return true;
0392     }
0393     return false;
0394   }
0395 
0396   //! Substitute
0397   void Substitute (const Standard_Integer theIndex,
0398                    const TheKeyType&      theKey1,
0399                    const TheItemType&     theItem)
0400   {
0401     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(),
0402                                   "NCollection_IndexedDataMap::Substitute : "
0403                                   "Index is out of range");
0404 
0405     // check if theKey1 is not already in the map
0406     size_t aHash;
0407     IndexedDataMapNode* aNode;
0408     if (lookup(theKey1, aNode, aHash))
0409     {
0410       if (aNode->Index() != theIndex)
0411       {
0412         throw Standard_DomainError("NCollection_IndexedDataMap::Substitute : "
0413                                    "Attempt to substitute existing key");
0414       }
0415       aNode->Key1() = theKey1;
0416       aNode->ChangeValue() = theItem;
0417       return;
0418     }
0419 
0420     // Find the node for the index I
0421     aNode = (IndexedDataMapNode* )myData2[theIndex - 1];
0422     
0423     // remove the old key
0424     const size_t iK = HashCode (aNode->Key1(), NbBuckets());
0425     IndexedDataMapNode * q = (IndexedDataMapNode *) myData1[iK];
0426     if (q == aNode)
0427       myData1[iK] = (IndexedDataMapNode *)aNode->Next();
0428     else 
0429     {
0430       while (q->Next() != aNode)
0431         q = (IndexedDataMapNode *) q->Next();
0432       q->Next() = aNode->Next();
0433     }
0434 
0435     // update the node
0436     aNode->Key1()  = theKey1;
0437     aNode->ChangeValue() = theItem;
0438     aNode->Next()  = myData1[aHash];
0439     myData1[aHash] = aNode;
0440   }
0441 
0442   //! Swaps two elements with the given indices.
0443   void Swap (const Standard_Integer theIndex1,
0444              const Standard_Integer theIndex2)
0445   {
0446     Standard_OutOfRange_Raise_if (theIndex1 < 1 || theIndex1 > Extent()
0447                                || theIndex2 < 1 || theIndex2 > Extent(), "NCollection_IndexedDataMap::Swap");
0448 
0449     if (theIndex1 == theIndex2)
0450     {
0451       return;
0452     }
0453 
0454     IndexedDataMapNode* aP1 = (IndexedDataMapNode* )myData2[theIndex1 - 1];
0455     IndexedDataMapNode* aP2 = (IndexedDataMapNode* )myData2[theIndex2 - 1];
0456     std::swap (aP1->Index(), aP2->Index());
0457     myData2[theIndex2 - 1] = aP1;
0458     myData2[theIndex1 - 1] = aP2;
0459   }
0460 
0461   //! RemoveLast
0462   void RemoveLast (void)
0463   {
0464     const Standard_Integer aLastIndex = Extent();
0465     Standard_OutOfRange_Raise_if (aLastIndex == 0, "NCollection_IndexedDataMap::RemoveLast");
0466 
0467     // Find the node for the last index and remove it
0468     IndexedDataMapNode* p = (IndexedDataMapNode* )myData2[aLastIndex - 1];
0469     myData2[aLastIndex - 1] = NULL;
0470     
0471     // remove the key
0472     const size_t iK1 = HashCode (p->Key1(), NbBuckets());
0473     IndexedDataMapNode* q = (IndexedDataMapNode *) myData1[iK1];
0474     if (q == p)
0475       myData1[iK1] = (IndexedDataMapNode *) p->Next();
0476     else 
0477     {
0478       while (q->Next() != p) 
0479         q = (IndexedDataMapNode *) q->Next();
0480       q->Next() = p->Next();
0481     }
0482     p->~IndexedDataMapNode();
0483     this->myAllocator->Free(p);
0484     Decrement();
0485   }
0486 
0487   //! Remove the key of the given index.
0488   //! Caution! The index of the last key can be changed.
0489   void RemoveFromIndex(const Standard_Integer theIndex)
0490   {
0491     const Standard_Integer aLastInd = Extent();
0492     Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > aLastInd, "NCollection_IndexedDataMap::Remove");
0493     if (theIndex != aLastInd)
0494     {
0495       Swap (theIndex, aLastInd);
0496     }
0497     RemoveLast();
0498   }
0499 
0500   //! Remove the given key.
0501   //! Caution! The index of the last key can be changed.
0502   void RemoveKey(const TheKeyType& theKey1)
0503   {
0504     Standard_Integer anIndToRemove = FindIndex(theKey1);
0505     if (anIndToRemove > 0) {
0506       RemoveFromIndex(anIndToRemove);
0507     }
0508   }
0509 
0510   //! FindKey
0511   const TheKeyType& FindKey (const Standard_Integer theIndex) const
0512   {
0513     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedDataMap::FindKey");
0514     IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[theIndex - 1];
0515     return aNode->Key1();
0516   }
0517 
0518   //! FindFromIndex
0519   const TheItemType& FindFromIndex (const Standard_Integer theIndex) const
0520   {
0521     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedDataMap::FindFromIndex");
0522     IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[theIndex - 1];
0523     return aNode->Value();
0524   }
0525 
0526   //! operator ()
0527   const TheItemType& operator() (const Standard_Integer theIndex) const { return FindFromIndex (theIndex); }
0528 
0529   //! ChangeFromIndex
0530   TheItemType& ChangeFromIndex (const Standard_Integer theIndex)
0531   {
0532     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedDataMap::ChangeFromIndex");
0533     IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[theIndex - 1];
0534     return aNode->ChangeValue();
0535   }
0536 
0537   //! operator ()
0538   TheItemType& operator() (const Standard_Integer theIndex) { return ChangeFromIndex (theIndex); }
0539 
0540   //! FindIndex
0541   Standard_Integer FindIndex(const TheKeyType& theKey1) const
0542   {
0543     IndexedDataMapNode* aNode;
0544     if (lookup(theKey1, aNode))
0545     {
0546       return aNode->Index();
0547     }
0548     return 0;
0549   }
0550 
0551   //! FindFromKey
0552   const TheItemType& FindFromKey(const TheKeyType& theKey1) const
0553   {
0554     Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_IndexedDataMap::FindFromKey");
0555     IndexedDataMapNode* aNode;
0556     if (lookup(theKey1, aNode))
0557     {
0558       return aNode->Value();
0559     }
0560     throw Standard_NoSuchObject("NCollection_IndexedDataMap::FindFromKey");
0561   }
0562 
0563   //! ChangeFromKey
0564   TheItemType& ChangeFromKey (const TheKeyType& theKey1)
0565   {
0566     Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_IndexedDataMap::ChangeFromKey");
0567     IndexedDataMapNode* aNode;
0568     if (lookup(theKey1, aNode))
0569     {
0570       return aNode->ChangeValue();
0571     }
0572     throw Standard_NoSuchObject("NCollection_IndexedDataMap::ChangeFromKey");
0573   }
0574 
0575   //! Seek returns pointer to Item by Key. Returns
0576   //! NULL if Key was not found.
0577   const TheItemType* Seek(const TheKeyType& theKey1) const
0578   {
0579     return const_cast< NCollection_IndexedDataMap * >( this )->ChangeSeek(theKey1);
0580   }
0581 
0582   //! ChangeSeek returns modifiable pointer to Item by Key. Returns
0583   //! NULL if Key was not found.
0584   TheItemType* ChangeSeek (const TheKeyType& theKey1)
0585   {
0586     IndexedDataMapNode* aNode;
0587     if (lookup(theKey1, aNode))
0588     {
0589       return &aNode->ChangeValue();
0590     }
0591     return nullptr;
0592   }
0593 
0594   //! Find value for key with copying.
0595   //! @return true if key was found
0596   Standard_Boolean FindFromKey (const TheKeyType& theKey1,
0597                                 TheItemType&      theValue) const
0598   {
0599     IndexedDataMapNode* aNode;
0600     if (lookup(theKey1, aNode))
0601     {
0602         theValue = aNode->Value();
0603         return Standard_True;
0604     }
0605     return Standard_False;
0606   }
0607 
0608   //! Clear data. If doReleaseMemory is false then the table of
0609   //! buckets is not released and will be reused.
0610   void Clear(const Standard_Boolean doReleaseMemory = Standard_False)
0611   { Destroy (IndexedDataMapNode::delNode, doReleaseMemory); }
0612 
0613   //! Clear data and reset allocator
0614   void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
0615   { 
0616     Clear(theAllocator != this->myAllocator);
0617     this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
0618                     NCollection_BaseAllocator::CommonBaseAllocator() );
0619   }
0620 
0621   //! Destructor
0622   virtual ~NCollection_IndexedDataMap (void)
0623   { Clear(true); }
0624 
0625   //! Size
0626   Standard_Integer Size(void) const
0627   { return Extent(); }
0628 
0629 protected:
0630 
0631   //! Lookup for particular key in map.
0632   //! @param[in] theKey key to compute hash
0633   //! @param[out] theNode the detected node with equal key. Can be null.
0634   //! @param[out] theHash computed bounded hash code for current key.
0635   //! @return true if key is found
0636   Standard_Boolean lookup(const TheKeyType& theKey, IndexedDataMapNode*& theNode, size_t& theHash) const
0637   {
0638     theHash = HashCode(theKey, NbBuckets());
0639     if (IsEmpty())
0640       return Standard_False; // Not found
0641     for (theNode = (IndexedDataMapNode*)myData1[theHash];
0642          theNode; theNode = (IndexedDataMapNode*)theNode->Next())
0643     {
0644       if (IsEqual(theNode->Key1(), theKey))
0645         return Standard_True;
0646     }
0647     return Standard_False; // Not found
0648   }
0649 
0650   //! Lookup for particular key in map.
0651   //! @param[in] theKey key to compute hash
0652   //! @param[out] theNode the detected node with equal key. Can be null.
0653   //! @return true if key is found
0654   Standard_Boolean lookup(const TheKeyType& theKey, IndexedDataMapNode*& theNode) const
0655   {
0656     if (IsEmpty())
0657       return Standard_False; // Not found
0658     for (theNode = (IndexedDataMapNode*)myData1[HashCode(theKey, NbBuckets())];
0659       theNode; theNode = (IndexedDataMapNode*)theNode->Next())
0660     {
0661       if (IsEqual(theNode->Key1(), theKey))
0662       {
0663         return Standard_True;
0664       }
0665     }
0666     return Standard_False; // Not found
0667   }
0668 
0669   bool IsEqual(const TheKeyType& theKey1,
0670                const TheKeyType& theKey2) const
0671   {
0672     return myHasher(theKey1, theKey2);
0673   }
0674 
0675   size_t HashCode(const TheKeyType& theKey,
0676                   const int theUpperBound) const
0677   {
0678     return myHasher(theKey) % theUpperBound + 1;
0679   }
0680 
0681 protected:
0682 
0683   Hasher myHasher;
0684 };
0685 
0686 #endif