summaryrefslogtreecommitdiff
path: root/comphelper
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2011-02-14 15:37:58 +0000
committerCaolán McNamara <caolanm@redhat.com>2011-02-14 20:52:53 +0000
commit8a55872a3ca73014ae63c3c4e00de7df50a5452e (patch)
treeb2188fbd1efaff487b5c6b0f046620eabae4b03f /comphelper
parent6fd38fbdae654a3319b6bf808a415638dcdbbffe (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.hxx41
-rw-r--r--comphelper/qa/test_string.cxx160
-rw-r--r--comphelper/source/misc/string.cxx124
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);
}
} }