Index: sal/rtl/source/hash.cxx =================================================================== RCS file: /cvs/porting/sal/rtl/source/hash.cxx,v retrieving revision 1.3 diff -u -r1.3 hash.cxx --- sal/rtl/source/hash.cxx 19 Apr 2007 11:56:36 -0000 1.3 +++ sal/rtl/source/hash.cxx 15 Jun 2007 09:06:33 -0000 @@ -34,15 +34,17 @@ ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sal.hxx" - -#ifndef INCLUDED_RTL_ALLOCATOR_HXX -#include "rtl/allocator.hxx" -#endif +// #include "precompiled_sal.hxx" #include "hash.h" #include "strimp.h" +#include + +#if 0 +#ifndef INCLUDED_RTL_ALLOCATOR_HXX +#include "rtl/allocator.hxx" +#endif #include @@ -121,3 +123,192 @@ { pHash->erase(pString); } + +#else + +// --------------------------- start here --------------------------- + +struct StringHashTableImpl { + sal_uInt32 nEntries; + sal_uInt32 nSize; + rtl_uString **pData; +}; + +// Better / smaller / faster hash set .... + +// TODO: add bottom bit-set list terminator to string list + +static sal_uInt32 +getNextSize (sal_uInt32 nSize) +{ + // Sedgewick - Algorithms in C P577. + static const sal_uInt32 nPrimes[] = { 1021, 2039, 4093, 8191, 16381, 32749, + 65521, 131071,262139, 524287, 1048573, + 2097143, 4194301, 8388593, 16777213, + 33554393, 67108859, 134217689 }; + #define NUM_PRIMES (sizeof (nPrimes)/ sizeof (nPrimes[0])) + for (int i = 0; i < NUM_PRIMES; i++) + { + if (nPrimes[i] > nSize) + return nPrimes[i]; + } + return nSize * 2; +} + +static sal_uInt32 +hashString (rtl_uString *pString) +{ + return (sal_uInt32) rtl_ustr_hashCode_WithLength (pString->buffer, + pString->length); +} + +StringHashTable * +rtl_str_hash_new (sal_uInt32 nSize) +{ + StringHashTable *pHash = (StringHashTable *)malloc (sizeof (StringHashTable)); + + pHash->nEntries = 0; + pHash->nSize = getNextSize (nSize); + pHash->pData = (rtl_uString **) calloc (sizeof (rtl_uString *), pHash->nSize); + + return pHash; +} + +static void +rtl_str_hash_insert_nonequal (StringHashTable *pHash, + rtl_uString *pString) +{ + sal_uInt32 nHash = hashString (pString); + sal_uInt32 n; + rtl_uString *pHashStr; + + n = nHash % pHash->nSize; + while ((pHashStr = pHash->pData[n]) != NULL) { + n++; + if (n >= pHash->nSize) + n = 0; + } + pHash->pData[n] = pString; +} + +static void +rtl_str_hash_resize (StringHashTable *pHash, + sal_uInt32 nNewSize) +{ + sal_uInt32 i; + StringHashTable *pNewHash; + + OSL_ASSERT (nNewSize > pHash->nEntries); + + pNewHash = rtl_str_hash_new (nNewSize); + + for (i = 0; i < pHash->nSize; i++) + { + if (pHash->pData[i] != NULL) + rtl_str_hash_insert_nonequal (pNewHash, pHash->pData[i]); + } + pNewHash->nEntries = pHash->nEntries; + free (pHash->pData); + *pHash = *pNewHash; + pNewHash->pData = NULL; + rtl_str_hash_free (pNewHash); +} + +void +rtl_str_hash_free (StringHashTable *pHash) +{ + if (!pHash) + return; + if (pHash->pData) + free (pHash->pData); + free (pHash); +} + +static int +compareEqual (rtl_uString *pStringA, rtl_uString *pStringB) +{ + if (pStringA == pStringB) + return 1; + if (pStringA->length != pStringB->length) + return 0; + return !rtl_ustr_compare_WithLength( pStringA->buffer, pStringA->length, + pStringB->buffer, pStringB->length); +} + +rtl_uString * +rtl_str_hash_intern (StringHashTable *pHash, + rtl_uString *pString, + int can_return) +{ + sal_uInt32 nHash = hashString (pString); + sal_uInt32 n; + rtl_uString *pHashStr; + + // Should we resize ? + if (pHash->nEntries >= pHash->nSize/2) + rtl_str_hash_resize (pHash, getNextSize(pHash->nSize)); + + n = nHash % pHash->nSize; + while ((pHashStr = pHash->pData[n]) != NULL) { + if (compareEqual (pHashStr, pString)) + { + rtl_uString_acquire (pHashStr); + return pHashStr; + } + n++; + if (n >= pHash->nSize) + n = 0; + } + + if (!can_return) + { + rtl_uString *pCopy = NULL; + rtl_uString_newFromString( &pCopy, pString ); + pString = pCopy; + if (!pString) + return NULL; + } + + if (!SAL_STRING_IS_STATIC (pString)) + pString->refCount |= SAL_STRING_INTERN_FLAG; + pHash->pData[n] = pString; + pHash->nEntries++; + + return pString; +} + +void +rtl_str_hash_remove (StringHashTable *pHash, + rtl_uString *pString) +{ + sal_uInt32 n; + sal_uInt32 nHash = hashString (pString); + rtl_uString *pHashStr; + + n = nHash % pHash->nSize; + while ((pHashStr = pHash->pData[n]) != NULL) { + if (compareEqual (pHashStr, pString)) + break; + n++; + if (n >= pHash->nSize) + n = 0; + } + OSL_ASSERT (pHash->pData[n] != 0); + if (pHash->pData[n] == NULL) + return; + + pHash->pData[n++] = NULL; + pHash->nEntries--; + + while ((pHashStr = pHash->pData[n]) != NULL) { + pHash->pData[n] = NULL; + // FIXME: rather unsophisticated and N^2 in chain-length, but robust. + rtl_str_hash_insert_nonequal (pHash, pHashStr); + n++; + if (n >= pHash->nSize) + n = 0; + } + // FIXME: Should we down-size ? +} + +#endif