1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: locale.c,v $
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
;
51 typedef struct rtl_hashtable
56 RTL_HASHENTRY
** Table
;
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
);
73 rtl_hashentry_destroy(entry
->Next
);
75 rtl_freeMemory(entry
->Entry
);
76 rtl_freeMemory(entry
);
79 void rtl_hashtable_destroy(RTL_HASHTABLE
* table
)
90 if (table
->Table
[size
- 1])
91 rtl_hashentry_destroy(table
->Table
[size
- 1]);
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
];
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
*) );
115 (*table
)->Table
[nSize
- 1] = NULL
;
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
)
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
++;
149 RTL_HASHENTRY
*pEntry
= (*table
)->Table
[key
];
150 RTL_HASHENTRY
*newEntry
= NULL
;
154 if (value
->HashCode
== pEntry
->Entry
->HashCode
)
155 return pEntry
->Entry
;
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
++;
172 sal_Bool
rtl_hashtable_grow(RTL_HASHTABLE
** table
)
174 RTL_HASHTABLE
* pNewTable
= NULL
;
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
);
190 rtl_hashtable_add(&pNewTable
, pEntry
->Next
->Entry
);
191 pNext
= pEntry
->Next
;
192 rtl_freeMemory(pEntry
);
196 rtl_freeMemory(pEntry
);
201 rtl_freeMemory((*table
)->Table
);
202 rtl_freeMemory((*table
));
203 (*table
) = pNewTable
;
208 sal_Bool
rtl_hashtable_find(RTL_HASHTABLE
* table
, sal_Int32 key
, sal_Int32 hashCode
, rtl_Locale
** pValue
)
213 if (table
->Table
[key
])
215 RTL_HASHENTRY
*pEntry
= table
->Table
[key
];
217 while (pEntry
&& hashCode
!= pEntry
->Entry
->HashCode
)
218 pEntry
= pEntry
->Next
;
221 *pValue
= pEntry
->Entry
;
230 /*************************************************************************
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 /*************************************************************************
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
);
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
)
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;
283 if (!rtl_locale_init())
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
))
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
);
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 /*************************************************************************
362 sal_Int32 SAL_CALL
rtl_locale_equals( rtl_Locale
* This
, rtl_Locale
* obj
)