1 // Created on: 2002-04-24
2 // Created by: Alexander KARTOMIN (akm)
3 // Copyright (c) 2002-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
20 #ifndef NCollection_DataMap_HeaderFile
21 #define NCollection_DataMap_HeaderFile
23 #include <NCollection_BaseCollection.hxx>
24 #include <NCollection_BaseMap.hxx>
25 #include <NCollection_TListNode.hxx>
27 #include <NCollection_DefaultHasher.hxx>
29 #include <Standard_TypeMismatch.hxx>
30 #include <Standard_NoSuchObject.hxx>
33 * Purpose: The DataMap is a Map to store keys with associated
34 * Items. See Map from NCollection for a discussion
35 * about the number of buckets.
37 * The DataMap can be seen as an extended array where
38 * the Keys are the indices. For this reason the
39 * operator () is defined on DataMap to fetch an Item
40 * from a Key. So the following syntax can be used :
42 * anItem = aMap(aKey);
43 * aMap(aKey) = anItem;
45 * This analogy has its limit. aMap(aKey) = anItem
46 * can be done only if aKey was previously bound to
50 template < class TheKeyType,
52 class Hasher = NCollection_DefaultHasher<TheKeyType> > class NCollection_DataMap
54 : public NCollection_BaseCollection<TheItemType>,
55 public NCollection_BaseMap
57 // **************** Adaptation of the TListNode to the DATAmap
59 class DataMapNode : public NCollection_TListNode<TheItemType>
62 //! Constructor with 'Next'
63 DataMapNode (const TheKeyType& theKey,
64 const TheItemType& theItem,
65 NCollection_ListNode* theNext) :
66 NCollection_TListNode<TheItemType> (theItem, theNext)
69 const TheKeyType& Key (void) const
72 //! Static deleter to be passed to BaseList
73 static void delNode (NCollection_ListNode * theNode,
74 Handle(NCollection_BaseAllocator)& theAl)
76 ((DataMapNode *) theNode)->~DataMapNode();
85 // **************** Implementation of the Iterator interface.
87 : public NCollection_BaseCollection<TheItemType>::Iterator,
88 public NCollection_BaseMap::Iterator
93 NCollection_BaseMap::Iterator() {}
95 Iterator (const NCollection_DataMap& theMap) :
96 NCollection_BaseMap::Iterator(theMap) {}
97 //! Query if the end of collection is reached by iterator
98 virtual Standard_Boolean More(void) const
100 //! Make a step along the collection
101 virtual void Next(void)
104 virtual const TheItemType& Value(void) const
106 #if !defined No_Exception && !defined No_Standard_NoSuchObject
108 Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::Value");
110 return ((DataMapNode *) myNode)->Value();
112 //! Value change access
113 virtual TheItemType& ChangeValue(void) const
115 #if !defined No_Exception && !defined No_Standard_NoSuchObject
117 Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::ChangeValue");
119 return ((DataMapNode *) myNode)->ChangeValue();
122 const TheKeyType& Key (void) const
124 #if !defined No_Exception && !defined No_Standard_NoSuchObject
126 Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::Key");
128 return ((DataMapNode *) myNode)->Key();
133 // ---------- PUBLIC METHODS ------------
136 NCollection_DataMap (const Standard_Integer NbBuckets=1,
137 const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
138 : NCollection_BaseCollection<TheItemType>(theAllocator),
139 NCollection_BaseMap (NbBuckets, Standard_True) {}
142 NCollection_DataMap (const NCollection_DataMap& theOther)
143 : NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
144 NCollection_BaseMap (theOther.NbBuckets(), Standard_True)
145 { *this = theOther; }
147 //! Assign another collection
148 virtual void Assign(const NCollection_BaseCollection<TheItemType>& theOther)
150 if (this == &theOther)
152 Standard_TypeMismatch::Raise ("NCollection_DataMap::Assign impossible");
156 NCollection_DataMap& operator= (const NCollection_DataMap& theOther)
158 if (this == &theOther)
161 Clear(theOther.myAllocator);
162 ReSize (theOther.Extent()-1);
163 Iterator anIter(theOther);
164 for (; anIter.More(); anIter.Next())
165 Bind (anIter.Key(), anIter.Value());
170 void ReSize (const Standard_Integer N)
172 DataMapNode** newdata = NULL;
173 DataMapNode** dummy = NULL;
174 Standard_Integer newBuck;
175 if (BeginResize (N, newBuck,
176 (NCollection_ListNode**&)newdata,
177 (NCollection_ListNode**&)dummy,
182 DataMapNode** olddata = (DataMapNode**) myData1;
184 Standard_Integer i,k;
185 for (i = 0; i <= NbBuckets(); i++)
192 k = Hasher::HashCode(p->Key(),newBuck);
193 q = (DataMapNode*) p->Next();
194 p->Next() = newdata[k];
202 (NCollection_ListNode**&)newdata,
203 (NCollection_ListNode**&)dummy,
209 Standard_Boolean Bind (const TheKeyType& theKey, const TheItemType& theItem)
213 DataMapNode** data = (DataMapNode**)myData1;
214 Standard_Integer k = Hasher::HashCode (theKey, NbBuckets());
215 DataMapNode* p = data[k];
218 if (Hasher::IsEqual(p->Key(), theKey))
220 p->ChangeValue() = theItem;
221 return Standard_False;
223 p = (DataMapNode *) p->Next();
225 data[k] = new (this->myAllocator) DataMapNode (theKey, theItem, data[k]);
227 return Standard_True;
231 Standard_Boolean IsBound(const TheKeyType& K) const
234 return Standard_False;
235 DataMapNode** data = (DataMapNode**) myData1;
236 DataMapNode* p = data[Hasher::HashCode(K,NbBuckets())];
239 if (Hasher::IsEqual(p->Key(),K))
240 return Standard_True;
241 p = (DataMapNode *) p->Next();
243 return Standard_False;
247 Standard_Boolean UnBind(const TheKeyType& K)
250 return Standard_False;
251 DataMapNode** data = (DataMapNode**) myData1;
252 Standard_Integer k = Hasher::HashCode(K,NbBuckets());
253 DataMapNode* p = data[k];
254 DataMapNode* q = NULL;
257 if (Hasher::IsEqual(p->Key(),K))
261 q->Next() = p->Next();
263 data[k] = (DataMapNode*) p->Next();
265 this->myAllocator->Free(p);
266 return Standard_True;
269 p = (DataMapNode*) p->Next();
271 return Standard_False;
275 const TheItemType& Find(const TheKeyType& theKey) const
277 #if !defined No_Exception && !defined No_Standard_NoSuchObject
279 Standard_NoSuchObject::Raise ("NCollection_DataMap::Find");
281 DataMapNode* p = (DataMapNode*) myData1[Hasher::HashCode(theKey,NbBuckets())];
284 if (Hasher::IsEqual(p->Key(),theKey))
286 p = (DataMapNode*) p->Next();
288 Standard_NoSuchObject::Raise("NCollection_DataMap::Find");
289 return p->Value(); // This for compiler
292 //! Find value for key with copying.
293 //! @return true if key was found
294 Standard_Boolean Find (const TheKeyType& theKey,
295 TheItemType& theValue) const
299 return Standard_False;
302 for (DataMapNode* aNodeIter = (DataMapNode* )myData1[Hasher::HashCode (theKey, NbBuckets())];
304 aNodeIter = (DataMapNode* )aNodeIter->Next())
306 if (Hasher::IsEqual (aNodeIter->Key(), theKey))
308 theValue = aNodeIter->Value();
309 return Standard_True;
312 return Standard_False;
316 const TheItemType& operator() (const TheKeyType& theKey) const
317 { return Find(theKey); }
320 TheItemType& ChangeFind (const TheKeyType& theKey)
322 #if !defined No_Exception && !defined No_Standard_NoSuchObject
324 Standard_NoSuchObject::Raise ("NCollection_DataMap::Find");
326 DataMapNode* p = (DataMapNode*) myData1[Hasher::HashCode(theKey,NbBuckets())];
329 if (Hasher::IsEqual(p->Key(),theKey))
330 return p->ChangeValue();
331 p = (DataMapNode*) p->Next();
333 Standard_NoSuchObject::Raise("NCollection_DataMap::Find");
334 return p->ChangeValue(); // This for compiler
338 TheItemType& operator() (const TheKeyType& theKey)
339 { return ChangeFind(theKey); }
341 //! Clear data. If doReleaseMemory is false then the table of
342 //! buckets is not released and will be reused.
343 void Clear(const Standard_Boolean doReleaseMemory = Standard_True)
344 { Destroy (DataMapNode::delNode, this->myAllocator, doReleaseMemory); }
346 //! Clear data and reset allocator
347 void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
350 this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
351 NCollection_BaseAllocator::CommonBaseAllocator() );
355 ~NCollection_DataMap (void)
359 virtual Standard_Integer Size(void) const
363 // ----------- PRIVATE METHODS -----------
365 //! Creates Iterator for use on BaseCollection
366 virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator&
367 CreateIterator(void) const
368 { return *(new (this->IterAllocator()) Iterator(*this)); }