LibreOffice Module i18npool (master)  1
localedata.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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 <com/sun/star/text/HoriOrientation.hpp>
27 #include <comphelper/sequence.hxx>
28 #include <cppuhelper/implbase.hxx>
30 #include <localedata.hxx>
31 #include <i18nlangtag/mslangid.hxx>
33 #include <sal/log.hxx>
34 #include <osl/diagnose.h>
35 #include <sal/macros.h>
36 
37 namespace com::sun::star::uno { class XComponentContext; }
38 
39 using namespace com::sun::star::i18n;
40 using namespace com::sun::star::uno;
41 using namespace com::sun::star::lang;
42 using namespace com::sun::star;
43 
44 typedef sal_Unicode** (* MyFunc_Type)( sal_Int16&);
45 typedef sal_Unicode const *** (* MyFunc_Type2)( sal_Int16&, sal_Int16& );
46 typedef sal_Unicode const **** (* MyFunc_Type3)( sal_Int16&, sal_Int16&, sal_Int16& );
47 typedef sal_Unicode const * const * (* MyFunc_FormatCode)( sal_Int16&, sal_Unicode const *&, sal_Unicode const *& );
48 
49 #ifndef DISABLE_DYNLOADING
50 
51 static const char *lcl_DATA_EN = "localedata_en";
52 static const char *lcl_DATA_ES = "localedata_es";
53 static const char *lcl_DATA_EURO = "localedata_euro";
54 static const char *lcl_DATA_OTHERS = "localedata_others";
55 
56 const struct {
57  const char* pLocale;
58  const char* pLib;
59 } aLibTable[] = {
60  { "en_US", lcl_DATA_EN },
61  { "en_AU", lcl_DATA_EN },
62  { "en_BZ", lcl_DATA_EN },
63  { "en_CA", lcl_DATA_EN },
64  { "en_GB", lcl_DATA_EN },
65  { "en_IE", lcl_DATA_EN },
66  { "en_JM", lcl_DATA_EN },
67  { "en_NZ", lcl_DATA_EN },
68  { "en_PH", lcl_DATA_EN },
69  { "en_TT", lcl_DATA_EN },
70  { "en_ZA", lcl_DATA_EN },
71  { "en_ZW", lcl_DATA_EN },
72  { "en_NA", lcl_DATA_EN },
73  { "en_GH", lcl_DATA_EN },
74  { "en_MW", lcl_DATA_EN },
75  { "en_GM", lcl_DATA_EN },
76  { "en_BW", lcl_DATA_EN },
77  { "en_ZM", lcl_DATA_EN },
78  { "en_LK", lcl_DATA_EN },
79  { "en_NG", lcl_DATA_EN },
80  { "en_KE", lcl_DATA_EN },
81  { "en_DK", lcl_DATA_EN },
82 
83  { "es_ES", lcl_DATA_ES },
84  { "es_AR", lcl_DATA_ES },
85  { "es_BO", lcl_DATA_ES },
86  { "es_CL", lcl_DATA_ES },
87  { "es_CO", lcl_DATA_ES },
88  { "es_CR", lcl_DATA_ES },
89  { "es_DO", lcl_DATA_ES },
90  { "es_EC", lcl_DATA_ES },
91  { "es_GT", lcl_DATA_ES },
92  { "es_HN", lcl_DATA_ES },
93  { "es_MX", lcl_DATA_ES },
94  { "es_NI", lcl_DATA_ES },
95  { "es_PA", lcl_DATA_ES },
96  { "es_PE", lcl_DATA_ES },
97  { "es_PR", lcl_DATA_ES },
98  { "es_PY", lcl_DATA_ES },
99  { "es_SV", lcl_DATA_ES },
100  { "es_UY", lcl_DATA_ES },
101  { "es_VE", lcl_DATA_ES },
102  { "gl_ES", lcl_DATA_ES },
103 
104  { "de_DE", lcl_DATA_EURO },
105  { "de_AT", lcl_DATA_EURO },
106  { "de_CH", lcl_DATA_EURO },
107  { "de_LI", lcl_DATA_EURO },
108  { "de_LU", lcl_DATA_EURO },
109  { "fr_FR", lcl_DATA_EURO },
110  { "fr_BE", lcl_DATA_EURO },
111  { "fr_CA", lcl_DATA_EURO },
112  { "fr_CH", lcl_DATA_EURO },
113  { "fr_LU", lcl_DATA_EURO },
114  { "fr_MC", lcl_DATA_EURO },
115  { "fr_BF", lcl_DATA_EURO },
116  { "fr_CI", lcl_DATA_EURO },
117  { "fr_ML", lcl_DATA_EURO },
118  { "fr_SN", lcl_DATA_EURO },
119  { "fr_BJ", lcl_DATA_EURO },
120  { "fr_NE", lcl_DATA_EURO },
121  { "fr_TG", lcl_DATA_EURO },
122  { "it_IT", lcl_DATA_EURO },
123  { "it_CH", lcl_DATA_EURO },
124  { "sl_SI", lcl_DATA_EURO },
125  { "sv_SE", lcl_DATA_EURO },
126  { "sv_FI", lcl_DATA_EURO },
127  { "ca_ES", lcl_DATA_EURO },
128  { "ca_ES_valencia", lcl_DATA_EURO },
129  { "cs_CZ", lcl_DATA_EURO },
130  { "sk_SK", lcl_DATA_EURO },
131  { "da_DK", lcl_DATA_EURO },
132  { "el_GR", lcl_DATA_EURO },
133  { "fi_FI", lcl_DATA_EURO },
134  { "is_IS", lcl_DATA_EURO },
135  { "nl_BE", lcl_DATA_EURO },
136  { "nl_NL", lcl_DATA_EURO },
137  { "no_NO", lcl_DATA_EURO },
138  { "nn_NO", lcl_DATA_EURO },
139  { "nb_NO", lcl_DATA_EURO },
140  { "nds_DE", lcl_DATA_EURO },
141  { "pl_PL", lcl_DATA_EURO },
142  { "pt_BR", lcl_DATA_EURO },
143  { "pt_PT", lcl_DATA_EURO },
144  { "ru_RU", lcl_DATA_EURO },
145  { "tr_TR", lcl_DATA_EURO },
146  { "tt_RU", lcl_DATA_EURO },
147  { "et_EE", lcl_DATA_EURO },
148  { "vro_EE", lcl_DATA_EURO },
149  { "lb_LU", lcl_DATA_EURO },
150  { "lt_LT", lcl_DATA_EURO },
151  { "lv_LV", lcl_DATA_EURO },
152  { "uk_UA", lcl_DATA_EURO },
153  { "ro_RO", lcl_DATA_EURO },
154  { "cy_GB", lcl_DATA_EURO },
155  { "bg_BG", lcl_DATA_EURO },
156  { "sr_Latn_ME", lcl_DATA_EURO },
157  { "sr_Latn_RS", lcl_DATA_EURO },
158  { "sr_Latn_CS", lcl_DATA_EURO },
159  { "sr_ME", lcl_DATA_EURO },
160  { "sr_RS", lcl_DATA_EURO },
161  { "sr_CS", lcl_DATA_EURO },
162  { "hr_HR", lcl_DATA_EURO },
163  { "bs_BA", lcl_DATA_EURO },
164  { "eu_ES", lcl_DATA_EURO },
165  { "fo_FO", lcl_DATA_EURO },
166  { "ga_IE", lcl_DATA_EURO },
167  { "gd_GB", lcl_DATA_EURO },
168  { "ka_GE", lcl_DATA_EURO },
169  { "be_BY", lcl_DATA_EURO },
170  { "kl_GL", lcl_DATA_EURO },
171  { "mk_MK", lcl_DATA_EURO },
172  { "br_FR", lcl_DATA_EURO },
173  { "la_VA", lcl_DATA_EURO },
174  { "cv_RU", lcl_DATA_EURO },
175  { "wa_BE", lcl_DATA_EURO },
176  { "fur_IT", lcl_DATA_EURO },
177  { "gsc_FR", lcl_DATA_EURO },
178  { "fy_NL", lcl_DATA_EURO },
179  { "oc_FR", lcl_DATA_EURO },
180  { "mt_MT", lcl_DATA_EURO },
181  { "sc_IT", lcl_DATA_EURO },
182  { "ast_ES", lcl_DATA_EURO },
183  { "ltg_LV", lcl_DATA_EURO },
184  { "hsb_DE", lcl_DATA_EURO },
185  { "dsb_DE", lcl_DATA_EURO },
186  { "rue_SK", lcl_DATA_EURO },
187  { "an_ES", lcl_DATA_EURO },
188  { "myv_RU", lcl_DATA_EURO },
189  { "lld_IT", lcl_DATA_EURO },
190  { "cu_RU", lcl_DATA_EURO },
191  { "vec_IT", lcl_DATA_EURO },
192  { "szl_PL", lcl_DATA_EURO },
193  { "lij_IT", lcl_DATA_EURO },
194 
195  { "ja_JP", lcl_DATA_OTHERS },
196  { "ko_KR", lcl_DATA_OTHERS },
197  { "zh_CN", lcl_DATA_OTHERS },
198  { "zh_HK", lcl_DATA_OTHERS },
199  { "zh_SG", lcl_DATA_OTHERS },
200  { "zh_TW", lcl_DATA_OTHERS },
201  { "zh_MO", lcl_DATA_OTHERS },
202  { "en_HK", lcl_DATA_OTHERS }, // needs to be in OTHERS instead of EN because currency inherited from zh_HK
203 
204  { "ar_EG", lcl_DATA_OTHERS },
205  { "ar_DZ", lcl_DATA_OTHERS },
206  { "ar_LB", lcl_DATA_OTHERS },
207  { "ar_SA", lcl_DATA_OTHERS },
208  { "ar_TN", lcl_DATA_OTHERS },
209  { "he_IL", lcl_DATA_OTHERS },
210  { "hi_IN", lcl_DATA_OTHERS },
211  { "kn_IN", lcl_DATA_OTHERS },
212  { "ta_IN", lcl_DATA_OTHERS },
213  { "te_IN", lcl_DATA_OTHERS },
214  { "gu_IN", lcl_DATA_OTHERS },
215  { "mr_IN", lcl_DATA_OTHERS },
216  { "pa_IN", lcl_DATA_OTHERS },
217  { "bn_IN", lcl_DATA_OTHERS },
218  { "or_IN", lcl_DATA_OTHERS },
219  { "en_IN", lcl_DATA_OTHERS }, // keep in OTHERS for IN
220  { "ml_IN", lcl_DATA_OTHERS },
221  { "bn_BD", lcl_DATA_OTHERS },
222  { "th_TH", lcl_DATA_OTHERS },
223 
224  { "af_ZA", lcl_DATA_OTHERS },
225  { "hu_HU", lcl_DATA_OTHERS },
226  { "id_ID", lcl_DATA_OTHERS },
227  { "ms_MY", lcl_DATA_OTHERS },
228  { "en_MY", lcl_DATA_OTHERS }, // needs to be in OTHERS instead of EN because currency inherited from ms_MY
229  { "ia", lcl_DATA_OTHERS },
230  { "mn_Cyrl_MN", lcl_DATA_OTHERS },
231  { "az_AZ", lcl_DATA_OTHERS },
232  { "sw_TZ", lcl_DATA_OTHERS },
233  { "km_KH", lcl_DATA_OTHERS },
234  { "lo_LA", lcl_DATA_OTHERS },
235  { "rw_RW", lcl_DATA_OTHERS },
236  { "eo", lcl_DATA_OTHERS },
237  { "dz_BT", lcl_DATA_OTHERS },
238  { "ne_NP", lcl_DATA_OTHERS },
239  { "zu_ZA", lcl_DATA_OTHERS },
240  { "nso_ZA", lcl_DATA_OTHERS },
241  { "vi_VN", lcl_DATA_OTHERS },
242  { "tn_ZA", lcl_DATA_OTHERS },
243  { "xh_ZA", lcl_DATA_OTHERS },
244  { "st_ZA", lcl_DATA_OTHERS },
245  { "ss_ZA", lcl_DATA_OTHERS },
246  { "ve_ZA", lcl_DATA_OTHERS },
247  { "nr_ZA", lcl_DATA_OTHERS },
248  { "ts_ZA", lcl_DATA_OTHERS },
249  { "kmr_Latn_TR", lcl_DATA_OTHERS },
250  { "ak_GH", lcl_DATA_OTHERS },
251  { "af_NA", lcl_DATA_OTHERS },
252  { "am_ET", lcl_DATA_OTHERS },
253  { "ti_ER", lcl_DATA_OTHERS },
254  { "tg_TJ", lcl_DATA_OTHERS },
255  { "ky_KG", lcl_DATA_OTHERS },
256  { "kk_KZ", lcl_DATA_OTHERS },
257  { "fa_IR", lcl_DATA_OTHERS },
258  { "ha_Latn_GH", lcl_DATA_OTHERS },
259  { "ee_GH", lcl_DATA_OTHERS },
260  { "sg_CF", lcl_DATA_OTHERS },
261  { "lg_UG", lcl_DATA_OTHERS },
262  { "uz_UZ", lcl_DATA_OTHERS },
263  { "ln_CD", lcl_DATA_OTHERS },
264  { "hy_AM", lcl_DATA_OTHERS },
265  { "hil_PH", lcl_DATA_OTHERS },
266  { "so_SO", lcl_DATA_OTHERS },
267  { "gug_PY", lcl_DATA_OTHERS },
268  { "tk_TM", lcl_DATA_OTHERS },
269  { "my_MM", lcl_DATA_OTHERS },
270  { "shs_CA", lcl_DATA_OTHERS },
271  { "tpi_PG", lcl_DATA_OTHERS },
272  { "ar_OM", lcl_DATA_OTHERS },
273  { "ug_CN", lcl_DATA_OTHERS },
274  { "om_ET", lcl_DATA_OTHERS },
275  { "plt_MG", lcl_DATA_OTHERS },
276  { "mai_IN", lcl_DATA_OTHERS },
277  { "yi_US", lcl_DATA_OTHERS },
278  { "haw_US", lcl_DATA_OTHERS },
279  { "lif_NP", lcl_DATA_OTHERS },
280  { "ur_PK", lcl_DATA_OTHERS },
281  { "ht_HT", lcl_DATA_OTHERS },
282  { "jbo", lcl_DATA_OTHERS },
283  { "kab_DZ", lcl_DATA_OTHERS },
284  { "pt_AO", lcl_DATA_OTHERS },
285  { "pjt_AU", lcl_DATA_OTHERS },
286  { "pap_BQ", lcl_DATA_OTHERS },
287  { "pap_CW", lcl_DATA_OTHERS },
288  { "ebo_CG", lcl_DATA_OTHERS },
289  { "tyx_CG", lcl_DATA_OTHERS },
290  { "axk_CG", lcl_DATA_OTHERS },
291  { "beq_CG", lcl_DATA_OTHERS },
292  { "bkw_CG", lcl_DATA_OTHERS },
293  { "bvx_CG", lcl_DATA_OTHERS },
294  { "dde_CG", lcl_DATA_OTHERS },
295  { "iyx_CG", lcl_DATA_OTHERS },
296  { "kkw_CG", lcl_DATA_OTHERS },
297  { "kng_CG", lcl_DATA_OTHERS },
298  { "ldi_CG", lcl_DATA_OTHERS },
299  { "mdw_CG", lcl_DATA_OTHERS },
300  { "mkw_CG", lcl_DATA_OTHERS },
301  { "njx_CG", lcl_DATA_OTHERS },
302  { "ngz_CG", lcl_DATA_OTHERS },
303  { "njy_CG", lcl_DATA_OTHERS },
304  { "puu_CG", lcl_DATA_OTHERS },
305  { "sdj_CG", lcl_DATA_OTHERS },
306  { "tek_CG", lcl_DATA_OTHERS },
307  { "tsa_CG", lcl_DATA_OTHERS },
308  { "vif_CG", lcl_DATA_OTHERS },
309  { "xku_CG", lcl_DATA_OTHERS },
310  { "yom_CG", lcl_DATA_OTHERS },
311  { "sid_ET", lcl_DATA_OTHERS },
312  { "bo_CN", lcl_DATA_OTHERS },
313  { "bo_IN", lcl_DATA_OTHERS },
314  { "ar_AE", lcl_DATA_OTHERS },
315  { "ar_KW", lcl_DATA_OTHERS },
316  { "bm_ML", lcl_DATA_OTHERS },
317  { "pui_CO", lcl_DATA_OTHERS },
318  { "lgr_SB", lcl_DATA_OTHERS },
319  { "mos_BF", lcl_DATA_OTHERS },
320  { "ny_MW", lcl_DATA_OTHERS },
321  { "ar_BH", lcl_DATA_OTHERS },
322  { "ar_IQ", lcl_DATA_OTHERS },
323  { "ar_JO", lcl_DATA_OTHERS },
324  { "ar_LY", lcl_DATA_OTHERS },
325  { "ar_MA", lcl_DATA_OTHERS },
326  { "ar_QA", lcl_DATA_OTHERS },
327  { "ar_SY", lcl_DATA_OTHERS },
328  { "ar_YE", lcl_DATA_OTHERS },
329  { "ilo_PH", lcl_DATA_OTHERS },
330  { "ha_Latn_NG", lcl_DATA_OTHERS },
331  { "min_ID", lcl_DATA_OTHERS },
332  { "sun_ID", lcl_DATA_OTHERS },
333  { "en_IL", lcl_DATA_OTHERS } // needs to be in OTHERS instead of EN because inherits from he_IL
334 };
335 
336 #else
337 
338 #include "localedata_static.hxx"
339 
340 #endif
341 
342 const sal_Unicode cUnder = '_';
343 const sal_Unicode cHyphen = '-';
344 
346 
347 namespace i18npool {
348 
349 // static
350 Sequence< CalendarItem > LocaleDataImpl::downcastCalendarItems( const Sequence< CalendarItem2 > & rCi )
351 {
352  return comphelper::containerToSequence<CalendarItem>(rCi);
353 }
354 
355 
356 // static
357 Calendar LocaleDataImpl::downcastCalendar( const Calendar2 & rC )
358 {
359  Calendar aCal(
360  downcastCalendarItems( rC.Days),
361  downcastCalendarItems( rC.Months),
362  downcastCalendarItems( rC.Eras),
363  rC.StartOfWeek,
364  rC.MinimumNumberOfDaysForFirstWeek,
365  rC.Default,
366  rC.Name
367  );
368  return aCal;
369 }
370 
371 
372 LocaleDataImpl::LocaleDataImpl()
373 {
374 }
375 LocaleDataImpl::~LocaleDataImpl()
376 {
377 }
378 
379 
380 LocaleDataItem SAL_CALL
381 LocaleDataImpl::getLocaleItem( const Locale& rLocale )
382 {
383  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getLocaleItem" ));
384 
385  if ( func ) {
386  sal_Int16 dataItemCount = 0;
387  sal_Unicode **dataItem = func(dataItemCount);
388 
389  LocaleDataItem item{
390  OUString(dataItem[0]),
391  OUString(dataItem[1]),
392  OUString(dataItem[2]),
393  OUString(dataItem[3]),
394  OUString(dataItem[4]),
395  OUString(dataItem[5]),
396  OUString(dataItem[6]),
397  OUString(dataItem[7]),
398  OUString(dataItem[8]),
399  OUString(dataItem[9]),
400  OUString(dataItem[10]),
401  OUString(dataItem[11]),
402  OUString(dataItem[12]),
403  OUString(dataItem[13]),
404  OUString(dataItem[14]),
405  OUString(dataItem[15]),
406  OUString(dataItem[16]),
407  OUString(dataItem[17])
408  };
409  return item;
410  }
411  else {
412  LocaleDataItem item1;
413  return item1;
414  }
415 }
416 
417 
418 LocaleDataItem2 SAL_CALL
419 LocaleDataImpl::getLocaleItem2( const Locale& rLocale )
420 {
421  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getLocaleItem" ));
422 
423  if ( func ) {
424  sal_Int16 dataItemCount = 0;
425  sal_Unicode **dataItem = func(dataItemCount);
426 
427  assert(dataItemCount >= 18);
428 
429  LocaleDataItem2 item{
430  OUString(dataItem[0]),
431  OUString(dataItem[1]),
432  OUString(dataItem[2]),
433  OUString(dataItem[3]),
434  OUString(dataItem[4]),
435  OUString(dataItem[5]),
436  OUString(dataItem[6]),
437  OUString(dataItem[7]),
438  OUString(dataItem[8]),
439  OUString(dataItem[9]),
440  OUString(dataItem[10]),
441  OUString(dataItem[11]),
442  OUString(dataItem[12]),
443  OUString(dataItem[13]),
444  OUString(dataItem[14]),
445  OUString(dataItem[15]),
446  OUString(dataItem[16]),
447  OUString(dataItem[17]),
448  dataItemCount >= 19 ? OUString(dataItem[18]) : OUString()
449  };
450  return item;
451  }
452  else {
453  LocaleDataItem2 item1;
454  return item1;
455  }
456 }
457 
458 #ifndef DISABLE_DYNLOADING
459 
460 extern "C" { static void thisModule() {} }
461 
462 #endif
463 
464 namespace
465 {
466 
467 // implement the lookup table as a safe static object
468 class lcl_LookupTableHelper
469 {
470 public:
471  lcl_LookupTableHelper();
472  ~lcl_LookupTableHelper();
473 
474  oslGenericFunction getFunctionSymbolByName(
475  const OUString& localeName, const char* pFunction,
476  std::optional<LocaleDataLookupTableItem>& rOutCachedItem );
477 
478 private:
479  std::mutex maMutex;
480  ::std::vector< LocaleDataLookupTableItem > maLookupTable;
481 };
482 
483 // from instance.hxx: Helper base class for a late-initialized
484 // (default-constructed) static variable, implementing the double-checked
485 // locking pattern correctly.
486 // usage: lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic::get();
487 // retrieves the singleton lookup table instance
488 lcl_LookupTableHelper& lcl_LookupTableStatic()
489 {
490  static lcl_LookupTableHelper SINGLETON;
491  return SINGLETON;
492 }
493 
494 lcl_LookupTableHelper::lcl_LookupTableHelper()
495 {
496 }
497 
498 lcl_LookupTableHelper::~lcl_LookupTableHelper()
499 {
500  for ( const LocaleDataLookupTableItem& item : maLookupTable ) {
501  delete item.module;
502  }
503 }
504 
505 oslGenericFunction lcl_LookupTableHelper::getFunctionSymbolByName(
506  const OUString& localeName, const char* pFunction,
507  std::optional<LocaleDataLookupTableItem>& rOutCachedItem )
508 {
509  OUString aFallback;
510  bool bFallback = (localeName.indexOf( cUnder) < 0);
511  if (bFallback)
512  {
513  Locale aLocale;
514  aLocale.Language = localeName;
515  Locale aFbLocale = MsLangId::getFallbackLocale( aLocale);
516  if (aFbLocale == aLocale)
517  bFallback = false; // may be a "language-only-locale" like Interlingua (ia)
518  else
519  aFallback = LocaleDataImpl::getFirstLocaleServiceName( aFbLocale);
520  }
521 
522  for (const auto & i : aLibTable)
523  {
524  if (localeName.equalsAscii(i.pLocale) ||
525  (bFallback && aFallback.equalsAscii(i.pLocale)))
526  {
527 #ifndef DISABLE_DYNLOADING
528  {
529  std::unique_lock aGuard( maMutex );
530  for (LocaleDataLookupTableItem & rCurrent : maLookupTable)
531  {
532  if (rCurrent.dllName == i.pLib)
533  {
534  rOutCachedItem.emplace( rCurrent );
535  rOutCachedItem->localeName = i.pLocale;
536  OString sSymbolName = OString::Concat(pFunction) + "_" +
537  rOutCachedItem->localeName;
538  return rOutCachedItem->module->getFunctionSymbol(
539  sSymbolName.getStr());
540  }
541  }
542  }
543  // Library not loaded, load it and add it to the list.
544 #ifdef SAL_DLLPREFIX
545  OString sModuleName = // mostly "lib*.so"
546  OString::Concat(SAL_DLLPREFIX) + i.pLib + SAL_DLLEXTENSION;
547 #else
548  OString sModuleName = // mostly "*.dll"
549  OString::Concat(i.pLib) + SAL_DLLEXTENSION;
550 #endif
551  std::unique_ptr<osl::Module> module(new osl::Module());
552  if ( module->loadRelative(&thisModule, sModuleName.getStr()) )
553  {
554  std::unique_lock aGuard( maMutex );
555  auto pTmpModule = module.get();
556  maLookupTable.emplace_back(i.pLib, module.release(), i.pLocale);
557  rOutCachedItem.emplace( maLookupTable.back() );
558  OString sSymbolName = OString::Concat(pFunction) + "_" + rOutCachedItem->localeName;
559  return pTmpModule->getFunctionSymbol(sSymbolName.getStr());
560  }
561  else
562  module.reset();
563 #else
564  (void) rOutCachedItem;
565 
566  if( strcmp(pFunction, "getAllCalendars") == 0 )
567  return i.getAllCalendars;
568  else if( strcmp(pFunction, "getAllCurrencies") == 0 )
569  return i.getAllCurrencies;
570  else if( strcmp(pFunction, "getAllFormats0") == 0 )
571  return i.getAllFormats0;
572  else if( strcmp(pFunction, "getBreakIteratorRules") == 0 )
573  return i.getBreakIteratorRules;
574  else if( strcmp(pFunction, "getCollationOptions") == 0 )
575  return i.getCollationOptions;
576  else if( strcmp(pFunction, "getCollatorImplementation") == 0 )
577  return i.getCollatorImplementation;
578  else if( strcmp(pFunction, "getContinuousNumberingLevels") == 0 )
579  return i.getContinuousNumberingLevels;
580  else if( strcmp(pFunction, "getDateAcceptancePatterns") == 0 )
581  return i.getDateAcceptancePatterns;
582  else if( strcmp(pFunction, "getFollowPageWords") == 0 )
583  return i.getFollowPageWords;
584  else if( strcmp(pFunction, "getForbiddenCharacters") == 0 )
585  return i.getForbiddenCharacters;
586  else if( strcmp(pFunction, "getIndexAlgorithm") == 0 )
587  return i.getIndexAlgorithm;
588  else if( strcmp(pFunction, "getLCInfo") == 0 )
589  return i.getLCInfo;
590  else if( strcmp(pFunction, "getLocaleItem") == 0 )
591  return i.getLocaleItem;
592  else if( strcmp(pFunction, "getOutlineNumberingLevels") == 0 )
593  return i.getOutlineNumberingLevels;
594  else if( strcmp(pFunction, "getReservedWords") == 0 )
595  return i.getReservedWords;
596  else if( strcmp(pFunction, "getSearchOptions") == 0 )
597  return i.getSearchOptions;
598  else if( strcmp(pFunction, "getTransliterations") == 0 )
599  return i.getTransliterations;
600  else if( strcmp(pFunction, "getUnicodeScripts") == 0 )
601  return i.getUnicodeScripts;
602  else if( strcmp(pFunction, "getAllFormats1") == 0 )
603  return i.getAllFormats1;
604 #endif
605  }
606  }
607  return nullptr;
608 }
609 
610 } // anonymous namespace
611 
612 
613 // REF values equal offsets of counts within getAllCalendars() data structure!
614 #define REF_DAYS 0
615 #define REF_MONTHS 1
616 #define REF_GMONTHS 2
617 #define REF_PMONTHS 3
618 #define REF_ERAS 4
619 #define REF_OFFSET_COUNT 5
620 
621 Sequence< CalendarItem2 > &LocaleDataImpl::getCalendarItemByName(const OUString& name,
622  const Locale& rLocale, const Sequence< Calendar2 >& calendarsSeq, sal_Int16 item)
623 {
624  if (ref_name != name) {
625  OUString aLocStr, id;
626  sal_Int32 nLastUnder = name.lastIndexOf( cUnder);
627  SAL_WARN_IF( nLastUnder < 1, "i18npool",
628  "LocaleDataImpl::getCalendarItemByName - no '_' or first in name can't be right: " << name);
629  if (nLastUnder >= 0)
630  {
631  aLocStr = name.copy( 0, nLastUnder);
632  if (nLastUnder + 1 < name.getLength())
633  id = name.copy( nLastUnder + 1);
634  }
635  Locale loc( LanguageTag::convertToLocale( aLocStr.replace( cUnder, cHyphen)));
637  if (loc == rLocale) {
638  cals = calendarsSeq;
639  } else {
640  cals = getAllCalendars2(loc);
641  }
642  auto pCal = std::find_if(std::cbegin(cals), std::cend(cals),
643  [&id](const Calendar2& rCal) { return id == rCal.Name; });
644  if (pCal != std::cend(cals))
645  ref_cal = *pCal;
646  else {
647  // Referred locale not found, return name for en_US locale.
648  cals = getAllCalendars2( Locale("en", "US", OUString()) );
649  if (!cals.hasElements())
650  throw RuntimeException();
651  ref_cal = cals.getConstArray()[0];
652  }
653  ref_name = name;
654  }
655  switch (item)
656  {
657  case REF_DAYS:
658  return ref_cal.Days;
659  case REF_MONTHS:
660  return ref_cal.Months;
661  case REF_GMONTHS:
662  return ref_cal.GenitiveMonths;
663  case REF_PMONTHS:
664  return ref_cal.PartitiveMonths;
665  default:
666  OSL_FAIL( "LocaleDataImpl::getCalendarItemByName: unhandled REF_* case");
667  [[fallthrough]];
668  case REF_ERAS:
669  return ref_cal.Eras;
670  }
671 }
672 
673 Sequence< CalendarItem2 > LocaleDataImpl::getCalendarItems(
674  sal_Unicode const * const * const allCalendars, sal_Int16 & rnOffset,
675  const sal_Int16 nWhichItem, const sal_Int16 nCalendar,
676  const Locale & rLocale, const Sequence< Calendar2 > & calendarsSeq )
677 {
679  if ( allCalendars[rnOffset] == std::u16string_view(u"ref") )
680  {
681  aItems = getCalendarItemByName( OUString( allCalendars[rnOffset+1]), rLocale, calendarsSeq, nWhichItem);
682  rnOffset += 2;
683  }
684  else
685  {
686  const sal_Int32 nSize = allCalendars[nWhichItem][nCalendar];
687  aItems.realloc( nSize);
688  switch (nWhichItem)
689  {
690  case REF_DAYS:
691  case REF_MONTHS:
692  case REF_GMONTHS:
693  case REF_PMONTHS:
694  for (CalendarItem2& rItem : asNonConstRange(aItems))
695  {
696  rItem = CalendarItem2{ OUString(allCalendars[rnOffset]),
697  OUString(allCalendars[rnOffset+1]),
698  OUString(allCalendars[rnOffset+2]), OUString(allCalendars[rnOffset+3])};
699  rnOffset += 4;
700  }
701  break;
702  case REF_ERAS:
703  // Absent narrow name.
704  for (CalendarItem2& rItem : asNonConstRange(aItems))
705  {
706  rItem = CalendarItem2{ OUString(allCalendars[rnOffset]),
707  OUString(allCalendars[rnOffset+1]),
708  OUString(allCalendars[rnOffset+2]), OUString()};
709  rnOffset += 3;
710  }
711  break;
712  default:
713  OSL_FAIL( "LocaleDataImpl::getCalendarItems: unhandled REF_* case");
714  }
715  }
716  return aItems;
717 }
718 
719 Sequence< Calendar2 > SAL_CALL
720 LocaleDataImpl::getAllCalendars2( const Locale& rLocale )
721 {
722 
723  sal_Unicode const * const * allCalendars = nullptr;
724 
725  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getAllCalendars" ));
726 
727  if ( func ) {
728  sal_Int16 calendarsCount = 0;
729  allCalendars = func(calendarsCount);
730 
731  Sequence< Calendar2 > calendarsSeq(calendarsCount);
732  auto calendarsSeqRange = asNonConstRange(calendarsSeq);
733  sal_Int16 offset = REF_OFFSET_COUNT;
734  for(sal_Int16 i = 0; i < calendarsCount; i++) {
735  OUString calendarID(allCalendars[offset]);
736  offset++;
737  bool defaultCalendar = allCalendars[offset][0] != 0;
738  offset++;
739  Sequence< CalendarItem2 > days = getCalendarItems( allCalendars, offset, REF_DAYS, i,
740  rLocale, calendarsSeq);
741  Sequence< CalendarItem2 > months = getCalendarItems( allCalendars, offset, REF_MONTHS, i,
742  rLocale, calendarsSeq);
743  Sequence< CalendarItem2 > gmonths = getCalendarItems( allCalendars, offset, REF_GMONTHS, i,
744  rLocale, calendarsSeq);
745  Sequence< CalendarItem2 > pmonths = getCalendarItems( allCalendars, offset, REF_PMONTHS, i,
746  rLocale, calendarsSeq);
747  Sequence< CalendarItem2 > eras = getCalendarItems( allCalendars, offset, REF_ERAS, i,
748  rLocale, calendarsSeq);
749  OUString startOfWeekDay(allCalendars[offset]);
750  offset++;
751  sal_Int16 minimalDaysInFirstWeek = allCalendars[offset][0];
752  offset++;
753  Calendar2 aCalendar(days, months, gmonths, pmonths, eras, startOfWeekDay,
754  minimalDaysInFirstWeek, defaultCalendar, calendarID);
755  calendarsSeqRange[i] = aCalendar;
756  }
757  return calendarsSeq;
758  }
759  else {
760  return {};
761  }
762 }
763 
764 
765 Sequence< Calendar > SAL_CALL
766 LocaleDataImpl::getAllCalendars( const Locale& rLocale )
767 {
768  const Sequence< Calendar2 > aCal2( getAllCalendars2( rLocale));
769  std::vector<Calendar> aCal1;
770  aCal1.reserve(aCal2.getLength());
771  std::transform(aCal2.begin(), aCal2.end(), std::back_inserter(aCal1),
772  [](const Calendar2& rCal2) { return downcastCalendar(rCal2); });
773  return comphelper::containerToSequence(aCal1);
774 }
775 
776 
777 Sequence< Currency2 > SAL_CALL
778 LocaleDataImpl::getAllCurrencies2( const Locale& rLocale )
779 {
780  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getAllCurrencies" ));
781 
782  if ( func ) {
783  sal_Int16 currencyCount = 0;
784  sal_Unicode **allCurrencies = func(currencyCount);
785 
786  Sequence< Currency2 > seq(currencyCount);
787  auto seqRange = asNonConstRange(seq);
788  for(int i = 0, nOff = 0; i < currencyCount; i++, nOff += 8 ) {
789  Currency2 cur(
790  OUString(allCurrencies[nOff]), // string ID
791  OUString(allCurrencies[nOff+1]), // string Symbol
792  OUString(allCurrencies[nOff+2]), // string BankSymbol
793  OUString(allCurrencies[nOff+3]), // string Name
794  allCurrencies[nOff+4][0] != 0, // boolean Default
795  allCurrencies[nOff+5][0] != 0, // boolean UsedInCompatibleFormatCodes
796  allCurrencies[nOff+6][0], // short DecimalPlaces
797  allCurrencies[nOff+7][0] != 0 // boolean LegacyOnly
798  );
799  seqRange[i] = cur;
800  }
801  return seq;
802  }
803  else {
804  return {};
805  }
806 }
807 
808 
809 Sequence< Currency > SAL_CALL
810 LocaleDataImpl::getAllCurrencies( const Locale& rLocale )
811 {
812  return comphelper::containerToSequence<Currency>(getAllCurrencies2(rLocale));
813 }
814 
815 
817 LocaleDataImpl::getAllFormats( const Locale& rLocale )
818 {
819  const int SECTIONS = 2;
820  struct FormatSection
821  {
822  MyFunc_FormatCode func;
823  sal_Unicode const *from;
824  sal_Unicode const *to;
825  sal_Unicode const *const *formatArray;
826  sal_Int16 formatCount;
827 
828  FormatSection() : func(nullptr), from(nullptr), to(nullptr), formatArray(nullptr), formatCount(0) {}
829  sal_Int16 getFunc( LocaleDataImpl& rLocaleData, const Locale& rL, const char* pName )
830  {
831  func = reinterpret_cast<MyFunc_FormatCode>( rLocaleData.getFunctionSymbol( rL, pName));
832  if (func)
833  formatArray = func( formatCount, from, to);
834  return formatCount;
835  }
836  } section[SECTIONS];
837 
838  sal_Int32 formatCount;
839  formatCount = section[0].getFunc( *this, rLocale, "getAllFormats0");
840  formatCount += section[1].getFunc( *this, rLocale, "getAllFormats1");
841 
842  Sequence< FormatElement > seq(formatCount);
843  auto seqRange = asNonConstRange(seq);
844  sal_Int32 f = 0;
845  for (const FormatSection & s : section)
846  {
847  sal_Unicode const * const * const formatArray = s.formatArray;
848  if ( formatArray )
849  {
850  for (int i = 0, nOff = 0; i < s.formatCount; ++i, nOff += 7, ++f)
851  {
852  FormatElement elem(
853  OUString(formatArray[nOff]).replaceAll(s.from, s.to),
854  OUString(formatArray[nOff + 1]),
855  OUString(formatArray[nOff + 2]),
856  OUString(formatArray[nOff + 3]),
857  OUString(formatArray[nOff + 4]),
858  formatArray[nOff + 5][0],
859  formatArray[nOff + 6][0] != 0);
860  seqRange[f] = elem;
861  }
862  }
863  }
864  return seq;
865 }
866 
867 
868 Sequence< OUString > SAL_CALL
869 LocaleDataImpl::getDateAcceptancePatterns( const Locale& rLocale )
870 {
871  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getDateAcceptancePatterns" ));
872 
873  if (func)
874  {
875  sal_Int16 patternsCount = 0;
876  sal_Unicode **patternsArray = func( patternsCount );
877  Sequence< OUString > seq( patternsCount );
878  auto seqRange = asNonConstRange(seq);
879  for (sal_Int16 i = 0; i < patternsCount; ++i)
880  {
881  seqRange[i] = OUString( patternsArray[i] );
882  }
883  return seq;
884  }
885  else
886  {
887  return {};
888  }
889 }
890 
891 
892 #define COLLATOR_OFFSET_ALGO 0
893 #define COLLATOR_OFFSET_DEFAULT 1
894 #define COLLATOR_OFFSET_RULE 2
895 #define COLLATOR_ELEMENTS 3
896 
897 OUString
898 LocaleDataImpl::getCollatorRuleByAlgorithm( const Locale& rLocale, std::u16string_view algorithm )
899 {
900  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getCollatorImplementation" ));
901  if ( func ) {
902  sal_Int16 collatorCount = 0;
903  sal_Unicode **collatorArray = func(collatorCount);
904  for(sal_Int16 i = 0; i < collatorCount; i++)
905  if (algorithm == collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO])
906  return OUString(collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_RULE]);
907  }
908  return OUString();
909 }
910 
911 
913 LocaleDataImpl::getCollatorImplementations( const Locale& rLocale )
914 {
915  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getCollatorImplementation" ));
916 
917  if ( func ) {
918  sal_Int16 collatorCount = 0;
919  sal_Unicode **collatorArray = func(collatorCount);
920  Sequence< Implementation > seq(collatorCount);
921  auto seqRange = asNonConstRange(seq);
922  for(sal_Int16 i = 0; i < collatorCount; i++) {
923  Implementation impl(
924  OUString(collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO]),
925  collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_DEFAULT][0] != 0);
926  seqRange[i] = impl;
927  }
928  return seq;
929  }
930  else {
931  return {};
932  }
933 }
934 
935 Sequence< OUString > SAL_CALL
936 LocaleDataImpl::getCollationOptions( const Locale& rLocale )
937 {
938  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getCollationOptions" ));
939 
940  if ( func ) {
941  sal_Int16 optionsCount = 0;
942  sal_Unicode **optionsArray = func(optionsCount);
943  Sequence< OUString > seq(optionsCount);
944  auto seqRange = asNonConstRange(seq);
945  for(sal_Int16 i = 0; i < optionsCount; i++) {
946  seqRange[i] = OUString( optionsArray[i] );
947  }
948  return seq;
949  }
950  else {
951  return {};
952  }
953 }
954 
955 Sequence< OUString > SAL_CALL
956 LocaleDataImpl::getSearchOptions( const Locale& rLocale )
957 {
958  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getSearchOptions" ));
959 
960  if ( func ) {
961  sal_Int16 optionsCount = 0;
962  sal_Unicode **optionsArray = func(optionsCount);
963  Sequence< OUString > seq(optionsCount);
964  auto seqRange = asNonConstRange(seq);
965  for(sal_Int16 i = 0; i < optionsCount; i++) {
966  seqRange[i] = OUString( optionsArray[i] );
967  }
968  return seq;
969  }
970  else {
971  return {};
972  }
973 }
974 
975 sal_Unicode **
976 LocaleDataImpl::getIndexArray(const Locale& rLocale, sal_Int16& indexCount)
977 {
978  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getIndexAlgorithm" ));
979 
980  if (func)
981  return func(indexCount);
982  return nullptr;
983 }
984 
986 LocaleDataImpl::getIndexAlgorithm( const Locale& rLocale )
987 {
988  sal_Int16 indexCount = 0;
989  sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
990 
991  if ( indexArray ) {
992  Sequence< OUString > seq(indexCount);
993  auto seqRange = asNonConstRange(seq);
994  for(sal_Int16 i = 0; i < indexCount; i++) {
995  seqRange[i] = indexArray[i*5];
996  }
997  return seq;
998  }
999  else {
1000  return {};
1001  }
1002 }
1003 
1004 OUString
1005 LocaleDataImpl::getDefaultIndexAlgorithm( const Locale& rLocale )
1006 {
1007  sal_Int16 indexCount = 0;
1008  sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
1009 
1010  if ( indexArray ) {
1011  for(sal_Int16 i = 0; i < indexCount; i++) {
1012  if (indexArray[i*5 + 3][0])
1013  return OUString(indexArray[i*5]);
1014  }
1015  }
1016  return OUString();
1017 }
1018 
1019 bool
1020 LocaleDataImpl::hasPhonetic( const Locale& rLocale )
1021 {
1022  sal_Int16 indexCount = 0;
1023  sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
1024 
1025  if ( indexArray ) {
1026  for(sal_Int16 i = 0; i < indexCount; i++) {
1027  if (indexArray[i*5 + 4][0])
1028  return true;
1029  }
1030  }
1031  return false;
1032 }
1033 
1034 sal_Unicode **
1035 LocaleDataImpl::getIndexArrayForAlgorithm(const Locale& rLocale, std::u16string_view algorithm)
1036 {
1037  sal_Int16 indexCount = 0;
1038  sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
1039  if ( indexArray ) {
1040  for(sal_Int16 i = 0; i < indexCount; i++) {
1041  if (algorithm == indexArray[i*5])
1042  return indexArray+i*5;
1043  }
1044  }
1045  return nullptr;
1046 }
1047 
1048 bool
1049 LocaleDataImpl::isPhonetic( const Locale& rLocale, std::u16string_view algorithm )
1050 {
1051  sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1052  return indexArray && indexArray[4][0];
1053 }
1054 
1055 OUString
1056 LocaleDataImpl::getIndexKeysByAlgorithm( const Locale& rLocale, std::u16string_view algorithm )
1057 {
1058  sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1059  return indexArray ? (OUString::Concat(u"0-9") + indexArray[2]) : OUString();
1060 }
1061 
1062 OUString
1063 LocaleDataImpl::getIndexModuleByAlgorithm( const Locale& rLocale, std::u16string_view algorithm )
1064 {
1065  sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1066  return indexArray ? OUString(indexArray[1]) : OUString();
1067 }
1068 
1070 LocaleDataImpl::getUnicodeScripts( const Locale& rLocale )
1071 {
1072  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getUnicodeScripts" ));
1073 
1074  if ( func ) {
1075  sal_Int16 scriptCount = 0;
1076  sal_Unicode **scriptArray = func(scriptCount);
1077  Sequence< UnicodeScript > seq(scriptCount);
1078  auto seqRange = asNonConstRange(seq);
1079  for(sal_Int16 i = 0; i < scriptCount; i++) {
1080  seqRange[i] = UnicodeScript( OUString(scriptArray[i]).toInt32() );
1081  }
1082  return seq;
1083  }
1084  else {
1085  return {};
1086  }
1087 }
1088 
1090 LocaleDataImpl::getFollowPageWords( const Locale& rLocale )
1091 {
1092  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getFollowPageWords" ));
1093 
1094  if ( func ) {
1095  sal_Int16 wordCount = 0;
1096  sal_Unicode **wordArray = func(wordCount);
1097  Sequence< OUString > seq(wordCount);
1098  auto seqRange = asNonConstRange(seq);
1099  for(sal_Int16 i = 0; i < wordCount; i++) {
1100  seqRange[i] = OUString(wordArray[i]);
1101  }
1102  return seq;
1103  }
1104  else {
1105  return {};
1106  }
1107 }
1108 
1109 Sequence< OUString > SAL_CALL
1110 LocaleDataImpl::getTransliterations( const Locale& rLocale )
1111 {
1112  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getTransliterations" ));
1113 
1114  if ( func ) {
1115  sal_Int16 transliterationsCount = 0;
1116  sal_Unicode **transliterationsArray = func(transliterationsCount);
1117 
1118  Sequence< OUString > seq(transliterationsCount);
1119  auto seqRange = asNonConstRange(seq);
1120  for(int i = 0; i < transliterationsCount; i++) {
1121  OUString elem(transliterationsArray[i]);
1122  seqRange[i] = elem;
1123  }
1124  return seq;
1125  }
1126  else {
1127  return {};
1128  }
1129 
1130 
1131 }
1132 
1133 
1134 LanguageCountryInfo SAL_CALL
1135 LocaleDataImpl::getLanguageCountryInfo( const Locale& rLocale )
1136 {
1137  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getLCInfo" ));
1138 
1139  if ( func ) {
1140  sal_Int16 LCInfoCount = 0;
1141  sal_Unicode **LCInfoArray = func(LCInfoCount);
1142  LanguageCountryInfo info{OUString(LCInfoArray[0]),
1143  OUString(LCInfoArray[1]),
1144  OUString(LCInfoArray[2]),
1145  OUString(LCInfoArray[3]),
1146  OUString(LCInfoArray[4])};
1147  return info;
1148  }
1149  else {
1150  LanguageCountryInfo info1;
1151  return info1;
1152  }
1153 
1154 }
1155 
1156 
1157 ForbiddenCharacters SAL_CALL
1158 LocaleDataImpl::getForbiddenCharacters( const Locale& rLocale )
1159 {
1160  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" ));
1161 
1162  if ( func ) {
1163  sal_Int16 LCForbiddenCharactersCount = 0;
1164  sal_Unicode **LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1165  ForbiddenCharacters chars{
1166  OUString(LCForbiddenCharactersArray[0]), OUString(LCForbiddenCharactersArray[1])};
1167  return chars;
1168  }
1169  else {
1170  ForbiddenCharacters chars1;
1171  return chars1;
1172  }
1173 }
1174 
1175 OUString
1176 LocaleDataImpl::getHangingCharacters( const Locale& rLocale )
1177 {
1178  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" ));
1179 
1180  if ( func ) {
1181  sal_Int16 LCForbiddenCharactersCount = 0;
1182  sal_Unicode **LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1183  return OUString(LCForbiddenCharactersArray[2]);
1184  }
1185 
1186  return OUString();
1187 }
1188 
1190 LocaleDataImpl::getBreakIteratorRules( const Locale& rLocale )
1191 {
1192  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getBreakIteratorRules" ));
1193 
1194  if ( func ) {
1195  sal_Int16 LCBreakIteratorRuleCount = 0;
1196  sal_Unicode **LCBreakIteratorRulesArray = func(LCBreakIteratorRuleCount);
1197  Sequence< OUString > seq(LCBreakIteratorRuleCount);
1198  auto seqRange = asNonConstRange(seq);
1199  for(int i = 0; i < LCBreakIteratorRuleCount; i++) {
1200  OUString elem(LCBreakIteratorRulesArray[i]);
1201  seqRange[i] = elem;
1202  }
1203  return seq;
1204  }
1205  else {
1206  return {};
1207  }
1208 }
1209 
1210 
1211 Sequence< OUString > SAL_CALL
1212 LocaleDataImpl::getReservedWord( const Locale& rLocale )
1213 {
1214  MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getReservedWords" ));
1215 
1216  if ( func ) {
1217  sal_Int16 LCReservedWordsCount = 0;
1218  sal_Unicode **LCReservedWordsArray = func(LCReservedWordsCount);
1219  Sequence< OUString > seq(LCReservedWordsCount);
1220  auto seqRange = asNonConstRange(seq);
1221  for(int i = 0; i < LCReservedWordsCount; i++) {
1222  OUString elem(LCReservedWordsArray[i]);
1223  seqRange[i] = elem;
1224  }
1225  return seq;
1226  }
1227  else {
1228  return {};
1229  }
1230 }
1231 
1232 
1234 LocaleDataImpl::getContinuousNumberingLevels( const lang::Locale& rLocale )
1235 {
1236  // load symbol
1237  MyFunc_Type2 func = reinterpret_cast<MyFunc_Type2>(getFunctionSymbol( rLocale, "getContinuousNumberingLevels" ));
1238 
1239  if ( func )
1240  {
1241  // invoke function
1242  sal_Int16 nStyles;
1243  sal_Int16 nAttributes;
1244  sal_Unicode const *** p0 = func( nStyles, nAttributes );
1245 
1246  // allocate memory for nAttributes attributes for each of the nStyles styles.
1248  auto pvRange = asNonConstRange(pv);
1249  for( auto& i : pvRange ) {
1250  i = Sequence<beans::PropertyValue>( nAttributes );
1251  }
1252 
1253  sal_Unicode const *** pStyle = p0;
1254  for( int i=0; i<nStyles; i++ ) {
1255  sal_Unicode const ** pAttribute = pStyle[i];
1256  auto pvElementRange = asNonConstRange(pvRange[i]);
1257  for( int j=0; j<nAttributes; j++ ) { // prefix, numberingtype, ...
1258  sal_Unicode const * pString = pAttribute[j];
1259  beans::PropertyValue& rVal = pvElementRange[j];
1260  OUString sVal;
1261  if( pString ) {
1262  if( 0 != j && 2 != j )
1263  sVal = pString;
1264  else if( *pString )
1265  sVal = OUString( pString, 1 );
1266  }
1267 
1268  switch( j )
1269  {
1270  case 0:
1271  rVal.Name = "Prefix";
1272  rVal.Value <<= sVal;
1273  break;
1274  case 1:
1275  rVal.Name = "NumberingType";
1276  rVal.Value <<= static_cast<sal_Int16>(sVal.toInt32());
1277  break;
1278  case 2:
1279  rVal.Name = "Suffix";
1280  rVal.Value <<= sVal;
1281  break;
1282  case 3:
1283  rVal.Name = "Transliteration";
1284  rVal.Value <<= sVal;
1285  break;
1286  case 4:
1287  rVal.Name = "NatNum";
1288  rVal.Value <<= static_cast<sal_Int16>(sVal.toInt32());
1289  break;
1290  default:
1291  OSL_ASSERT(false);
1292  }
1293  }
1294  }
1295  return pv;
1296  }
1297 
1299 }
1300 
1301 // OutlineNumbering helper class
1302 
1303 namespace {
1304 
1305 struct OutlineNumberingLevel_Impl
1306 {
1307  OUString sPrefix;
1308  sal_Int16 nNumType; //css::style::NumberingType
1309  OUString sSuffix;
1312  sal_Int16 nParentNumbering;
1313  sal_Int32 nLeftMargin;
1315  sal_Int32 nFirstLineOffset;
1317  sal_Int32 nNatNum;
1318 };
1319 
1320 class OutlineNumbering : public cppu::WeakImplHelper < container::XIndexAccess >
1321 {
1322  // OutlineNumbering helper class
1323 
1324  std::unique_ptr<const OutlineNumberingLevel_Impl[]> m_pOutlineLevels;
1325  sal_Int16 m_nCount;
1326 public:
1327  OutlineNumbering(std::unique_ptr<const OutlineNumberingLevel_Impl[]> pOutlineLevels, int nLevels);
1328 
1329  //XIndexAccess
1330  virtual sal_Int32 SAL_CALL getCount( ) override;
1331  virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override;
1332 
1333  //XElementAccess
1334  virtual Type SAL_CALL getElementType( ) override;
1335  virtual sal_Bool SAL_CALL hasElements( ) override;
1336 };
1337 
1338 }
1339 
1341 LocaleDataImpl::getOutlineNumberingLevels( const lang::Locale& rLocale )
1342 {
1343  // load symbol
1344  MyFunc_Type3 func = reinterpret_cast<MyFunc_Type3>(getFunctionSymbol( rLocale, "getOutlineNumberingLevels" ));
1345 
1346  if ( func )
1347  {
1348  int i;
1349  // invoke function
1350  sal_Int16 nStyles;
1351  sal_Int16 nLevels;
1352  sal_Int16 nAttributes;
1353  sal_Unicode const **** p0 = func( nStyles, nLevels, nAttributes );
1354 
1356  auto aRetRange = asNonConstRange(aRet);
1357  sal_Unicode const **** pStyle = p0;
1358  for( i=0; i<nStyles; i++ )
1359  {
1360  int j;
1361 
1362  std::unique_ptr<OutlineNumberingLevel_Impl[]> level(new OutlineNumberingLevel_Impl[ nLevels+1 ]);
1363  sal_Unicode const *** pLevel = pStyle[i];
1364  for( j = 0; j < nLevels; j++ )
1365  {
1366  sal_Unicode const ** pAttribute = pLevel[j];
1367  for( int k=0; k<nAttributes; k++ )
1368  {
1369  OUString tmp( pAttribute[k] );
1370  switch( k )
1371  {
1372  case 0: level[j].sPrefix = tmp; break;
1373  case 1: level[j].nNumType = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1374  case 2: level[j].sSuffix = tmp; break;
1375  case 3: level[j].cBulletChar = sal::static_int_cast<sal_Unicode>(tmp.toUInt32(16)); break; // base 16
1376  case 4: level[j].sBulletFontName = tmp; break;
1377  case 5: level[j].nParentNumbering = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1378  case 6: level[j].nLeftMargin = tmp.toInt32(); break;
1379  case 7: level[j].nSymbolTextDistance = tmp.toInt32(); break;
1380  case 8: level[j].nFirstLineOffset = tmp.toInt32(); break;
1381  case 9: break;
1382  case 10: level[j].sTransliteration = tmp; break;
1383  case 11: level[j].nNatNum = tmp.toInt32(); break;
1384  default:
1385  OSL_ASSERT(false);
1386  }
1387  }
1388  }
1389  level[j].sPrefix.clear();
1390  level[j].nNumType = 0;
1391  level[j].sSuffix.clear();
1392  level[j].cBulletChar = 0;
1393  level[j].sBulletFontName.clear();
1394  level[j].nParentNumbering = 0;
1395  level[j].nLeftMargin = 0;
1396  level[j].nSymbolTextDistance = 0;
1397  level[j].nFirstLineOffset = 0;
1398  level[j].sTransliteration.clear();
1399  level[j].nNatNum = 0;
1400  aRetRange[i] = new OutlineNumbering( std::move(level), nLevels );
1401  }
1402  return aRet;
1403  }
1404  else {
1405  return {};
1406  }
1407 }
1408 
1409 // helper functions
1410 
1411 oslGenericFunction LocaleDataImpl::getFunctionSymbol( const Locale& rLocale, const char* pFunction )
1412 {
1413  lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic();
1414 
1415  if (moCachedItem && moCachedItem->equals(rLocale))
1416  {
1417  OString sSymbolName = OString::Concat(pFunction) + "_" +
1418  moCachedItem->localeName;
1419  return moCachedItem->module->getFunctionSymbol(sSymbolName.getStr());
1420  }
1421 
1422  oslGenericFunction pSymbol = nullptr;
1423  std::optional<LocaleDataLookupTableItem> oCachedItem;
1424 
1425  // Load function with name <func>_<lang>_<country> or <func>_<bcp47> and
1426  // fallbacks.
1427  pSymbol = rLookupTable.getFunctionSymbolByName( LocaleDataImpl::getFirstLocaleServiceName( rLocale),
1428  pFunction, oCachedItem);
1429  if (!pSymbol)
1430  {
1431  ::std::vector< OUString > aFallbacks( LocaleDataImpl::getFallbackLocaleServiceNames( rLocale));
1432  for (const auto& rFallback : aFallbacks)
1433  {
1434  pSymbol = rLookupTable.getFunctionSymbolByName(rFallback, pFunction, oCachedItem);
1435  if (pSymbol)
1436  break;
1437  }
1438  }
1439  if (!pSymbol)
1440  {
1441  // load default function with name <func>_en_US
1442  pSymbol = rLookupTable.getFunctionSymbolByName("en_US", pFunction, oCachedItem);
1443  }
1444 
1445  if (!pSymbol)
1446  // Appropriate symbol could not be found. Give up.
1447  throw RuntimeException();
1448 
1449  if (oCachedItem)
1450  moCachedItem = std::move(oCachedItem);
1451  if (moCachedItem)
1452  moCachedItem->aLocale = rLocale;
1453 
1454  return pSymbol;
1455 }
1456 
1457 Sequence< Locale > SAL_CALL
1458 LocaleDataImpl::getAllInstalledLocaleNames()
1459 {
1461  auto seqRange = asNonConstRange(seq);
1462  sal_Int16 nInstalled = 0;
1463 
1464  for(const auto & i : aLibTable) {
1465  OUString name = OUString::createFromAscii( i.pLocale );
1466 
1467  // Check if the locale is really available and not just in the table,
1468  // don't allow fall backs.
1469  std::optional<LocaleDataLookupTableItem> oCachedItem;
1470  if (lcl_LookupTableStatic().getFunctionSymbolByName( name, "getLocaleItem", oCachedItem )) {
1471  if( oCachedItem )
1472  moCachedItem = std::move( oCachedItem );
1473  seqRange[nInstalled++] = LanguageTag::convertToLocale( name.replace( cUnder, cHyphen), false);
1474  }
1475  }
1476  if ( nInstalled < nbOfLocales )
1477  seq.realloc( nInstalled ); // reflect reality
1478 
1479  return seq;
1480 }
1481 
1482 using namespace ::com::sun::star::container;
1483 using namespace ::com::sun::star::beans;
1484 using namespace ::com::sun::star::text;
1485 
1486 OutlineNumbering::OutlineNumbering(std::unique_ptr<const OutlineNumberingLevel_Impl[]> pOutlnLevels, int nLevels) :
1487  m_pOutlineLevels(std::move(pOutlnLevels)),
1488  m_nCount(sal::static_int_cast<sal_Int16>(nLevels))
1489 {
1490 }
1491 
1492 sal_Int32 OutlineNumbering::getCount( )
1493 {
1494  return m_nCount;
1495 }
1496 
1497 Any OutlineNumbering::getByIndex( sal_Int32 nIndex )
1498 {
1499  if(nIndex < 0 || nIndex >= m_nCount)
1500  throw IndexOutOfBoundsException();
1501  const OutlineNumberingLevel_Impl* pTemp = m_pOutlineLevels.get();
1502  pTemp += nIndex;
1503  Any aRet;
1504 
1505  Sequence<PropertyValue> aOutlineNumbering(12);
1506  PropertyValue* pValues = aOutlineNumbering.getArray();
1507  pValues[0].Name = "Prefix";
1508  pValues[0].Value <<= pTemp->sPrefix;
1509  pValues[1].Name = "NumberingType";
1510  pValues[1].Value <<= pTemp->nNumType;
1511  pValues[2].Name = "Suffix";
1512  pValues[2].Value <<= pTemp->sSuffix;
1513  pValues[3].Name = "BulletChar";
1514  pValues[3].Value <<= OUString(&pTemp->cBulletChar, 1);
1515  pValues[4].Name = "BulletFontName";
1516  pValues[4].Value <<= pTemp->sBulletFontName;
1517  pValues[5].Name = "ParentNumbering";
1518  pValues[5].Value <<= pTemp->nParentNumbering;
1519  pValues[6].Name = "LeftMargin";
1520  pValues[6].Value <<= pTemp->nLeftMargin;
1521  pValues[7].Name = "SymbolTextDistance";
1522  pValues[7].Value <<= pTemp->nSymbolTextDistance;
1523  pValues[8].Name = "FirstLineOffset";
1524  pValues[8].Value <<= pTemp->nFirstLineOffset;
1525  pValues[9].Name = "Adjust";
1526  pValues[9].Value <<= sal_Int16(HoriOrientation::LEFT);
1527  pValues[10].Name = "Transliteration";
1528  pValues[10].Value <<= pTemp->sTransliteration;
1529  pValues[11].Name = "NatNum";
1530  pValues[11].Value <<= pTemp->nNatNum;
1531  aRet <<= aOutlineNumbering;
1532  return aRet;
1533 }
1534 
1535 Type OutlineNumbering::getElementType( )
1536 {
1538 }
1539 
1540 sal_Bool OutlineNumbering::hasElements( )
1541 {
1542  return m_nCount > 0;
1543 }
1544 
1545 OUString SAL_CALL
1547 {
1548  return "com.sun.star.i18n.LocaleDataImpl";
1549 }
1550 
1551 sal_Bool SAL_CALL LocaleDataImpl::supportsService(const OUString& rServiceName)
1552 {
1553  return cppu::supportsService(this, rServiceName);
1554 }
1555 
1556 Sequence< OUString > SAL_CALL
1558 {
1559  Sequence< OUString > aRet {
1560  "com.sun.star.i18n.LocaleData",
1561  "com.sun.star.i18n.LocaleData2"
1562  };
1563  return aRet;
1564 }
1565 
1566 // static
1567 OUString LocaleDataImpl::getFirstLocaleServiceName( const css::lang::Locale & rLocale )
1568 {
1569  if (rLocale.Language == I18NLANGTAG_QLT)
1570  return rLocale.Variant.replace( cHyphen, cUnder);
1571  else if (!rLocale.Country.isEmpty())
1572  return rLocale.Language + "_" + rLocale.Country;
1573  else
1574  return rLocale.Language;
1575 }
1576 
1577 // static
1578 ::std::vector< OUString > LocaleDataImpl::getFallbackLocaleServiceNames( const css::lang::Locale & rLocale )
1579 {
1580  ::std::vector< OUString > aVec;
1581  if (rLocale.Language == I18NLANGTAG_QLT)
1582  {
1583  aVec = LanguageTag( rLocale).getFallbackStrings( false);
1584  for (auto& rItem : aVec)
1585  {
1586  rItem = rItem.replace(cHyphen, cUnder);
1587  }
1588  }
1589  else if (!rLocale.Country.isEmpty())
1590  {
1591  aVec.push_back( rLocale.Language);
1592  }
1593  // else nothing, language-only was the first
1594  return aVec;
1595 }
1596 
1597 }
1598 
1599 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1601  css::uno::XComponentContext *,
1602  css::uno::Sequence<css::uno::Any> const &)
1603 {
1604  return cppu::acquire(new i18npool::LocaleDataImpl());
1605 }
1606 
1607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Unicode **(* MyFunc_Type)(sal_Int16 &)
Definition: localedata.cxx:44
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Type
#define REF_DAYS
Definition: localedata.cxx:614
std::unique_ptr< const OutlineNumberingLevel_Impl[]> m_pOutlineLevels
#define SAL_DLLEXTENSION
const char * pLocale
Definition: localedata.cxx:57
virtual OUString SAL_CALL getImplementationName() override
const sal_Int16 nbOfLocales
Definition: localedata.cxx:345
#define REF_PMONTHS
Definition: localedata.cxx:617
sal_Int32 toInt32(OUString const &rStr)
OUString sTransliteration
constexpr OUStringLiteral I18NLANGTAG_QLT
sal_Unicode const ****(* MyFunc_Type3)(sal_Int16 &, sal_Int16 &, sal_Int16 &)
Definition: localedata.cxx:46
sal_Int32 nFirstLineOffset
sal_Int32 nLeftMargin
#define COLLATOR_OFFSET_ALGO
Definition: localedata.cxx:892
static css::lang::Locale getFallbackLocale(const css::lang::Locale &rLocale)
sal_uInt16 sal_Unicode
const sal_Unicode cUnder
Definition: localedata.cxx:342
OUString sSuffix
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
UBlockCode from
UBlockCode to
sal_Int16 nNumType
#define REF_GMONTHS
Definition: localedata.cxx:616
::std::vector< LocaleDataLookupTableItem > maLookupTable
Definition: localedata.cxx:480
#define REF_ERAS
Definition: localedata.cxx:618
#define SAL_N_ELEMENTS(arr)
sal_Unicode cBulletChar
static OUString getFirstLocaleServiceName(const css::lang::Locale &rLocale)
Generates a _ or (if Language=="qlt") string suitable as part of service...
#define COLLATOR_OFFSET_DEFAULT
Definition: localedata.cxx:893
sal_uInt16 char * pName
int i
sal_Int32 nSymbolTextDistance
static const char * lcl_DATA_ES
Definition: localedata.cxx:52
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_i18n_LocaleDataImpl_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
const sal_Unicode cHyphen
Definition: localedata.cxx:343
sal_Int16 nAttributes
float u
unsigned char sal_Bool
static const char * lcl_DATA_EURO
Definition: localedata.cxx:53
const struct @0 aLibTable[]
Constant values shared between i18npool and, for example, the number formatter.
OUString sBulletFontName
OUString sPrefix
::std::vector< OUString > getFallbackStrings(bool bIncludeFullBcp47) const
static::std::vector< OUString > getFallbackLocaleServiceNames(const css::lang::Locale &rLocale)
Generates fallback strings suitable as parts of service names, excluding the one obtained via getFirs...
#define COLLATOR_ELEMENTS
Definition: localedata.cxx:895
sal_Int16 m_nCount
const PropertyValue * pValues
sal_Unicode const ***(* MyFunc_Type2)(sal_Int16 &, sal_Int16 &)
Definition: localedata.cxx:45
static const char * lcl_DATA_EN
Definition: localedata.cxx:51
#define SAL_WARN_IF(condition, area, stream)
#define REF_MONTHS
Definition: localedata.cxx:615
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
#define COLLATOR_OFFSET_RULE
Definition: localedata.cxx:894
oslGenericFunction getFunctionSymbol(const css::lang::Locale &rLocale, const char *pFunction)
const char * name
sal_Unicode const *const *(* MyFunc_FormatCode)(sal_Int16 &, sal_Unicode const *&, sal_Unicode const *&)
Definition: localedata.cxx:47
void(* f)(TrueTypeTable *)
static const char * lcl_DATA_OTHERS
Definition: localedata.cxx:54
sal_Int32 nNatNum
#define REF_OFFSET_COUNT
Definition: localedata.cxx:619
sal_Int16 nParentNumbering
static void thisModule()
Definition: localedata.cxx:460
std::mutex maMutex
Definition: localedata.cxx:479
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
const char * pLib
Definition: localedata.cxx:58
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo