Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:47:42

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_DataMap_HeaderFile
0017 #define NCollection_DataMap_HeaderFile
0018 
0019 #include <NCollection_BaseMap.hxx>
0020 #include <NCollection_TListNode.hxx>
0021 #include <NCollection_StlIterator.hxx>
0022 #include <NCollection_DefaultHasher.hxx>
0023 
0024 #include <Standard_TypeMismatch.hxx>
0025 #include <Standard_NoSuchObject.hxx>
0026 
0027 /**
0028 * Purpose:     The DataMap is a Map to store keys with associated
0029 *              Items. See Map  from NCollection for  a discussion
0030 *              about the number of buckets.
0031 *
0032 *              The DataMap can be seen as an extended array where
0033 *              the Keys  are the   indices.  For this reason  the
0034 *              operator () is defined on DataMap to fetch an Item
0035 *              from a Key. So the following syntax can be used :
0036 *
0037 *              anItem = aMap(aKey);
0038 *              aMap(aKey) = anItem;
0039 *
0040 *              This analogy has its  limit.   aMap(aKey) = anItem
0041 *              can  be done only  if aKey was previously bound to
0042 *              an item in the map.
0043 */              
0044 
0045 template < class TheKeyType, 
0046            class TheItemType, 
0047            class Hasher = NCollection_DefaultHasher<TheKeyType> >
0048 class NCollection_DataMap : public NCollection_BaseMap
0049 {
0050 public:
0051   //! STL-compliant typedef for key type
0052   typedef TheKeyType key_type;
0053   //! STL-compliant typedef for value type
0054   typedef TheItemType value_type;
0055 
0056 public:
0057   // **************** Adaptation of the TListNode to the DATAmap
0058   class DataMapNode : public NCollection_TListNode<TheItemType>
0059   {
0060   public:
0061     //! Constructor with 'Next'
0062     DataMapNode (const TheKeyType&     theKey, 
0063                  const TheItemType&    theItem, 
0064                  NCollection_ListNode* theNext) :
0065       NCollection_TListNode<TheItemType> (theItem, theNext),
0066       myKey(theKey)
0067     {}
0068 
0069     //! Key
0070     const TheKeyType& Key (void) const
0071     { return myKey; }
0072     
0073     //! Static deleter to be passed to BaseMap
0074     static void delNode (NCollection_ListNode * theNode, 
0075                          Handle(NCollection_BaseAllocator)& theAl)
0076     {
0077       ((DataMapNode *) theNode)->~DataMapNode();
0078       theAl->Free(theNode);
0079     }
0080 
0081   private:
0082     TheKeyType    myKey;
0083   };
0084 
0085  public:
0086   // **************** Implementation of the Iterator interface.
0087   class Iterator : public NCollection_BaseMap::Iterator
0088   {
0089   public:
0090     //! Empty constructor
0091     Iterator (void) :
0092       NCollection_BaseMap::Iterator() {}
0093     //! Constructor
0094     Iterator (const NCollection_DataMap& theMap) :
0095       NCollection_BaseMap::Iterator(theMap) {}
0096     //! Query if the end of collection is reached by iterator
0097     Standard_Boolean More(void) const
0098     { return PMore(); }
0099     //! Make a step along the collection
0100     void Next(void)
0101     { PNext(); }
0102     //! Value inquiry
0103     const TheItemType& Value(void) const
0104     {  
0105       Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::Value");  
0106       return ((DataMapNode *) myNode)->Value();
0107     }
0108     //! Value change access
0109     TheItemType& ChangeValue(void) const
0110     {  
0111       Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::ChangeValue");  
0112       return ((DataMapNode *) myNode)->ChangeValue();
0113     }
0114     //! Key
0115     const TheKeyType& Key (void) const
0116     { 
0117       Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::Key");  
0118       return ((DataMapNode *) myNode)->Key();
0119     }
0120   };
0121   
0122   //! Shorthand for a regular iterator type.
0123   typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
0124 
0125   //! Shorthand for a constant iterator type.
0126   typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true> const_iterator;
0127 
0128   //! Returns an iterator pointing to the first element in the map.
0129   iterator begin() const { return Iterator (*this); }
0130 
0131   //! Returns an iterator referring to the past-the-end element in the map.
0132   iterator end() const { return Iterator(); }
0133 
0134   //! Returns a const iterator pointing to the first element in the map.
0135   const_iterator cbegin() const { return Iterator (*this); }
0136 
0137   //! Returns a const iterator referring to the past-the-end element in the map.
0138   const_iterator cend() const { return Iterator(); }
0139 
0140  public:
0141   // ---------- PUBLIC METHODS ------------
0142 
0143   //! Empty Constructor.
0144   NCollection_DataMap() : NCollection_BaseMap (1, Standard_True, Handle(NCollection_BaseAllocator)()) {}
0145 
0146   //! Constructor
0147   explicit NCollection_DataMap (const Standard_Integer theNbBuckets,
0148                                 const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
0149   : NCollection_BaseMap (theNbBuckets, Standard_True, theAllocator) {}
0150 
0151   //! Copy constructor
0152   NCollection_DataMap (const NCollection_DataMap& theOther)
0153     : NCollection_BaseMap (theOther.NbBuckets(), Standard_True, theOther.myAllocator) 
0154   { *this = theOther; }
0155 
0156   //! Exchange the content of two maps without re-allocations.
0157   //! Notice that allocators will be swapped as well!
0158   void Exchange (NCollection_DataMap& theOther)
0159   {
0160     this->exchangeMapsData (theOther);
0161   }
0162 
0163   //! Assignment.
0164   //! This method does not change the internal allocator.
0165   NCollection_DataMap& Assign (const NCollection_DataMap& theOther)
0166   { 
0167     if (this == &theOther)
0168       return *this;
0169 
0170     Clear();
0171     Standard_Integer anExt = theOther.Extent();
0172     if (anExt)
0173     {
0174       ReSize (anExt-1);
0175       Iterator anIter(theOther);
0176       for (; anIter.More(); anIter.Next())
0177         Bind (anIter.Key(), anIter.Value());
0178     }
0179     return *this;
0180   }
0181 
0182   //! Assignment operator
0183   NCollection_DataMap& operator= (const NCollection_DataMap& theOther)
0184   { 
0185     return Assign (theOther);
0186   }
0187 
0188   //! ReSize
0189   void ReSize (const Standard_Integer N)
0190   {
0191     NCollection_ListNode** newdata = NULL;
0192     NCollection_ListNode** dummy   = NULL;
0193     Standard_Integer newBuck;
0194     if (BeginResize (N, newBuck, newdata, dummy))
0195     {
0196       if (myData1) 
0197       {
0198         DataMapNode** olddata = (DataMapNode**) myData1;
0199         DataMapNode *p, *q;
0200         Standard_Integer i,k;
0201         for (i = 0; i <= NbBuckets(); i++) 
0202         {
0203           if (olddata[i]) 
0204           {
0205             p = olddata[i];
0206             while (p) 
0207             {
0208               k = Hasher::HashCode(p->Key(),newBuck);
0209               q = (DataMapNode*) p->Next();
0210               p->Next() = newdata[k];
0211               newdata[k] = p;
0212               p = q;
0213             }
0214           }
0215         }
0216       }
0217       EndResize (N, newBuck, newdata, dummy);
0218     }
0219   }
0220 
0221   //! Bind binds Item to Key in map.
0222   //! @param theKey  key to add/update
0223   //! @param theItem new item; overrides value previously bound to the key, if any
0224   //! @return Standard_True if Key was not bound already
0225   Standard_Boolean Bind (const TheKeyType& theKey, const TheItemType& theItem)
0226   {
0227     if (Resizable()) 
0228       ReSize(Extent());
0229     DataMapNode** data = (DataMapNode**)myData1;
0230     Standard_Integer k = Hasher::HashCode (theKey, NbBuckets());
0231     DataMapNode* p = data[k];
0232     while (p) 
0233     {
0234       if (Hasher::IsEqual(p->Key(), theKey))
0235       {
0236         p->ChangeValue() = theItem;
0237         return Standard_False;
0238       }
0239       p = (DataMapNode *) p->Next();
0240     }
0241     data[k] = new (this->myAllocator) DataMapNode (theKey, theItem, data[k]);
0242     Increment();
0243     return Standard_True;
0244   }
0245 
0246   //! Bound binds Item to Key in map. Returns modifiable Item 
0247   TheItemType* Bound (const TheKeyType& theKey, const TheItemType& theItem)
0248   {
0249     if (Resizable()) 
0250       ReSize(Extent());
0251     DataMapNode** data = (DataMapNode**)myData1;
0252     Standard_Integer k = Hasher::HashCode (theKey, NbBuckets());
0253     DataMapNode* p = data[k];
0254     while (p)
0255     {
0256       if (Hasher::IsEqual(p->Key(), theKey))
0257       {
0258         p->ChangeValue() = theItem;
0259         return &p->ChangeValue();
0260       }
0261       p = (DataMapNode*)p->Next();
0262     }
0263     data[k] = new (this->myAllocator) DataMapNode (theKey, theItem, data[k]);
0264     Increment();
0265     return &data[k]->ChangeValue();
0266   }
0267 
0268   //! IsBound
0269   Standard_Boolean IsBound(const TheKeyType& theKey) const
0270   {
0271     DataMapNode* p;
0272     return lookup(theKey, p);
0273   }
0274 
0275   //! UnBind removes Item Key pair from map
0276   Standard_Boolean UnBind(const TheKeyType& theKey)
0277   {
0278     if (IsEmpty()) 
0279       return Standard_False;
0280     DataMapNode** data = (DataMapNode**) myData1;
0281     Standard_Integer k = Hasher::HashCode(theKey,NbBuckets());
0282     DataMapNode* p = data[k];
0283     DataMapNode* q = NULL;
0284     while (p) 
0285     {
0286       if (Hasher::IsEqual(p->Key(), theKey))
0287       {
0288         Decrement();
0289         if (q) 
0290           q->Next() = p->Next();
0291         else
0292           data[k] = (DataMapNode*) p->Next();
0293         p->~DataMapNode();
0294         this->myAllocator->Free(p);
0295         return Standard_True;
0296       }
0297       q = p;
0298       p = (DataMapNode*) p->Next();
0299     }
0300     return Standard_False;
0301   }
0302 
0303   //! Seek returns pointer to Item by Key. Returns
0304   //! NULL is Key was not bound.
0305   const TheItemType* Seek(const TheKeyType& theKey) const
0306   {
0307     DataMapNode* p = 0;
0308     if (!lookup(theKey, p))
0309       return 0L;
0310     return &p->Value();
0311   }
0312 
0313   //! Find returns the Item for Key. Raises if Key was not bound
0314   const TheItemType& Find(const TheKeyType& theKey) const
0315   {
0316     DataMapNode* p = 0;
0317     if (!lookup(theKey, p))
0318       throw Standard_NoSuchObject("NCollection_DataMap::Find");
0319     return p->Value();
0320   }
0321 
0322   //! Find Item for key with copying.
0323   //! @return true if key was found
0324   Standard_Boolean Find (const TheKeyType& theKey,
0325                          TheItemType&      theValue) const
0326   {
0327     DataMapNode* p = 0;
0328     if (!lookup(theKey, p))
0329       return Standard_False;
0330 
0331     theValue = p->Value();
0332     return Standard_True;
0333   }
0334 
0335   //! operator ()
0336   const TheItemType& operator() (const TheKeyType& theKey) const
0337   { return Find(theKey); }
0338 
0339   //! ChangeSeek returns modifiable pointer to Item by Key. Returns
0340   //! NULL is Key was not bound.
0341   TheItemType* ChangeSeek(const TheKeyType& theKey)
0342   {
0343     DataMapNode* p = 0;
0344     if (!lookup(theKey, p))
0345       return 0L;
0346     return &p->ChangeValue();
0347   }
0348 
0349   //! ChangeFind returns mofifiable Item by Key. Raises if Key was not bound
0350   TheItemType& ChangeFind (const TheKeyType& theKey)
0351   {
0352     DataMapNode* p = 0;
0353     if (!lookup(theKey, p))
0354       throw Standard_NoSuchObject("NCollection_DataMap::Find");
0355     return p->ChangeValue();
0356   }
0357 
0358   //! operator ()
0359   TheItemType& operator() (const TheKeyType& theKey)
0360   { return ChangeFind(theKey); }
0361 
0362   //! Clear data. If doReleaseMemory is false then the table of
0363   //! buckets is not released and will be reused.
0364   void Clear(const Standard_Boolean doReleaseMemory = Standard_True)
0365   { Destroy (DataMapNode::delNode, doReleaseMemory); }
0366 
0367   //! Clear data and reset allocator
0368   void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
0369   { 
0370     Clear();
0371     this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
0372                     NCollection_BaseAllocator::CommonBaseAllocator() );
0373   }
0374 
0375   //! Destructor
0376   virtual ~NCollection_DataMap (void)
0377   { Clear(); }
0378 
0379   //! Size
0380   Standard_Integer Size(void) const
0381   { return Extent(); }
0382 
0383   
0384  protected:
0385   // ---------- PROTECTED METHODS ----------
0386   //! Lookup for particular key in map. Returns true if key is found and
0387   //! thepNode points to binded node. Returns false if key is not found,
0388   //! thehNode value is this case is not usable.
0389   Standard_Boolean lookup(const TheKeyType& theKey,DataMapNode*& thepNode) const
0390   {
0391     if (IsEmpty())
0392       return Standard_False; // Not found
0393     for (thepNode = (DataMapNode*)myData1[Hasher::HashCode(theKey, NbBuckets())];
0394          thepNode; thepNode = (DataMapNode*)thepNode->Next())
0395     {
0396       if (Hasher::IsEqual(thepNode->Key(), theKey)) 
0397         return Standard_True;
0398     }
0399     return Standard_False; // Not found
0400   }
0401 
0402 };
0403 
0404 #endif
0405