View | Details | Raw Unified | Return to issue 78496
Collapse All | Expand All

(-)sal/rtl/source/hash.cxx (+221 lines)
Lines 26-37 Link Here
26
 ************************************************************************/
26
 ************************************************************************/
27
27
28
// MARKER(update_precomp.py): autogen include statement, do not remove
28
// MARKER(update_precomp.py): autogen include statement, do not remove
29
#if 0
29
#include "precompiled_sal.hxx"
30
#include "precompiled_sal.hxx"
30
#include "rtl/allocator.hxx"
31
#include "rtl/allocator.hxx"
32
#endif
31
33
32
#include "hash.h"
34
#include "hash.h"
33
#include "strimp.h"
35
#include "strimp.h"
36
#include <osl/diagnose.h>
34
37
38
#if 0
35
39
36
#include <hash_set>
40
#include <hash_set>
37
41
Lines 110-113 rtl_str_hash_remove (rtl_uString *pString) Link Here
110
    getHashTable()->erase(pString);
114
    getHashTable()->erase(pString);
111
}
115
}
112
116
117
#endif
118
119
// --------------------------- start here ---------------------------
120
121
struct StringHashTableImpl {
122
    sal_uInt32    nEntries;
123
    sal_uInt32    nSize;
124
    rtl_uString **pData;
125
};
126
127
typedef StringHashTableImpl StringHashTable;
128
129
extern "C" {
130
131
// Only for use in the implementation
132
StringHashTable *rtl_str_hash_new (sal_uInt32 nSize);
133
void rtl_str_hash_free (StringHashTable *pHash);
134
135
}
136
137
StringHashTable *
138
getHashTable ()
139
{
140
    static StringHashTable *pInternPool = NULL;
141
    if (pInternPool == NULL) {
142
        static StringHashTable* pHash = rtl_str_hash_new(1024);
143
        pInternPool = pHash;
144
    }
145
    return pInternPool;
146
}
147
148
extern "C" {
149
150
// Better / smaller / faster hash set ....
151
152
// TODO: add bottom bit-set list terminator to string list
153
154
static sal_uInt32
155
getNextSize (sal_uInt32 nSize)
156
{
157
    // Sedgewick - Algorithms in C P577.
158
    static const sal_uInt32 nPrimes[] = { 1021, 2039, 4093, 8191, 16381, 32749,
159
                                          65521, 131071,262139, 524287, 1048573,
160
                                          2097143, 4194301, 8388593, 16777213,
161
                                          33554393, 67108859, 134217689 };
162
    #define NUM_PRIMES (sizeof (nPrimes)/ sizeof (nPrimes[0]))
163
    for (sal_uInt32 i = 0; i < NUM_PRIMES; i++)
164
    {
165
        if (nPrimes[i] > nSize)
166
            return nPrimes[i];
167
    }
168
    return nSize * 2;
169
}
170
171
static sal_uInt32
172
hashString (rtl_uString *pString)
173
{
174
    return (sal_uInt32) rtl_ustr_hashCode_WithLength (pString->buffer,
175
                                                      pString->length);
176
}
177
178
StringHashTable *
179
rtl_str_hash_new (sal_uInt32 nSize)
180
{
181
    StringHashTable *pHash = (StringHashTable *)malloc (sizeof (StringHashTable));
182
183
    pHash->nEntries = 0;
184
    pHash->nSize = getNextSize (nSize);
185
    pHash->pData = (rtl_uString **) calloc (sizeof (rtl_uString *), pHash->nSize);
186
187
    return pHash;
188
}
189
190
void
191
rtl_str_hash_free (StringHashTable *pHash)
192
{
193
    if (!pHash)
194
        return;
195
    if (pHash->pData)
196
        free (pHash->pData);
197
    free (pHash);
198
}
199
200
static void
201
rtl_str_hash_insert_nonequal (StringHashTable   *pHash,
202
                              rtl_uString       *pString)
203
{
204
    sal_uInt32  nHash = hashString (pString);
205
    sal_uInt32  n;
206
    rtl_uString *pHashStr;
207
208
    n = nHash % pHash->nSize;
209
    while ((pHashStr = pHash->pData[n]) != NULL) {
210
        n++;
211
        if (n >= pHash->nSize)
212
            n = 0;
213
    }
214
    pHash->pData[n] = pString;
215
}
216
217
static void
218
rtl_str_hash_resize (sal_uInt32        nNewSize)
219
{
220
    sal_uInt32 i;
221
    StringHashTable *pNewHash;
222
    StringHashTable *pHash = getHashTable();
223
224
    OSL_ASSERT (nNewSize > pHash->nEntries);
225
226
    pNewHash = rtl_str_hash_new (nNewSize);
227
228
    for (i = 0; i < pHash->nSize; i++)
229
    {
230
        if (pHash->pData[i] != NULL)
231
            rtl_str_hash_insert_nonequal (pNewHash, pHash->pData[i]);
232
    }
233
    pNewHash->nEntries = pHash->nEntries;
234
    free (pHash->pData);
235
    *pHash = *pNewHash;
236
    pNewHash->pData = NULL;
237
    rtl_str_hash_free (pNewHash);
238
}
239
240
static int
241
compareEqual (rtl_uString *pStringA, rtl_uString *pStringB)
242
{
243
    if (pStringA == pStringB)
244
        return 1;
245
    if (pStringA->length != pStringB->length)
246
        return 0;
247
    return !rtl_ustr_compare_WithLength( pStringA->buffer, pStringA->length,
248
                                         pStringB->buffer, pStringB->length);
249
}
250
251
252
rtl_uString *
253
rtl_str_hash_intern (rtl_uString       *pString,
254
                     int                can_return)
255
{
256
    sal_uInt32  nHash = hashString (pString);
257
    sal_uInt32  n;
258
    rtl_uString *pHashStr;
259
    
260
    StringHashTable *pHash = getHashTable();
261
262
    // Should we resize ?
263
    if (pHash->nEntries >= pHash->nSize/2)
264
        rtl_str_hash_resize (getNextSize(pHash->nSize));
265
266
    n = nHash % pHash->nSize;
267
    while ((pHashStr = pHash->pData[n]) != NULL) {
268
        if (compareEqual (pHashStr, pString))
269
        {
270
            rtl_uString_acquire (pHashStr);
271
            return pHashStr;
272
        }
273
        n++;
274
        if (n >= pHash->nSize)
275
            n = 0;
276
    }
277
278
    if (!can_return)
279
    {
280
        rtl_uString *pCopy = NULL;
281
        rtl_uString_newFromString( &pCopy, pString );
282
        pString = pCopy;
283
        if (!pString)
284
            return NULL;
285
    }
286
287
    if (!SAL_STRING_IS_STATIC (pString))
288
        pString->refCount |= SAL_STRING_INTERN_FLAG;
289
    pHash->pData[n] = pString;
290
    pHash->nEntries++;
291
292
    return pString;
293
}
294
295
void
296
rtl_str_hash_remove (rtl_uString       *pString)
297
{
298
    sal_uInt32   n;
299
    sal_uInt32   nHash = hashString (pString);
300
    rtl_uString *pHashStr;
301
302
    StringHashTable *pHash = getHashTable();
303
304
    n = nHash % pHash->nSize;
305
    while ((pHashStr = pHash->pData[n]) != NULL) {
306
        if (compareEqual (pHashStr, pString))
307
            break;
308
        n++;
309
        if (n >= pHash->nSize)
310
            n = 0;
311
    }
312
    OSL_ASSERT (pHash->pData[n] != 0);
313
    if (pHash->pData[n] == NULL)
314
        return;
315
316
    pHash->pData[n++] = NULL;
317
    pHash->nEntries--;
318
319
    if (n >= pHash->nSize)
320
        n = 0;
321
322
    while ((pHashStr = pHash->pData[n]) != NULL) {
323
        pHash->pData[n] = NULL;
324
        // FIXME: rather unsophisticated and N^2 in chain-length, but robust.
325
        rtl_str_hash_insert_nonequal (pHash, pHashStr);
326
        n++;
327
        if (n >= pHash->nSize)
328
            n = 0;
329
    }
330
    // FIXME: Should we down-size ?
331
}
332
333
113
}
334
}

Return to issue 78496