1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hash.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 // #include "precompiled_sal.hxx"
36 #include <osl/diagnose.h>
40 #include "rtl/allocator.hxx"
47 size_t operator()(rtl_uString
* const &rString
) const
48 { return (size_t)rtl_ustr_hashCode_WithLength( rString
->buffer
, rString
->length
); }
52 sal_Bool
operator() ( rtl_uString
* const &pStringA
,
53 rtl_uString
* const &pStringB
) const
55 if (pStringA
== pStringB
)
57 if (pStringA
->length
!= pStringB
->length
)
59 return !rtl_ustr_compare_WithLength( pStringA
->buffer
, pStringA
->length
,
60 pStringB
->buffer
, pStringB
->length
);
65 typedef std::hash_set
< rtl_uString
*, UStringHash
, UStringEqual
,
66 rtl::Allocator
<rtl_uString
*> > UniqueHash
;
68 struct StringHashTableImpl
: public UniqueHash
70 StringHashTableImpl(sal_uInt32 nSize
) : UniqueHash( nSize
) {}
74 rtl_str_hash_new (sal_uInt32 nSize
)
76 return new StringHashTableImpl (nSize
);
80 rtl_str_hash_free (StringHashTable
*pHash
)
86 rtl_str_hash_intern (StringHashTable
*pHash
,
90 UniqueHash::iterator aIter
;
91 aIter
= pHash
->find(pString
);
92 if (aIter
!= pHash
->end())
94 rtl_uString
*pHashStr
= *aIter
;
95 rtl_uString_acquire (pHashStr
);
100 rtl_uString
*pCopy
= NULL
;
101 rtl_uString_newFromString( &pCopy
, pString
);
107 if (!SAL_STRING_IS_STATIC (pString
))
108 pString
->refCount
|= SAL_STRING_INTERN_FLAG
;
109 pHash
->insert(pString
);
115 rtl_str_hash_remove (StringHashTable
*pHash
,
116 rtl_uString
*pString
)
118 pHash
->erase(pString
);
123 // --------------------------- start here ---------------------------
125 struct StringHashTableImpl
{
131 // Better / smaller / faster hash set ....
133 // TODO: add bottom bit-set list terminator to string list
136 getNextSize (sal_uInt32 nSize
)
138 // Sedgewick - Algorithms in C P577.
139 static const sal_uInt32 nPrimes
[] = { 1021, 2039, 4093, 8191, 16381, 32749,
140 65521, 131071,262139, 524287, 1048573,
141 2097143, 4194301, 8388593, 16777213,
142 33554393, 67108859, 134217689 };
143 #define NUM_PRIMES (sizeof (nPrimes)/ sizeof (nPrimes[0]))
144 for (int i
= 0; i
< NUM_PRIMES
; i
++)
146 if (nPrimes
[i
] > nSize
)
153 hashString (rtl_uString
*pString
)
155 return (sal_uInt32
) rtl_ustr_hashCode_WithLength (pString
->buffer
,
160 rtl_str_hash_new (sal_uInt32 nSize
)
162 StringHashTable
*pHash
= (StringHashTable
*)malloc (sizeof (StringHashTable
));
165 pHash
->nSize
= getNextSize (nSize
);
166 pHash
->pData
= (rtl_uString
**) calloc (sizeof (rtl_uString
*), pHash
->nSize
);
172 rtl_str_hash_insert_nonequal (StringHashTable
*pHash
,
173 rtl_uString
*pString
)
175 sal_uInt32 nHash
= hashString (pString
);
177 rtl_uString
*pHashStr
;
179 n
= nHash
% pHash
->nSize
;
180 while ((pHashStr
= pHash
->pData
[n
]) != NULL
) {
182 if (n
>= pHash
->nSize
)
185 pHash
->pData
[n
] = pString
;
189 rtl_str_hash_resize (StringHashTable
*pHash
,
193 StringHashTable
*pNewHash
;
195 OSL_ASSERT (nNewSize
> pHash
->nEntries
);
197 pNewHash
= rtl_str_hash_new (nNewSize
);
199 for (i
= 0; i
< pHash
->nSize
; i
++)
201 if (pHash
->pData
[i
] != NULL
)
202 rtl_str_hash_insert_nonequal (pNewHash
, pHash
->pData
[i
]);
204 pNewHash
->nEntries
= pHash
->nEntries
;
207 pNewHash
->pData
= NULL
;
208 rtl_str_hash_free (pNewHash
);
212 rtl_str_hash_free (StringHashTable
*pHash
)
222 compareEqual (rtl_uString
*pStringA
, rtl_uString
*pStringB
)
224 if (pStringA
== pStringB
)
226 if (pStringA
->length
!= pStringB
->length
)
228 return !rtl_ustr_compare_WithLength( pStringA
->buffer
, pStringA
->length
,
229 pStringB
->buffer
, pStringB
->length
);
233 rtl_str_hash_intern (StringHashTable
*pHash
,
234 rtl_uString
*pString
,
237 sal_uInt32 nHash
= hashString (pString
);
239 rtl_uString
*pHashStr
;
241 // Should we resize ?
242 if (pHash
->nEntries
>= pHash
->nSize
/2)
243 rtl_str_hash_resize (pHash
, getNextSize(pHash
->nSize
));
245 n
= nHash
% pHash
->nSize
;
246 while ((pHashStr
= pHash
->pData
[n
]) != NULL
) {
247 if (compareEqual (pHashStr
, pString
))
249 rtl_uString_acquire (pHashStr
);
253 if (n
>= pHash
->nSize
)
259 rtl_uString
*pCopy
= NULL
;
260 rtl_uString_newFromString( &pCopy
, pString
);
266 if (!SAL_STRING_IS_STATIC (pString
))
267 pString
->refCount
|= SAL_STRING_INTERN_FLAG
;
268 pHash
->pData
[n
] = pString
;
275 rtl_str_hash_remove (StringHashTable
*pHash
,
276 rtl_uString
*pString
)
279 sal_uInt32 nHash
= hashString (pString
);
280 rtl_uString
*pHashStr
;
282 n
= nHash
% pHash
->nSize
;
283 while ((pHashStr
= pHash
->pData
[n
]) != NULL
) {
284 if (compareEqual (pHashStr
, pString
))
287 if (n
>= pHash
->nSize
)
290 OSL_ASSERT (pHash
->pData
[n
] != 0);
291 if (pHash
->pData
[n
] == NULL
)
294 pHash
->pData
[n
++] = NULL
;
297 if (n
>= pHash
->nSize
)
300 while ((pHashStr
= pHash
->pData
[n
]) != NULL
) {
301 pHash
->pData
[n
] = NULL
;
302 // FIXME: rather unsophisticated and N^2 in chain-length, but robust.
303 rtl_str_hash_insert_nonequal (pHash
, pHashStr
);
305 if (n
>= pHash
->nSize
)
308 // FIXME: Should we down-size ?