b311480e |
1 | // Created on: 2002-04-24 |
2 | // Created by: Alexander KARTOMIN (akm) |
973c2be1 |
3 | // Copyright (c) 2002-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
7fd59977 |
15 | |
16 | #ifndef NCollection_IndexedDataMap_HeaderFile |
17 | #define NCollection_IndexedDataMap_HeaderFile |
18 | |
19 | #include <NCollection_BaseCollection.hxx> |
20 | #include <NCollection_BaseMap.hxx> |
21 | #include <NCollection_TListNode.hxx> |
22 | #include <Standard_TypeMismatch.hxx> |
23 | #include <Standard_NoSuchObject.hxx> |
9991c9c2 |
24 | |
25 | #include <NCollection_DefaultHasher.hxx> |
26 | |
7fd59977 |
27 | #if !defined No_Exception && !defined No_Standard_OutOfRange |
28 | #include <Standard_OutOfRange.hxx> |
29 | #endif |
30 | |
7fd59977 |
31 | /** |
32 | * Purpose: An indexed map is used to store keys and to bind |
33 | * an index to them. Each new key stored in the map |
34 | * gets an index. Index are incremented as keys are |
35 | * stored in the map. A key can be found by the index |
36 | * and an index by the key. No key but the last can |
37 | * be removed so the indices are in the range 1.. |
38 | * Extent. An Item is stored with each key. |
39 | * |
40 | * This class is similar to IndexedMap from |
41 | * NCollection with the Item as a new feature. Note |
42 | * the important difference on the operator (). In |
43 | * the IndexedMap this operator returns the Key. In |
44 | * the IndexedDataMap this operator returns the Item. |
45 | * |
46 | * See the class Map from NCollection for a |
47 | * discussion about the number of buckets. |
48 | */ |
9991c9c2 |
49 | |
50 | template < class TheKeyType, |
51 | class TheItemType, |
52 | class Hasher = NCollection_DefaultHasher<TheKeyType> > |
53 | class NCollection_IndexedDataMap |
7fd59977 |
54 | : public NCollection_BaseCollection<TheItemType>, |
55 | public NCollection_BaseMap |
56 | { |
57 | //! Adaptation of the TListNode to the INDEXEDDatamap |
58 | private: |
59 | class IndexedDataMapNode : public NCollection_TListNode<TheItemType> |
60 | { |
61 | public: |
62 | //! Constructor with 'Next' |
63 | IndexedDataMapNode (const TheKeyType& theKey1, |
64 | const Standard_Integer theKey2, |
65 | const TheItemType& theItem, |
66 | NCollection_ListNode* theNext1, |
67 | NCollection_ListNode* theNext2) : |
68 | NCollection_TListNode<TheItemType>(theItem,theNext1) |
69 | { |
70 | myKey1 = theKey1; |
71 | myKey2 = theKey2; |
72 | myNext2 = (IndexedDataMapNode *) theNext2; |
73 | } |
74 | //! Key1 |
75 | TheKeyType& Key1 (void) |
76 | { return myKey1; } |
77 | //! Key2 |
78 | const Standard_Integer& Key2 (void) |
79 | { return myKey2; } |
80 | //! Next2 |
81 | IndexedDataMapNode*& Next2 (void) |
82 | { return myNext2; } |
83 | |
84 | //! Static deleter to be passed to BaseList |
85 | static void delNode (NCollection_ListNode * theNode, |
86 | Handle(NCollection_BaseAllocator)& theAl) |
87 | { |
88 | ((IndexedDataMapNode *) theNode)->~IndexedDataMapNode(); |
89 | theAl->Free(theNode); |
90 | } |
91 | private: |
92 | TheKeyType myKey1; |
93 | Standard_Integer myKey2; |
94 | IndexedDataMapNode * myNext2; |
95 | }; |
96 | |
97 | public: |
98 | //! Implementation of the Iterator interface. |
99 | class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator |
100 | { |
101 | public: |
102 | //! Empty constructor |
103 | Iterator (void) : |
104 | myMap(NULL), |
105 | myIndex(0) {} |
106 | //! Constructor |
ad3217cd |
107 | Iterator (const NCollection_IndexedDataMap& theMap) |
108 | : myMap ((NCollection_IndexedDataMap* )&theMap), |
109 | myNode (myMap->nodeFromIndex (1)), |
110 | myIndex (1) {} |
7fd59977 |
111 | //! Query if the end of collection is reached by iterator |
112 | virtual Standard_Boolean More(void) const |
113 | { return (myIndex <= myMap->Extent()); } |
114 | //! Make a step along the collection |
115 | virtual void Next(void) |
ad3217cd |
116 | { |
117 | myNode = myMap->nodeFromIndex (++myIndex); |
118 | } |
7fd59977 |
119 | //! Value access |
120 | virtual const TheItemType& Value(void) const |
121 | { |
122 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
123 | if (!More()) |
124 | Standard_NoSuchObject::Raise("NCollection_IndexedDataMap::Iterator::Value"); |
125 | #endif |
ad3217cd |
126 | return myNode->Value(); |
7fd59977 |
127 | } |
128 | //! ChangeValue access |
129 | virtual TheItemType& ChangeValue(void) const |
130 | { |
131 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
132 | if (!More()) |
133 | Standard_NoSuchObject::Raise("NCollection_IndexedDataMap::Iterator::ChangeValue"); |
134 | #endif |
ad3217cd |
135 | return myNode->ChangeValue(); |
136 | } |
137 | //! Key |
138 | const TheKeyType& Key() const |
139 | { |
140 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
141 | if (!More()) |
142 | Standard_NoSuchObject::Raise("NCollection_DataMap::Iterator::Key"); |
143 | #endif |
144 | return myNode->Key1(); |
7fd59977 |
145 | } |
7fd59977 |
146 | private: |
ad3217cd |
147 | NCollection_IndexedDataMap* myMap; //!< Pointer to the map being iterated |
148 | IndexedDataMapNode* myNode; //!< Current node |
149 | Standard_Integer myIndex; //!< Current index |
7fd59977 |
150 | }; |
151 | |
152 | public: |
153 | // ---------- PUBLIC METHODS ------------ |
154 | |
155 | //! Constructor |
156 | NCollection_IndexedDataMap (const Standard_Integer NbBuckets=1, |
157 | const Handle(NCollection_BaseAllocator)& theAllocator = 0L) |
158 | : NCollection_BaseCollection<TheItemType>(theAllocator), |
159 | NCollection_BaseMap (NbBuckets, Standard_False) {} |
160 | |
161 | //! Copy constructor |
162 | NCollection_IndexedDataMap (const NCollection_IndexedDataMap& theOther) |
163 | : NCollection_BaseCollection<TheItemType>(theOther.myAllocator), |
164 | NCollection_BaseMap (theOther.NbBuckets(), Standard_False) |
165 | { *this = theOther; } |
166 | |
167 | //! Assign another collection |
168 | virtual void Assign(const NCollection_BaseCollection<TheItemType>& theOther) |
169 | { |
170 | if (this == &theOther) |
171 | return; |
172 | Standard_TypeMismatch::Raise("NCollection_IndexedDataMap::Assign"); |
173 | } |
174 | |
ab2db9a5 |
175 | //! Exchange the content of two maps without re-allocations. |
176 | //! Notice that allocators will be swapped as well! |
177 | void Exchange (NCollection_IndexedDataMap& theOther) |
178 | { |
179 | this->exchangeAllocators (theOther); |
180 | this->exchangeMapsData (theOther); |
181 | } |
182 | |
7fd59977 |
183 | //! = another map |
184 | NCollection_IndexedDataMap& operator= |
185 | (const NCollection_IndexedDataMap& theOther) |
186 | { |
187 | if (this == &theOther) |
188 | return *this; |
189 | |
190 | Clear(theOther.myAllocator); |
191 | ReSize (theOther.Extent()-1); |
192 | Standard_Integer i; |
193 | for (i=1; i<=theOther.Extent(); i++) |
194 | { |
195 | TheKeyType aKey1 = theOther.FindKey(i); |
196 | TheItemType anItem = theOther.FindFromIndex(i); |
9991c9c2 |
197 | Standard_Integer iK1 = Hasher::HashCode (aKey1, NbBuckets()); |
198 | Standard_Integer iK2 = ::HashCode (i, NbBuckets()); |
7fd59977 |
199 | IndexedDataMapNode * pNode = |
200 | new (this->myAllocator) IndexedDataMapNode (aKey1, i, anItem, |
201 | myData1[iK1], myData2[iK2]); |
202 | myData1[iK1] = pNode; |
203 | myData2[iK2] = pNode; |
204 | Increment(); |
205 | } |
206 | return *this; |
207 | } |
208 | |
209 | //! ReSize |
210 | void ReSize (const Standard_Integer N) |
211 | { |
fd03ee4b |
212 | NCollection_ListNode** ppNewData1 = NULL; |
213 | NCollection_ListNode** ppNewData2 = NULL; |
7fd59977 |
214 | Standard_Integer newBuck; |
fd03ee4b |
215 | if (BeginResize (N, newBuck, ppNewData1, ppNewData2, this->myAllocator)) |
7fd59977 |
216 | { |
217 | if (myData1) |
218 | { |
219 | IndexedDataMapNode *p, *q; |
220 | Standard_Integer i, iK1, iK2; |
221 | for (i = 0; i <= NbBuckets(); i++) |
222 | { |
223 | if (myData1[i]) |
224 | { |
225 | p = (IndexedDataMapNode *) myData1[i]; |
226 | while (p) |
227 | { |
9991c9c2 |
228 | iK1 = Hasher::HashCode (p->Key1(), newBuck); |
229 | iK2 = ::HashCode (p->Key2(), newBuck); |
7fd59977 |
230 | q = (IndexedDataMapNode*) p->Next(); |
231 | p->Next() = ppNewData1[iK1]; |
fd03ee4b |
232 | p->Next2() = (IndexedDataMapNode*)ppNewData2[iK2]; |
7fd59977 |
233 | ppNewData1[iK1] = p; |
234 | ppNewData2[iK2] = p; |
235 | p = q; |
236 | } |
237 | } |
238 | } |
239 | } |
fd03ee4b |
240 | EndResize (N, newBuck, ppNewData1, ppNewData2, this->myAllocator); |
7fd59977 |
241 | } |
242 | } |
243 | |
244 | //! Add |
245 | Standard_Integer Add (const TheKeyType& theKey1, const TheItemType& theItem) |
246 | { |
247 | if (Resizable()) |
248 | ReSize(Extent()); |
9991c9c2 |
249 | Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); |
7fd59977 |
250 | IndexedDataMapNode * pNode; |
251 | pNode = (IndexedDataMapNode *) myData1[iK1]; |
252 | while (pNode) |
253 | { |
9991c9c2 |
254 | if (Hasher::IsEqual (pNode->Key1(), theKey1)) |
7fd59977 |
255 | return pNode->Key2(); |
256 | pNode = (IndexedDataMapNode *) pNode->Next(); |
257 | } |
258 | Increment(); |
9991c9c2 |
259 | Standard_Integer iK2 = ::HashCode(Extent(),NbBuckets()); |
7fd59977 |
260 | pNode = new (this->myAllocator) IndexedDataMapNode (theKey1, Extent(), theItem, |
261 | myData1[iK1], myData2[iK2]); |
262 | myData1[iK1] = pNode; |
263 | myData2[iK2] = pNode; |
264 | return Extent(); |
265 | } |
266 | |
267 | //! Contains |
268 | Standard_Boolean Contains (const TheKeyType& theKey1) const |
269 | { |
270 | if (IsEmpty()) |
271 | return Standard_False; |
9991c9c2 |
272 | Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); |
7fd59977 |
273 | IndexedDataMapNode * pNode1; |
274 | pNode1 = (IndexedDataMapNode *) myData1[iK1]; |
275 | while (pNode1) |
276 | { |
9991c9c2 |
277 | if (Hasher::IsEqual(pNode1->Key1(), theKey1)) |
7fd59977 |
278 | return Standard_True; |
279 | pNode1 = (IndexedDataMapNode *) pNode1->Next(); |
280 | } |
281 | return Standard_False; |
282 | } |
283 | |
284 | //! Substitute |
285 | void Substitute (const Standard_Integer theIndex, |
286 | const TheKeyType& theKey1, |
287 | const TheItemType& theItem) |
288 | { |
289 | #if !defined No_Exception && !defined No_Standard_OutOfRange |
290 | if (theIndex < 1 || theIndex > Extent()) |
291 | Standard_OutOfRange::Raise ("NCollection_IndexedDataMap::Substitute"); |
292 | #endif |
293 | IndexedDataMapNode * p; |
294 | // check if theKey1 is not already in the map |
9991c9c2 |
295 | Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); |
7fd59977 |
296 | p = (IndexedDataMapNode *) myData1[iK1]; |
297 | while (p) |
298 | { |
9991c9c2 |
299 | if (Hasher::IsEqual (p->Key1(), theKey1)) |
7fd59977 |
300 | Standard_DomainError::Raise("NCollection_IndexedDataMap::Substitute"); |
301 | p = (IndexedDataMapNode *) p->Next(); |
302 | } |
303 | |
304 | // Find the node for the index I |
9991c9c2 |
305 | Standard_Integer iK2 = ::HashCode (theIndex, NbBuckets()); |
7fd59977 |
306 | p = (IndexedDataMapNode *) myData2[iK2]; |
307 | while (p) |
308 | { |
309 | if (p->Key2() == theIndex) |
310 | break; |
311 | p = (IndexedDataMapNode*) p->Next2(); |
312 | } |
313 | |
314 | // remove the old key |
9991c9c2 |
315 | Standard_Integer iK = Hasher::HashCode (p->Key1(), NbBuckets()); |
7fd59977 |
316 | IndexedDataMapNode * q = (IndexedDataMapNode *) myData1[iK]; |
317 | if (q == p) |
318 | myData1[iK] = (IndexedDataMapNode *) p->Next(); |
319 | else |
320 | { |
321 | while (q->Next() != p) |
322 | q = (IndexedDataMapNode *) q->Next(); |
323 | q->Next() = p->Next(); |
324 | } |
325 | |
326 | // update the node |
327 | p->Key1() = theKey1; |
328 | p->ChangeValue() = theItem; |
329 | p->Next() = myData1[iK1]; |
330 | myData1[iK1] = p; |
331 | } |
332 | |
333 | //! RemoveLast |
334 | void RemoveLast (void) |
335 | { |
336 | #if !defined No_Exception && !defined No_Standard_OutOfRange |
337 | if (Extent() == 0) |
338 | Standard_OutOfRange::Raise ("NCollection_IndexedDataMap::RemoveLast"); |
339 | #endif |
340 | IndexedDataMapNode * p, * q; |
341 | // Find the node for the last index and remove it |
9991c9c2 |
342 | Standard_Integer iK2 = ::HashCode (Extent(), NbBuckets()); |
7fd59977 |
343 | p = (IndexedDataMapNode *) myData2[iK2]; |
344 | q = NULL; |
345 | while (p) |
346 | { |
347 | if (p->Key2() == Extent()) |
348 | break; |
349 | q = p; |
350 | p = (IndexedDataMapNode*) p->Next2(); |
351 | } |
352 | if (q == NULL) |
353 | myData2[iK2] = (IndexedDataMapNode *) p->Next2(); |
354 | else |
355 | q->Next2() = p->Next2(); |
356 | |
357 | // remove the key |
9991c9c2 |
358 | Standard_Integer iK1 = Hasher::HashCode (p->Key1(), NbBuckets()); |
7fd59977 |
359 | q = (IndexedDataMapNode *) myData1[iK1]; |
360 | if (q == p) |
361 | myData1[iK1] = (IndexedDataMapNode *) p->Next(); |
362 | else |
363 | { |
364 | while (q->Next() != p) |
365 | q = (IndexedDataMapNode *) q->Next(); |
366 | q->Next() = p->Next(); |
367 | } |
368 | p->~IndexedDataMapNode(); |
369 | this->myAllocator->Free(p); |
370 | Decrement(); |
371 | } |
372 | |
373 | //! FindKey |
374 | const TheKeyType& FindKey (const Standard_Integer theKey2) const |
375 | { |
376 | #if !defined No_Exception && !defined No_Standard_OutOfRange |
377 | if (theKey2 < 1 || theKey2 > Extent()) |
378 | Standard_OutOfRange::Raise ("NCollection_IndexedDataMap::FindKey"); |
379 | #endif |
ad3217cd |
380 | IndexedDataMapNode* aNode = nodeFromIndex (theKey2); |
381 | if (aNode == NULL) |
7fd59977 |
382 | { |
ad3217cd |
383 | Standard_NoSuchObject::Raise ("NCollection_IndexedDataMap::FindKey"); |
7fd59977 |
384 | } |
ad3217cd |
385 | return aNode->Key1(); |
7fd59977 |
386 | } |
387 | |
388 | //! FindFromIndex |
389 | const TheItemType& FindFromIndex (const Standard_Integer theKey2) const |
390 | { |
391 | #if !defined No_Exception && !defined No_Standard_OutOfRange |
392 | if (theKey2 < 1 || theKey2 > Extent()) |
393 | Standard_OutOfRange::Raise ("NCollection_IndexedDataMap::FindFromIndex"); |
394 | #endif |
ad3217cd |
395 | IndexedDataMapNode* aNode = nodeFromIndex (theKey2); |
396 | if (aNode == NULL) |
7fd59977 |
397 | { |
ad3217cd |
398 | Standard_NoSuchObject::Raise ("NCollection_IndexedDataMap::FindFromIndex"); |
7fd59977 |
399 | } |
ad3217cd |
400 | return aNode->Value(); |
7fd59977 |
401 | } |
402 | |
403 | //! operator () |
404 | const TheItemType& operator() (const Standard_Integer theKey2) const |
405 | { return FindFromIndex (theKey2); } |
406 | |
407 | //! ChangeFromIndex |
408 | TheItemType& ChangeFromIndex (const Standard_Integer theKey2) |
409 | { |
410 | #if !defined No_Exception && !defined No_Standard_OutOfRange |
411 | if (theKey2 < 1 || theKey2 > Extent()) |
412 | Standard_OutOfRange::Raise("NCollection_IndexedDataMap::ChangeFromIndex"); |
413 | #endif |
ad3217cd |
414 | IndexedDataMapNode* aNode = nodeFromIndex (theKey2); |
415 | if (aNode == NULL) |
7fd59977 |
416 | { |
ad3217cd |
417 | Standard_NoSuchObject::Raise ("NCollection_IndexedDataMap::ChangeFromIndex"); |
7fd59977 |
418 | } |
ad3217cd |
419 | return aNode->ChangeValue(); |
7fd59977 |
420 | } |
421 | |
422 | //! operator () |
423 | TheItemType& operator() (const Standard_Integer theKey2) |
424 | { return ChangeFromIndex (theKey2); } |
425 | |
426 | //! FindIndex |
427 | Standard_Integer FindIndex(const TheKeyType& theKey1) const |
428 | { |
429 | if (IsEmpty()) return 0; |
430 | IndexedDataMapNode * pNode1 = |
9991c9c2 |
431 | (IndexedDataMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; |
7fd59977 |
432 | while (pNode1) |
433 | { |
9991c9c2 |
434 | if (Hasher::IsEqual (pNode1->Key1(), theKey1)) |
7fd59977 |
435 | return pNode1->Key2(); |
436 | pNode1 = (IndexedDataMapNode*) pNode1->Next(); |
437 | } |
438 | return 0; |
439 | } |
440 | |
441 | //! FindFromKey |
442 | const TheItemType& FindFromKey(const TheKeyType& theKey1) const |
443 | { |
444 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
445 | if (IsEmpty()) |
446 | Standard_NoSuchObject::Raise ("NCollection_IndexedDataMap::FindFromKey"); |
447 | #endif |
448 | IndexedDataMapNode * pNode1 = |
9991c9c2 |
449 | (IndexedDataMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; |
7fd59977 |
450 | while (pNode1) |
451 | { |
9991c9c2 |
452 | if (Hasher::IsEqual (pNode1->Key1(), theKey1)) |
7fd59977 |
453 | return pNode1->Value(); |
454 | pNode1 = (IndexedDataMapNode*) pNode1->Next(); |
455 | } |
456 | Standard_NoSuchObject::Raise("NCollection_IndexedDataMap::FindFromKey"); |
457 | return pNode1->Value(); |
458 | } |
459 | |
460 | //! ChangeFromKey |
461 | TheItemType& ChangeFromKey (const TheKeyType& theKey1) |
462 | { |
463 | #if !defined No_Exception && !defined No_Standard_NoSuchObject |
464 | if (IsEmpty()) |
465 | Standard_NoSuchObject::Raise("NCollection_IndexedDataMap::ChangeFromKey"); |
466 | #endif |
467 | IndexedDataMapNode * pNode1 = |
9991c9c2 |
468 | (IndexedDataMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; |
7fd59977 |
469 | while (pNode1) |
470 | { |
9991c9c2 |
471 | if (Hasher::IsEqual (pNode1->Key1(), theKey1)) |
7fd59977 |
472 | return pNode1->ChangeValue(); |
473 | pNode1 = (IndexedDataMapNode*) pNode1->Next(); |
474 | } |
475 | Standard_NoSuchObject::Raise("NCollection_IndexedDataMap::ChangeFromKey"); |
476 | return pNode1->ChangeValue(); |
477 | } |
478 | |
ad3217cd |
479 | //! Find value for key with copying. |
480 | //! @return true if key was found |
481 | Standard_Boolean FindFromKey (const TheKeyType& theKey1, |
482 | TheItemType& theValue) const |
483 | { |
484 | if (IsEmpty()) |
485 | { |
486 | return Standard_False; |
487 | } |
488 | for (IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData1[Hasher::HashCode (theKey1, NbBuckets())]; |
489 | aNode != NULL; aNode = (IndexedDataMapNode* )aNode->Next()) |
490 | { |
491 | if (Hasher::IsEqual (aNode->Key1(), theKey1)) |
492 | { |
493 | theValue = aNode->Value(); |
494 | return Standard_True; |
495 | } |
496 | } |
497 | return Standard_False; |
498 | } |
499 | |
7fd59977 |
500 | //! Clear data. If doReleaseMemory is false then the table of |
501 | //! buckets is not released and will be reused. |
502 | void Clear(const Standard_Boolean doReleaseMemory = Standard_True) |
503 | { Destroy (IndexedDataMapNode::delNode, this->myAllocator, doReleaseMemory); } |
504 | |
505 | //! Clear data and reset allocator |
506 | void Clear (const Handle(NCollection_BaseAllocator)& theAllocator) |
507 | { |
508 | Clear(); |
509 | this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator : |
510 | NCollection_BaseAllocator::CommonBaseAllocator() ); |
511 | } |
512 | |
513 | //! Destructor |
514 | ~NCollection_IndexedDataMap (void) |
515 | { Clear(); } |
516 | |
517 | //! Size |
518 | virtual Standard_Integer Size(void) const |
519 | { return Extent(); } |
520 | |
521 | private: |
522 | // ----------- PRIVATE METHODS ----------- |
523 | |
524 | //! Creates Iterator for use on BaseCollection |
525 | virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& |
526 | CreateIterator(void) const |
527 | { return *(new (this->IterAllocator()) Iterator(*this)); } |
528 | |
ad3217cd |
529 | //! Find map node associated with specified index. |
530 | //! Return NULL if not found (exception-free internal implementation). |
531 | IndexedDataMapNode* nodeFromIndex (const Standard_Integer theKey2) const |
532 | { |
533 | if (Extent() == 0) |
534 | { |
535 | return NULL; |
536 | } |
537 | for (IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[::HashCode (theKey2, NbBuckets())]; |
538 | aNode != NULL; aNode = (IndexedDataMapNode* )aNode->Next2()) |
539 | { |
540 | if (aNode->Key2() == theKey2) |
541 | { |
542 | return aNode; |
543 | } |
544 | } |
545 | return NULL; |
546 | } |
547 | |
7fd59977 |
548 | }; |
549 | |
7fd59977 |
550 | #endif |