Avoid a warning shown since bumping Windows baseline
[LibreOffice.git] / i18npool / source / localedata / localedata.cxx
blobeb0da4fbc8ef2b73e6a0985ec06d415211256904
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
21 #include <mutex>
22 #include <string_view>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/container/XIndexAccess.hpp>
25 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26 #include <comphelper/sequence.hxx>
27 #include <cppuhelper/implbase.hxx>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <editeng/svxenum.hxx>
30 #include <localedata.hxx>
31 #include <i18nlangtag/mslangid.hxx>
32 #include <i18nlangtag/languagetag.hxx>
33 #include <sal/log.hxx>
34 #include <osl/diagnose.h>
35 #include <sal/macros.h>
36 #include <o3tl/string_view.hxx>
38 namespace com::sun::star::uno { class XComponentContext; }
40 using namespace com::sun::star::i18n;
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::lang;
43 using namespace com::sun::star;
44 using i18npool::DataLocaleLibrary;
46 typedef OUString const * (* MyFuncOUString_Type)( sal_Int16&);
47 typedef OUString const ** (* MyFunc_Type2)( sal_Int16&, sal_Int16& );
48 typedef OUString const *** (* MyFunc_Type3)( sal_Int16&, sal_Int16&, sal_Int16& );
49 typedef OUString const * (* MyFunc_FormatCode)( sal_Int16&, sal_Unicode const *&, sal_Unicode const *& );
51 #ifndef DISABLE_DYNLOADING
53 #ifdef SAL_DLLPREFIX
54 // mostly "lib*.so"
55 constexpr const char* lcl_DATA_EN = SAL_DLLPREFIX "localedata_en" SAL_DLLEXTENSION;
56 constexpr const char* lcl_DATA_ES = SAL_DLLPREFIX "localedata_es" SAL_DLLEXTENSION;
57 constexpr const char* lcl_DATA_EURO = SAL_DLLPREFIX "localedata_euro" SAL_DLLEXTENSION;
58 constexpr const char* lcl_DATA_OTHERS = SAL_DLLPREFIX "localedata_others" SAL_DLLEXTENSION;
59 #else
60 // mostly "*.dll"
61 constexpr const char* lcl_DATA_EN = "localedata_en" SAL_DLLEXTENSION;
62 constexpr const char* lcl_DATA_ES = "localedata_es" SAL_DLLEXTENSION;
63 constexpr const char* lcl_DATA_EURO = "localedata_euro" SAL_DLLEXTENSION;
64 constexpr const char* lcl_DATA_OTHERS = "localedata_others" SAL_DLLEXTENSION;
65 #endif
67 static const char* getLibraryName(DataLocaleLibrary aLib) {
68 switch(aLib) {
69 case DataLocaleLibrary::EN:
70 return lcl_DATA_EN;
71 case DataLocaleLibrary::ES:
72 return lcl_DATA_ES;
73 case DataLocaleLibrary::EURO:
74 return lcl_DATA_EURO;
75 case DataLocaleLibrary::OTHERS:
76 return lcl_DATA_OTHERS;
78 return nullptr;
81 constexpr struct {
82 const char* pLocale;
83 i18npool::DataLocaleLibrary pLib;
84 } aLibTable[] = {
85 { "en_US", DataLocaleLibrary::EN },
86 { "en_AU", DataLocaleLibrary::EN },
87 { "en_BZ", DataLocaleLibrary::EN },
88 { "en_CA", DataLocaleLibrary::EN },
89 { "en_GB", DataLocaleLibrary::EN },
90 { "en_IE", DataLocaleLibrary::EN },
91 { "en_JM", DataLocaleLibrary::EN },
92 { "en_NZ", DataLocaleLibrary::EN },
93 { "en_PH", DataLocaleLibrary::EN },
94 { "en_TT", DataLocaleLibrary::EN },
95 { "en_ZA", DataLocaleLibrary::EN },
96 { "en_ZW", DataLocaleLibrary::EN },
97 { "en_NA", DataLocaleLibrary::EN },
98 { "en_GH", DataLocaleLibrary::EN },
99 { "en_MW", DataLocaleLibrary::EN },
100 { "en_GM", DataLocaleLibrary::EN },
101 { "en_BW", DataLocaleLibrary::EN },
102 { "en_ZM", DataLocaleLibrary::EN },
103 { "en_LK", DataLocaleLibrary::EN },
104 { "en_NG", DataLocaleLibrary::EN },
105 { "en_KE", DataLocaleLibrary::EN },
106 { "en_DK", DataLocaleLibrary::EN },
107 { "en_MU", DataLocaleLibrary::EN },
109 { "es_ES", DataLocaleLibrary::ES },
110 { "es_AR", DataLocaleLibrary::ES },
111 { "es_BO", DataLocaleLibrary::ES },
112 { "es_CL", DataLocaleLibrary::ES },
113 { "es_CO", DataLocaleLibrary::ES },
114 { "es_CR", DataLocaleLibrary::ES },
115 { "es_DO", DataLocaleLibrary::ES },
116 { "es_EC", DataLocaleLibrary::ES },
117 { "es_GT", DataLocaleLibrary::ES },
118 { "es_HN", DataLocaleLibrary::ES },
119 { "es_MX", DataLocaleLibrary::ES },
120 { "es_NI", DataLocaleLibrary::ES },
121 { "es_PA", DataLocaleLibrary::ES },
122 { "es_PE", DataLocaleLibrary::ES },
123 { "es_PR", DataLocaleLibrary::ES },
124 { "es_PY", DataLocaleLibrary::ES },
125 { "es_SV", DataLocaleLibrary::ES },
126 { "es_UY", DataLocaleLibrary::ES },
127 { "es_VE", DataLocaleLibrary::ES },
128 { "gl_ES", DataLocaleLibrary::ES },
129 { "oc_ES_aranes", DataLocaleLibrary::ES },
131 { "de_DE", DataLocaleLibrary::EURO },
132 { "de_AT", DataLocaleLibrary::EURO },
133 { "de_CH", DataLocaleLibrary::EURO },
134 { "de_LI", DataLocaleLibrary::EURO },
135 { "de_LU", DataLocaleLibrary::EURO },
136 { "fr_FR", DataLocaleLibrary::EURO },
137 { "fr_BE", DataLocaleLibrary::EURO },
138 { "fr_CA", DataLocaleLibrary::EURO },
139 { "fr_CH", DataLocaleLibrary::EURO },
140 { "fr_LU", DataLocaleLibrary::EURO },
141 { "fr_MC", DataLocaleLibrary::EURO },
142 { "fr_BF", DataLocaleLibrary::EURO },
143 { "fr_CI", DataLocaleLibrary::EURO },
144 { "fr_ML", DataLocaleLibrary::EURO },
145 { "fr_SN", DataLocaleLibrary::EURO },
146 { "fr_BJ", DataLocaleLibrary::EURO },
147 { "fr_NE", DataLocaleLibrary::EURO },
148 { "fr_TG", DataLocaleLibrary::EURO },
149 { "fr_GN", DataLocaleLibrary::EURO },
150 { "it_IT", DataLocaleLibrary::EURO },
151 { "it_CH", DataLocaleLibrary::EURO },
152 { "sl_SI", DataLocaleLibrary::EURO },
153 { "sv_SE", DataLocaleLibrary::EURO },
154 { "sv_FI", DataLocaleLibrary::EURO },
155 { "ca_ES", DataLocaleLibrary::EURO },
156 { "ca_ES_valencia", DataLocaleLibrary::EURO },
157 { "cs_CZ", DataLocaleLibrary::EURO },
158 { "sk_SK", DataLocaleLibrary::EURO },
159 { "da_DK", DataLocaleLibrary::EURO },
160 { "el_GR", DataLocaleLibrary::EURO },
161 { "fi_FI", DataLocaleLibrary::EURO },
162 { "is_IS", DataLocaleLibrary::EURO },
163 { "nl_BE", DataLocaleLibrary::EURO },
164 { "nl_NL", DataLocaleLibrary::EURO },
165 { "no_NO", DataLocaleLibrary::EURO },
166 { "nn_NO", DataLocaleLibrary::EURO },
167 { "nb_NO", DataLocaleLibrary::EURO },
168 { "nds_DE", DataLocaleLibrary::EURO },
169 { "pl_PL", DataLocaleLibrary::EURO },
170 { "pt_PT", DataLocaleLibrary::EURO },
171 { "pt_BR", DataLocaleLibrary::EURO }, // needs to be in EURO because inherits from pt_PT
172 { "pt_MZ", DataLocaleLibrary::EURO }, // needs to be in EURO because inherits from pt_PT
173 { "ru_RU", DataLocaleLibrary::EURO },
174 { "tr_TR", DataLocaleLibrary::EURO },
175 { "tt_RU", DataLocaleLibrary::EURO },
176 { "et_EE", DataLocaleLibrary::EURO },
177 { "vro_EE", DataLocaleLibrary::EURO },
178 { "lb_LU", DataLocaleLibrary::EURO },
179 { "lt_LT", DataLocaleLibrary::EURO },
180 { "lv_LV", DataLocaleLibrary::EURO },
181 { "uk_UA", DataLocaleLibrary::EURO },
182 { "ro_RO", DataLocaleLibrary::EURO },
183 { "cy_GB", DataLocaleLibrary::EURO },
184 { "bg_BG", DataLocaleLibrary::EURO },
185 { "sr_Latn_ME", DataLocaleLibrary::EURO },
186 { "sr_Latn_RS", DataLocaleLibrary::EURO },
187 { "sr_Latn_CS", DataLocaleLibrary::EURO },
188 { "sr_ME", DataLocaleLibrary::EURO },
189 { "sr_RS", DataLocaleLibrary::EURO },
190 { "sr_CS", DataLocaleLibrary::EURO },
191 { "hr_HR", DataLocaleLibrary::EURO },
192 { "bs_BA", DataLocaleLibrary::EURO },
193 { "eu_ES", DataLocaleLibrary::EURO },
194 { "fo_FO", DataLocaleLibrary::EURO },
195 { "ga_IE", DataLocaleLibrary::EURO },
196 { "gd_GB", DataLocaleLibrary::EURO },
197 { "ka_GE", DataLocaleLibrary::EURO },
198 { "be_BY", DataLocaleLibrary::EURO },
199 { "kl_GL", DataLocaleLibrary::EURO },
200 { "mk_MK", DataLocaleLibrary::EURO },
201 { "br_FR", DataLocaleLibrary::EURO },
202 { "la_VA", DataLocaleLibrary::EURO },
203 { "cv_RU", DataLocaleLibrary::EURO },
204 { "wa_BE", DataLocaleLibrary::EURO },
205 { "fur_IT", DataLocaleLibrary::EURO },
206 { "gsc_FR", DataLocaleLibrary::EURO },
207 { "fy_NL", DataLocaleLibrary::EURO },
208 { "oc_FR_lengadoc", DataLocaleLibrary::EURO },
209 { "mt_MT", DataLocaleLibrary::EURO },
210 { "sc_IT", DataLocaleLibrary::EURO },
211 { "ast_ES", DataLocaleLibrary::EURO },
212 { "ltg_LV", DataLocaleLibrary::EURO },
213 { "hsb_DE", DataLocaleLibrary::EURO },
214 { "dsb_DE", DataLocaleLibrary::EURO },
215 { "rue_SK", DataLocaleLibrary::EURO },
216 { "an_ES", DataLocaleLibrary::EURO },
217 { "myv_RU", DataLocaleLibrary::EURO },
218 { "lld_IT", DataLocaleLibrary::EURO },
219 { "cu_RU", DataLocaleLibrary::EURO },
220 { "vec_IT", DataLocaleLibrary::EURO },
221 { "szl_PL", DataLocaleLibrary::EURO },
222 { "lij_IT", DataLocaleLibrary::EURO },
224 { "ja_JP", DataLocaleLibrary::OTHERS },
225 { "ko_KR", DataLocaleLibrary::OTHERS },
226 { "zh_CN", DataLocaleLibrary::OTHERS },
227 { "zh_HK", DataLocaleLibrary::OTHERS },
228 { "zh_SG", DataLocaleLibrary::OTHERS },
229 { "zh_TW", DataLocaleLibrary::OTHERS },
230 { "zh_MO", DataLocaleLibrary::OTHERS },
231 { "en_HK", DataLocaleLibrary::OTHERS }, // needs to be in OTHERS instead of EN because currency inherited from zh_HK
233 { "ar_EG", DataLocaleLibrary::OTHERS },
234 { "ar_DZ", DataLocaleLibrary::OTHERS },
235 { "ar_LB", DataLocaleLibrary::OTHERS },
236 { "ar_SA", DataLocaleLibrary::OTHERS },
237 { "ar_TN", DataLocaleLibrary::OTHERS },
238 { "he_IL", DataLocaleLibrary::OTHERS },
239 { "hi_IN", DataLocaleLibrary::OTHERS },
240 { "kn_IN", DataLocaleLibrary::OTHERS },
241 { "ta_IN", DataLocaleLibrary::OTHERS },
242 { "te_IN", DataLocaleLibrary::OTHERS },
243 { "gu_IN", DataLocaleLibrary::OTHERS },
244 { "mr_IN", DataLocaleLibrary::OTHERS },
245 { "pa_IN", DataLocaleLibrary::OTHERS },
246 { "bn_IN", DataLocaleLibrary::OTHERS },
247 { "or_IN", DataLocaleLibrary::OTHERS },
248 { "en_IN", DataLocaleLibrary::OTHERS }, // keep in OTHERS for IN
249 { "ml_IN", DataLocaleLibrary::OTHERS },
250 { "bn_BD", DataLocaleLibrary::OTHERS },
251 { "th_TH", DataLocaleLibrary::OTHERS },
253 { "af_ZA", DataLocaleLibrary::OTHERS },
254 { "hu_HU", DataLocaleLibrary::OTHERS },
255 { "id_ID", DataLocaleLibrary::OTHERS },
256 { "ms_MY", DataLocaleLibrary::OTHERS },
257 { "en_MY", DataLocaleLibrary::OTHERS }, // needs to be in OTHERS instead of EN because currency inherited from ms_MY
258 { "ia", DataLocaleLibrary::OTHERS },
259 { "mn_Cyrl_MN", DataLocaleLibrary::OTHERS },
260 { "az_AZ", DataLocaleLibrary::OTHERS },
261 { "sw_TZ", DataLocaleLibrary::OTHERS },
262 { "km_KH", DataLocaleLibrary::OTHERS },
263 { "lo_LA", DataLocaleLibrary::OTHERS },
264 { "rw_RW", DataLocaleLibrary::OTHERS },
265 { "eo", DataLocaleLibrary::OTHERS },
266 { "dz_BT", DataLocaleLibrary::OTHERS },
267 { "ne_NP", DataLocaleLibrary::OTHERS },
268 { "zu_ZA", DataLocaleLibrary::OTHERS },
269 { "nso_ZA", DataLocaleLibrary::OTHERS },
270 { "vi_VN", DataLocaleLibrary::OTHERS },
271 { "tn_ZA", DataLocaleLibrary::OTHERS },
272 { "xh_ZA", DataLocaleLibrary::OTHERS },
273 { "st_ZA", DataLocaleLibrary::OTHERS },
274 { "ss_ZA", DataLocaleLibrary::OTHERS },
275 { "ve_ZA", DataLocaleLibrary::OTHERS },
276 { "nr_ZA", DataLocaleLibrary::OTHERS },
277 { "ts_ZA", DataLocaleLibrary::OTHERS },
278 { "kmr_Latn_TR", DataLocaleLibrary::OTHERS },
279 { "ak_GH", DataLocaleLibrary::OTHERS },
280 { "af_NA", DataLocaleLibrary::OTHERS },
281 { "am_ET", DataLocaleLibrary::OTHERS },
282 { "ti_ER", DataLocaleLibrary::OTHERS },
283 { "tg_TJ", DataLocaleLibrary::OTHERS },
284 { "ky_KG", DataLocaleLibrary::OTHERS },
285 { "kk_KZ", DataLocaleLibrary::OTHERS },
286 { "fa_IR", DataLocaleLibrary::OTHERS },
287 { "ha_Latn_GH", DataLocaleLibrary::OTHERS },
288 { "ee_GH", DataLocaleLibrary::OTHERS },
289 { "sg_CF", DataLocaleLibrary::OTHERS },
290 { "lg_UG", DataLocaleLibrary::OTHERS },
291 { "uz_UZ", DataLocaleLibrary::OTHERS },
292 { "ln_CD", DataLocaleLibrary::OTHERS },
293 { "hy_AM", DataLocaleLibrary::OTHERS },
294 { "hil_PH", DataLocaleLibrary::OTHERS },
295 { "so_SO", DataLocaleLibrary::OTHERS },
296 { "gug_PY", DataLocaleLibrary::OTHERS },
297 { "tk_TM", DataLocaleLibrary::OTHERS },
298 { "my_MM", DataLocaleLibrary::OTHERS },
299 { "shs_CA", DataLocaleLibrary::OTHERS },
300 { "tpi_PG", DataLocaleLibrary::OTHERS },
301 { "ar_OM", DataLocaleLibrary::OTHERS },
302 { "ug_CN", DataLocaleLibrary::OTHERS },
303 { "om_ET", DataLocaleLibrary::OTHERS },
304 { "plt_MG", DataLocaleLibrary::OTHERS },
305 { "mai_IN", DataLocaleLibrary::OTHERS },
306 { "yi_US", DataLocaleLibrary::OTHERS },
307 { "haw_US", DataLocaleLibrary::OTHERS },
308 { "lif_NP", DataLocaleLibrary::OTHERS },
309 { "ur_PK", DataLocaleLibrary::OTHERS },
310 { "ht_HT", DataLocaleLibrary::OTHERS },
311 { "jbo", DataLocaleLibrary::OTHERS },
312 { "kab_DZ", DataLocaleLibrary::OTHERS },
313 { "pt_AO", DataLocaleLibrary::OTHERS },
314 { "pjt_AU", DataLocaleLibrary::OTHERS },
315 { "pap_BQ", DataLocaleLibrary::OTHERS },
316 { "pap_CW", DataLocaleLibrary::OTHERS },
317 { "ebo_CG", DataLocaleLibrary::OTHERS },
318 { "tyx_CG", DataLocaleLibrary::OTHERS },
319 { "axk_CG", DataLocaleLibrary::OTHERS },
320 { "beq_CG", DataLocaleLibrary::OTHERS },
321 { "bkw_CG", DataLocaleLibrary::OTHERS },
322 { "bvx_CG", DataLocaleLibrary::OTHERS },
323 { "dde_CG", DataLocaleLibrary::OTHERS },
324 { "iyx_CG", DataLocaleLibrary::OTHERS },
325 { "kkw_CG", DataLocaleLibrary::OTHERS },
326 { "kng_CG", DataLocaleLibrary::OTHERS },
327 { "ldi_CG", DataLocaleLibrary::OTHERS },
328 { "mdw_CG", DataLocaleLibrary::OTHERS },
329 { "mkw_CG", DataLocaleLibrary::OTHERS },
330 { "njx_CG", DataLocaleLibrary::OTHERS },
331 { "ngz_CG", DataLocaleLibrary::OTHERS },
332 { "njy_CG", DataLocaleLibrary::OTHERS },
333 { "puu_CG", DataLocaleLibrary::OTHERS },
334 { "sdj_CG", DataLocaleLibrary::OTHERS },
335 { "tek_CG", DataLocaleLibrary::OTHERS },
336 { "tsa_CG", DataLocaleLibrary::OTHERS },
337 { "vif_CG", DataLocaleLibrary::OTHERS },
338 { "xku_CG", DataLocaleLibrary::OTHERS },
339 { "yom_CG", DataLocaleLibrary::OTHERS },
340 { "sid_ET", DataLocaleLibrary::OTHERS },
341 { "bo_CN", DataLocaleLibrary::OTHERS },
342 { "bo_IN", DataLocaleLibrary::OTHERS },
343 { "ar_AE", DataLocaleLibrary::OTHERS },
344 { "ar_KW", DataLocaleLibrary::OTHERS },
345 { "bm_ML", DataLocaleLibrary::OTHERS },
346 { "pui_CO", DataLocaleLibrary::OTHERS },
347 { "lgr_SB", DataLocaleLibrary::OTHERS },
348 { "mos_BF", DataLocaleLibrary::OTHERS },
349 { "ny_MW", DataLocaleLibrary::OTHERS },
350 { "ar_BH", DataLocaleLibrary::OTHERS },
351 { "ar_IQ", DataLocaleLibrary::OTHERS },
352 { "ar_JO", DataLocaleLibrary::OTHERS },
353 { "ar_LY", DataLocaleLibrary::OTHERS },
354 { "ar_MA", DataLocaleLibrary::OTHERS },
355 { "ar_QA", DataLocaleLibrary::OTHERS },
356 { "ar_SY", DataLocaleLibrary::OTHERS },
357 { "ar_YE", DataLocaleLibrary::OTHERS },
358 { "ilo_PH", DataLocaleLibrary::OTHERS },
359 { "ha_Latn_NG", DataLocaleLibrary::OTHERS },
360 { "min_ID", DataLocaleLibrary::OTHERS },
361 { "sun_ID", DataLocaleLibrary::OTHERS },
362 { "en_IL", DataLocaleLibrary::OTHERS }, // needs to be in OTHERS instead of EN because inherits from he_IL
363 { "pdc_US", DataLocaleLibrary::OTHERS },
364 { "dv_MV", DataLocaleLibrary::OTHERS },
365 { "mfe_MU", DataLocaleLibrary::OTHERS },
366 { "sat_IN", DataLocaleLibrary::OTHERS },
367 { "sat_Olck_IN", DataLocaleLibrary::OTHERS }
370 #else
372 #include "localedata_static.hxx"
374 #endif
376 const sal_Unicode cUnder = '_';
377 const sal_Unicode cHyphen = '-';
379 const sal_Int16 nbOfLocales = SAL_N_ELEMENTS(aLibTable);
381 namespace i18npool {
383 // static
384 Sequence< CalendarItem > LocaleDataImpl::downcastCalendarItems( const Sequence< CalendarItem2 > & rCi )
386 return comphelper::containerToSequence<CalendarItem>(rCi);
390 // static
391 Calendar LocaleDataImpl::downcastCalendar( const Calendar2 & rC )
393 Calendar aCal(
394 downcastCalendarItems( rC.Days),
395 downcastCalendarItems( rC.Months),
396 downcastCalendarItems( rC.Eras),
397 rC.StartOfWeek,
398 rC.MinimumNumberOfDaysForFirstWeek,
399 rC.Default,
400 rC.Name
402 return aCal;
406 LocaleDataImpl::LocaleDataImpl()
409 LocaleDataImpl::~LocaleDataImpl()
414 LocaleDataItem SAL_CALL
415 LocaleDataImpl::getLocaleItem( const Locale& rLocale )
417 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getLocaleItem" ));
419 if ( func ) {
420 sal_Int16 dataItemCount = 0;
421 OUString const *dataItem = func(dataItemCount);
423 LocaleDataItem item{
424 dataItem[0],
425 dataItem[1],
426 dataItem[2],
427 dataItem[3],
428 dataItem[4],
429 dataItem[5],
430 dataItem[6],
431 dataItem[7],
432 dataItem[8],
433 dataItem[9],
434 dataItem[10],
435 dataItem[11],
436 dataItem[12],
437 dataItem[13],
438 dataItem[14],
439 dataItem[15],
440 dataItem[16],
441 dataItem[17]
443 return item;
445 else {
446 LocaleDataItem item1;
447 return item1;
452 LocaleDataItem2 SAL_CALL
453 LocaleDataImpl::getLocaleItem2( const Locale& rLocale )
455 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getLocaleItem" ));
457 if ( func ) {
458 sal_Int16 dataItemCount = 0;
459 OUString const *dataItem = func(dataItemCount);
461 assert(dataItemCount >= 18);
463 LocaleDataItem2 item{
464 dataItem[0],
465 dataItem[1],
466 dataItem[2],
467 dataItem[3],
468 dataItem[4],
469 dataItem[5],
470 dataItem[6],
471 dataItem[7],
472 dataItem[8],
473 dataItem[9],
474 dataItem[10],
475 dataItem[11],
476 dataItem[12],
477 dataItem[13],
478 dataItem[14],
479 dataItem[15],
480 dataItem[16],
481 dataItem[17],
482 dataItemCount >= 19 ? dataItem[18] : OUString()
484 return item;
486 else {
487 LocaleDataItem2 item1;
488 return item1;
492 #ifndef DISABLE_DYNLOADING
494 extern "C" { static void thisModule() {} }
496 #endif
498 namespace
501 // implement the lookup table as a safe static object
502 class lcl_LookupTableHelper
504 public:
505 lcl_LookupTableHelper();
506 ~lcl_LookupTableHelper();
508 oslGenericFunction getFunctionSymbolByName(
509 const OUString& localeName, const char* pFunction,
510 std::optional<LocaleDataLookupTableItem>& rOutCachedItem );
512 private:
513 std::mutex maMutex;
514 ::std::vector< LocaleDataLookupTableItem > maLookupTable;
517 // from instance.hxx: Helper base class for a late-initialized
518 // (default-constructed) static variable, implementing the double-checked
519 // locking pattern correctly.
520 // usage: lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic::get();
521 // retrieves the singleton lookup table instance
522 lcl_LookupTableHelper& lcl_LookupTableStatic()
524 static lcl_LookupTableHelper SINGLETON;
525 return SINGLETON;
528 lcl_LookupTableHelper::lcl_LookupTableHelper()
532 lcl_LookupTableHelper::~lcl_LookupTableHelper()
534 for ( const LocaleDataLookupTableItem& item : maLookupTable ) {
535 delete item.module;
539 oslGenericFunction lcl_LookupTableHelper::getFunctionSymbolByName(
540 const OUString& localeName, const char* pFunction,
541 std::optional<LocaleDataLookupTableItem>& rOutCachedItem )
543 OUString aFallback;
544 bool bFallback = (localeName.indexOf( cUnder) < 0);
545 if (bFallback)
547 Locale aLocale;
548 aLocale.Language = localeName;
549 Locale aFbLocale = MsLangId::getFallbackLocale( aLocale);
550 if (aFbLocale == aLocale)
551 bFallback = false; // may be a "language-only-locale" like Interlingua (ia)
552 else
553 aFallback = LocaleDataImpl::getFirstLocaleServiceName( aFbLocale);
556 for (const auto & i : aLibTable)
558 if (localeName.equalsAscii(i.pLocale) ||
559 (bFallback && aFallback.equalsAscii(i.pLocale)))
561 #ifndef DISABLE_DYNLOADING
563 std::unique_lock aGuard( maMutex );
564 for (LocaleDataLookupTableItem & rCurrent : maLookupTable)
566 if (rCurrent.dllName == i.pLib)
568 rOutCachedItem.emplace( rCurrent );
569 rOutCachedItem->localeName = i.pLocale;
570 OString sSymbolName = OString::Concat(pFunction) + "_" +
571 rOutCachedItem->localeName;
572 return rOutCachedItem->module->getFunctionSymbol(
573 sSymbolName.getStr());
577 // Library not loaded, load it and add it to the list.
578 std::unique_ptr<osl::Module> module(new osl::Module());
579 if ( module->loadRelative(&thisModule, getLibraryName(i.pLib)) )
581 std::unique_lock aGuard( maMutex );
582 auto pTmpModule = module.get();
583 maLookupTable.emplace_back(i.pLib, module.release(), i.pLocale);
584 rOutCachedItem.emplace( maLookupTable.back() );
585 OString sSymbolName = OString::Concat(pFunction) + "_" + rOutCachedItem->localeName;
586 return pTmpModule->getFunctionSymbol(sSymbolName.getStr());
588 else
589 module.reset();
590 #else
591 (void) rOutCachedItem;
593 if( strcmp(pFunction, "getAllCalendars") == 0 )
594 return i.getAllCalendars;
595 else if( strcmp(pFunction, "getAllCurrencies") == 0 )
596 return i.getAllCurrencies;
597 else if( strcmp(pFunction, "getAllFormats0") == 0 )
598 return i.getAllFormats0;
599 else if( strcmp(pFunction, "getBreakIteratorRules") == 0 )
600 return i.getBreakIteratorRules;
601 else if( strcmp(pFunction, "getCollationOptions") == 0 )
602 return i.getCollationOptions;
603 else if( strcmp(pFunction, "getCollatorImplementation") == 0 )
604 return i.getCollatorImplementation;
605 else if( strcmp(pFunction, "getContinuousNumberingLevels") == 0 )
606 return i.getContinuousNumberingLevels;
607 else if( strcmp(pFunction, "getDateAcceptancePatterns") == 0 )
608 return i.getDateAcceptancePatterns;
609 else if( strcmp(pFunction, "getFollowPageWords") == 0 )
610 return i.getFollowPageWords;
611 else if( strcmp(pFunction, "getForbiddenCharacters") == 0 )
612 return i.getForbiddenCharacters;
613 else if( strcmp(pFunction, "getIndexAlgorithm") == 0 )
614 return i.getIndexAlgorithm;
615 else if( strcmp(pFunction, "getLCInfo") == 0 )
616 return i.getLCInfo;
617 else if( strcmp(pFunction, "getLocaleItem") == 0 )
618 return i.getLocaleItem;
619 else if( strcmp(pFunction, "getOutlineNumberingLevels") == 0 )
620 return i.getOutlineNumberingLevels;
621 else if( strcmp(pFunction, "getReservedWords") == 0 )
622 return i.getReservedWords;
623 else if( strcmp(pFunction, "getSearchOptions") == 0 )
624 return i.getSearchOptions;
625 else if( strcmp(pFunction, "getTransliterations") == 0 )
626 return i.getTransliterations;
627 else if( strcmp(pFunction, "getUnicodeScripts") == 0 )
628 return i.getUnicodeScripts;
629 else if( strcmp(pFunction, "getAllFormats1") == 0 )
630 return i.getAllFormats1;
631 #endif
634 return nullptr;
637 } // anonymous namespace
640 // REF values equal offsets of counts within getAllCalendars() data structure!
641 #define REF_DAYS 0
642 #define REF_MONTHS 1
643 #define REF_GMONTHS 2
644 #define REF_PMONTHS 3
645 #define REF_ERAS 4
646 #define REF_OFFSET_COUNT 5
648 Sequence< CalendarItem2 > &LocaleDataImpl::getCalendarItemByName(const OUString& name,
649 const Locale& rLocale, const Sequence< Calendar2 >& calendarsSeq, sal_Int16 item)
651 if (ref_name != name) {
652 OUString aLocStr, id;
653 sal_Int32 nLastUnder = name.lastIndexOf( cUnder);
654 SAL_WARN_IF( nLastUnder < 1, "i18npool",
655 "LocaleDataImpl::getCalendarItemByName - no '_' or first in name can't be right: " << name);
656 if (nLastUnder >= 0)
658 aLocStr = name.copy( 0, nLastUnder);
659 if (nLastUnder + 1 < name.getLength())
660 id = name.copy( nLastUnder + 1);
662 Locale loc( LanguageTag::convertToLocale( aLocStr.replace( cUnder, cHyphen)));
663 Sequence < Calendar2 > cals;
664 if (loc == rLocale) {
665 cals = calendarsSeq;
666 } else {
667 cals = getAllCalendars2(loc);
669 auto pCal = std::find_if(std::cbegin(cals), std::cend(cals),
670 [&id](const Calendar2& rCal) { return id == rCal.Name; });
671 if (pCal != std::cend(cals))
672 ref_cal = *pCal;
673 else {
674 // Referred locale not found, return name for en_US locale.
675 cals = getAllCalendars2( Locale(u"en"_ustr, u"US"_ustr, OUString()) );
676 if (!cals.hasElements())
677 throw RuntimeException();
678 ref_cal = cals.getConstArray()[0];
680 ref_name = name;
682 switch (item)
684 case REF_DAYS:
685 return ref_cal.Days;
686 case REF_MONTHS:
687 return ref_cal.Months;
688 case REF_GMONTHS:
689 return ref_cal.GenitiveMonths;
690 case REF_PMONTHS:
691 return ref_cal.PartitiveMonths;
692 default:
693 OSL_FAIL( "LocaleDataImpl::getCalendarItemByName: unhandled REF_* case");
694 [[fallthrough]];
695 case REF_ERAS:
696 return ref_cal.Eras;
700 Sequence< CalendarItem2 > LocaleDataImpl::getCalendarItems(
701 OUString const * allCalendars, sal_Int16 & rnOffset,
702 const sal_Int16 nWhichItem, const sal_Int16 nCalendar,
703 const Locale & rLocale, const Sequence< Calendar2 > & calendarsSeq )
705 Sequence< CalendarItem2 > aItems;
706 if ( allCalendars[rnOffset] == std::u16string_view(u"ref") )
708 aItems = getCalendarItemByName( allCalendars[rnOffset+1], rLocale, calendarsSeq, nWhichItem);
709 rnOffset += 2;
711 else
713 const sal_Int32 nSize = allCalendars[nWhichItem][nCalendar];
714 aItems.realloc( nSize);
715 switch (nWhichItem)
717 case REF_DAYS:
718 case REF_MONTHS:
719 case REF_GMONTHS:
720 case REF_PMONTHS:
721 for (CalendarItem2& rItem : asNonConstRange(aItems))
723 rItem = CalendarItem2{ allCalendars[rnOffset],
724 allCalendars[rnOffset+1],
725 allCalendars[rnOffset+2], allCalendars[rnOffset+3]};
726 rnOffset += 4;
728 break;
729 case REF_ERAS:
730 // Absent narrow name.
731 for (CalendarItem2& rItem : asNonConstRange(aItems))
733 rItem = CalendarItem2{ allCalendars[rnOffset],
734 allCalendars[rnOffset+1],
735 allCalendars[rnOffset+2], OUString()};
736 rnOffset += 3;
738 break;
739 default:
740 OSL_FAIL( "LocaleDataImpl::getCalendarItems: unhandled REF_* case");
743 return aItems;
746 Sequence< Calendar2 > SAL_CALL
747 LocaleDataImpl::getAllCalendars2( const Locale& rLocale )
750 OUString const * allCalendars = nullptr;
752 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getAllCalendars" ));
754 if ( func ) {
755 sal_Int16 calendarsCount = 0;
756 allCalendars = func(calendarsCount);
758 Sequence< Calendar2 > calendarsSeq(calendarsCount);
759 auto calendarsSeqRange = asNonConstRange(calendarsSeq);
760 sal_Int16 offset = REF_OFFSET_COUNT;
761 for(sal_Int16 i = 0; i < calendarsCount; i++) {
762 OUString calendarID(allCalendars[offset]);
763 offset++;
764 bool defaultCalendar = allCalendars[offset][0] != 0;
765 offset++;
766 Sequence< CalendarItem2 > days = getCalendarItems( allCalendars, offset, REF_DAYS, i,
767 rLocale, calendarsSeq);
768 Sequence< CalendarItem2 > months = getCalendarItems( allCalendars, offset, REF_MONTHS, i,
769 rLocale, calendarsSeq);
770 Sequence< CalendarItem2 > gmonths = getCalendarItems( allCalendars, offset, REF_GMONTHS, i,
771 rLocale, calendarsSeq);
772 Sequence< CalendarItem2 > pmonths = getCalendarItems( allCalendars, offset, REF_PMONTHS, i,
773 rLocale, calendarsSeq);
774 Sequence< CalendarItem2 > eras = getCalendarItems( allCalendars, offset, REF_ERAS, i,
775 rLocale, calendarsSeq);
776 OUString startOfWeekDay(allCalendars[offset]);
777 offset++;
778 sal_Int16 minimalDaysInFirstWeek = allCalendars[offset][0];
779 offset++;
780 calendarsSeqRange[i] = Calendar2(days, months, gmonths, pmonths, eras, startOfWeekDay,
781 minimalDaysInFirstWeek, defaultCalendar, calendarID);
783 return calendarsSeq;
785 else {
786 return {};
791 Sequence< Calendar > SAL_CALL
792 LocaleDataImpl::getAllCalendars( const Locale& rLocale )
794 const Sequence< Calendar2 > aCal2( getAllCalendars2( rLocale));
795 std::vector<Calendar> aCal1;
796 aCal1.reserve(aCal2.getLength());
797 std::transform(aCal2.begin(), aCal2.end(), std::back_inserter(aCal1),
798 [](const Calendar2& rCal2) { return downcastCalendar(rCal2); });
799 return comphelper::containerToSequence(aCal1);
803 Sequence< Currency2 > SAL_CALL
804 LocaleDataImpl::getAllCurrencies2( const Locale& rLocale )
806 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getAllCurrencies" ));
808 if ( func ) {
809 sal_Int16 currencyCount = 0;
810 OUString const *allCurrencies = func(currencyCount);
812 Sequence< Currency2 > seq(currencyCount);
813 auto seqRange = asNonConstRange(seq);
814 for(int i = 0, nOff = 0; i < currencyCount; i++, nOff += 8 ) {
815 seqRange[i] = Currency2(
816 allCurrencies[nOff], // string ID
817 allCurrencies[nOff+1], // string Symbol
818 allCurrencies[nOff+2], // string BankSymbol
819 allCurrencies[nOff+3], // string Name
820 allCurrencies[nOff+4][0] != 0, // boolean Default
821 allCurrencies[nOff+5][0] != 0, // boolean UsedInCompatibleFormatCodes
822 allCurrencies[nOff+6][0], // short DecimalPlaces
823 allCurrencies[nOff+7][0] != 0 // boolean LegacyOnly
826 return seq;
828 else {
829 return {};
834 Sequence< Currency > SAL_CALL
835 LocaleDataImpl::getAllCurrencies( const Locale& rLocale )
837 return comphelper::containerToSequence<Currency>(getAllCurrencies2(rLocale));
841 Sequence< FormatElement > SAL_CALL
842 LocaleDataImpl::getAllFormats( const Locale& rLocale )
844 const int SECTIONS = 2;
845 struct FormatSection
847 MyFunc_FormatCode func;
848 sal_Unicode const *from;
849 sal_Unicode const *to;
850 OUString const *formatArray;
851 sal_Int16 formatCount;
853 FormatSection() : func(nullptr), from(nullptr), to(nullptr), formatArray(nullptr), formatCount(0) {}
854 sal_Int16 getFunc( LocaleDataImpl& rLocaleData, const Locale& rL, const char* pName )
856 func = reinterpret_cast<MyFunc_FormatCode>( rLocaleData.getFunctionSymbol( rL, pName));
857 if (func)
858 formatArray = func( formatCount, from, to);
859 return formatCount;
861 } section[SECTIONS];
863 sal_Int32 formatCount;
864 formatCount = section[0].getFunc( *this, rLocale, "getAllFormats0");
865 formatCount += section[1].getFunc( *this, rLocale, "getAllFormats1");
867 Sequence< FormatElement > seq(formatCount);
868 auto seqRange = asNonConstRange(seq);
869 sal_Int32 f = 0;
870 for (const FormatSection & s : section)
872 OUString const * const formatArray = s.formatArray;
873 if ( formatArray )
875 for (int i = 0, nOff = 0; i < s.formatCount; ++i, nOff += 7, ++f)
877 seqRange[f] = FormatElement(
878 formatArray[nOff].replaceAll(s.from, s.to),
879 formatArray[nOff + 1],
880 formatArray[nOff + 2],
881 formatArray[nOff + 3],
882 formatArray[nOff + 4],
883 formatArray[nOff + 5][0],
884 formatArray[nOff + 6][0] != 0);
888 return seq;
892 Sequence< OUString > SAL_CALL
893 LocaleDataImpl::getDateAcceptancePatterns( const Locale& rLocale )
895 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getDateAcceptancePatterns" ));
897 if (func)
899 sal_Int16 patternsCount = 0;
900 OUString const *patternsArray = func( patternsCount );
901 Sequence< OUString > seq( patternsCount );
902 auto seqRange = asNonConstRange(seq);
903 for (sal_Int16 i = 0; i < patternsCount; ++i)
905 seqRange[i] = patternsArray[i];
907 return seq;
909 else
911 return {};
916 #define COLLATOR_OFFSET_ALGO 0
917 #define COLLATOR_OFFSET_DEFAULT 1
918 #define COLLATOR_OFFSET_RULE 2
919 #define COLLATOR_ELEMENTS 3
921 OUString
922 LocaleDataImpl::getCollatorRuleByAlgorithm( const Locale& rLocale, std::u16string_view algorithm )
924 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getCollatorImplementation" ));
925 if ( func ) {
926 sal_Int16 collatorCount = 0;
927 OUString const *collatorArray = func(collatorCount);
928 for(sal_Int16 i = 0; i < collatorCount; i++)
929 if (algorithm == collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO])
930 return collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_RULE];
932 return OUString();
936 Sequence< Implementation > SAL_CALL
937 LocaleDataImpl::getCollatorImplementations( const Locale& rLocale )
939 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getCollatorImplementation" ));
941 if ( func ) {
942 sal_Int16 collatorCount = 0;
943 OUString const *collatorArray = func(collatorCount);
944 Sequence< Implementation > seq(collatorCount);
945 auto seqRange = asNonConstRange(seq);
946 for(sal_Int16 i = 0; i < collatorCount; i++) {
947 seqRange[i] = Implementation(
948 collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO],
949 collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_DEFAULT][0] != 0);
951 return seq;
953 else {
954 return {};
958 Sequence< OUString > SAL_CALL
959 LocaleDataImpl::getCollationOptions( const Locale& rLocale )
961 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getCollationOptions" ));
963 if ( func ) {
964 sal_Int16 optionsCount = 0;
965 OUString const *optionsArray = func(optionsCount);
966 Sequence< OUString > seq(optionsCount);
967 auto seqRange = asNonConstRange(seq);
968 for(sal_Int16 i = 0; i < optionsCount; i++) {
969 seqRange[i] = optionsArray[i];
971 return seq;
973 else {
974 return {};
978 Sequence< OUString > SAL_CALL
979 LocaleDataImpl::getSearchOptions( const Locale& rLocale )
981 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getSearchOptions" ));
983 if ( func ) {
984 sal_Int16 optionsCount = 0;
985 OUString const *optionsArray = func(optionsCount);
986 return Sequence< OUString >(optionsArray, optionsCount);
988 else {
989 return {};
993 OUString const *
994 LocaleDataImpl::getIndexArray(const Locale& rLocale, sal_Int16& indexCount)
996 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getIndexAlgorithm" ));
998 if (func)
999 return func(indexCount);
1000 return nullptr;
1003 Sequence< OUString >
1004 LocaleDataImpl::getIndexAlgorithm( const Locale& rLocale )
1006 sal_Int16 indexCount = 0;
1007 OUString const *indexArray = getIndexArray(rLocale, indexCount);
1009 if ( indexArray ) {
1010 Sequence< OUString > seq(indexCount);
1011 auto seqRange = asNonConstRange(seq);
1012 for(sal_Int16 i = 0; i < indexCount; i++) {
1013 seqRange[i] = indexArray[i*5];
1015 return seq;
1017 else {
1018 return {};
1022 OUString
1023 LocaleDataImpl::getDefaultIndexAlgorithm( const Locale& rLocale )
1025 sal_Int16 indexCount = 0;
1026 OUString const *indexArray = getIndexArray(rLocale, indexCount);
1028 if ( indexArray ) {
1029 for(sal_Int16 i = 0; i < indexCount; i++) {
1030 if (indexArray[i*5 + 3][0])
1031 return indexArray[i*5];
1034 return OUString();
1037 bool
1038 LocaleDataImpl::hasPhonetic( const Locale& rLocale )
1040 sal_Int16 indexCount = 0;
1041 OUString const *indexArray = getIndexArray(rLocale, indexCount);
1043 if ( indexArray ) {
1044 for(sal_Int16 i = 0; i < indexCount; i++) {
1045 if (indexArray[i*5 + 4][0])
1046 return true;
1049 return false;
1052 OUString const *
1053 LocaleDataImpl::getIndexArrayForAlgorithm(const Locale& rLocale, std::u16string_view algorithm)
1055 sal_Int16 indexCount = 0;
1056 OUString const *indexArray = getIndexArray(rLocale, indexCount);
1057 if ( indexArray ) {
1058 for(sal_Int16 i = 0; i < indexCount; i++) {
1059 if (algorithm == indexArray[i*5])
1060 return indexArray+i*5;
1063 return nullptr;
1066 bool
1067 LocaleDataImpl::isPhonetic( const Locale& rLocale, std::u16string_view algorithm )
1069 OUString const *indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1070 return indexArray && indexArray[4][0];
1073 OUString
1074 LocaleDataImpl::getIndexKeysByAlgorithm( const Locale& rLocale, std::u16string_view algorithm )
1076 OUString const *indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1077 return indexArray ? (OUString::Concat(u"0-9") + indexArray[2]) : OUString();
1080 OUString
1081 LocaleDataImpl::getIndexModuleByAlgorithm( const Locale& rLocale, std::u16string_view algorithm )
1083 OUString const *indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1084 return indexArray ? indexArray[1] : OUString();
1087 Sequence< UnicodeScript >
1088 LocaleDataImpl::getUnicodeScripts( const Locale& rLocale )
1090 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getUnicodeScripts" ));
1092 if ( func ) {
1093 sal_Int16 scriptCount = 0;
1094 OUString const *scriptArray = func(scriptCount);
1095 Sequence< UnicodeScript > seq(scriptCount);
1096 auto seqRange = asNonConstRange(seq);
1097 for(sal_Int16 i = 0; i < scriptCount; i++) {
1098 seqRange[i] = UnicodeScript( o3tl::toInt32(scriptArray[i].subView(0, 1)) );
1100 return seq;
1102 else {
1103 return {};
1107 Sequence< OUString >
1108 LocaleDataImpl::getFollowPageWords( const Locale& rLocale )
1110 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getFollowPageWords" ));
1112 if ( func ) {
1113 sal_Int16 wordCount = 0;
1114 OUString const *wordArray = func(wordCount);
1115 return Sequence< OUString >(wordArray, wordCount);
1117 else {
1118 return {};
1122 Sequence< OUString > SAL_CALL
1123 LocaleDataImpl::getTransliterations( const Locale& rLocale )
1125 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getTransliterations" ));
1127 if ( func ) {
1128 sal_Int16 transliterationsCount = 0;
1129 const OUString *transliterationsArray = func(transliterationsCount);
1130 return Sequence< OUString >(transliterationsArray, transliterationsCount);
1132 else {
1133 return {};
1140 LanguageCountryInfo SAL_CALL
1141 LocaleDataImpl::getLanguageCountryInfo( const Locale& rLocale )
1143 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getLCInfo" ));
1145 if ( func ) {
1146 sal_Int16 LCInfoCount = 0;
1147 OUString const *LCInfoArray = func(LCInfoCount);
1148 LanguageCountryInfo info{LCInfoArray[0],
1149 LCInfoArray[1],
1150 LCInfoArray[2],
1151 LCInfoArray[3],
1152 LCInfoArray[4]};
1153 return info;
1155 else {
1156 LanguageCountryInfo info1;
1157 return info1;
1163 ForbiddenCharacters SAL_CALL
1164 LocaleDataImpl::getForbiddenCharacters( const Locale& rLocale )
1166 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" ));
1168 if ( func ) {
1169 sal_Int16 LCForbiddenCharactersCount = 0;
1170 OUString const *LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1171 assert(LCForbiddenCharactersCount == 3);
1172 ForbiddenCharacters chars{
1173 LCForbiddenCharactersArray[0], LCForbiddenCharactersArray[1]};
1174 return chars;
1176 else {
1177 ForbiddenCharacters chars1;
1178 return chars1;
1182 OUString
1183 LocaleDataImpl::getHangingCharacters( const Locale& rLocale )
1185 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" ));
1187 if ( func ) {
1188 sal_Int16 LCForbiddenCharactersCount = 0;
1189 const OUString *LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1190 assert(LCForbiddenCharactersCount == 3);
1191 return LCForbiddenCharactersArray[2];
1194 return OUString();
1197 Sequence< OUString >
1198 LocaleDataImpl::getBreakIteratorRules( const Locale& rLocale )
1200 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getBreakIteratorRules" ));
1202 if ( func ) {
1203 sal_Int16 LCBreakIteratorRuleCount = 0;
1204 OUString const *LCBreakIteratorRulesArray = func(LCBreakIteratorRuleCount);
1205 return Sequence< OUString >(LCBreakIteratorRulesArray, LCBreakIteratorRuleCount);
1207 else {
1208 return {};
1213 Sequence< OUString > SAL_CALL
1214 LocaleDataImpl::getReservedWord( const Locale& rLocale )
1216 MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getReservedWords" ));
1218 if ( func ) {
1219 sal_Int16 LCReservedWordsCount = 0;
1220 OUString const *LCReservedWordsArray = func(LCReservedWordsCount);
1221 return Sequence< OUString >(LCReservedWordsArray, LCReservedWordsCount);
1223 else {
1224 return {};
1229 Sequence< Sequence<beans::PropertyValue> >
1230 LocaleDataImpl::getContinuousNumberingLevels( const lang::Locale& rLocale )
1232 // load symbol
1233 MyFunc_Type2 func = reinterpret_cast<MyFunc_Type2>(getFunctionSymbol( rLocale, "getContinuousNumberingLevels" ));
1235 if ( func )
1237 // invoke function
1238 sal_Int16 nStyles;
1239 sal_Int16 nAttributes;
1240 OUString const ** p0 = func( nStyles, nAttributes );
1242 // allocate memory for nAttributes attributes for each of the nStyles styles.
1243 Sequence< Sequence<beans::PropertyValue> > pv( nStyles );
1244 auto pvRange = asNonConstRange(pv);
1245 for( auto& i : pvRange ) {
1246 i = Sequence<beans::PropertyValue>( nAttributes );
1249 OUString const ** pStyle = p0;
1250 for( int i=0; i<nStyles; i++ ) {
1251 OUString const * pAttribute = pStyle[i];
1252 auto pvElementRange = asNonConstRange(pvRange[i]);
1253 for( int j=0; j<nAttributes; j++ ) { // prefix, numberingtype, ...
1254 OUString const & pString = pAttribute[j];
1255 beans::PropertyValue& rVal = pvElementRange[j];
1256 OUString sVal;
1257 if( 0 != j && 2 != j )
1258 sVal = pString;
1259 else if( !pString.isEmpty() )
1260 sVal = pString.copy( 0, 1 );
1262 switch( j )
1264 case 0:
1265 rVal.Name = "Prefix";
1266 rVal.Value <<= sVal;
1267 break;
1268 case 1:
1269 rVal.Name = "NumberingType";
1270 rVal.Value <<= static_cast<sal_Int16>(sVal.toInt32());
1271 break;
1272 case 2:
1273 rVal.Name = "Suffix";
1274 rVal.Value <<= sVal;
1275 break;
1276 case 3:
1277 rVal.Name = "Transliteration";
1278 rVal.Value <<= sVal;
1279 break;
1280 case 4:
1281 rVal.Name = "NatNum";
1282 rVal.Value <<= static_cast<sal_Int16>(sVal.toInt32());
1283 break;
1284 default:
1285 OSL_ASSERT(false);
1289 return pv;
1292 return Sequence< Sequence<beans::PropertyValue> >();
1295 // OutlineNumbering helper class
1297 namespace {
1299 struct OutlineNumberingLevel_Impl
1301 OUString sPrefix;
1302 sal_Int16 nNumType; //css::style::NumberingType
1303 OUString sSuffix;
1304 sal_Unicode cBulletChar;
1305 OUString sBulletFontName;
1306 sal_Int16 nParentNumbering;
1307 sal_Int32 nLeftMargin;
1308 sal_Int32 nSymbolTextDistance;
1309 sal_Int32 nFirstLineOffset;
1310 sal_Int16 nAdjust;
1311 OUString sTransliteration;
1312 sal_Int32 nNatNum;
1315 class OutlineNumbering : public cppu::WeakImplHelper < container::XIndexAccess >
1317 // OutlineNumbering helper class
1319 std::unique_ptr<const OutlineNumberingLevel_Impl[]> m_pOutlineLevels;
1320 sal_Int16 m_nCount;
1321 public:
1322 OutlineNumbering(std::unique_ptr<const OutlineNumberingLevel_Impl[]> pOutlineLevels, int nLevels);
1324 //XIndexAccess
1325 virtual sal_Int32 SAL_CALL getCount( ) override;
1326 virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override;
1328 //XElementAccess
1329 virtual Type SAL_CALL getElementType( ) override;
1330 virtual sal_Bool SAL_CALL hasElements( ) override;
1335 Sequence< Reference<container::XIndexAccess> >
1336 LocaleDataImpl::getOutlineNumberingLevels( const lang::Locale& rLocale )
1338 // load symbol
1339 MyFunc_Type3 func = reinterpret_cast<MyFunc_Type3>(getFunctionSymbol( rLocale, "getOutlineNumberingLevels" ));
1341 if ( func )
1343 int i;
1344 // invoke function
1345 sal_Int16 nStyles;
1346 sal_Int16 nLevels;
1347 sal_Int16 nAttributes;
1348 OUString const *** p0 = func( nStyles, nLevels, nAttributes );
1350 Sequence< Reference<container::XIndexAccess> > aRet( nStyles );
1351 auto aRetRange = asNonConstRange(aRet);
1352 OUString const *** pStyle = p0;
1353 for( i=0; i<nStyles; i++ )
1355 int j;
1357 std::unique_ptr<OutlineNumberingLevel_Impl[]> level(new OutlineNumberingLevel_Impl[ nLevels+1 ]);
1358 OUString const ** pLevel = pStyle[i];
1359 for( j = 0; j < nLevels; j++ )
1361 OUString const * pAttribute = pLevel[j];
1362 for( int k=0; k<nAttributes; k++ )
1364 OUString tmp( pAttribute[k] );
1365 switch( k )
1367 case 0: level[j].sPrefix = tmp; break;
1368 case 1: level[j].nNumType = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1369 case 2: level[j].sSuffix = tmp; break;
1370 case 3: level[j].cBulletChar = sal::static_int_cast<sal_Unicode>(tmp.toUInt32(16)); break; // base 16
1371 case 4: level[j].sBulletFontName = tmp; break;
1372 case 5: level[j].nParentNumbering = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1373 case 6: level[j].nLeftMargin = tmp.toInt32(); break;
1374 case 7: level[j].nSymbolTextDistance = tmp.toInt32(); break;
1375 case 8: level[j].nFirstLineOffset = tmp.toInt32(); break;
1376 case 9: level[j].nAdjust = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1377 case 10: level[j].sTransliteration = tmp; break;
1378 case 11: level[j].nNatNum = tmp.toInt32(); break;
1379 default:
1380 OSL_ASSERT(false);
1384 level[j].sPrefix.clear();
1385 level[j].nNumType = 0;
1386 level[j].sSuffix.clear();
1387 level[j].nAdjust = 0;
1388 level[j].cBulletChar = 0;
1389 level[j].sBulletFontName.clear();
1390 level[j].nParentNumbering = 0;
1391 level[j].nLeftMargin = 0;
1392 level[j].nSymbolTextDistance = 0;
1393 level[j].nFirstLineOffset = 0;
1394 level[j].sTransliteration.clear();
1395 level[j].nNatNum = 0;
1396 aRetRange[i] = new OutlineNumbering( std::move(level), nLevels );
1398 return aRet;
1400 else {
1401 return {};
1405 // helper functions
1407 oslGenericFunction LocaleDataImpl::getFunctionSymbol( const Locale& rLocale, const char* pFunction )
1409 lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic();
1411 if (moCachedItem && moCachedItem->equals(rLocale))
1413 OString sSymbolName = OString::Concat(pFunction) + "_" +
1414 moCachedItem->localeName;
1415 return moCachedItem->module->getFunctionSymbol(sSymbolName.getStr());
1418 oslGenericFunction pSymbol = nullptr;
1419 std::optional<LocaleDataLookupTableItem> oCachedItem;
1421 // Load function with name <func>_<lang>_<country> or <func>_<bcp47> and
1422 // fallbacks.
1423 pSymbol = rLookupTable.getFunctionSymbolByName( LocaleDataImpl::getFirstLocaleServiceName( rLocale),
1424 pFunction, oCachedItem);
1425 if (!pSymbol)
1427 ::std::vector< OUString > aFallbacks( LocaleDataImpl::getFallbackLocaleServiceNames( rLocale));
1428 for (const auto& rFallback : aFallbacks)
1430 pSymbol = rLookupTable.getFunctionSymbolByName(rFallback, pFunction, oCachedItem);
1431 if (pSymbol)
1432 break;
1435 if (!pSymbol)
1437 // load default function with name <func>_en_US
1438 pSymbol = rLookupTable.getFunctionSymbolByName(u"en_US"_ustr, pFunction, oCachedItem);
1441 if (!pSymbol)
1442 // Appropriate symbol could not be found. Give up.
1443 throw RuntimeException();
1445 if (oCachedItem)
1446 moCachedItem = std::move(oCachedItem);
1447 if (moCachedItem)
1448 moCachedItem->aLocale = rLocale;
1450 return pSymbol;
1453 Sequence< Locale > SAL_CALL
1454 LocaleDataImpl::getAllInstalledLocaleNames()
1456 Sequence< lang::Locale > seq( nbOfLocales );
1457 auto seqRange = asNonConstRange(seq);
1458 sal_Int16 nInstalled = 0;
1460 for(const auto & i : aLibTable) {
1461 OUString name = OUString::createFromAscii( i.pLocale );
1463 // Check if the locale is really available and not just in the table,
1464 // don't allow fall backs.
1465 std::optional<LocaleDataLookupTableItem> oCachedItem;
1466 if (lcl_LookupTableStatic().getFunctionSymbolByName( name, "getLocaleItem", oCachedItem )) {
1467 if( oCachedItem )
1468 moCachedItem = std::move( oCachedItem );
1469 seqRange[nInstalled++] = LanguageTag::convertToLocale( name.replace( cUnder, cHyphen), false);
1472 if ( nInstalled < nbOfLocales )
1473 seq.realloc( nInstalled ); // reflect reality
1475 return seq;
1478 using namespace ::com::sun::star::container;
1479 using namespace ::com::sun::star::beans;
1481 OutlineNumbering::OutlineNumbering(std::unique_ptr<const OutlineNumberingLevel_Impl[]> pOutlnLevels, int nLevels) :
1482 m_pOutlineLevels(std::move(pOutlnLevels)),
1483 m_nCount(sal::static_int_cast<sal_Int16>(nLevels))
1487 sal_Int32 OutlineNumbering::getCount( )
1489 return m_nCount;
1492 Any OutlineNumbering::getByIndex( sal_Int32 nIndex )
1494 if(nIndex < 0 || nIndex >= m_nCount)
1495 throw IndexOutOfBoundsException();
1496 const OutlineNumberingLevel_Impl* pTemp = m_pOutlineLevels.get();
1497 pTemp += nIndex;
1498 Any aRet;
1500 Sequence<PropertyValue> aOutlineNumbering(12);
1501 PropertyValue* pValues = aOutlineNumbering.getArray();
1502 pValues[0].Name = "Prefix";
1503 pValues[0].Value <<= pTemp->sPrefix;
1504 pValues[1].Name = "NumberingType";
1505 pValues[1].Value <<= pTemp->nNumType;
1506 pValues[2].Name = "Suffix";
1507 pValues[2].Value <<= pTemp->sSuffix;
1508 pValues[3].Name = "BulletChar";
1509 pValues[3].Value <<= OUString(&pTemp->cBulletChar, 1);
1510 pValues[4].Name = "BulletFontName";
1511 pValues[4].Value <<= pTemp->sBulletFontName;
1512 pValues[5].Name = "ParentNumbering";
1513 pValues[5].Value <<= pTemp->nParentNumbering;
1514 pValues[6].Name = "LeftMargin";
1515 pValues[6].Value <<= pTemp->nLeftMargin;
1516 pValues[7].Name = "SymbolTextDistance";
1517 pValues[7].Value <<= pTemp->nSymbolTextDistance;
1518 pValues[8].Name = "FirstLineOffset";
1519 pValues[8].Value <<= pTemp->nFirstLineOffset;
1520 pValues[9].Name = "Adjust";
1521 pValues[9].Value <<= pTemp->nAdjust;
1522 pValues[10].Name = "Transliteration";
1523 pValues[10].Value <<= pTemp->sTransliteration;
1524 pValues[11].Name = "NatNum";
1525 pValues[11].Value <<= pTemp->nNatNum;
1526 aRet <<= aOutlineNumbering;
1527 return aRet;
1530 Type OutlineNumbering::getElementType( )
1532 return cppu::UnoType<Sequence<PropertyValue>>::get();
1535 sal_Bool OutlineNumbering::hasElements( )
1537 return m_nCount > 0;
1540 OUString SAL_CALL
1541 LocaleDataImpl::getImplementationName()
1543 return u"com.sun.star.i18n.LocaleDataImpl"_ustr;
1546 sal_Bool SAL_CALL LocaleDataImpl::supportsService(const OUString& rServiceName)
1548 return cppu::supportsService(this, rServiceName);
1551 Sequence< OUString > SAL_CALL
1552 LocaleDataImpl::getSupportedServiceNames()
1554 Sequence< OUString > aRet {
1555 u"com.sun.star.i18n.LocaleData"_ustr,
1556 u"com.sun.star.i18n.LocaleData2"_ustr
1558 return aRet;
1561 // static
1562 OUString LocaleDataImpl::getFirstLocaleServiceName( const css::lang::Locale & rLocale )
1564 if (rLocale.Language == I18NLANGTAG_QLT)
1565 return rLocale.Variant.replace( cHyphen, cUnder);
1566 else if (!rLocale.Country.isEmpty())
1567 return rLocale.Language + "_" + rLocale.Country;
1568 else
1569 return rLocale.Language;
1572 // static
1573 ::std::vector< OUString > LocaleDataImpl::getFallbackLocaleServiceNames( const css::lang::Locale & rLocale )
1575 ::std::vector< OUString > aVec;
1576 if (rLocale.Language == I18NLANGTAG_QLT)
1578 aVec = LanguageTag( rLocale).getFallbackStrings( false);
1579 for (auto& rItem : aVec)
1581 rItem = rItem.replace(cHyphen, cUnder);
1584 else if (!rLocale.Country.isEmpty())
1586 aVec.push_back( rLocale.Language);
1588 // else nothing, language-only was the first
1589 return aVec;
1594 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1595 com_sun_star_i18n_LocaleDataImpl_get_implementation(
1596 css::uno::XComponentContext *,
1597 css::uno::Sequence<css::uno::Any> const &)
1599 return cppu::acquire(new i18npool::LocaleDataImpl());
1602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */