Update ooo320-m1
[ooovba.git] / sal / rtl / source / locale.c
blobe705a8785d018dccb16159a0400fe395cadfa7bb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: locale.c,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "rtl/locale.h"
33 #include "osl/diagnose.h"
34 #include "rtl/alloc.h"
36 #include "internal/once.h"
38 static sal_Int32 RTL_HASHTABLE_SIZE[] =
40 7, 31, 127, 251, 509, 1021, 2039, 4093
43 typedef struct rtl_hashentry RTL_HASHENTRY;
45 struct rtl_hashentry
47 rtl_Locale* Entry;
48 RTL_HASHENTRY* Next;
51 typedef struct rtl_hashtable
53 sal_Int8 iSize;
54 sal_Int32 Size;
55 sal_Int32 Elements;
56 RTL_HASHENTRY** Table;
57 } RTL_HASHTABLE;
59 static RTL_HASHTABLE* g_pLocaleTable = NULL;
61 static rtl_Locale* g_pDefaultLocale = NULL;
63 static int rtl_locale_init (void);
65 /*************************************************************************
67 void rtl_hashentry_destroy(RTL_HASHENTRY* entry)
69 rtl_uString_release(entry->Entry->Language);
70 rtl_uString_release(entry->Entry->Country);
71 rtl_uString_release(entry->Entry->Variant);
72 if (entry->Next)
73 rtl_hashentry_destroy(entry->Next);
75 rtl_freeMemory(entry->Entry);
76 rtl_freeMemory(entry);
79 void rtl_hashtable_destroy(RTL_HASHTABLE* table)
81 sal_Int32 size = 0;
83 if (!table)
84 return;
86 size = table->Size;
88 while (size)
90 if (table->Table[size - 1])
91 rtl_hashentry_destroy(table->Table[size - 1]);
92 size--;
95 rtl_freeMemory(table->Table);
96 rtl_freeMemory(table);
99 void rtl_hashtable_init(RTL_HASHTABLE** table, sal_Int8 sizeIndex)
101 sal_Int32 nSize = RTL_HASHTABLE_SIZE[sizeIndex];
103 if (*table)
104 rtl_hashtable_destroy(*table);
106 *table = (RTL_HASHTABLE*)rtl_allocateMemory( sizeof(RTL_HASHTABLE) );
108 (*table)->iSize = sizeIndex;
109 (*table)->Size = nSize;
110 (*table)->Elements = 0;
111 (*table)->Table = (RTL_HASHENTRY**)rtl_allocateMemory( (*table)->Size * sizeof(RTL_HASHENTRY*) );
113 while (nSize)
115 (*table)->Table[nSize - 1] = NULL;
116 nSize--;
120 sal_Int32 rtl_hashfunc(RTL_HASHTABLE* table, sal_Int32 key)
122 return ( (sal_uInt32) key % table->Size);
125 sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table);
127 rtl_Locale* rtl_hashtable_add(RTL_HASHTABLE** table, rtl_Locale* value)
129 sal_Int32 key = 0;
131 if (!(*table))
132 return NULL;
134 if ((*table)->Elements > ((*table)->Size / 2))
135 rtl_hashtable_grow(table);
137 key = rtl_hashfunc(*table, value->HashCode);
139 if (!(*table)->Table[key])
141 RTL_HASHENTRY *newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) );
142 newEntry->Entry = value;
143 newEntry->Next = NULL;
144 (*table)->Table[key] = newEntry;
145 (*table)->Elements++;
146 return NULL;
147 } else
149 RTL_HASHENTRY *pEntry = (*table)->Table[key];
150 RTL_HASHENTRY *newEntry = NULL;
152 while (pEntry)
154 if (value->HashCode == pEntry->Entry->HashCode)
155 return pEntry->Entry;
157 if (!pEntry->Next)
158 break;
160 pEntry = pEntry->Next;
163 newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) );
164 newEntry->Entry = value;
165 newEntry->Next = NULL;
166 pEntry->Next = newEntry;
167 (*table)->Elements++;
168 return NULL;
172 sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table)
174 RTL_HASHTABLE* pNewTable = NULL;
175 sal_Int32 i = 0;
177 rtl_hashtable_init(&pNewTable, (sal_Int8)((*table)->iSize + 1));
179 while (i < (*table)->Size)
181 if ((*table)->Table[i])
183 RTL_HASHENTRY *pNext;
184 RTL_HASHENTRY *pEntry = (*table)->Table[i];
186 rtl_hashtable_add(&pNewTable, pEntry->Entry);
188 while (pEntry->Next)
190 rtl_hashtable_add(&pNewTable, pEntry->Next->Entry);
191 pNext = pEntry->Next;
192 rtl_freeMemory(pEntry);
193 pEntry = pNext;
196 rtl_freeMemory(pEntry);
198 i++;
201 rtl_freeMemory((*table)->Table);
202 rtl_freeMemory((*table));
203 (*table) = pNewTable;
205 return sal_True;
208 sal_Bool rtl_hashtable_find(RTL_HASHTABLE * table, sal_Int32 key, sal_Int32 hashCode, rtl_Locale** pValue)
210 if (!table)
211 return sal_False;
213 if (table->Table[key])
215 RTL_HASHENTRY *pEntry = table->Table[key];
217 while (pEntry && hashCode != pEntry->Entry->HashCode)
218 pEntry = pEntry->Next;
220 if (pEntry)
221 *pValue = pEntry->Entry;
222 else
223 return sal_False;
224 } else
225 return sal_False;
227 return sal_True;
230 /*************************************************************************
231 * rtl_locale_init
233 static void rtl_locale_once_init (void)
235 OSL_ASSERT(g_pLocaleTable == 0);
236 rtl_hashtable_init(&g_pLocaleTable, 1);
239 static int rtl_locale_init (void)
241 static sal_once_type g_once = SAL_ONCE_INIT;
242 SAL_ONCE(&g_once, rtl_locale_once_init);
243 return (g_pLocaleTable != 0);
246 /*************************************************************************
247 * rtl_locale_fini
249 #if defined(__GNUC__)
250 static void rtl_locale_fini (void) __attribute__((destructor));
251 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
252 #pragma fini(rtl_locale_fini)
253 static void rtl_locale_fini (void);
254 #endif /* __GNUC__ || __SUNPRO_C */
256 void rtl_locale_fini (void)
258 if (g_pLocaleTable != 0)
260 rtl_hashtable_destroy (g_pLocaleTable);
261 g_pLocaleTable = 0;
265 /*************************************************************************
266 * rtl_locale_register
268 rtl_Locale * SAL_CALL rtl_locale_register( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant )
270 sal_Unicode c = 0;
271 rtl_uString* sLanguage = NULL;
272 rtl_uString* sCountry = NULL;
273 rtl_uString* sVariant = NULL;
274 rtl_Locale *newLocale = NULL;
275 sal_Int32 hashCode = -1;
276 sal_Int32 key = 0;
278 if ( !country )
279 country = &c;
280 if ( !variant )
281 variant = &c;
283 if (!rtl_locale_init())
284 return NULL;
286 hashCode = rtl_ustr_hashCode(language) ^ rtl_ustr_hashCode(country) ^ rtl_ustr_hashCode(variant);
287 key = rtl_hashfunc(g_pLocaleTable, hashCode);
289 if (rtl_hashtable_find(g_pLocaleTable, key, hashCode, &newLocale))
290 return newLocale;
292 rtl_uString_newFromStr(&sLanguage, language);
293 rtl_uString_newFromStr(&sCountry, country);
294 rtl_uString_newFromStr(&sVariant, variant);
296 newLocale = (rtl_Locale*)rtl_allocateMemory( sizeof(rtl_Locale) );
298 newLocale->Language = sLanguage;
299 newLocale->Country = sCountry;
300 newLocale->Variant = sVariant;
301 newLocale->HashCode = hashCode;
303 rtl_hashtable_add(&g_pLocaleTable, newLocale);
305 return newLocale;
308 /*************************************************************************
309 * rtl_locale_getDefault
311 rtl_Locale * SAL_CALL rtl_locale_getDefault()
313 return g_pDefaultLocale;
316 /*************************************************************************
317 * rtl_locale_setDefault
319 void SAL_CALL rtl_locale_setDefault( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant )
321 g_pDefaultLocale = rtl_locale_register(language, country, variant);
324 /*************************************************************************
325 * rtl_locale_getLanguage
327 rtl_uString * SAL_CALL rtl_locale_getLanguage( rtl_Locale * This )
329 rtl_uString_acquire(This->Language);
330 return This->Language;
333 /*************************************************************************
334 * rtl_locale_getCountry
336 rtl_uString * SAL_CALL rtl_locale_getCountry( rtl_Locale * This )
338 rtl_uString_acquire(This->Country);
339 return This->Country;
342 /*************************************************************************
343 * rtl_locale_getVariant
345 rtl_uString * SAL_CALL rtl_locale_getVariant( rtl_Locale * This )
347 rtl_uString_acquire(This->Variant);
348 return This->Variant;
351 /*************************************************************************
352 * rtl_locale_hashCode
354 sal_Int32 SAL_CALL rtl_locale_hashCode( rtl_Locale * This )
356 return This->HashCode;
359 /*************************************************************************
360 * rtl_locale_equals
362 sal_Int32 SAL_CALL rtl_locale_equals( rtl_Locale * This, rtl_Locale * obj )
364 return This == obj;