1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "rtl/locale.h"
22 #include "osl/diagnose.h"
23 #include "rtl/alloc.h"
25 #include "internal/rtllifecycle.h"
27 static sal_Int32 RTL_HASHTABLE_SIZE
[] =
29 7, 31, 127, 251, 509, 1021, 2039, 4093
43 RTL_HASHENTRY
** Table
;
46 static RTL_HASHTABLE
* g_pLocaleTable
= NULL
;
48 static rtl_Locale
* g_pDefaultLocale
= NULL
;
50 /*************************************************************************
52 extern "C" void rtl_hashentry_destroy(RTL_HASHENTRY
* entry
)
54 rtl_uString_release(entry
->Entry
->Language
);
55 rtl_uString_release(entry
->Entry
->Country
);
56 rtl_uString_release(entry
->Entry
->Variant
);
58 rtl_hashentry_destroy(entry
->Next
);
60 rtl_freeMemory(entry
->Entry
);
61 rtl_freeMemory(entry
);
64 extern "C" void rtl_hashtable_destroy(RTL_HASHTABLE
* table
)
75 if (table
->Table
[size
- 1])
76 rtl_hashentry_destroy(table
->Table
[size
- 1]);
80 rtl_freeMemory(table
->Table
);
81 rtl_freeMemory(table
);
84 extern "C" void rtl_hashtable_init(RTL_HASHTABLE
** table
, sal_Int8 sizeIndex
)
86 sal_Int32 nSize
= RTL_HASHTABLE_SIZE
[sizeIndex
];
89 rtl_hashtable_destroy(*table
);
91 *table
= (RTL_HASHTABLE
*)rtl_allocateMemory( sizeof(RTL_HASHTABLE
) );
93 (*table
)->iSize
= sizeIndex
;
94 (*table
)->Size
= nSize
;
95 (*table
)->Elements
= 0;
96 (*table
)->Table
= (RTL_HASHENTRY
**)rtl_allocateMemory( (*table
)->Size
* sizeof(RTL_HASHENTRY
*) );
100 (*table
)->Table
[nSize
- 1] = NULL
;
105 extern "C" sal_Int32
rtl_hashfunc(RTL_HASHTABLE
* table
, sal_Int32 key
)
107 return ( (sal_uInt32
) key
% table
->Size
);
110 extern "C" sal_Bool
rtl_hashtable_grow(RTL_HASHTABLE
** table
);
112 extern "C" rtl_Locale
* rtl_hashtable_add(RTL_HASHTABLE
** table
, rtl_Locale
* value
)
119 if ((*table
)->Elements
> ((*table
)->Size
/ 2))
120 rtl_hashtable_grow(table
);
122 key
= rtl_hashfunc(*table
, value
->HashCode
);
124 RTL_HASHENTRY
**pEntry
= &(*table
)->Table
[key
];
127 if (value
->HashCode
== (*pEntry
)->Entry
->HashCode
)
128 return (*pEntry
)->Entry
;
129 pEntry
= &(*pEntry
)->Next
;
132 RTL_HASHENTRY
*newEntry
= (RTL_HASHENTRY
*)rtl_allocateMemory( sizeof(RTL_HASHENTRY
) );
133 newEntry
->Entry
= value
;
134 newEntry
->Next
= NULL
;
136 (*table
)->Elements
++;
140 sal_Bool
rtl_hashtable_grow(RTL_HASHTABLE
** table
)
142 RTL_HASHTABLE
* pNewTable
= NULL
;
145 rtl_hashtable_init(&pNewTable
, (sal_Int8
)((*table
)->iSize
+ 1));
147 while (i
< (*table
)->Size
)
149 if ((*table
)->Table
[i
])
151 RTL_HASHENTRY
*pNext
;
152 RTL_HASHENTRY
*pEntry
= (*table
)->Table
[i
];
154 rtl_hashtable_add(&pNewTable
, pEntry
->Entry
);
158 rtl_hashtable_add(&pNewTable
, pEntry
->Next
->Entry
);
159 pNext
= pEntry
->Next
;
160 rtl_freeMemory(pEntry
);
164 rtl_freeMemory(pEntry
);
169 rtl_freeMemory((*table
)->Table
);
170 rtl_freeMemory((*table
));
171 (*table
) = pNewTable
;
176 extern "C" sal_Bool
rtl_hashtable_find(RTL_HASHTABLE
* table
, sal_Int32 key
, sal_Int32 hashCode
, rtl_Locale
** pValue
)
181 if (table
->Table
[key
])
183 RTL_HASHENTRY
*pEntry
= table
->Table
[key
];
185 while (pEntry
&& hashCode
!= pEntry
->Entry
->HashCode
)
186 pEntry
= pEntry
->Next
;
189 *pValue
= pEntry
->Entry
;
198 /*************************************************************************
201 void rtl_locale_init()
203 OSL_ASSERT(g_pLocaleTable
== 0);
204 rtl_hashtable_init(&g_pLocaleTable
, 1);
207 /*************************************************************************
210 void rtl_locale_fini()
212 if (g_pLocaleTable
!= 0)
214 rtl_hashtable_destroy (g_pLocaleTable
);
219 /*************************************************************************
220 * rtl_locale_register
222 rtl_Locale
* SAL_CALL
rtl_locale_register( const sal_Unicode
* language
, const sal_Unicode
* country
, const sal_Unicode
* variant
)
225 rtl_uString
* sLanguage
= NULL
;
226 rtl_uString
* sCountry
= NULL
;
227 rtl_uString
* sVariant
= NULL
;
228 rtl_Locale
*newLocale
= NULL
;
229 sal_Int32 hashCode
= -1;
237 ensureLocaleSingleton();
241 hashCode
= rtl_ustr_hashCode(language
) ^ rtl_ustr_hashCode(country
) ^ rtl_ustr_hashCode(variant
);
242 key
= rtl_hashfunc(g_pLocaleTable
, hashCode
);
244 if (rtl_hashtable_find(g_pLocaleTable
, key
, hashCode
, &newLocale
))
247 rtl_uString_newFromStr(&sLanguage
, language
);
248 rtl_uString_newFromStr(&sCountry
, country
);
249 rtl_uString_newFromStr(&sVariant
, variant
);
251 newLocale
= (rtl_Locale
*)rtl_allocateMemory( sizeof(rtl_Locale
) );
253 newLocale
->Language
= sLanguage
;
254 newLocale
->Country
= sCountry
;
255 newLocale
->Variant
= sVariant
;
256 newLocale
->HashCode
= hashCode
;
258 rtl_hashtable_add(&g_pLocaleTable
, newLocale
);
263 /*************************************************************************
264 * rtl_locale_getDefault
266 rtl_Locale
* SAL_CALL
rtl_locale_getDefault()
268 return g_pDefaultLocale
;
271 /*************************************************************************
272 * rtl_locale_setDefault
274 void SAL_CALL
rtl_locale_setDefault( const sal_Unicode
* language
, const sal_Unicode
* country
, const sal_Unicode
* variant
)
276 g_pDefaultLocale
= rtl_locale_register(language
, country
, variant
);
279 /*************************************************************************
280 * rtl_locale_getLanguage
282 rtl_uString
* SAL_CALL
rtl_locale_getLanguage( rtl_Locale
* This
)
284 rtl_uString_acquire(This
->Language
);
285 return This
->Language
;
288 /*************************************************************************
289 * rtl_locale_getCountry
291 rtl_uString
* SAL_CALL
rtl_locale_getCountry( rtl_Locale
* This
)
293 rtl_uString_acquire(This
->Country
);
294 return This
->Country
;
297 /*************************************************************************
298 * rtl_locale_getVariant
300 rtl_uString
* SAL_CALL
rtl_locale_getVariant( rtl_Locale
* This
)
302 rtl_uString_acquire(This
->Variant
);
303 return This
->Variant
;
306 /*************************************************************************
307 * rtl_locale_hashCode
309 sal_Int32 SAL_CALL
rtl_locale_hashCode( rtl_Locale
* This
)
311 return This
->HashCode
;
314 /*************************************************************************
317 sal_Int32 SAL_CALL
rtl_locale_equals( rtl_Locale
* This
, rtl_Locale
* obj
)
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */