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