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