Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
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;
56 : :
57 : : static rtl_Locale* g_pDefaultLocale = NULL;
58 : :
59 : : /*************************************************************************
60 : : */
61 : 2985 : extern "C" void rtl_hashentry_destroy(RTL_HASHENTRY* entry)
62 : : {
63 : 2985 : rtl_uString_release(entry->Entry->Language);
64 : 2985 : rtl_uString_release(entry->Entry->Country);
65 : 2985 : rtl_uString_release(entry->Entry->Variant);
66 [ - + ]: 2985 : if (entry->Next)
67 : 0 : rtl_hashentry_destroy(entry->Next);
68 : :
69 : 2985 : rtl_freeMemory(entry->Entry);
70 : 2985 : rtl_freeMemory(entry);
71 : 2985 : }
72 : :
73 : 2975 : extern "C" void rtl_hashtable_destroy(RTL_HASHTABLE* table)
74 : : {
75 : 2975 : sal_Int32 size = 0;
76 : :
77 [ - + ]: 2975 : if (!table)
78 : 2975 : return;
79 : :
80 : 2975 : size = table->Size;
81 : :
82 [ + + ]: 95200 : while (size)
83 : : {
84 [ + + ]: 92225 : if (table->Table[size - 1])
85 : 2985 : rtl_hashentry_destroy(table->Table[size - 1]);
86 : 92225 : size--;
87 : : }
88 : :
89 : 2975 : rtl_freeMemory(table->Table);
90 : 2975 : rtl_freeMemory(table);
91 : : }
92 : :
93 : 2975 : extern "C" void rtl_hashtable_init(RTL_HASHTABLE** table, sal_Int8 sizeIndex)
94 : : {
95 : 2975 : sal_Int32 nSize = RTL_HASHTABLE_SIZE[sizeIndex];
96 : :
97 [ - + ]: 2975 : if (*table)
98 : 0 : rtl_hashtable_destroy(*table);
99 : :
100 : 2975 : *table = (RTL_HASHTABLE*)rtl_allocateMemory( sizeof(RTL_HASHTABLE) );
101 : :
102 : 2975 : (*table)->iSize = sizeIndex;
103 : 2975 : (*table)->Size = nSize;
104 : 2975 : (*table)->Elements = 0;
105 : 2975 : (*table)->Table = (RTL_HASHENTRY**)rtl_allocateMemory( (*table)->Size * sizeof(RTL_HASHENTRY*) );
106 : :
107 [ + + ]: 95200 : while (nSize)
108 : : {
109 : 92225 : (*table)->Table[nSize - 1] = NULL;
110 : 92225 : nSize--;
111 : : }
112 : 2975 : }
113 : :
114 : 6055 : extern "C" sal_Int32 rtl_hashfunc(RTL_HASHTABLE* table, sal_Int32 key)
115 : : {
116 : 6055 : return ( (sal_uInt32) key % table->Size);
117 : : }
118 : :
119 : : extern "C" sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table);
120 : :
121 : 2985 : extern "C" rtl_Locale* rtl_hashtable_add(RTL_HASHTABLE** table, rtl_Locale* value)
122 : : {
123 : 2985 : sal_Int32 key = 0;
124 : :
125 [ - + ]: 2985 : if (!(*table))
126 : 0 : return NULL;
127 : :
128 [ - + ]: 2985 : if ((*table)->Elements > ((*table)->Size / 2))
129 : 0 : rtl_hashtable_grow(table);
130 : :
131 : 2985 : key = rtl_hashfunc(*table, value->HashCode);
132 : :
133 [ + - ]: 2985 : if (!(*table)->Table[key])
134 : : {
135 : 2985 : RTL_HASHENTRY *newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) );
136 : 2985 : newEntry->Entry = value;
137 : 2985 : newEntry->Next = NULL;
138 : 2985 : (*table)->Table[key] = newEntry;
139 : 2985 : (*table)->Elements++;
140 : 2985 : return NULL;
141 : : } else
142 : : {
143 : 0 : RTL_HASHENTRY *pEntry = (*table)->Table[key];
144 : 0 : RTL_HASHENTRY *newEntry = NULL;
145 : :
146 [ # # ]: 0 : while (pEntry)
147 : : {
148 [ # # ]: 0 : if (value->HashCode == pEntry->Entry->HashCode)
149 : 0 : return pEntry->Entry;
150 : :
151 [ # # ]: 0 : if (!pEntry->Next)
152 : 0 : break;
153 : :
154 : 0 : pEntry = pEntry->Next;
155 : : }
156 : :
157 : 0 : newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) );
158 : 0 : newEntry->Entry = value;
159 : 0 : newEntry->Next = NULL;
160 : 0 : pEntry->Next = newEntry;
161 : 0 : (*table)->Elements++;
162 : 2985 : return NULL;
163 : : }
164 : : }
165 : :
166 : 0 : sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table)
167 : : {
168 : 0 : RTL_HASHTABLE* pNewTable = NULL;
169 : 0 : sal_Int32 i = 0;
170 : :
171 [ # # ]: 0 : rtl_hashtable_init(&pNewTable, (sal_Int8)((*table)->iSize + 1));
172 : :
173 [ # # ]: 0 : while (i < (*table)->Size)
174 : : {
175 [ # # ]: 0 : if ((*table)->Table[i])
176 : : {
177 : : RTL_HASHENTRY *pNext;
178 : 0 : RTL_HASHENTRY *pEntry = (*table)->Table[i];
179 : :
180 [ # # ]: 0 : rtl_hashtable_add(&pNewTable, pEntry->Entry);
181 : :
182 [ # # ]: 0 : while (pEntry->Next)
183 : : {
184 [ # # ]: 0 : rtl_hashtable_add(&pNewTable, pEntry->Next->Entry);
185 : 0 : pNext = pEntry->Next;
186 : 0 : rtl_freeMemory(pEntry);
187 : 0 : pEntry = pNext;
188 : : }
189 : :
190 : 0 : rtl_freeMemory(pEntry);
191 : : }
192 : 0 : i++;
193 : : }
194 : :
195 : 0 : rtl_freeMemory((*table)->Table);
196 : 0 : rtl_freeMemory((*table));
197 : 0 : (*table) = pNewTable;
198 : :
199 : 0 : return sal_True;
200 : : }
201 : :
202 : 3070 : extern "C" sal_Bool rtl_hashtable_find(RTL_HASHTABLE * table, sal_Int32 key, sal_Int32 hashCode, rtl_Locale** pValue)
203 : : {
204 [ - + ]: 3070 : if (!table)
205 : 0 : return sal_False;
206 : :
207 [ + + ]: 3070 : if (table->Table[key])
208 : : {
209 : 85 : RTL_HASHENTRY *pEntry = table->Table[key];
210 : :
211 [ + - ][ - + ]: 85 : while (pEntry && hashCode != pEntry->Entry->HashCode)
[ - + ]
212 : 0 : pEntry = pEntry->Next;
213 : :
214 [ + - ]: 85 : if (pEntry)
215 : 85 : *pValue = pEntry->Entry;
216 : : else
217 : 0 : return sal_False;
218 : : } else
219 : 3070 : return sal_False;
220 : :
221 : 85 : return sal_True;
222 : : }
223 : :
224 : : /*************************************************************************
225 : : * rtl_locale_init
226 : : */
227 : 2975 : void rtl_locale_init()
228 : : {
229 : : OSL_ASSERT(g_pLocaleTable == 0);
230 : 2975 : rtl_hashtable_init(&g_pLocaleTable, 1);
231 : 2975 : }
232 : :
233 : : /*************************************************************************
234 : : * rtl_locale_fini
235 : : */
236 : 2975 : void rtl_locale_fini()
237 : : {
238 [ + - ]: 2975 : if (g_pLocaleTable != 0)
239 : : {
240 : 2975 : rtl_hashtable_destroy (g_pLocaleTable);
241 : 2975 : g_pLocaleTable = 0;
242 : : }
243 : 2975 : }
244 : :
245 : : /*************************************************************************
246 : : * rtl_locale_register
247 : : */
248 : 3070 : rtl_Locale * SAL_CALL rtl_locale_register( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant )
249 : : {
250 : 3070 : sal_Unicode c = 0;
251 : 3070 : rtl_uString* sLanguage = NULL;
252 : 3070 : rtl_uString* sCountry = NULL;
253 : 3070 : rtl_uString* sVariant = NULL;
254 : 3070 : rtl_Locale *newLocale = NULL;
255 : 3070 : sal_Int32 hashCode = -1;
256 : 3070 : sal_Int32 key = 0;
257 : :
258 [ - + ]: 3070 : if ( !country )
259 : 0 : country = &c;
260 [ + + ]: 3070 : if ( !variant )
261 : 10 : variant = &c;
262 : :
263 [ + - ]: 3070 : ensureLocaleSingleton();
264 [ - + ]: 3070 : if (!g_pLocaleTable)
265 : 0 : return NULL;
266 : :
267 : 3070 : hashCode = rtl_ustr_hashCode(language) ^ rtl_ustr_hashCode(country) ^ rtl_ustr_hashCode(variant);
268 : 3070 : key = rtl_hashfunc(g_pLocaleTable, hashCode);
269 : :
270 [ + + ]: 3070 : if (rtl_hashtable_find(g_pLocaleTable, key, hashCode, &newLocale))
271 : 85 : return newLocale;
272 : :
273 : 2985 : rtl_uString_newFromStr(&sLanguage, language);
274 : 2985 : rtl_uString_newFromStr(&sCountry, country);
275 : 2985 : rtl_uString_newFromStr(&sVariant, variant);
276 : :
277 : 2985 : newLocale = (rtl_Locale*)rtl_allocateMemory( sizeof(rtl_Locale) );
278 : :
279 : 2985 : newLocale->Language = sLanguage;
280 : 2985 : newLocale->Country = sCountry;
281 : 2985 : newLocale->Variant = sVariant;
282 : 2985 : newLocale->HashCode = hashCode;
283 : :
284 [ + - ]: 2985 : rtl_hashtable_add(&g_pLocaleTable, newLocale);
285 : :
286 : 3070 : return newLocale;
287 : : }
288 : :
289 : : /*************************************************************************
290 : : * rtl_locale_getDefault
291 : : */
292 : 50 : rtl_Locale * SAL_CALL rtl_locale_getDefault()
293 : : {
294 : 50 : return g_pDefaultLocale;
295 : : }
296 : :
297 : : /*************************************************************************
298 : : * rtl_locale_setDefault
299 : : */
300 : 75 : void SAL_CALL rtl_locale_setDefault( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant )
301 : : {
302 : 75 : g_pDefaultLocale = rtl_locale_register(language, country, variant);
303 : 75 : }
304 : :
305 : : /*************************************************************************
306 : : * rtl_locale_getLanguage
307 : : */
308 : 5 : rtl_uString * SAL_CALL rtl_locale_getLanguage( rtl_Locale * This )
309 : : {
310 : 5 : rtl_uString_acquire(This->Language);
311 : 5 : return This->Language;
312 : : }
313 : :
314 : : /*************************************************************************
315 : : * rtl_locale_getCountry
316 : : */
317 : 5 : rtl_uString * SAL_CALL rtl_locale_getCountry( rtl_Locale * This )
318 : : {
319 : 5 : rtl_uString_acquire(This->Country);
320 : 5 : return This->Country;
321 : : }
322 : :
323 : : /*************************************************************************
324 : : * rtl_locale_getVariant
325 : : */
326 : 5 : rtl_uString * SAL_CALL rtl_locale_getVariant( rtl_Locale * This )
327 : : {
328 : 5 : rtl_uString_acquire(This->Variant);
329 : 5 : return This->Variant;
330 : : }
331 : :
332 : : /*************************************************************************
333 : : * rtl_locale_hashCode
334 : : */
335 : 5 : sal_Int32 SAL_CALL rtl_locale_hashCode( rtl_Locale * This )
336 : : {
337 : 5 : return This->HashCode;
338 : : }
339 : :
340 : : /*************************************************************************
341 : : * rtl_locale_equals
342 : : */
343 : 5 : sal_Int32 SAL_CALL rtl_locale_equals( rtl_Locale * This, rtl_Locale * obj )
344 : : {
345 : 5 : return This == obj;
346 : : }
347 : :
348 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|