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 <comphelper/sequence.hxx>
25 #include <cppuhelper/supportsservice.hxx>
28 using namespace com::sun::star
;
29 using namespace com::sun::star::i18n
;
30 using namespace com::sun::star::lang
;
31 using namespace com::sun::star::uno
;
35 CollatorImpl::CollatorImpl( const Reference
< XComponentContext
>& rxContext
) : m_xContext(rxContext
)
37 mxLocaleData
.set( LocaleData2::create(rxContext
) );
41 CollatorImpl::~CollatorImpl()
46 CollatorImpl::compareSubstring( const OUString
& str1
, sal_Int32 off1
, sal_Int32 len1
,
47 const OUString
& str2
, sal_Int32 off2
, sal_Int32 len2
)
50 return cachedItem
->xC
->compareSubstring(str1
, off1
, len1
, str2
, off2
, len2
);
52 sal_Unicode
*unistr1
= const_cast<sal_Unicode
*>(str1
.getStr()) + off1
;
53 sal_Unicode
*unistr2
= const_cast<sal_Unicode
*>(str2
.getStr()) + off2
;
54 for (int i
= 0; i
< len1
&& i
< len2
; i
++)
55 if (unistr1
[i
] != unistr2
[i
])
56 return unistr1
[i
] < unistr2
[i
] ? -1 : 1;
57 return len1
== len2
? 0 : (len1
< len2
? -1 : 1);
61 CollatorImpl::compareString( const OUString
& in_str1
, const OUString
& in_str2
)
64 return cachedItem
->xC
->compareString(in_str1
, in_str2
);
66 return CollatorImpl::compareSubstring(in_str1
, 0, in_str1
.getLength(), in_str2
, 0, in_str2
.getLength());
71 CollatorImpl::loadDefaultCollator(const lang::Locale
& rLocale
, sal_Int32 collatorOptions
)
73 const Sequence
< Implementation
> &imp
= mxLocaleData
->getCollatorImplementations(rLocale
);
74 auto pImpl
= std::find_if(imp
.begin(), imp
.end(),
75 [](const Implementation
& rImp
) { return rImp
.isDefault
; });
76 if (pImpl
!= imp
.end())
77 return loadCollatorAlgorithm(pImpl
->unoID
, rLocale
, collatorOptions
);
79 throw RuntimeException(); // not default is defined
84 CollatorImpl::loadCollatorAlgorithm(const OUString
& impl
, const lang::Locale
& rLocale
, sal_Int32 collatorOptions
)
86 if (! cachedItem
|| ! cachedItem
->equals(rLocale
, impl
))
87 loadCachedCollator(rLocale
, impl
);
90 throw RuntimeException(); // impl could not be loaded
92 cachedItem
->xC
->loadCollatorAlgorithm(cachedItem
->algorithm
, nLocale
, collatorOptions
);
98 CollatorImpl::loadCollatorAlgorithmWithEndUserOption(const OUString
& impl
, const lang::Locale
& rLocale
,
99 const Sequence
< sal_Int32
>& collatorOptions
)
101 sal_Int32 options
= std::accumulate(collatorOptions
.begin(), collatorOptions
.end(),
102 sal_Int32(0), [](sal_Int32 nSum
, sal_Int32 nOpt
) { return nSum
| nOpt
; });
103 loadCollatorAlgorithm(impl
, rLocale
, options
);
106 Sequence
< OUString
> SAL_CALL
107 CollatorImpl::listCollatorAlgorithms( const lang::Locale
& rLocale
)
110 const Sequence
< Implementation
> &imp
= mxLocaleData
->getCollatorImplementations(rLocale
);
111 Sequence
< OUString
> list(imp
.getLength());
112 auto pBegin
= list
.begin();
115 for (const auto& rImpl
: imp
) {
117 //if the current algorithm is default and the position is not on the first one, then switch
118 if (rImpl
.isDefault
&& pId
!= pBegin
)
119 std::swap(*pBegin
, *pId
);
125 Sequence
< sal_Int32
> SAL_CALL
126 CollatorImpl::listCollatorOptions( const OUString
& /*collatorAlgorithmName*/ )
128 const Sequence
< OUString
> option_str
= mxLocaleData
->getCollationOptions(nLocale
);
129 Sequence
< sal_Int32
> option_int(option_str
.getLength());
131 std::transform(option_str
.begin(), option_str
.end(), option_int
.begin(), [](const OUString
& rOpt
) {
132 return rOpt
== "IGNORE_CASE" ? CollatorOptions::CollatorOptions_IGNORE_CASE
:
133 rOpt
== "IGNORE_KANA" ? CollatorOptions::CollatorOptions_IGNORE_KANA
:
134 rOpt
== "IGNORE_WIDTH" ? CollatorOptions::CollatorOptions_IGNORE_WIDTH
: 0; });
140 CollatorImpl::createCollator(const lang::Locale
& rLocale
, const OUString
& serviceName
, const OUString
& rSortAlgorithm
)
142 for (size_t l
= 0; l
< lookupTable
.size(); l
++) {
143 cachedItem
= lookupTable
[l
].get();
144 if (cachedItem
->service
== serviceName
) {// cross locale sharing
145 lookupTable
.emplace_back(new lookupTableItem(rLocale
, rSortAlgorithm
, serviceName
, cachedItem
->xC
));
146 cachedItem
= lookupTable
.back().get();
150 Reference
< XInterface
> xI
=
151 m_xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.i18n.Collator_" + serviceName
, m_xContext
);
154 Reference
< XCollator
> xC
;
155 xC
.set( xI
, UNO_QUERY
);
157 lookupTable
.emplace_back(new lookupTableItem(rLocale
, rSortAlgorithm
, serviceName
, xC
));
158 cachedItem
= lookupTable
.back().get();
166 CollatorImpl::loadCachedCollator(const lang::Locale
& rLocale
, const OUString
& rSortAlgorithm
)
168 for (const auto& i
: lookupTable
) {
169 cachedItem
= i
.get();
170 if (cachedItem
->equals(rLocale
, rSortAlgorithm
)) {
175 bool bLoaded
= false;
176 if (!rSortAlgorithm
.isEmpty())
178 // Load service with name <base>_<lang>_<country>_<algorithm> or
179 // <base>_<bcp47>_<algorithm> and fallbacks.
180 bLoaded
= createCollator( rLocale
,
181 LocaleDataImpl::getFirstLocaleServiceName( rLocale
) + "_" + rSortAlgorithm
, rSortAlgorithm
);
184 ::std::vector
< OUString
> aFallbacks( LocaleDataImpl::getFallbackLocaleServiceNames( rLocale
));
185 for (auto const& fallback
: aFallbacks
)
187 bLoaded
= createCollator( rLocale
, fallback
+ "_" + rSortAlgorithm
, rSortAlgorithm
);
193 // load service with name <base>_<algorithm>
194 bLoaded
= createCollator( rLocale
, rSortAlgorithm
, rSortAlgorithm
);
200 // load default service with name <base>_Unicode
201 bLoaded
= createCollator( rLocale
, "Unicode", rSortAlgorithm
);
204 cachedItem
= nullptr;
205 throw RuntimeException(); // could not load any service
210 OUString SAL_CALL
CollatorImpl::getImplementationName()
212 return "com.sun.star.i18n.Collator";
215 sal_Bool SAL_CALL
CollatorImpl::supportsService(const OUString
& rServiceName
)
217 return cppu::supportsService(this, rServiceName
);
220 Sequence
< OUString
> SAL_CALL
221 CollatorImpl::getSupportedServiceNames()
223 return { "com.sun.star.i18n.Collator" };
228 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
229 com_sun_star_i18n_Collator_get_implementation(
230 css::uno::XComponentContext
*context
,
231 css::uno::Sequence
<css::uno::Any
> const &)
233 return cppu::acquire(new i18npool::CollatorImpl(context
));
236 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */