xref: /aoo41x/main/tools/workben/hashtbl.cxx (revision 89b56da7)
1*89b56da7SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*89b56da7SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*89b56da7SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*89b56da7SAndrew Rist  * distributed with this work for additional information
6*89b56da7SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*89b56da7SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*89b56da7SAndrew Rist  * "License"); you may not use this file except in compliance
9*89b56da7SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*89b56da7SAndrew Rist  *
11*89b56da7SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*89b56da7SAndrew Rist  *
13*89b56da7SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*89b56da7SAndrew Rist  * software distributed under the License is distributed on an
15*89b56da7SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*89b56da7SAndrew Rist  * KIND, either express or implied.  See the License for the
17*89b56da7SAndrew Rist  * specific language governing permissions and limitations
18*89b56da7SAndrew Rist  * under the License.
19*89b56da7SAndrew Rist  *
20*89b56da7SAndrew Rist  *************************************************************/
21*89b56da7SAndrew Rist 
22*89b56da7SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_tools.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <tlgen.hxx>
28cdf0e10cSrcweir #include "hashtbl.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <algorithm>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir // -------------------------------------------------------------
33cdf0e10cSrcweir // class HashItem
34cdf0e10cSrcweir //
35cdf0e10cSrcweir class HashItem
36cdf0e10cSrcweir {
37cdf0e10cSrcweir     enum ETag { TAG_EMPTY, TAG_USED, TAG_DELETED };
38cdf0e10cSrcweir 
39cdf0e10cSrcweir     void*   m_pObject;
40cdf0e10cSrcweir     ETag    m_Tag;
41cdf0e10cSrcweir     String  m_Key;
42cdf0e10cSrcweir 
43cdf0e10cSrcweir public:
HashItem()44cdf0e10cSrcweir     HashItem() { m_Tag = TAG_EMPTY; m_pObject = NULL; }
45cdf0e10cSrcweir 
IsDeleted() const46cdf0e10cSrcweir     BOOL IsDeleted() const
47cdf0e10cSrcweir     {   return m_Tag == TAG_DELETED; }
48cdf0e10cSrcweir 
IsEmpty() const49cdf0e10cSrcweir     BOOL IsEmpty() const
50cdf0e10cSrcweir     {   return m_Tag == TAG_DELETED || m_Tag == TAG_EMPTY; }
51cdf0e10cSrcweir 
IsFree() const52cdf0e10cSrcweir     BOOL IsFree() const
53cdf0e10cSrcweir     {   return m_Tag == TAG_EMPTY; }
54cdf0e10cSrcweir 
IsUsed() const55cdf0e10cSrcweir     BOOL IsUsed() const
56cdf0e10cSrcweir     {   return m_Tag == TAG_USED; }
57cdf0e10cSrcweir 
Delete()58cdf0e10cSrcweir     void Delete()
59cdf0e10cSrcweir     { m_Tag = TAG_DELETED; m_Key = ""; m_pObject = NULL; }
60cdf0e10cSrcweir 
GetKey() const61cdf0e10cSrcweir     String const& GetKey() const
62cdf0e10cSrcweir     { return m_Key; }
63cdf0e10cSrcweir 
GetObject() const64cdf0e10cSrcweir     void* GetObject() const
65cdf0e10cSrcweir     { return m_pObject; }
66cdf0e10cSrcweir 
SetObject(String const Key,void * pObject)67cdf0e10cSrcweir     void SetObject(String const Key, void *pObject)
68cdf0e10cSrcweir     { m_Tag = TAG_USED; m_Key = Key; m_pObject = pObject; }
69cdf0e10cSrcweir };
70cdf0e10cSrcweir 
71cdf0e10cSrcweir // #define MIN(a,b) (a)<(b)?(a):(b)
72cdf0e10cSrcweir // #define MAX(a,b) (a)>(b)?(a):(b)
73cdf0e10cSrcweir 
74cdf0e10cSrcweir // -------------------------------------------------------------
75cdf0e10cSrcweir // class HashTable
76cdf0e10cSrcweir //
77cdf0e10cSrcweir 
78cdf0e10cSrcweir /*static*/ double HashTable::m_defMaxLoadFactor = 0.8;
79cdf0e10cSrcweir /*static*/ double HashTable::m_defDefGrowFactor = 2.0;
80cdf0e10cSrcweir 
HashTable(ULONG lSize,BOOL bOwner,double dMaxLoadFactor,double dGrowFactor)81cdf0e10cSrcweir HashTable::HashTable(ULONG lSize, BOOL bOwner, double dMaxLoadFactor, double dGrowFactor)
82cdf0e10cSrcweir {
83cdf0e10cSrcweir     m_lSize          = lSize;
84cdf0e10cSrcweir     m_bOwner         = bOwner;
85cdf0e10cSrcweir     m_lElem          = 0;
86cdf0e10cSrcweir     m_dMaxLoadFactor = std::max(0.5,std::min(1.0,dMaxLoadFactor));  // 0.5 ... 1.0
87cdf0e10cSrcweir     m_dGrowFactor    = std::max(1.3,(5.0,dGrowFactor));     // 1.3 ... 5.0
88cdf0e10cSrcweir     m_pData          = new HashItem [lSize];
89cdf0e10cSrcweir 
90cdf0e10cSrcweir // Statistik
91cdf0e10cSrcweir #ifdef DBG_UTIL
92cdf0e10cSrcweir 	m_aStatistic.m_lSingleHash = 0;
93cdf0e10cSrcweir 	m_aStatistic.m_lDoubleHash = 0;
94cdf0e10cSrcweir 	m_aStatistic.m_lProbe	   = 0;
95cdf0e10cSrcweir #endif
96cdf0e10cSrcweir }
97cdf0e10cSrcweir 
~HashTable()98cdf0e10cSrcweir HashTable::~HashTable()
99cdf0e10cSrcweir {
100cdf0e10cSrcweir     // Wenn die HashTable der Owner der Objecte ist,
101cdf0e10cSrcweir     // m�ssen die Destruktoren separat gerufen werden.
102cdf0e10cSrcweir     // Dies geschieht �ber die virtuelle Methode OnDeleteObject()
103cdf0e10cSrcweir     //
104cdf0e10cSrcweir     // Problem: Virtuelle Funktionen sind im Destructor nicht virtuell!!
105cdf0e10cSrcweir     //          Der Code mu� deshalb ins Macro
106cdf0e10cSrcweir 
107cdf0e10cSrcweir     /*
108cdf0e10cSrcweir     if (m_bOwner)
109cdf0e10cSrcweir     {
110cdf0e10cSrcweir         for (ULONG i=0; i<GetSize(); i++)
111cdf0e10cSrcweir         {
112cdf0e10cSrcweir             void *pObject = GetObjectAt(i);
113cdf0e10cSrcweir 
114cdf0e10cSrcweir             if (pObject != NULL)
115cdf0e10cSrcweir                 OnDeleteObject(pObject());
116cdf0e10cSrcweir         }
117cdf0e10cSrcweir     }
118cdf0e10cSrcweir     */
119cdf0e10cSrcweir 
120cdf0e10cSrcweir     // Speicher f�r HashItems freigeben
121cdf0e10cSrcweir     delete [] m_pData;
122cdf0e10cSrcweir }
123cdf0e10cSrcweir 
GetObjectAt(ULONG lPos) const124cdf0e10cSrcweir void* HashTable::GetObjectAt(ULONG lPos) const
125cdf0e10cSrcweir // Gibt Objekt zur�ck, wenn es eines gibt, sonst NULL;
126cdf0e10cSrcweir {
127cdf0e10cSrcweir     DBG_ASSERT(lPos<m_lSize, "HashTable::GetObjectAt()");
128cdf0e10cSrcweir 
129cdf0e10cSrcweir     HashItem *pItem = &m_pData[lPos];
130cdf0e10cSrcweir 
131cdf0e10cSrcweir     return pItem->IsUsed() ? pItem->GetObject() : NULL;
132cdf0e10cSrcweir }
133cdf0e10cSrcweir 
OnDeleteObject(void *)134cdf0e10cSrcweir void HashTable::OnDeleteObject(void*)
135cdf0e10cSrcweir {
136cdf0e10cSrcweir     DBG_ERROR("HashTable::OnDeleteObject(void*) nicht �berladen");
137cdf0e10cSrcweir }
138cdf0e10cSrcweir 
Hash(String const & Key) const139cdf0e10cSrcweir ULONG HashTable::Hash(String const& Key) const
140cdf0e10cSrcweir {
141cdf0e10cSrcweir 	/*
142cdf0e10cSrcweir     ULONG lHash = 0;
143cdf0e10cSrcweir     ULONG i,n;
144cdf0e10cSrcweir 
145cdf0e10cSrcweir     for (i=0,n=Key.Len(); i<n; i++)
146cdf0e10cSrcweir     {
147cdf0e10cSrcweir         lHash *= 256L;
148cdf0e10cSrcweir         lHash += (ULONG)(USHORT)Key.GetStr()[i];
149cdf0e10cSrcweir         lHash %= m_lSize;
150cdf0e10cSrcweir     }
151cdf0e10cSrcweir     return lHash;
152cdf0e10cSrcweir 	*/
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 	// Hashfunktion von P.J. Weinberger
155cdf0e10cSrcweir 	// aus dem "Drachenbuch" von Aho/Sethi/Ullman
156cdf0e10cSrcweir     ULONG i,n;
157cdf0e10cSrcweir 	ULONG h = 0;
158cdf0e10cSrcweir 	ULONG g = 0;
159cdf0e10cSrcweir 
160cdf0e10cSrcweir     for (i=0,n=Key.Len(); i<n; i++)
161cdf0e10cSrcweir 	{
162cdf0e10cSrcweir 		h = (h<<4) + (ULONG)(USHORT)Key.GetStr()[i];
163cdf0e10cSrcweir 		g = h & 0xf0000000;
164cdf0e10cSrcweir 
165cdf0e10cSrcweir 		if (g != 0)
166cdf0e10cSrcweir 		{
167cdf0e10cSrcweir 			h = h ^ (g >> 24);
168cdf0e10cSrcweir 			h = h ^ g;
169cdf0e10cSrcweir 		}
170cdf0e10cSrcweir 	}
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 	return h % m_lSize;
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
DHash(String const & Key,ULONG lOldHash) const175cdf0e10cSrcweir ULONG HashTable::DHash(String const& Key, ULONG lOldHash) const
176cdf0e10cSrcweir {
177cdf0e10cSrcweir     ULONG lHash = lOldHash;
178cdf0e10cSrcweir     ULONG i,n;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     for (i=0,n=Key.Len(); i<n; i++)
181cdf0e10cSrcweir     {
182cdf0e10cSrcweir         lHash *= 256L;
183cdf0e10cSrcweir         lHash += (ULONG)(USHORT)Key.GetStr()[i];
184cdf0e10cSrcweir         lHash %= m_lSize;
185cdf0e10cSrcweir     }
186cdf0e10cSrcweir     return lHash;
187cdf0e10cSrcweir 
188cdf0e10cSrcweir /*    return
189cdf0e10cSrcweir 		(
190cdf0e10cSrcweir 			lHash
191cdf0e10cSrcweir 		+	(char)Key.GetStr()[0] * 256
192cdf0e10cSrcweir 		+	(char)Key.GetStr()[Key.Len()-1]
193cdf0e10cSrcweir 		+	1
194cdf0e10cSrcweir 		)
195cdf0e10cSrcweir 		% m_lSize;
196cdf0e10cSrcweir */
197cdf0e10cSrcweir }
198cdf0e10cSrcweir 
Probe(ULONG lPos) const199cdf0e10cSrcweir ULONG HashTable::Probe(ULONG lPos) const
200cdf0e10cSrcweir // gibt den Folgewert von lPos zur�ck
201cdf0e10cSrcweir {
202cdf0e10cSrcweir     lPos++; if (lPos==m_lSize) lPos=0;
203cdf0e10cSrcweir     return lPos;
204cdf0e10cSrcweir }
205cdf0e10cSrcweir 
IsFull() const206cdf0e10cSrcweir BOOL HashTable::IsFull() const
207cdf0e10cSrcweir {
208cdf0e10cSrcweir     return m_lElem>=m_lSize;
209cdf0e10cSrcweir }
210cdf0e10cSrcweir 
Insert(String const & Key,void * pObject)211cdf0e10cSrcweir BOOL HashTable::Insert(String const& Key, void* pObject)
212cdf0e10cSrcweir // pre:  Key ist nicht im Dictionary enthalten, sonst return FALSE
213cdf0e10cSrcweir //       Dictionary ist nicht voll, sonst return FALSE
214cdf0e10cSrcweir // post: pObject ist unter Key im Dictionary; m_nElem wurde erh�ht
215cdf0e10cSrcweir {
216cdf0e10cSrcweir     SmartGrow();
217cdf0e10cSrcweir 
218cdf0e10cSrcweir     if (IsFull())
219cdf0e10cSrcweir     {
220cdf0e10cSrcweir         DBG_ERROR("HashTable::Insert() is full");
221cdf0e10cSrcweir         return FALSE;
222cdf0e10cSrcweir     }
223cdf0e10cSrcweir 
224cdf0e10cSrcweir     if (FindPos(Key) != NULL )
225cdf0e10cSrcweir         return FALSE;
226cdf0e10cSrcweir 
227cdf0e10cSrcweir     ULONG     lPos  = Hash(Key);
228cdf0e10cSrcweir     HashItem *pItem = &m_pData[lPos];
229cdf0e10cSrcweir 
230cdf0e10cSrcweir     // first hashing
231cdf0e10cSrcweir     //
232cdf0e10cSrcweir     if (pItem->IsEmpty())
233cdf0e10cSrcweir     {
234cdf0e10cSrcweir         pItem->SetObject(Key, pObject);
235cdf0e10cSrcweir         m_lElem++;
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 		#ifdef DBG_UTIL
238cdf0e10cSrcweir 		m_aStatistic.m_lSingleHash++;
239cdf0e10cSrcweir 		#endif
240cdf0e10cSrcweir 
241cdf0e10cSrcweir         return TRUE;
242cdf0e10cSrcweir     }
243cdf0e10cSrcweir 
244cdf0e10cSrcweir     // double hashing
245cdf0e10cSrcweir     //
246cdf0e10cSrcweir     lPos  = DHash(Key,lPos);
247cdf0e10cSrcweir     pItem = &m_pData[lPos];
248cdf0e10cSrcweir 
249cdf0e10cSrcweir     if (pItem->IsEmpty())
250cdf0e10cSrcweir     {
251cdf0e10cSrcweir         pItem->SetObject(Key, pObject);
252cdf0e10cSrcweir         m_lElem++;
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 		#ifdef DBG_UTIL
255cdf0e10cSrcweir 		m_aStatistic.m_lDoubleHash++;
256cdf0e10cSrcweir 		#endif
257cdf0e10cSrcweir 
258cdf0e10cSrcweir         return TRUE;
259cdf0e10cSrcweir     }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     // linear probing
262cdf0e10cSrcweir     //
263cdf0e10cSrcweir     do
264cdf0e10cSrcweir     {
265cdf0e10cSrcweir 		#ifdef DBG_UTIL
266cdf0e10cSrcweir 		m_aStatistic.m_lProbe++;
267cdf0e10cSrcweir 		#endif
268cdf0e10cSrcweir 
269cdf0e10cSrcweir         lPos  = Probe(lPos);
270cdf0e10cSrcweir         pItem = &m_pData[lPos];
271cdf0e10cSrcweir     }
272cdf0e10cSrcweir     while(!pItem->IsEmpty());
273cdf0e10cSrcweir 
274cdf0e10cSrcweir     pItem->SetObject(Key, pObject);
275cdf0e10cSrcweir     m_lElem++;
276cdf0e10cSrcweir     return TRUE;
277cdf0e10cSrcweir }
278cdf0e10cSrcweir 
FindPos(String const & Key) const279cdf0e10cSrcweir HashItem* HashTable::FindPos(String const& Key) const
280cdf0e10cSrcweir // sucht den Key; gibt Refrenz auf den Eintrag (gefunden)
281cdf0e10cSrcweir // oder NULL (nicht gefunden) zur�ck
282cdf0e10cSrcweir //
283cdf0e10cSrcweir // pre:  -
284cdf0e10cSrcweir // post: -
285cdf0e10cSrcweir {
286cdf0e10cSrcweir     // first hashing
287cdf0e10cSrcweir     //
288cdf0e10cSrcweir     ULONG     lPos  = Hash(Key);
289cdf0e10cSrcweir     HashItem *pItem = &m_pData[lPos];
290cdf0e10cSrcweir 
291cdf0e10cSrcweir     if (pItem->IsUsed()
292cdf0e10cSrcweir     &&  pItem->GetKey() == Key)
293cdf0e10cSrcweir     {
294cdf0e10cSrcweir         return pItem;
295cdf0e10cSrcweir     }
296cdf0e10cSrcweir 
297cdf0e10cSrcweir     // double hashing
298cdf0e10cSrcweir     //
299cdf0e10cSrcweir     if (pItem->IsDeleted() || pItem->IsUsed())
300cdf0e10cSrcweir     {
301cdf0e10cSrcweir         lPos  = DHash(Key,lPos);
302cdf0e10cSrcweir         pItem = &m_pData[lPos];
303cdf0e10cSrcweir 
304cdf0e10cSrcweir         if (pItem->IsUsed()
305cdf0e10cSrcweir         &&  pItem->GetKey() == Key)
306cdf0e10cSrcweir         {
307cdf0e10cSrcweir             return pItem;
308cdf0e10cSrcweir         }
309cdf0e10cSrcweir 
310cdf0e10cSrcweir         // linear probing
311cdf0e10cSrcweir         //
312cdf0e10cSrcweir         if (pItem->IsDeleted() || pItem->IsUsed())
313cdf0e10cSrcweir         {
314cdf0e10cSrcweir             ULONG n      = 0;
315cdf0e10cSrcweir             BOOL  bFound = FALSE;
316cdf0e10cSrcweir             BOOL  bEnd   = FALSE;
317cdf0e10cSrcweir 
318cdf0e10cSrcweir             do
319cdf0e10cSrcweir             {
320cdf0e10cSrcweir                 n++;
321cdf0e10cSrcweir                 lPos   = Probe(lPos);
322cdf0e10cSrcweir                 pItem  = &m_pData[lPos];
323cdf0e10cSrcweir 
324cdf0e10cSrcweir                 bFound =  pItem->IsUsed()
325cdf0e10cSrcweir                        && pItem->GetKey() == Key;
326cdf0e10cSrcweir 
327cdf0e10cSrcweir                 bEnd = !(n<m_lSize || pItem->IsFree());
328cdf0e10cSrcweir             }
329cdf0e10cSrcweir             while(!bFound && !bEnd);
330cdf0e10cSrcweir 
331cdf0e10cSrcweir             return bFound ? pItem : NULL;
332cdf0e10cSrcweir         }
333cdf0e10cSrcweir     }
334cdf0e10cSrcweir 
335cdf0e10cSrcweir     // nicht gefunden
336cdf0e10cSrcweir     //
337cdf0e10cSrcweir     return NULL;
338cdf0e10cSrcweir }
339cdf0e10cSrcweir 
Find(String const & Key) const340cdf0e10cSrcweir void* HashTable::Find(String const& Key) const
341cdf0e10cSrcweir // Gibt Verweis des Objektes zur�ck, das unter Key abgespeichert ist,
342cdf0e10cSrcweir // oder NULL wenn nicht vorhanden.
343cdf0e10cSrcweir //
344cdf0e10cSrcweir // pre:  -
345cdf0e10cSrcweir // post: -
346cdf0e10cSrcweir {
347cdf0e10cSrcweir     HashItem *pItem = FindPos(Key);
348cdf0e10cSrcweir 
349cdf0e10cSrcweir     if (pItem != NULL
350cdf0e10cSrcweir     &&  pItem->GetKey() == Key)
351cdf0e10cSrcweir         return pItem->GetObject();
352cdf0e10cSrcweir     else
353cdf0e10cSrcweir         return NULL;
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
Delete(String const & Key)356cdf0e10cSrcweir void* HashTable::Delete(String const& Key)
357cdf0e10cSrcweir // L�scht Objekt, das unter Key abgespeichert ist und gibt Verweis
358cdf0e10cSrcweir // darauf zur�ck.
359cdf0e10cSrcweir // Gibt NULL zur�ck, wenn Key nicht vorhanden ist.
360cdf0e10cSrcweir //
361cdf0e10cSrcweir // pre:  -
362cdf0e10cSrcweir // post: Objekt ist nicht mehr enthalten; m_lElem dekrementiert
363cdf0e10cSrcweir //       Wenn die HashTable der Owner ist, wurde das Object gel�scht
364cdf0e10cSrcweir {
365cdf0e10cSrcweir     HashItem *pItem = FindPos(Key);
366cdf0e10cSrcweir 
367cdf0e10cSrcweir     if (pItem != NULL
368cdf0e10cSrcweir     &&  pItem->GetKey() == Key)
369cdf0e10cSrcweir     {
370cdf0e10cSrcweir         void* pObject = pItem->GetObject();
371cdf0e10cSrcweir 
372cdf0e10cSrcweir         if (m_bOwner)
373cdf0e10cSrcweir             OnDeleteObject(pObject);
374cdf0e10cSrcweir 
375cdf0e10cSrcweir         pItem->Delete();
376cdf0e10cSrcweir         m_lElem--;
377cdf0e10cSrcweir         return pObject;
378cdf0e10cSrcweir     }
379cdf0e10cSrcweir     else
380cdf0e10cSrcweir     {
381cdf0e10cSrcweir         return NULL;
382cdf0e10cSrcweir     }
383cdf0e10cSrcweir }
384cdf0e10cSrcweir 
CalcLoadFactor() const385cdf0e10cSrcweir double HashTable::CalcLoadFactor() const
386cdf0e10cSrcweir // prozentuale Belegung der Hashtabelle berechnen
387cdf0e10cSrcweir {
388cdf0e10cSrcweir     return double(m_lElem) / double(m_lSize);
389cdf0e10cSrcweir }
390cdf0e10cSrcweir 
SmartGrow()391cdf0e10cSrcweir void HashTable::SmartGrow()
392cdf0e10cSrcweir // Achtung: da die Objekte umkopiert werden, darf die OnDeleteObject-Methode
393cdf0e10cSrcweir //          nicht gerufen werden
394cdf0e10cSrcweir {
395cdf0e10cSrcweir     double dLoadFactor = CalcLoadFactor();
396cdf0e10cSrcweir 
397cdf0e10cSrcweir     if (dLoadFactor <= m_dMaxLoadFactor)
398cdf0e10cSrcweir         return; // nothing to grow
399cdf0e10cSrcweir 
400cdf0e10cSrcweir     ULONG     lOldSize = m_lSize;              // alte Daten sichern
401cdf0e10cSrcweir     HashItem* pOldData = m_pData;
402cdf0e10cSrcweir 
403cdf0e10cSrcweir     m_lSize = ULONG (m_dGrowFactor * m_lSize); // neue Gr��e
404cdf0e10cSrcweir     m_pData = new HashItem[m_lSize];           // neue Daten holen
405cdf0e10cSrcweir 
406cdf0e10cSrcweir     // kein Speicher:
407cdf0e10cSrcweir     // Zustand "Tabelle voll" wird in Insert abgefangen
408cdf0e10cSrcweir     //
409cdf0e10cSrcweir     if (m_pData == NULL)
410cdf0e10cSrcweir     {
411cdf0e10cSrcweir         m_lSize = lOldSize;
412cdf0e10cSrcweir         m_pData = pOldData;
413cdf0e10cSrcweir         return;
414cdf0e10cSrcweir     }
415cdf0e10cSrcweir 
416cdf0e10cSrcweir     m_lElem = 0;                               // noch keine neuen Daten
417cdf0e10cSrcweir 
418cdf0e10cSrcweir     // Umkopieren der Daten
419cdf0e10cSrcweir     //
420cdf0e10cSrcweir     for (ULONG i=0; i<lOldSize; i++)
421cdf0e10cSrcweir     {
422cdf0e10cSrcweir         HashItem *pItem = &pOldData[i];
423cdf0e10cSrcweir 
424cdf0e10cSrcweir         if (pItem->IsUsed())
425cdf0e10cSrcweir             Insert(pItem->GetKey(),pItem->GetObject());
426cdf0e10cSrcweir     }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir     delete [] pOldData;
429cdf0e10cSrcweir }
430cdf0e10cSrcweir 
431cdf0e10cSrcweir // Iterator ---------------------------------------------------------
432cdf0e10cSrcweir //
433cdf0e10cSrcweir 
HashTableIterator(HashTable const & aTable)434cdf0e10cSrcweir HashTableIterator::HashTableIterator(HashTable const& aTable)
435cdf0e10cSrcweir : m_aTable(aTable)
436cdf0e10cSrcweir {
437cdf0e10cSrcweir 	m_lAt = 0;
438cdf0e10cSrcweir }
439cdf0e10cSrcweir 
GetFirst()440cdf0e10cSrcweir void* HashTableIterator::GetFirst()
441cdf0e10cSrcweir {
442cdf0e10cSrcweir 	m_lAt = 0;
443cdf0e10cSrcweir 	return FindValidObject(TRUE /* forward */);
444cdf0e10cSrcweir }
445cdf0e10cSrcweir 
GetLast()446cdf0e10cSrcweir void* HashTableIterator::GetLast()
447cdf0e10cSrcweir {
448cdf0e10cSrcweir 	m_lAt = m_aTable.GetSize() -1;
449cdf0e10cSrcweir 	return FindValidObject(FALSE /* backward */);
450cdf0e10cSrcweir }
451cdf0e10cSrcweir 
GetNext()452cdf0e10cSrcweir void* HashTableIterator::GetNext()
453cdf0e10cSrcweir {
454cdf0e10cSrcweir 	if (m_lAt+1 >= m_aTable.GetSize())
455cdf0e10cSrcweir 		return NULL;
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 	m_lAt++;
458cdf0e10cSrcweir 	return FindValidObject(TRUE /* forward */);
459cdf0e10cSrcweir }
460cdf0e10cSrcweir 
GetPrev()461cdf0e10cSrcweir void* HashTableIterator::GetPrev()
462cdf0e10cSrcweir {
463cdf0e10cSrcweir 	if (m_lAt <= 0)
464cdf0e10cSrcweir 		return NULL;
465cdf0e10cSrcweir 
466cdf0e10cSrcweir 	m_lAt--;
467cdf0e10cSrcweir 	return FindValidObject(FALSE /* backward */);
468cdf0e10cSrcweir }
469cdf0e10cSrcweir 
FindValidObject(BOOL bForward)470cdf0e10cSrcweir void* HashTableIterator::FindValidObject(BOOL bForward)
471cdf0e10cSrcweir // Sucht nach einem vorhandenen Objekt ab der aktuellen
472cdf0e10cSrcweir // Position.
473cdf0e10cSrcweir //
474cdf0e10cSrcweir // pre:  ab inkl. m_lAt soll die Suche beginnen
475cdf0e10cSrcweir // post: if not found then
476cdf0e10cSrcweir //			if bForward == TRUE then
477cdf0e10cSrcweir //				m_lAt == m_aTable.GetSize() -1
478cdf0e10cSrcweir //			else
479cdf0e10cSrcweir //				m_lAt == 0
480cdf0e10cSrcweir //		 else
481cdf0e10cSrcweir //			m_lAt ist die gefundene Position
482cdf0e10cSrcweir {
483cdf0e10cSrcweir 	void *pObject = m_aTable.GetObjectAt(m_lAt);
484cdf0e10cSrcweir 
485cdf0e10cSrcweir 	if (pObject != NULL)
486cdf0e10cSrcweir 		return pObject;
487cdf0e10cSrcweir 
488cdf0e10cSrcweir 	while (pObject == NULL
489cdf0e10cSrcweir 	   && (bForward ? ((m_lAt+1) < m_aTable.GetSize())
490cdf0e10cSrcweir 					:   m_lAt    > 0))
491cdf0e10cSrcweir 	{
492cdf0e10cSrcweir 		if (bForward)
493cdf0e10cSrcweir 			m_lAt++;
494cdf0e10cSrcweir 		else
495cdf0e10cSrcweir 			m_lAt--;
496cdf0e10cSrcweir 
497cdf0e10cSrcweir 		pObject = m_aTable.GetObjectAt(m_lAt);
498cdf0e10cSrcweir 	}
499cdf0e10cSrcweir 
500cdf0e10cSrcweir #ifdef DBG_UTIL
501cdf0e10cSrcweir 
502cdf0e10cSrcweir 	if (pObject == NULL)
503cdf0e10cSrcweir 	{
504cdf0e10cSrcweir 		DBG_ASSERT(bForward ? m_lAt == m_aTable.GetSize() -1 : m_lAt == 0,
505cdf0e10cSrcweir 			"HashTableIterator::FindValidObject()");
506cdf0e10cSrcweir 	}
507cdf0e10cSrcweir 
508cdf0e10cSrcweir #endif
509cdf0e10cSrcweir 
510cdf0e10cSrcweir 	return pObject;
511cdf0e10cSrcweir }
512