diff options
author | Noel Grandin <noelgrandin@gmail.com> | 2018-09-16 09:10:22 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2018-10-05 08:07:17 +0200 |
commit | 35a7dd63dd8e2c8489ef95c661d5373247f7ed3b (patch) | |
tree | fae9ed3a235239573072bc82038e4f3b89586221 /sal/rtl | |
parent | 09841225fc055f8270cee3059253f923dd544797 (diff) |
use std::unordered_map in locale
instead of hand-coded hash table
Change-Id: I1c52f98b5a72609f7cd8086227017a486d97520e
Reviewed-on: https://gerrit.libreoffice.org/60706
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'sal/rtl')
-rw-r--r-- | sal/rtl/locale.cxx | 212 |
1 files changed, 23 insertions, 189 deletions
diff --git a/sal/rtl/locale.cxx b/sal/rtl/locale.cxx index 579538f056f3..e362a342bcbc 100644 --- a/sal/rtl/locale.cxx +++ b/sal/rtl/locale.cxx @@ -23,202 +23,40 @@ #include <osl/diagnose.h> #include <rtllifecycle.h> +#include <memory> +#include <unordered_map> -static const sal_Int32 RTL_HASHTABLE_SIZE[] = +struct locale_deleter { - 7, 31, 127, 251, 509, 1021, 2039, 4093 -}; - -struct RTL_HASHENTRY -{ - rtl_Locale* Entry; - RTL_HASHENTRY* Next; -}; - -struct RTL_HASHTABLE -{ - sal_Int8 iSize; - sal_Int32 Size; - sal_Int32 Elements; - RTL_HASHENTRY** Table; -}; - -static RTL_HASHTABLE* g_pLocaleTable = nullptr; - -static rtl_Locale* g_pDefaultLocale = nullptr; - -namespace { - -void rtl_hashentry_destroy(RTL_HASHENTRY* entry) -{ - rtl_uString_release(entry->Entry->Language); - rtl_uString_release(entry->Entry->Country); - rtl_uString_release(entry->Entry->Variant); - - if (entry->Next) - rtl_hashentry_destroy(entry->Next); - - free(entry->Entry); - free(entry); -} - -void rtl_hashtable_destroy(RTL_HASHTABLE* table) -{ - sal_Int32 size = 0; - - if (!table) - return; - - size = table->Size; - - while (size) - { - if (table->Table[size - 1]) - rtl_hashentry_destroy(table->Table[size - 1]); - - size--; - } - - free(table->Table); - free(table); -} - -void rtl_hashtable_init(RTL_HASHTABLE** table, sal_Int8 sizeIndex) -{ - sal_Int32 nSize = RTL_HASHTABLE_SIZE[sizeIndex]; - - if (*table) - rtl_hashtable_destroy(*table); - - *table = static_cast< RTL_HASHTABLE* >(malloc(sizeof(RTL_HASHTABLE))); - - (*table)->iSize = sizeIndex; - (*table)->Size = nSize; - (*table)->Elements = 0; - (*table)->Table = static_cast< RTL_HASHENTRY** >(malloc((*table)->Size * sizeof(RTL_HASHENTRY*))); - - while (nSize) - { - (*table)->Table[nSize - 1] = nullptr; - nSize--; - } -} - -sal_Int32 rtl_hashfunc(RTL_HASHTABLE* table, sal_Int32 key) -{ - return (static_cast<sal_uInt32>(key) % table->Size); -} - -bool rtl_hashtable_grow(RTL_HASHTABLE** table); - -rtl_Locale* rtl_hashtable_add(RTL_HASHTABLE** table, rtl_Locale* value) -{ - sal_Int32 key = 0; - - if (!(*table)) - return nullptr; - - if ((*table)->Elements > ((*table)->Size / 2)) - rtl_hashtable_grow(table); - - key = rtl_hashfunc(*table, value->HashCode); - - RTL_HASHENTRY **pEntry = &(*table)->Table[key]; - while (*pEntry) + void operator() (rtl_Locale* p) noexcept { - if (value->HashCode == (*pEntry)->Entry->HashCode) - return (*pEntry)->Entry; - - pEntry = &(*pEntry)->Next; - } - - RTL_HASHENTRY *newEntry = static_cast< RTL_HASHENTRY* >(malloc(sizeof(RTL_HASHENTRY))); - newEntry->Entry = value; - newEntry->Next = nullptr; - *pEntry = newEntry; - (*table)->Elements++; - return nullptr; -} - -bool rtl_hashtable_grow(RTL_HASHTABLE** table) -{ - RTL_HASHTABLE* pNewTable = nullptr; - sal_Int32 i = 0; - - rtl_hashtable_init(&pNewTable, static_cast<sal_Int8>((*table)->iSize + 1)); - - while (i < (*table)->Size) - { - if ((*table)->Table[i]) - { - RTL_HASHENTRY *pNext; - RTL_HASHENTRY *pEntry = (*table)->Table[i]; - - rtl_hashtable_add(&pNewTable, pEntry->Entry); - - while (pEntry->Next) - { - rtl_hashtable_add(&pNewTable, pEntry->Next->Entry); - pNext = pEntry->Next; - free(pEntry); - pEntry = pNext; - } - - free(pEntry); - } - - i++; + rtl_uString_release(p->Language); + rtl_uString_release(p->Country); + rtl_uString_release(p->Variant); + delete p; } +}; - free((*table)->Table); - free(*table); - (*table) = pNewTable; - - return true; -} - -bool rtl_hashtable_find(RTL_HASHTABLE * table, sal_Int32 key, sal_Int32 hashCode, rtl_Locale** pValue) -{ - if (!table) - return false; - - if (table->Table[key]) - { - RTL_HASHENTRY *pEntry = table->Table[key]; +using locale_unique_ptr = std::unique_ptr<rtl_Locale, locale_deleter>; - while (pEntry && hashCode != pEntry->Entry->HashCode) - { - pEntry = pEntry->Next; - } +static std::unordered_map<sal_Int32, locale_unique_ptr>* g_pLocaleTable = nullptr; - if (pEntry) - *pValue = pEntry->Entry; - else - return false; - } - else - { - return false; - } - - return true; -} - -} +static rtl_Locale* g_pDefaultLocale = nullptr; void rtl_locale_init() { - OSL_ASSERT(!g_pLocaleTable); - rtl_hashtable_init(&g_pLocaleTable, 1); + if (!g_pLocaleTable) + g_pLocaleTable = new std::unordered_map<sal_Int32, locale_unique_ptr>; } void rtl_locale_fini() { if (g_pLocaleTable) { - rtl_hashtable_destroy (g_pLocaleTable); + delete g_pLocaleTable; g_pLocaleTable = nullptr; } + g_pDefaultLocale = nullptr; } rtl_Locale * SAL_CALL rtl_locale_register(const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant) @@ -227,9 +65,7 @@ rtl_Locale * SAL_CALL rtl_locale_register(const sal_Unicode * language, const sa rtl_uString* sLanguage = nullptr; rtl_uString* sCountry = nullptr; rtl_uString* sVariant = nullptr; - rtl_Locale *newLocale = nullptr; sal_Int32 hashCode = -1; - sal_Int32 key = 0; if (!country) country = &c; @@ -238,29 +74,27 @@ rtl_Locale * SAL_CALL rtl_locale_register(const sal_Unicode * language, const sa variant = &c; ensureLocaleSingleton(); - if (!g_pLocaleTable) - return nullptr; hashCode = rtl_ustr_hashCode(language) ^ rtl_ustr_hashCode(country) ^ rtl_ustr_hashCode(variant); - key = rtl_hashfunc(g_pLocaleTable, hashCode); - if (rtl_hashtable_find(g_pLocaleTable, key, hashCode, &newLocale)) - return newLocale; + auto it = g_pLocaleTable->find(hashCode); + if (it != g_pLocaleTable->end()) + return it->second.get(); rtl_uString_newFromStr(&sLanguage, language); rtl_uString_newFromStr(&sCountry, country); rtl_uString_newFromStr(&sVariant, variant); - newLocale = static_cast<rtl_Locale*>(malloc( sizeof(rtl_Locale) )); + locale_unique_ptr newLocale(new rtl_Locale); newLocale->Language = sLanguage; newLocale->Country = sCountry; newLocale->Variant = sVariant; newLocale->HashCode = hashCode; - rtl_hashtable_add(&g_pLocaleTable, newLocale); - - return newLocale; + auto ret = newLocale.get(); + g_pLocaleTable->insert(it, std::pair<sal_Int32, locale_unique_ptr>( hashCode, std::move(newLocale) ) ); + return ret; } rtl_Locale * SAL_CALL rtl_locale_getDefault() |