Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-02 08:23:04

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