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 | |