1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <collatorImpl.hxx>
21 #include <localedata.hxx>
22 #include <com/sun/star/i18n/CollatorOptions.hpp>
23 #include <com/sun/star/i18n/LocaleData2.hpp>
24 #include <cppuhelper/supportsservice.hxx>
27 using namespace com::sun::star
;
28 using namespace com::sun::star::i18n
;
29 using namespace com::sun::star::lang
;
30 using namespace com::sun::star::uno
;
34 CollatorImpl::CollatorImpl( const Reference
< XComponentContext
>& rxContext
) : m_xContext(rxContext
)
36 mxLocaleData
.set( LocaleData2::create(rxContext
) );
40 CollatorImpl::~CollatorImpl()
45 CollatorImpl::compareSubstring( const OUString
& str1
, sal_Int32 off1
, sal_Int32 len1
,
46 const OUString
& str2
, sal_Int32 off2
, sal_Int32 len2
)
49 return cachedItem
->xC
->compareSubstring(str1
, off1
, len1
, str2
, off2
, len2
);
51 sal_Unicode
*unistr1
= const_cast<sal_Unicode
*>(str1
.getStr()) + off1
;
52 sal_Unicode
*unistr2
= const_cast<sal_Unicode
*>(str2
.getStr()) + off2
;
53 for (int i
= 0; i
< len1
&& i
< len2
; i
++)
54 if (unistr1
[i
] != unistr2
[i
])
55 return unistr1
[i
] < unistr2
[i
] ? -1 : 1;
56 return len1
== len2
? 0 : (len1
< len2
? -1 : 1);
60 CollatorImpl::compareString( const OUString
& in_str1
, const OUString
& in_str2
)
63 return cachedItem
->xC
->compareString(in_str1
, in_str2
);
65 return CollatorImpl::compareSubstring(in_str1
, 0, in_str1
.getLength(), in_str2
, 0, in_str2
.getLength());
70 CollatorImpl::loadDefaultCollator(const lang::Locale
& rLocale
, sal_Int32 collatorOptions
)
72 const Sequence
< Implementation
> &imp
= mxLocaleData
->getCollatorImplementations(rLocale
);
73 auto pImpl
= std::find_if(imp
.begin(), imp
.end(),
74 [](const Implementation
& rImp
) { return rImp
.isDefault
; });
75 if (pImpl
!= imp
.end())
76 return loadCollatorAlgorithm(pImpl
->unoID
, rLocale
, collatorOptions
);
78 throw RuntimeException(); // not default is defined
83 CollatorImpl::loadCollatorAlgorithm(const OUString
& impl
, const lang::Locale
& rLocale
, sal_Int32 collatorOptions
)
85 if (! cachedItem
|| ! cachedItem
->equals(rLocale
, impl
))
86 loadCachedCollator(rLocale
, impl
);
89 throw RuntimeException(); // impl could not be loaded
91 cachedItem
->xC
->loadCollatorAlgorithm(cachedItem
->algorithm
, nLocale
, collatorOptions
);
97 CollatorImpl::loadCollatorAlgorithmWithEndUserOption(const OUString
& impl
, const lang::Locale
& rLocale
,
98 const Sequence
< sal_Int32
>& collatorOptions
)
100 sal_Int32 options
= std::accumulate(collatorOptions
.begin(), collatorOptions
.end(),
101 sal_Int32(0), [](sal_Int32 nSum
, sal_Int32 nOpt
) { return nSum
| nOpt
; });
102 loadCollatorAlgorithm(impl
, rLocale
, options
);
105 Sequence
< OUString
> SAL_CALL
106 CollatorImpl::listCollatorAlgorithms( const lang::Locale
& rLocale
)
109 const Sequence
< Implementation
> &imp
= mxLocaleData
->getCollatorImplementations(rLocale
);
110 Sequence
< OUString
> list(imp
.getLength());
111 auto pBegin
= list
.begin();
114 for (const auto& rImpl
: imp
) {
116 //if the current algorithm is default and the position is not on the first one, then switch
117 if (rImpl
.isDefault
&& pId
!= pBegin
)
118 std::swap(*pBegin
, *pId
);
124 Sequence
< sal_Int32
> SAL_CALL
125 CollatorImpl::listCollatorOptions( const OUString
& /*collatorAlgorithmName*/ )
127 const Sequence
< OUString
> option_str
= mxLocaleData
->getCollationOptions(nLocale
);
128 Sequence
< sal_Int32
> option_int(option_str
.getLength());
130 std::transform(option_str
.begin(), option_str
.end(), option_int
.begin(), [](const OUString
& rOpt
) {
131 return rOpt
== "IGNORE_CASE" ? CollatorOptions::CollatorOptions_IGNORE_CASE
:
132 rOpt
== "IGNORE_KANA" ? CollatorOptions::CollatorOptions_IGNORE_KANA
:
133 rOpt
== "IGNORE_WIDTH" ? CollatorOptions::CollatorOptions_IGNORE_WIDTH
: 0; });
139 CollatorImpl::createCollator(const lang::Locale
& rLocale
, const OUString
& serviceName
, const OUString
& rSortAlgorithm
)
141 for (size_t l
= 0; l
< lookupTable
.size(); l
++) {
142 cachedItem
= lookupTable
[l
].get();
143 if (cachedItem
->service
== serviceName
) {// cross locale sharing
144 lookupTable
.emplace_back(new lookupTableItem(rLocale
, rSortAlgorithm
, serviceName
, cachedItem
->xC
));
145 cachedItem
= lookupTable
.back().get();
149 Reference
< XInterface
> xI
=
150 m_xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.i18n.Collator_" + serviceName
, m_xContext
);
153 Reference
< XCollator
> xC
;
154 xC
.set( xI
, UNO_QUERY
);
156 lookupTable
.emplace_back(new lookupTableItem(rLocale
, rSortAlgorithm
, serviceName
, xC
));
157 cachedItem
= lookupTable
.back().get();
165 CollatorImpl::loadCachedCollator(const lang::Locale
& rLocale
, const OUString
& rSortAlgorithm
)
167 for (const auto& i
: lookupTable
) {
168 cachedItem
= i
.get();
169 if (cachedItem
->equals(rLocale
, rSortAlgorithm
)) {
174 bool bLoaded
= false;
175 if (!rSortAlgorithm
.isEmpty())
177 // Load service with name <base>_<lang>_<country>_<algorithm> or
178 // <base>_<bcp47>_<algorithm> and fallbacks.
179 bLoaded
= createCollator( rLocale
,
180 LocaleDataImpl::getFirstLocaleServiceName( rLocale
) + "_" + rSortAlgorithm
, rSortAlgorithm
);
183 ::std::vector
< OUString
> aFallbacks( LocaleDataImpl::getFallbackLocaleServiceNames( rLocale
));
184 for (auto const& fallback
: aFallbacks
)
186 bLoaded
= createCollator( rLocale
, fallback
+ "_" + rSortAlgorithm
, rSortAlgorithm
);
192 // load service with name <base>_<algorithm>
193 bLoaded
= createCollator( rLocale
, rSortAlgorithm
, rSortAlgorithm
);
199 // load default service with name <base>_Unicode
200 bLoaded
= createCollator( rLocale
, "Unicode", rSortAlgorithm
);
203 cachedItem
= nullptr;
204 throw RuntimeException(); // could not load any service
209 OUString SAL_CALL
CollatorImpl::getImplementationName()
211 return "com.sun.star.i18n.Collator";
214 sal_Bool SAL_CALL
CollatorImpl::supportsService(const OUString
& rServiceName
)
216 return cppu::supportsService(this, rServiceName
);
219 Sequence
< OUString
> SAL_CALL
220 CollatorImpl::getSupportedServiceNames()
222 return { "com.sun.star.i18n.Collator" };
227 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
228 com_sun_star_i18n_Collator_get_implementation(
229 css::uno::XComponentContext
*context
,
230 css::uno::Sequence
<css::uno::Any
> const &)
232 return cppu::acquire(new i18npool::CollatorImpl(context
));
235 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */