Lines 1-3
Link Here
|
|
|
1 |
#include <stdio.h> |
1 |
/************************************************************************* |
2 |
/************************************************************************* |
2 |
* |
3 |
* |
3 |
* OpenOffice.org - a multi-platform office productivity suite |
4 |
* OpenOffice.org - a multi-platform office productivity suite |
Lines 34-48
Link Here
|
34 |
************************************************************************/ |
35 |
************************************************************************/ |
35 |
|
36 |
|
36 |
// MARKER(update_precomp.py): autogen include statement, do not remove |
37 |
// MARKER(update_precomp.py): autogen include statement, do not remove |
37 |
#include "precompiled_sal.hxx" |
38 |
// #include "precompiled_sal.hxx" |
38 |
|
|
|
39 |
#ifndef INCLUDED_RTL_ALLOCATOR_HXX |
40 |
#include "rtl/allocator.hxx" |
41 |
#endif |
42 |
|
39 |
|
43 |
#include "hash.h" |
40 |
#include "hash.h" |
44 |
#include "strimp.h" |
41 |
#include "strimp.h" |
|
|
42 |
#include <osl/diagnose.h> |
45 |
|
43 |
|
|
|
44 |
#if 0 |
45 |
|
46 |
#ifndef INCLUDED_RTL_ALLOCATOR_HXX |
47 |
#include "rtl/allocator.hxx" |
48 |
#endif |
46 |
|
49 |
|
47 |
#include <hash_set> |
50 |
#include <hash_set> |
48 |
|
51 |
|
Lines 121-123
Link Here
|
121 |
{ |
124 |
{ |
122 |
pHash->erase(pString); |
125 |
pHash->erase(pString); |
123 |
} |
126 |
} |
|
|
127 |
|
128 |
#else |
129 |
|
130 |
// --------------------------- start here --------------------------- |
131 |
|
132 |
struct StringHashTableImpl { |
133 |
sal_uInt32 nEntries; |
134 |
sal_uInt32 nSize; |
135 |
rtl_uString **pData; |
136 |
}; |
137 |
|
138 |
// Better / smaller / faster hash set .... |
139 |
|
140 |
// TODO: add bottom bit-set list terminator to string list |
141 |
|
142 |
static sal_uInt32 |
143 |
getNextSize (sal_uInt32 nSize) |
144 |
{ |
145 |
return nSize * 2; |
146 |
} |
147 |
|
148 |
static sal_uInt32 |
149 |
hashString (rtl_uString *pString) |
150 |
{ |
151 |
return (sal_uInt32) rtl_ustr_hashCode_WithLength (pString->buffer, |
152 |
pString->length); |
153 |
} |
154 |
|
155 |
StringHashTable * |
156 |
rtl_str_hash_new (sal_uInt32 nSize) |
157 |
{ |
158 |
StringHashTable *pHash = (StringHashTable *)malloc (sizeof (StringHashTable)); |
159 |
|
160 |
pHash->nEntries = 0; |
161 |
pHash->nSize = getNextSize (nSize); |
162 |
pHash->pData = (rtl_uString **) calloc (sizeof (rtl_uString *), pHash->nSize); |
163 |
|
164 |
return pHash; |
165 |
} |
166 |
|
167 |
static void |
168 |
rtl_str_hash_insert_nonequal (StringHashTable *pHash, |
169 |
rtl_uString *pString) |
170 |
{ |
171 |
sal_uInt32 nHash = hashString (pString); |
172 |
sal_uInt32 n; |
173 |
rtl_uString *pHashStr; |
174 |
|
175 |
n = nHash % pHash->nSize; |
176 |
while ((pHashStr = pHash->pData[n]) != NULL) { |
177 |
n++; |
178 |
if (n >= pHash->nSize) |
179 |
n = 0; |
180 |
} |
181 |
pHash->pData[n] = pString; |
182 |
} |
183 |
|
184 |
static void |
185 |
rtl_str_hash_resize (StringHashTable *pHash, |
186 |
sal_uInt32 nNewSize) |
187 |
{ |
188 |
sal_uInt32 i; |
189 |
StringHashTable *pNewHash; |
190 |
|
191 |
OSL_ASSERT (nNewSize > pHash->nEntries); |
192 |
// fprintf (stderr, "Newsize %d entries %d\n", |
193 |
// (int)nNewSize, (int)pHash->nEntries); |
194 |
|
195 |
pNewHash = rtl_str_hash_new (nNewSize); |
196 |
|
197 |
for (i = 0; i < pHash->nSize; i++) |
198 |
{ |
199 |
if (pHash->pData[i] != NULL) |
200 |
rtl_str_hash_insert_nonequal (pNewHash, pHash->pData[i]); |
201 |
} |
202 |
pNewHash->nEntries = pHash->nEntries; |
203 |
free (pHash->pData); |
204 |
*pHash = *pNewHash; |
205 |
pNewHash->pData = NULL; |
206 |
rtl_str_hash_free (pNewHash); |
207 |
// fprintf (stderr, "resize hash to %d\n", (int)nNewSize); |
208 |
} |
209 |
|
210 |
void |
211 |
rtl_str_hash_free (StringHashTable *pHash) |
212 |
{ |
213 |
if (!pHash) |
214 |
return; |
215 |
if (pHash->pData) |
216 |
free (pHash->pData); |
217 |
free (pHash); |
218 |
} |
219 |
|
220 |
static int |
221 |
compareEqual (rtl_uString *pStringA, rtl_uString *pStringB) |
222 |
{ |
223 |
if (pStringA == pStringB) |
224 |
return 1; |
225 |
if (pStringA->length != pStringB->length) |
226 |
return 0; |
227 |
return !rtl_ustr_compare_WithLength( pStringA->buffer, pStringA->length, |
228 |
pStringB->buffer, pStringB->length); |
229 |
} |
230 |
|
231 |
rtl_uString * |
232 |
rtl_str_hash_intern (StringHashTable *pHash, |
233 |
rtl_uString *pString, |
234 |
int can_return) |
235 |
{ |
236 |
sal_uInt32 nHash = hashString (pString); |
237 |
sal_uInt32 n; |
238 |
rtl_uString *pHashStr; |
239 |
|
240 |
// Should we resize ? |
241 |
if (pHash->nEntries >= pHash->nSize/2) |
242 |
rtl_str_hash_resize (pHash, getNextSize(pHash->nSize)); |
243 |
|
244 |
n = nHash % pHash->nSize; |
245 |
while ((pHashStr = pHash->pData[n]) != NULL) { |
246 |
if (compareEqual (pHashStr, pString)) |
247 |
{ |
248 |
rtl_uString_acquire (pHashStr); |
249 |
return pHashStr; |
250 |
} |
251 |
n++; |
252 |
if (n >= pHash->nSize) |
253 |
n = 0; |
254 |
} |
255 |
|
256 |
if (!can_return) |
257 |
{ |
258 |
rtl_uString *pCopy = NULL; |
259 |
rtl_uString_newFromString( &pCopy, pString ); |
260 |
pString = pCopy; |
261 |
if (!pString) |
262 |
return NULL; |
263 |
} |
264 |
|
265 |
if (!SAL_STRING_IS_STATIC (pString)) |
266 |
pString->refCount |= SAL_STRING_INTERN_FLAG; |
267 |
pHash->pData[n] = pString; |
268 |
pHash->nEntries++; |
269 |
|
270 |
// fprintf (stderr, "hash insert %d\n", pHash->nEntries); |
271 |
|
272 |
return pString; |
273 |
} |
274 |
|
275 |
void |
276 |
rtl_str_hash_remove (StringHashTable *pHash, |
277 |
rtl_uString *pString) |
278 |
{ |
279 |
sal_uInt32 n; |
280 |
sal_uInt32 nHash = hashString (pString); |
281 |
rtl_uString *pHashStr; |
282 |
|
283 |
n = nHash % pHash->nSize; |
284 |
while ((pHashStr = pHash->pData[n]) != NULL) { |
285 |
if (compareEqual (pHashStr, pString)) |
286 |
break; |
287 |
n++; |
288 |
if (n >= pHash->nSize) |
289 |
n = 0; |
290 |
} |
291 |
OSL_ASSERT (pHash->pData[n] != 0); |
292 |
if (pHash->pData[n] == NULL) |
293 |
{ |
294 |
fprintf (stderr, "hash remove non-existent entity\n"); |
295 |
return; |
296 |
} |
297 |
pHash->pData[n++] = NULL; |
298 |
pHash->nEntries--; |
299 |
|
300 |
// fprintf (stderr, "hash remove %d\n", pHash->nEntries); |
301 |
|
302 |
while ((pHashStr = pHash->pData[n]) != NULL) { |
303 |
pHash->pData[n] = NULL; |
304 |
// FIXME: rather unsophisticated and N^2 in chain-length |
305 |
rtl_str_hash_insert_nonequal (pHash, pHashStr); |
306 |
n++; |
307 |
if (n >= pHash->nSize) |
308 |
n = 0; |
309 |
} |
310 |
// FIXME: Should we down-size ? |
311 |
} |
312 |
|
313 |
// FIXME - add bottom-bit set to terminate list ... |
314 |
|
315 |
#endif |
316 |
|
317 |
// TODO: |
318 |
// consider bucket overlaps: |
319 |
// a a b a a b [ how do we terminate ? ] - just run until the 0 ? |
320 |
// -- any terminator behaves the same ? -- |
321 |
// non-null inserts: |
322 |
// 3 scenarios: insert & removal & lookup ;-) |
323 |
// insert: [a a ~a ] -> [a a a ~b] |
324 |
// insert: [a ~a ] -> [ a a ~b ] - ie. merged chains - un-merging ? |
325 |
// [ how do we un-merge ? - re-hashing strings ? ] |
326 |
// if we collide with another chain: need to de-terminate it ? |
327 |
|