| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | #include "rtl/locale.h" |
| 30 | |
| 31 | #include "osl/diagnose.h" |
| 32 | #include "rtl/alloc.h" |
| 33 | |
| 34 | #include "internal/rtllifecycle.h" |
| 35 | |
| 36 | static sal_Int32 RTL_HASHTABLE_SIZE[] = |
| 37 | { |
| 38 | 7, 31, 127, 251, 509, 1021, 2039, 4093 |
| 39 | }; |
| 40 | |
| 41 | struct RTL_HASHENTRY |
| 42 | { |
| 43 | rtl_Locale* Entry; |
| 44 | RTL_HASHENTRY* Next; |
| 45 | }; |
| 46 | |
| 47 | struct RTL_HASHTABLE |
| 48 | { |
| 49 | sal_Int8 iSize; |
| 50 | sal_Int32 Size; |
| 51 | sal_Int32 Elements; |
| 52 | RTL_HASHENTRY** Table; |
| 53 | }; |
| 54 | |
| 55 | static RTL_HASHTABLE* g_pLocaleTable = NULL__null; |
| 56 | |
| 57 | static rtl_Locale* g_pDefaultLocale = NULL__null; |
| 58 | |
| 59 | |
| 60 | |
| 61 | extern "C" void rtl_hashentry_destroy(RTL_HASHENTRY* entry) |
| 62 | { |
| 63 | rtl_uString_release(entry->Entry->Language); |
| 64 | rtl_uString_release(entry->Entry->Country); |
| 65 | rtl_uString_release(entry->Entry->Variant); |
| 66 | if (entry->Next) |
| 67 | rtl_hashentry_destroy(entry->Next); |
| 68 | |
| 69 | rtl_freeMemory(entry->Entry); |
| 70 | rtl_freeMemory(entry); |
| 71 | } |
| 72 | |
| 73 | extern "C" void rtl_hashtable_destroy(RTL_HASHTABLE* table) |
| 74 | { |
| 75 | sal_Int32 size = 0; |
| 76 | |
| 77 | if (!table) |
| 78 | return; |
| 79 | |
| 80 | size = table->Size; |
| 81 | |
| 82 | while (size) |
| 83 | { |
| 84 | if (table->Table[size - 1]) |
| 85 | rtl_hashentry_destroy(table->Table[size - 1]); |
| 86 | size--; |
| 87 | } |
| 88 | |
| 89 | rtl_freeMemory(table->Table); |
| 90 | rtl_freeMemory(table); |
| 91 | } |
| 92 | |
| 93 | extern "C" void rtl_hashtable_init(RTL_HASHTABLE** table, sal_Int8 sizeIndex) |
| 94 | { |
| 95 | sal_Int32 nSize = RTL_HASHTABLE_SIZE[sizeIndex]; |
| 96 | |
| 97 | if (*table) |
| 98 | rtl_hashtable_destroy(*table); |
| 99 | |
| 100 | *table = (RTL_HASHTABLE*)rtl_allocateMemory( sizeof(RTL_HASHTABLE) ); |
| 101 | |
| 102 | (*table)->iSize = sizeIndex; |
| 103 | (*table)->Size = nSize; |
| 104 | (*table)->Elements = 0; |
| 105 | (*table)->Table = (RTL_HASHENTRY**)rtl_allocateMemory( (*table)->Size * sizeof(RTL_HASHENTRY*) ); |
| 106 | |
| 107 | while (nSize) |
| 108 | { |
| 109 | (*table)->Table[nSize - 1] = NULL__null; |
| 110 | nSize--; |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | extern "C" sal_Int32 rtl_hashfunc(RTL_HASHTABLE* table, sal_Int32 key) |
| 115 | { |
| 116 | return ( (sal_uInt32) key % table->Size); |
| 117 | } |
| 118 | |
| 119 | extern "C" sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table); |
| 120 | |
| 121 | extern "C" rtl_Locale* rtl_hashtable_add(RTL_HASHTABLE** table, rtl_Locale* value) |
| 122 | { |
| 123 | sal_Int32 key = 0; |
| 124 | |
| 125 | if (!(*table)) |
| |
| 126 | return NULL__null; |
| 127 | |
| 128 | if ((*table)->Elements > ((*table)->Size / 2)) |
| |
| 129 | rtl_hashtable_grow(table); |
| 130 | |
| 131 | key = rtl_hashfunc(*table, value->HashCode); |
| 132 | |
| 133 | if (!(*table)->Table[key]) |
| |
| 134 | { |
| 135 | RTL_HASHENTRY *newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) ); |
| 136 | newEntry->Entry = value; |
| 137 | newEntry->Next = NULL__null; |
| 138 | (*table)->Table[key] = newEntry; |
| 139 | (*table)->Elements++; |
| 140 | return NULL__null; |
| 141 | } else |
| 142 | { |
| 143 | RTL_HASHENTRY *pEntry = (*table)->Table[key]; |
| 10 | | Variable 'pEntry' initialized here | |
|
| 144 | RTL_HASHENTRY *newEntry = NULL__null; |
| 145 | |
| 146 | while (pEntry) |
| 11 | | Loop condition is false. Execution continues on line 157 | |
|
| 147 | { |
| 148 | if (value->HashCode == pEntry->Entry->HashCode) |
| 149 | return pEntry->Entry; |
| 150 | |
| 151 | if (!pEntry->Next) |
| 152 | break; |
| 153 | |
| 154 | pEntry = pEntry->Next; |
| 155 | } |
| 156 | |
| 157 | newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) ); |
| 158 | newEntry->Entry = value; |
| 159 | newEntry->Next = NULL__null; |
| 160 | pEntry->Next = newEntry; |
| 12 | | Access to field 'Next' results in a dereference of a null pointer (loaded from variable 'pEntry') |
|
| 161 | (*table)->Elements++; |
| 162 | return NULL__null; |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table) |
| 167 | { |
| 168 | RTL_HASHTABLE* pNewTable = NULL__null; |
| 169 | sal_Int32 i = 0; |
| 170 | |
| 171 | rtl_hashtable_init(&pNewTable, (sal_Int8)((*table)->iSize + 1)); |
| 172 | |
| 173 | while (i < (*table)->Size) |
| 174 | { |
| 175 | if ((*table)->Table[i]) |
| 176 | { |
| 177 | RTL_HASHENTRY *pNext; |
| 178 | RTL_HASHENTRY *pEntry = (*table)->Table[i]; |
| 179 | |
| 180 | rtl_hashtable_add(&pNewTable, pEntry->Entry); |
| 181 | |
| 182 | while (pEntry->Next) |
| 183 | { |
| 184 | rtl_hashtable_add(&pNewTable, pEntry->Next->Entry); |
| 185 | pNext = pEntry->Next; |
| 186 | rtl_freeMemory(pEntry); |
| 187 | pEntry = pNext; |
| 188 | } |
| 189 | |
| 190 | rtl_freeMemory(pEntry); |
| 191 | } |
| 192 | i++; |
| 193 | } |
| 194 | |
| 195 | rtl_freeMemory((*table)->Table); |
| 196 | rtl_freeMemory((*table)); |
| 197 | (*table) = pNewTable; |
| 198 | |
| 199 | return sal_True((sal_Bool)1); |
| 200 | } |
| 201 | |
| 202 | extern "C" sal_Bool rtl_hashtable_find(RTL_HASHTABLE * table, sal_Int32 key, sal_Int32 hashCode, rtl_Locale** pValue) |
| 203 | { |
| 204 | if (!table) |
| 205 | return sal_False((sal_Bool)0); |
| 206 | |
| 207 | if (table->Table[key]) |
| 208 | { |
| 209 | RTL_HASHENTRY *pEntry = table->Table[key]; |
| 210 | |
| 211 | while (pEntry && hashCode != pEntry->Entry->HashCode) |
| 212 | pEntry = pEntry->Next; |
| 213 | |
| 214 | if (pEntry) |
| 215 | *pValue = pEntry->Entry; |
| 216 | else |
| 217 | return sal_False((sal_Bool)0); |
| 218 | } else |
| 219 | return sal_False((sal_Bool)0); |
| 220 | |
| 221 | return sal_True((sal_Bool)1); |
| 222 | } |
| 223 | |
| 224 | |
| 225 | |
| 226 | |
| 227 | void rtl_locale_init() |
| 228 | { |
| 229 | OSL_ASSERT(g_pLocaleTable == 0)do { if (true && (!(g_pLocaleTable == 0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/locale.cxx" ":" "229" ": "), "OSL_ASSERT: %s", "g_pLocaleTable == 0"); } } while (false); |
| 230 | rtl_hashtable_init(&g_pLocaleTable, 1); |
| 231 | } |
| 232 | |
| 233 | |
| 234 | |
| 235 | |
| 236 | void rtl_locale_fini() |
| 237 | { |
| 238 | if (g_pLocaleTable != 0) |
| 239 | { |
| 240 | rtl_hashtable_destroy (g_pLocaleTable); |
| 241 | g_pLocaleTable = 0; |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | |
| 246 | |
| 247 | |
| 248 | rtl_Locale * SAL_CALL rtl_locale_register( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant ) |
| 249 | { |
| 250 | sal_Unicode c = 0; |
| 251 | rtl_uString* sLanguage = NULL__null; |
| 252 | rtl_uString* sCountry = NULL__null; |
| 253 | rtl_uString* sVariant = NULL__null; |
| 254 | rtl_Locale *newLocale = NULL__null; |
| 255 | sal_Int32 hashCode = -1; |
| 256 | sal_Int32 key = 0; |
| 257 | |
| 258 | if ( !country ) |
| |
| 259 | country = &c; |
| 260 | if ( !variant ) |
| |
| 261 | variant = &c; |
| 262 | |
| 263 | ensureLocaleSingleton(); |
| 264 | if (!g_pLocaleTable) |
| |
| 265 | return NULL__null; |
| 266 | |
| 267 | hashCode = rtl_ustr_hashCode(language) ^ rtl_ustr_hashCode(country) ^ rtl_ustr_hashCode(variant); |
| 268 | key = rtl_hashfunc(g_pLocaleTable, hashCode); |
| 269 | |
| 270 | if (rtl_hashtable_find(g_pLocaleTable, key, hashCode, &newLocale)) |
| |
| 271 | return newLocale; |
| 272 | |
| 273 | rtl_uString_newFromStr(&sLanguage, language); |
| 274 | rtl_uString_newFromStr(&sCountry, country); |
| 275 | rtl_uString_newFromStr(&sVariant, variant); |
| 276 | |
| 277 | newLocale = (rtl_Locale*)rtl_allocateMemory( sizeof(rtl_Locale) ); |
| 278 | |
| 279 | newLocale->Language = sLanguage; |
| 280 | newLocale->Country = sCountry; |
| 281 | newLocale->Variant = sVariant; |
| 282 | newLocale->HashCode = hashCode; |
| 283 | |
| 284 | rtl_hashtable_add(&g_pLocaleTable, newLocale); |
| 6 | | Calling 'rtl_hashtable_add' | |
|
| 285 | |
| 286 | return newLocale; |
| 287 | } |
| 288 | |
| 289 | |
| 290 | |
| 291 | |
| 292 | rtl_Locale * SAL_CALL rtl_locale_getDefault() |
| 293 | { |
| 294 | return g_pDefaultLocale; |
| 295 | } |
| 296 | |
| 297 | |
| 298 | |
| 299 | |
| 300 | void SAL_CALL rtl_locale_setDefault( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant ) |
| 301 | { |
| 302 | g_pDefaultLocale = rtl_locale_register(language, country, variant); |
| 1 | Calling 'rtl_locale_register' | |
|
| 303 | } |
| 304 | |
| 305 | |
| 306 | |
| 307 | |
| 308 | rtl_uString * SAL_CALL rtl_locale_getLanguage( rtl_Locale * This ) |
| 309 | { |
| 310 | rtl_uString_acquire(This->Language); |
| 311 | return This->Language; |
| 312 | } |
| 313 | |
| 314 | |
| 315 | |
| 316 | |
| 317 | rtl_uString * SAL_CALL rtl_locale_getCountry( rtl_Locale * This ) |
| 318 | { |
| 319 | rtl_uString_acquire(This->Country); |
| 320 | return This->Country; |
| 321 | } |
| 322 | |
| 323 | |
| 324 | |
| 325 | |
| 326 | rtl_uString * SAL_CALL rtl_locale_getVariant( rtl_Locale * This ) |
| 327 | { |
| 328 | rtl_uString_acquire(This->Variant); |
| 329 | return This->Variant; |
| 330 | } |
| 331 | |
| 332 | |
| 333 | |
| 334 | |
| 335 | sal_Int32 SAL_CALL rtl_locale_hashCode( rtl_Locale * This ) |
| 336 | { |
| 337 | return This->HashCode; |
| 338 | } |
| 339 | |
| 340 | |
| 341 | |
| 342 | |
| 343 | sal_Int32 SAL_CALL rtl_locale_equals( rtl_Locale * This, rtl_Locale * obj ) |
| 344 | { |
| 345 | return This == obj; |
| 346 | } |
| 347 | |
| 348 | |