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

(-)sal/rtl/source/hash.cxx (-5 / +209 lines)
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

Return to issue 78496