1 // Created on: 2002-04-24
2 // Created by: Alexander KARTOMIN (akm)
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef NCollection_DataMap_HeaderFile
17 #define NCollection_DataMap_HeaderFile
19 #include <NCollection_BaseCollection.hxx>
20 #include <NCollection_BaseMap.hxx>
21 #include <NCollection_TListNode.hxx>
22 #include <NCollection_StlIterator.hxx>
23 #include <NCollection_DefaultHasher.hxx>
25 #include <Standard_TypeMismatch.hxx>
26 #include <Standard_NoSuchObject.hxx>
29 * Purpose: The DataMap is a Map to store keys with associated
30 * Items. See Map from NCollection for a discussion
31 * about the number of buckets.
33 * The DataMap can be seen as an extended array where
34 * the Keys are the indices. For this reason the
35 * operator () is defined on DataMap to fetch an Item
36 * from a Key. So the following syntax can be used :
38 * anItem = aMap(aKey);
39 * aMap(aKey) = anItem;
41 * This analogy has its limit. aMap(aKey) = anItem
42 * can be done only if aKey was previously bound to
46 template < class TheKeyType,
48 class Hasher = NCollection_DefaultHasher<TheKeyType> > class NCollection_DataMap
50 : public NCollection_BaseCollection<TheItemType>,
51 public NCollection_BaseMap
53 // **************** Adaptation of the TListNode to the DATAmap
55 class DataMapNode : public NCollection_TListNode<TheItemType>
58 //! Constructor with 'Next'
59 DataMapNode (const TheKeyType& theKey,
60 const TheItemType& theItem,
61 NCollection_ListNode* theNext) :
62 NCollection_TListNode<TheItemType> (theItem, theNext)
65 const TheKeyType& Key (void) const
68 //! Static deleter to be passed to BaseList
69 static void delNode (NCollection_ListNode * theNode,
70 Handle(NCollection_BaseAllocator)& theAl)
72 ((DataMapNode *) theNode)->~DataMapNode();
81 // **************** Implementation of the Iterator interface.
83 : public NCollection_BaseCollection<TheItemType>::Iterator,
84 public NCollection_BaseMap::Iterator
89 NCollection_BaseMap::Iterator() {}
91 Iterator (const NCollection_DataMap& theMap) :
92 NCollection_BaseMap::Iterator(theMap) {}
93 //! Query if the end of collection is reached by iterator
94 virtual Standard_Boolean More(void) const
96 //! Make a step along the collection
97 virtual void Next(void)
100 virtual const TheItemType& Value(void) const
102 #if !defined No_Exception && !defined No_Standard_NoSuchObject
104 Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::Value");
106 return ((DataMapNode *) myNode)->Value();
108 //! Value change access
109 virtual TheItemType& ChangeValue(void) const
111 #if !defined No_Exception && !defined No_Standard_NoSuchObject
113 Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::ChangeValue");
115 return ((DataMapNode *) myNode)->ChangeValue();
118 const TheKeyType& Key (void) const
120 #if !defined No_Exception && !defined No_Standard_NoSuchObject
122 Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::Key");
124 return ((DataMapNode *) myNode)->Key();
128 //! Shorthand for a regular iterator type.
129 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
131 //! Shorthand for a constant iterator type.
132 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true> const_iterator;
134 //! Returns an iterator pointing to the first element in the map.
135 iterator begin() const { return Iterator (*this); }
137 //! Returns an iterator referring to the past-the-end element in the map.
138 iterator end() const { return Iterator(); }
140 //! Returns a const iterator pointing to the first element in the map.
141 const_iterator cbegin() const { return Iterator (*this); }
143 //! Returns a const iterator referring to the past-the-end element in the map.
144 const_iterator cend() const { return Iterator(); }
147 // ---------- PUBLIC METHODS ------------
150 NCollection_DataMap (const Standard_Integer NbBuckets=1,
151 const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
152 : NCollection_BaseCollection<TheItemType>(theAllocator),
153 NCollection_BaseMap (NbBuckets, Standard_True) {}
156 NCollection_DataMap (const NCollection_DataMap& theOther)
157 : NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
158 NCollection_BaseMap (theOther.NbBuckets(), Standard_True)
159 { *this = theOther; }
161 //! Assign another collection
162 virtual void Assign(const NCollection_BaseCollection<TheItemType>& theOther)
164 if (this == &theOther)
166 Standard_TypeMismatch::Raise ("NCollection_DataMap::Assign impossible");
169 //! Exchange the content of two maps without re-allocations.
170 //! Notice that allocators will be swapped as well!
171 void Exchange (NCollection_DataMap& theOther)
173 this->exchangeAllocators (theOther);
174 this->exchangeMapsData (theOther);
178 NCollection_DataMap& operator= (const NCollection_DataMap& theOther)
180 if (this == &theOther)
183 Clear(theOther.myAllocator);
184 ReSize (theOther.Extent()-1);
185 Iterator anIter(theOther);
186 for (; anIter.More(); anIter.Next())
187 Bind (anIter.Key(), anIter.Value());
192 void ReSize (const Standard_Integer N)
194 NCollection_ListNode** newdata = NULL;
195 NCollection_ListNode** dummy = NULL;
196 Standard_Integer newBuck;
197 if (BeginResize (N, newBuck, newdata, dummy, this->myAllocator))
201 DataMapNode** olddata = (DataMapNode**) myData1;
203 Standard_Integer i,k;
204 for (i = 0; i <= NbBuckets(); i++)
211 k = Hasher::HashCode(p->Key(),newBuck);
212 q = (DataMapNode*) p->Next();
213 p->Next() = newdata[k];
220 EndResize (N, newBuck, newdata, dummy, this->myAllocator);
225 Standard_Boolean Bind (const TheKeyType& theKey, const TheItemType& theItem)
229 DataMapNode** data = (DataMapNode**)myData1;
230 Standard_Integer k = Hasher::HashCode (theKey, NbBuckets());
231 DataMapNode* p = data[k];
234 if (Hasher::IsEqual(p->Key(), theKey))
236 p->ChangeValue() = theItem;
237 return Standard_False;
239 p = (DataMapNode *) p->Next();
241 data[k] = new (this->myAllocator) DataMapNode (theKey, theItem, data[k]);
243 return Standard_True;
247 Standard_Boolean IsBound(const TheKeyType& K) const
250 return Standard_False;
251 DataMapNode** data = (DataMapNode**) myData1;
252 DataMapNode* p = data[Hasher::HashCode(K,NbBuckets())];
255 if (Hasher::IsEqual(p->Key(),K))
256 return Standard_True;
257 p = (DataMapNode *) p->Next();
259 return Standard_False;
263 Standard_Boolean UnBind(const TheKeyType& K)
266 return Standard_False;
267 DataMapNode** data = (DataMapNode**) myData1;
268 Standard_Integer k = Hasher::HashCode(K,NbBuckets());
269 DataMapNode* p = data[k];
270 DataMapNode* q = NULL;
273 if (Hasher::IsEqual(p->Key(),K))
277 q->Next() = p->Next();
279 data[k] = (DataMapNode*) p->Next();
281 this->myAllocator->Free(p);
282 return Standard_True;
285 p = (DataMapNode*) p->Next();
287 return Standard_False;
291 const TheItemType& Find(const TheKeyType& theKey) const
293 #if !defined No_Exception && !defined No_Standard_NoSuchObject
295 Standard_NoSuchObject::Raise ("NCollection_DataMap::Find");
297 DataMapNode* p = (DataMapNode*) myData1[Hasher::HashCode(theKey,NbBuckets())];
300 if (Hasher::IsEqual(p->Key(),theKey))
302 p = (DataMapNode*) p->Next();
304 Standard_NoSuchObject::Raise("NCollection_DataMap::Find");
305 return p->Value(); // This for compiler
308 //! Find value for key with copying.
309 //! @return true if key was found
310 Standard_Boolean Find (const TheKeyType& theKey,
311 TheItemType& theValue) const
315 return Standard_False;
318 for (DataMapNode* aNodeIter = (DataMapNode* )myData1[Hasher::HashCode (theKey, NbBuckets())];
320 aNodeIter = (DataMapNode* )aNodeIter->Next())
322 if (Hasher::IsEqual (aNodeIter->Key(), theKey))
324 theValue = aNodeIter->Value();
325 return Standard_True;
328 return Standard_False;
332 const TheItemType& operator() (const TheKeyType& theKey) const
333 { return Find(theKey); }
336 TheItemType& ChangeFind (const TheKeyType& theKey)
338 #if !defined No_Exception && !defined No_Standard_NoSuchObject
340 Standard_NoSuchObject::Raise ("NCollection_DataMap::Find");
342 DataMapNode* p = (DataMapNode*) myData1[Hasher::HashCode(theKey,NbBuckets())];
345 if (Hasher::IsEqual(p->Key(),theKey))
346 return p->ChangeValue();
347 p = (DataMapNode*) p->Next();
349 Standard_NoSuchObject::Raise("NCollection_DataMap::Find");
350 return p->ChangeValue(); // This for compiler
354 TheItemType& operator() (const TheKeyType& theKey)
355 { return ChangeFind(theKey); }
357 //! Clear data. If doReleaseMemory is false then the table of
358 //! buckets is not released and will be reused.
359 void Clear(const Standard_Boolean doReleaseMemory = Standard_True)
360 { Destroy (DataMapNode::delNode, this->myAllocator, doReleaseMemory); }
362 //! Clear data and reset allocator
363 void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
366 this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
367 NCollection_BaseAllocator::CommonBaseAllocator() );
371 ~NCollection_DataMap (void)
375 virtual Standard_Integer Size(void) const
379 // ----------- PRIVATE METHODS -----------
381 //! Creates Iterator for use on BaseCollection
382 virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator&
383 CreateIterator(void) const
384 { return *(new (this->IterAllocator()) Iterator(*this)); }