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