xref: /aoo41x/main/soldep/bootstrp/hashtbl.cxx (revision d9e04f7d)
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