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