diff options
author | Caolán McNamara <caolanm@redhat.com> | 2011-02-14 15:37:58 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2011-02-14 20:52:53 +0000 |
commit | 8a55872a3ca73014ae63c3c4e00de7df50a5452e (patch) | |
tree | b2188fbd1efaff487b5c6b0f046620eabae4b03f /comphelper | |
parent | 6fd38fbdae654a3319b6bf808a415638dcdbbffe (diff) |
Adjust this to use a Collator to do the string compare
And a break-iterator to break it up into string/digit sections. A bit over
engineered I guess.
Diffstat (limited to 'comphelper')
-rw-r--r-- | comphelper/inc/comphelper/string.hxx | 41 | ||||
-rw-r--r-- | comphelper/qa/test_string.cxx | 160 | ||||
-rw-r--r-- | comphelper/source/misc/string.cxx | 124 |
3 files changed, 246 insertions, 79 deletions
diff --git a/comphelper/inc/comphelper/string.hxx b/comphelper/inc/comphelper/string.hxx index 9ef4ec657bbb..5cca225df8c6 100644 --- a/comphelper/inc/comphelper/string.hxx +++ b/comphelper/inc/comphelper/string.hxx @@ -36,6 +36,9 @@ #include "sal/types.h" #include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/i18n/XCollator.hpp> +#include <com/sun/star/i18n/XBreakIterator.hpp> namespace rtl { class OUString; } @@ -147,27 +150,27 @@ COMPHELPER_DLLPUBLIC ::com::sun::star::uno::Sequence< ::rtl::OUString > < 0 - if this string is less than the string argument > 0 - if this string is greater than the string argument */ -COMPHELPER_DLLPUBLIC sal_Int32 compareNatural( const ::rtl::OUString &rLHS, const ::rtl::OUString &rRHS ) +COMPHELPER_DLLPUBLIC sal_Int32 compareNatural( const ::rtl::OUString &rLHS, const ::rtl::OUString &rRHS, + const ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCollator > &rCollator, + const ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > &rBI, + const ::com::sun::star::lang::Locale &rLocale ) SAL_THROW(()); -/** - Compares two strings using natural order. - - For non digit characters, the comparison use the same algorithm as - rtl_str_compare. When a number is encountered during the comparison, - natural order is used. Thus, Heading 10 will be considered as greater - than Heading 2. Numerical comparison is done using decimal representation. - - Beware that "MyString 001" and "MyString 1" will be considered as equal - since leading 0 are meaningless. - - @param str the object to be compared. - @return 0 - if both strings are equal - < 0 - if this string is less than the string argument - > 0 - if this string is greater than the string argument - */ -COMPHELPER_DLLPUBLIC sal_Int32 compareNatural( const ::rtl::OString &rLHS, const ::rtl::OString &rRHS ) - SAL_THROW(()); +class COMPHELPER_DLLPUBLIC NaturalStringSorter +{ +private: + ::com::sun::star::lang::Locale m_aLocale; + ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCollator > m_xCollator; + ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > m_xBI; +public: + NaturalStringSorter( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > &rContext, + const ::com::sun::star::lang::Locale &rLocale); + sal_Int32 compare(const rtl::OUString &rLHS, const rtl::OUString &rRHS) + { + return compareNatural(rLHS, rRHS, m_xCollator, m_xBI, m_aLocale); + } +}; } } diff --git a/comphelper/qa/test_string.cxx b/comphelper/qa/test_string.cxx index ab13c8814b38..a5826ae3628d 100644 --- a/comphelper/qa/test_string.cxx +++ b/comphelper/qa/test_string.cxx @@ -30,6 +30,8 @@ #include "sal/config.h" #include "comphelper/string.hxx" +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/i18n/CharType.hpp> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> @@ -84,61 +86,197 @@ void TestString::test() CPPUNIT_ASSERT(n3 == -1); } +using namespace ::com::sun::star; + +class testCollator : public cppu::WeakImplHelper1< i18n::XCollator > +{ +public: + virtual sal_Int32 SAL_CALL compareSubstring( + const rtl::OUString& str1, sal_Int32 off1, sal_Int32 len1, + const rtl::OUString& str2, sal_Int32 off2, sal_Int32 len2) throw(uno::RuntimeException) + { + return str1.copy(off1, len1).compareTo(str2.copy(off2, len2)); + } + virtual sal_Int32 SAL_CALL compareString( + const rtl::OUString& str1, + const rtl::OUString& str2) throw(uno::RuntimeException) + { + return str1.compareTo(str2); + } + virtual sal_Int32 SAL_CALL loadDefaultCollator(const lang::Locale&, sal_Int32) + throw(uno::RuntimeException) {return 0;} + virtual sal_Int32 SAL_CALL loadCollatorAlgorithm(const rtl::OUString&, + const lang::Locale&, sal_Int32) throw(uno::RuntimeException) {return 0;} + virtual void SAL_CALL loadCollatorAlgorithmWithEndUserOption(const rtl::OUString&, + const lang::Locale&, const uno::Sequence< sal_Int32 >&) throw(uno::RuntimeException) {} + virtual uno::Sequence< rtl::OUString > SAL_CALL listCollatorAlgorithms(const lang::Locale&) + throw(uno::RuntimeException) + { + return uno::Sequence< rtl::OUString >(); + } + virtual uno::Sequence< sal_Int32 > SAL_CALL listCollatorOptions(const rtl::OUString&) + throw(uno::RuntimeException) + { + return uno::Sequence< sal_Int32 >(); + } +}; + +#define IS_DIGIT(CHAR) (((CHAR) >= 48) && ((CHAR <= 57))) + +class testBreakIterator : public cppu::WeakImplHelper1< i18n::XBreakIterator > +{ +public: + virtual sal_Int32 SAL_CALL nextCharacters( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& ) + throw(uno::RuntimeException) {return -1;} + virtual sal_Int32 SAL_CALL previousCharacters( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& ) + throw(uno::RuntimeException) {return -1;} + + virtual i18n::Boundary SAL_CALL previousWord( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16) throw(uno::RuntimeException) + { return i18n::Boundary(); } + virtual i18n::Boundary SAL_CALL nextWord( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16) throw(uno::RuntimeException) + { return i18n::Boundary(); } + virtual i18n::Boundary SAL_CALL getWordBoundary( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16, sal_Bool ) + throw(uno::RuntimeException) + { return i18n::Boundary(); } + + virtual sal_Bool SAL_CALL isBeginWord( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16 ) throw(uno::RuntimeException) + { return false; } + virtual sal_Bool SAL_CALL isEndWord( const rtl::OUString&, sal_Int32, + const lang::Locale& , sal_Int16 ) throw(uno::RuntimeException) + { return false; } + virtual sal_Int16 SAL_CALL getWordType( const rtl::OUString&, sal_Int32, + const lang::Locale& ) throw(uno::RuntimeException) + { return 0; } + + virtual sal_Int32 SAL_CALL beginOfSentence( const rtl::OUString&, sal_Int32, + const lang::Locale& ) throw(uno::RuntimeException) + { return 0; } + virtual sal_Int32 SAL_CALL endOfSentence( const rtl::OUString& rText, sal_Int32, + const lang::Locale& ) throw(uno::RuntimeException) + { return rText.getLength(); } + + virtual i18n::LineBreakResults SAL_CALL getLineBreak( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int32, + const i18n::LineBreakHyphenationOptions&, + const i18n::LineBreakUserOptions&) + throw(uno::RuntimeException) + { + return i18n::LineBreakResults(); + } + + virtual sal_Int16 SAL_CALL getScriptType( const rtl::OUString&, sal_Int32 ) + throw(uno::RuntimeException) { return -1; } + virtual sal_Int32 SAL_CALL beginOfScript( const rtl::OUString&, sal_Int32, + sal_Int16 ) throw(uno::RuntimeException) { return -1; } + virtual sal_Int32 SAL_CALL endOfScript( const rtl::OUString&, sal_Int32, + sal_Int16 ) throw(uno::RuntimeException) { return -1; } + virtual sal_Int32 SAL_CALL previousScript( const rtl::OUString&, sal_Int32, + sal_Int16 ) throw(uno::RuntimeException) { return -1; } + virtual sal_Int32 SAL_CALL nextScript( const rtl::OUString&, sal_Int32, + sal_Int16 ) throw(uno::RuntimeException) { return -1; } + + virtual sal_Int32 SAL_CALL beginOfCharBlock( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16 ) throw(uno::RuntimeException) { return -1; } + virtual sal_Int32 SAL_CALL endOfCharBlock( const rtl::OUString& rText, sal_Int32 nStartPos, + const lang::Locale&, sal_Int16 CharType ) throw(uno::RuntimeException) + { + const sal_Unicode *pStr = rText.getStr()+nStartPos; + for (sal_Int16 nI = nStartPos; nI < rText.getLength(); ++nI) + { + if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr)) + return nI; + else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr)) + return nI; + ++pStr; + } + return -1; + } + virtual sal_Int32 SAL_CALL previousCharBlock( const rtl::OUString&, sal_Int32, + const lang::Locale&, sal_Int16 ) throw(uno::RuntimeException) { return -1; } + virtual sal_Int32 SAL_CALL nextCharBlock( const rtl::OUString& rText, sal_Int32 nStartPos, + const lang::Locale&, sal_Int16 CharType ) throw(uno::RuntimeException) + { + const sal_Unicode *pStr = rText.getStr()+nStartPos; + for (sal_Int16 nI = nStartPos; nI < rText.getLength(); ++nI) + { + if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr)) + return nI; + else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr)) + return nI; + ++pStr; + } + return -1; + } +}; + void TestString::testNatural() { using namespace comphelper::string; + + uno::Reference< i18n::XCollator > xCollator(new testCollator); + uno::Reference< i18n::XBreakIterator > xBI(new testBreakIterator); + // --- Some generic tests to ensure we do not alter original behavior // outside what we want CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC")))) == 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))), xCollator, xBI, lang::Locale()) == 0 ); // Case sensitivity CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc")))) < 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc"))), xCollator, xBI, lang::Locale()) < 0 ); // Reverse CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC")))) > 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))), xCollator, xBI, lang::Locale()) > 0 ); // First shorter CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongstring"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongerstring")))) > 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongstring"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongerstring"))), xCollator, xBI, lang::Locale()) > 0 ); // Second shorter CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongerstring"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongstring")))) < 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongerstring"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongstring"))), xCollator, xBI, lang::Locale()) < 0 ); // -- Here we go on natural order, each one is followed by classic compare and the reverse comparison // That's why we originally made the patch CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10")))) < 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10"))), xCollator, xBI, lang::Locale()) < 0 ); // Original behavior CPPUNIT_ASSERT( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9"))).compareTo(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10")))) > 0 ); CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9")))) > 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9"))), xCollator, xBI, lang::Locale()) > 0 ); // Harder CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th")))) < 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th"))), xCollator, xBI, lang::Locale()) < 0 ); CPPUNIT_ASSERT( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th"))).compareTo(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th")))) > 0 ); CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th")))) > 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th"))), xCollator, xBI, lang::Locale()) > 0 ); // Hardest CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010")))) < 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010"))), xCollator, xBI, lang::Locale()) < 0 ); CPPUNIT_ASSERT( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08"))).compareTo(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010")))) > 0 ); CPPUNIT_ASSERT( - compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08")))) > 0 + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08"))), xCollator, xBI, lang::Locale()) > 0 + ); + CPPUNIT_ASSERT( + compareNatural(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("apple10apple"))), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("apple10apple"))), xCollator, xBI, lang::Locale()) == 0 ); } diff --git a/comphelper/source/misc/string.cxx b/comphelper/source/misc/string.cxx index 7e7ddf511799..1edf6846cf23 100644 --- a/comphelper/source/misc/string.cxx +++ b/comphelper/source/misc/string.cxx @@ -42,6 +42,8 @@ #include <comphelper/stlunosequence.hxx> #include <comphelper/stl_types.hxx> +#include <com/sun/star/i18n/CharType.hpp> + namespace comphelper { namespace string { @@ -92,10 +94,12 @@ rtl::OUString searchAndReplaceAsciiL( return _source; } +using namespace ::com::sun::star; + // convert between sequence of string and comma separated string ::rtl::OUString convertCommaSeparated( - ::com::sun::star::uno::Sequence< ::rtl::OUString > const& i_rSeq) + uno::Sequence< ::rtl::OUString > const& i_rSeq) { ::rtl::OUStringBuffer buf; ::comphelper::intersperse( @@ -105,7 +109,7 @@ rtl::OUString searchAndReplaceAsciiL( return buf.makeStringAndClear(); } -::com::sun::star::uno::Sequence< ::rtl::OUString > +uno::Sequence< ::rtl::OUString > convertCommaSeparated( ::rtl::OUString const& i_rString ) { std::vector< ::rtl::OUString > vec; @@ -118,64 +122,86 @@ rtl::OUString searchAndReplaceAsciiL( vec.push_back(kw); } } while (idx >= 0); - ::com::sun::star::uno::Sequence< ::rtl::OUString > kws(vec.size()); + uno::Sequence< ::rtl::OUString > kws(vec.size()); std::copy(vec.begin(), vec.end(), stl_begin(kws)); return kws; } -#define IS_DIGIT(CHAR) (((CHAR) >= 48) && ((CHAR <= 57))) -template<typename IMPL_RTL_STRCODE, typename IMPL_RTL_USTRCODE> - sal_Int32 SAL_CALL compareNaturalImpl(const IMPL_RTL_STRCODE* pStr1, const IMPL_RTL_STRCODE* pStr2) +sal_Int32 compareNatural( const ::rtl::OUString & rLHS, const ::rtl::OUString & rRHS, + const uno::Reference< i18n::XCollator > &rCollator, + const uno::Reference< i18n::XBreakIterator > &rBI, + const lang::Locale &rLocale) SAL_THROW(()) { - sal_Int32 nRet; - do { - while ( ((nRet = ((sal_Int32)(IMPL_RTL_USTRCODE(*pStr1)))- - ((sal_Int32)(IMPL_RTL_USTRCODE(*pStr2)))) == 0) && - *pStr2 ) - { - pStr1++; - pStr2++; - } - - if(*pStr1 && *pStr2) - { - IMPL_RTL_STRCODE c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 ); - IMPL_RTL_STRCODE c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 ); - sal_Int64 number1 = 0; - sal_Int64 number2 = 0; - if(IS_DIGIT(c1) && IS_DIGIT(c2)) - { - do - { - number1 = number1 * 10 + (c1 - '0'); - pStr1++; - c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 ); - } while(IS_DIGIT(c1)); - - do - { - number2 = number2 * 10 + (c2 - '0'); - pStr2++; - c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 ); - } while(IS_DIGIT(c2)); - - nRet = number1 - number2; - } - } - } while(nRet == 0 && *pStr1 && *pStr2); + sal_Int16 nRet = 0; - return nRet; -} + sal_Int16 nLHSLastNonDigitPos = 0; + sal_Int16 nRHSLastNonDigitPos = 0; + sal_Int16 nLHSFirstDigitPos = 0; + sal_Int16 nRHSFirstDigitPos = 0; -sal_Int32 compareNatural( const ::rtl::OUString & rLHS, const ::rtl::OUString & rRHS ) SAL_THROW(()) -{ - return compareNaturalImpl<sal_Unicode, sal_Unicode>(rLHS.pData->buffer, rRHS.pData->buffer); + while (nLHSFirstDigitPos < rLHS.getLength() || nRHSFirstDigitPos < rRHS.getLength()) + { + sal_Int16 nLHSChunkLen; + sal_Int16 nRHSChunkLen; + + //Compare non digit block as normal strings + nLHSFirstDigitPos = rBI->nextCharBlock(rLHS, nLHSLastNonDigitPos, + rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nRHSFirstDigitPos = rBI->nextCharBlock(rRHS, nRHSLastNonDigitPos, + rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + if (nLHSFirstDigitPos == -1) + nLHSFirstDigitPos = rLHS.getLength(); + if (nRHSFirstDigitPos == -1) + nRHSFirstDigitPos = rRHS.getLength(); + nLHSChunkLen = nLHSFirstDigitPos - nLHSLastNonDigitPos; + nRHSChunkLen = nRHSFirstDigitPos - nRHSLastNonDigitPos; + + nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos, + nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen); + if (nRet != 0) + return nRet; + + //Compare digit block as one number vs another + nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos, + rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nRHSLastNonDigitPos = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos, + rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + if (nLHSLastNonDigitPos == -1) + nLHSLastNonDigitPos = rLHS.getLength(); + if (nRHSLastNonDigitPos == -1) + nRHSLastNonDigitPos = rRHS.getLength(); + nLHSChunkLen = nLHSLastNonDigitPos - nLHSFirstDigitPos; + nRHSChunkLen = nRHSLastNonDigitPos - nRHSFirstDigitPos; + + //To-Do: Possibly scale down those unicode codepoints that relate to + //numbers outside of the normal 0-9 range, e.g. see GetLocalizedChar in + //vcl + sal_Int32 nLHS = rLHS.copy(nLHSFirstDigitPos, nLHSChunkLen).toInt32(); + sal_Int32 nRHS = rRHS.copy(nRHSFirstDigitPos, nRHSChunkLen).toInt32(); + + nRet = nLHS-nRHS; + if (nRet != 0) + return nRet; + } + + return nRet; } -sal_Int32 compareNatural( const ::rtl::OString & rLHS, const ::rtl::OString & rRHS ) SAL_THROW(()) +NaturalStringSorter::NaturalStringSorter( + const uno::Reference< uno::XComponentContext > &rContext, + const lang::Locale &rLocale) : m_aLocale(rLocale) { - return compareNaturalImpl<sal_Char, unsigned char>(rLHS.pData->buffer, rRHS.pData->buffer); + uno::Reference< lang::XMultiComponentFactory > xFactory(rContext->getServiceManager(), + uno::UNO_SET_THROW); + + m_xCollator = uno::Reference< i18n::XCollator >(xFactory->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.Collator")), rContext), + uno::UNO_QUERY_THROW); + m_xCollator->loadDefaultCollator(m_aLocale, 0); + m_xBI = uno::Reference< i18n::XBreakIterator >(xFactory->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.BreakIterator")), rContext), + uno::UNO_QUERY_THROW); } } } |