b311480e |
1 | // Created on: 2002-04-24 |
2 | // Created by: Alexander KARTOMIN (akm) |
3 | // Copyright (c) 2002-2012 OPEN CASCADE SAS |
4 | // |
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. |
9 | // |
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. |
12 | // |
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. |
19 | |
7fd59977 |
20 | #ifndef NCollection_DataMap_HeaderFile |
21 | #define NCollection_DataMap_HeaderFile |
22 | |
23 | #include <NCollection_BaseCollection.hxx> |
24 | #include <NCollection_BaseMap.hxx> |
25 | #include <NCollection_TListNode.hxx> |
26 | |
9991c9c2 |
27 | #include <NCollection_DefaultHasher.hxx> |
28 | |
7fd59977 |
29 | #include <Standard_TypeMismatch.hxx> |
30 | #include <Standard_NoSuchObject.hxx> |
31 | |
7fd59977 |
32 | /** |
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. |
36 | * |
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 : |
41 | * |
42 | * anItem = aMap(aKey); |
43 | * aMap(aKey) = anItem; |
44 | * |
45 | * This analogy has its limit. aMap(aKey) = anItem |
46 | * can be done only if aKey was previously bound to |
47 | * an item in the map. |
48 | */ |
9991c9c2 |
49 | |
50 | template < class TheKeyType, |
51 | class TheItemType, |
52 | class Hasher = NCollection_DefaultHasher<TheKeyType> > class NCollection_DataMap |
53 | |
7fd59977 |
54 | : public NCollection_BaseCollection<TheItemType>, |
55 | public NCollection_BaseMap |
56 | { |
57 | // **************** Adaptation of the TListNode to the DATAmap |
58 | public: |
59 | class DataMapNode : public NCollection_TListNode<TheItemType> |
60 | { |
61 | public: |
62 | //! Constructor with 'Next' |
63 | DataMapNode (const TheKeyType& theKey, |
64 | const TheItemType& theItem, |
65 | NCollection_ListNode* theNext) : |
66 | NCollection_TListNode<TheItemType> (theItem, theNext) |
67 | { myKey = theKey; } |
68 | //! Key |
69 | const TheKeyType& Key (void) const |
70 | { return myKey; } |
71 | |
72 | //! Static deleter to be passed to BaseList |
73 | static void delNode (NCollection_ListNode * theNode, |
74 | Handle(NCollection_BaseAllocator)& theAl) |
75 | { |
76 | ((DataMapNode *) theNode)->~DataMapNode(); |
77 | theAl->Free(theNode); |
78 | } |
79 | |
80 | private: |
81 | TheKeyType myKey; |
82 | }; |
83 | |
84 | public: |
85 | // **************** Implementation of the Iterator interface. |
86 | class Iterator |
87 | : public NCollection_BaseCollection<TheItemType>::Iterator, |
88 | public NCollection_BaseMap::Iterator |
89 | { |
90 | public: |
91 | //! Empty constructor |
92 | Iterator (void) : |
93 | NCollection_BaseMap::Iterator() {} |
94 | //! Constructor |
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 |
99 | { return PMore(); } |
100 | //! Make a step along the collection |
101 | virtual void Next(void) |
102 | { PNext(); } |
103 | //! Value inquiry |
104 | virtual const TheItemType& Value(void) const |
105 | { |
106 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
107 | if (!More()) |
108 | Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::Value"); |
109 | #endif |
110 | return ((DataMapNode *) myNode)->Value(); |
111 | } |
112 | //! Value change access |
113 | virtual TheItemType& ChangeValue(void) const |
114 | { |
115 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
116 | if (!More()) |
117 | Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::ChangeValue"); |
118 | #endif |
119 | return ((DataMapNode *) myNode)->ChangeValue(); |
120 | } |
121 | //! Key |
122 | const TheKeyType& Key (void) const |
123 | { |
124 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
125 | if (!More()) |
126 | Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::Key"); |
127 | #endif |
128 | return ((DataMapNode *) myNode)->Key(); |
129 | } |
7fd59977 |
130 | }; |
131 | |
132 | public: |
133 | // ---------- PUBLIC METHODS ------------ |
134 | |
135 | //! Constructor |
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) {} |
140 | |
141 | //! Copy constructor |
142 | NCollection_DataMap (const NCollection_DataMap& theOther) |
143 | : NCollection_BaseCollection<TheItemType>(theOther.myAllocator), |
144 | NCollection_BaseMap (theOther.NbBuckets(), Standard_True) |
145 | { *this = theOther; } |
146 | |
147 | //! Assign another collection |
148 | virtual void Assign(const NCollection_BaseCollection<TheItemType>& theOther) |
149 | { |
150 | if (this == &theOther) |
151 | return; |
152 | Standard_TypeMismatch::Raise ("NCollection_DataMap::Assign impossible"); |
153 | } |
154 | |
155 | //! = another map |
156 | NCollection_DataMap& operator= (const NCollection_DataMap& theOther) |
157 | { |
158 | if (this == &theOther) |
159 | return *this; |
160 | |
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()); |
166 | return *this; |
167 | } |
168 | |
169 | //! ReSize |
170 | void ReSize (const Standard_Integer N) |
171 | { |
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, |
178 | this->myAllocator)) |
179 | { |
180 | if (myData1) |
181 | { |
182 | DataMapNode** olddata = (DataMapNode**) myData1; |
183 | DataMapNode *p, *q; |
184 | Standard_Integer i,k; |
185 | for (i = 0; i <= NbBuckets(); i++) |
186 | { |
187 | if (olddata[i]) |
188 | { |
189 | p = olddata[i]; |
190 | while (p) |
191 | { |
9991c9c2 |
192 | k = Hasher::HashCode(p->Key(),newBuck); |
7fd59977 |
193 | q = (DataMapNode*) p->Next(); |
194 | p->Next() = newdata[k]; |
195 | newdata[k] = p; |
196 | p = q; |
197 | } |
198 | } |
199 | } |
200 | } |
201 | EndResize(N,newBuck, |
202 | (NCollection_ListNode**&)newdata, |
203 | (NCollection_ListNode**&)dummy, |
204 | this->myAllocator); |
205 | } |
206 | } |
207 | |
208 | //! Bind |
209 | Standard_Boolean Bind (const TheKeyType& theKey, const TheItemType& theItem) |
210 | { |
211 | if (Resizable()) |
212 | ReSize(Extent()); |
213 | DataMapNode** data = (DataMapNode**)myData1; |
9991c9c2 |
214 | Standard_Integer k = Hasher::HashCode (theKey, NbBuckets()); |
7fd59977 |
215 | DataMapNode* p = data[k]; |
216 | while (p) |
217 | { |
9991c9c2 |
218 | if (Hasher::IsEqual(p->Key(), theKey)) |
7fd59977 |
219 | { |
220 | p->ChangeValue() = theItem; |
221 | return Standard_False; |
222 | } |
223 | p = (DataMapNode *) p->Next(); |
224 | } |
225 | data[k] = new (this->myAllocator) DataMapNode (theKey, theItem, data[k]); |
226 | Increment(); |
227 | return Standard_True; |
228 | } |
229 | |
230 | //! IsBound |
231 | Standard_Boolean IsBound(const TheKeyType& K) const |
232 | { |
233 | if (IsEmpty()) |
234 | return Standard_False; |
235 | DataMapNode** data = (DataMapNode**) myData1; |
9991c9c2 |
236 | DataMapNode* p = data[Hasher::HashCode(K,NbBuckets())]; |
7fd59977 |
237 | while (p) |
238 | { |
9991c9c2 |
239 | if (Hasher::IsEqual(p->Key(),K)) |
7fd59977 |
240 | return Standard_True; |
241 | p = (DataMapNode *) p->Next(); |
242 | } |
243 | return Standard_False; |
244 | } |
245 | |
246 | //! UnBind |
247 | Standard_Boolean UnBind(const TheKeyType& K) |
248 | { |
249 | if (IsEmpty()) |
250 | return Standard_False; |
251 | DataMapNode** data = (DataMapNode**) myData1; |
9991c9c2 |
252 | Standard_Integer k = Hasher::HashCode(K,NbBuckets()); |
7fd59977 |
253 | DataMapNode* p = data[k]; |
254 | DataMapNode* q = NULL; |
255 | while (p) |
256 | { |
9991c9c2 |
257 | if (Hasher::IsEqual(p->Key(),K)) |
7fd59977 |
258 | { |
259 | Decrement(); |
260 | if (q) |
261 | q->Next() = p->Next(); |
262 | else |
263 | data[k] = (DataMapNode*) p->Next(); |
264 | p->~DataMapNode(); |
265 | this->myAllocator->Free(p); |
266 | return Standard_True; |
267 | } |
268 | q = p; |
269 | p = (DataMapNode*) p->Next(); |
270 | } |
271 | return Standard_False; |
272 | } |
273 | |
274 | //! Find |
275 | const TheItemType& Find(const TheKeyType& theKey) const |
276 | { |
277 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
278 | if (IsEmpty()) |
279 | Standard_NoSuchObject::Raise ("NCollection_DataMap::Find"); |
280 | #endif |
9991c9c2 |
281 | DataMapNode* p = (DataMapNode*) myData1[Hasher::HashCode(theKey,NbBuckets())]; |
7fd59977 |
282 | while (p) |
283 | { |
9991c9c2 |
284 | if (Hasher::IsEqual(p->Key(),theKey)) |
7fd59977 |
285 | return p->Value(); |
286 | p = (DataMapNode*) p->Next(); |
287 | } |
288 | Standard_NoSuchObject::Raise("NCollection_DataMap::Find"); |
289 | return p->Value(); // This for compiler |
290 | } |
291 | |
a174a3c5 |
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 |
296 | { |
297 | if (IsEmpty()) |
298 | { |
299 | return Standard_False; |
300 | } |
301 | |
302 | for (DataMapNode* aNodeIter = (DataMapNode* )myData1[Hasher::HashCode (theKey, NbBuckets())]; |
303 | aNodeIter != NULL; |
304 | aNodeIter = (DataMapNode* )aNodeIter->Next()) |
305 | { |
306 | if (Hasher::IsEqual (aNodeIter->Key(), theKey)) |
307 | { |
308 | theValue = aNodeIter->Value(); |
309 | return Standard_True; |
310 | } |
311 | } |
312 | return Standard_False; |
313 | } |
314 | |
7fd59977 |
315 | //! operator () |
316 | const TheItemType& operator() (const TheKeyType& theKey) const |
317 | { return Find(theKey); } |
318 | |
319 | //! ChangeFind |
320 | TheItemType& ChangeFind (const TheKeyType& theKey) |
321 | { |
322 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
323 | if (IsEmpty()) |
324 | Standard_NoSuchObject::Raise ("NCollection_DataMap::Find"); |
325 | #endif |
9991c9c2 |
326 | DataMapNode* p = (DataMapNode*) myData1[Hasher::HashCode(theKey,NbBuckets())]; |
7fd59977 |
327 | while (p) |
328 | { |
9991c9c2 |
329 | if (Hasher::IsEqual(p->Key(),theKey)) |
7fd59977 |
330 | return p->ChangeValue(); |
331 | p = (DataMapNode*) p->Next(); |
332 | } |
333 | Standard_NoSuchObject::Raise("NCollection_DataMap::Find"); |
334 | return p->ChangeValue(); // This for compiler |
335 | } |
336 | |
337 | //! operator () |
338 | TheItemType& operator() (const TheKeyType& theKey) |
339 | { return ChangeFind(theKey); } |
340 | |
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); } |
345 | |
346 | //! Clear data and reset allocator |
347 | void Clear (const Handle(NCollection_BaseAllocator)& theAllocator) |
348 | { |
349 | Clear(); |
350 | this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator : |
351 | NCollection_BaseAllocator::CommonBaseAllocator() ); |
352 | } |
353 | |
354 | //! Destructor |
355 | ~NCollection_DataMap (void) |
356 | { Clear(); } |
357 | |
358 | //! Size |
359 | virtual Standard_Integer Size(void) const |
360 | { return Extent(); } |
361 | |
362 | private: |
363 | // ----------- PRIVATE METHODS ----------- |
364 | |
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)); } |
369 | |
370 | }; |
371 | |
7fd59977 |
372 | #endif |
9991c9c2 |
373 | |