[Libreoffice-commits] .: 4 commits - comphelper/inc comphelper/qa comphelper/source vcl/inc

Caolán McNamara caolan at kemper.freedesktop.org
Mon Feb 14 12:53:31 PST 2011


 comphelper/inc/comphelper/string.hxx |   41 ++++----
 comphelper/qa/test_string.cxx        |  160 ++++++++++++++++++++++++++++++++---
 comphelper/source/misc/string.cxx    |  130 +++++++++++++++++-----------
 vcl/inc/vcl/unohelp.hxx              |   13 +-
 4 files changed, 258 insertions(+), 86 deletions(-)

New commits:
commit aef78e6feac8a7c6b3f916bdecebff4aebc7c616
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Feb 14 20:50:09 2011 +0000

    visibility markup is in the wrong place

diff --git a/vcl/inc/vcl/unohelp.hxx b/vcl/inc/vcl/unohelp.hxx
index 1dc6c22..a24633d 100644
--- a/vcl/inc/vcl/unohelp.hxx
+++ b/vcl/inc/vcl/unohelp.hxx
@@ -58,13 +58,12 @@ namespace vcl
 {
 namespace unohelper
 {
-
-::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > VCL_DLLPUBLIC GetMultiServiceFactory();
-::com::sun::star::uno::Reference < ::com::sun::star::i18n::XBreakIterator > VCL_DLLPUBLIC CreateBreakIterator();
-::com::sun::star::uno::Reference < ::com::sun::star::i18n::XCharacterClassification> VCL_DLLPUBLIC CreateCharacterClassification();
-::com::sun::star::uno::Reference < ::com::sun::star::i18n::XCollator > VCL_DLLPUBLIC CreateCollator();
-::rtl::OUString VCL_DLLPUBLIC CreateLibraryName( const sal_Char* pModName, sal_Bool bSUPD );
-void VCL_DLLPUBLIC NotifyAccessibleStateEventGlobally( const ::com::sun::star::accessibility::AccessibleEventObject& rEventObject );
+VCL_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > GetMultiServiceFactory();
+VCL_DLLPUBLIC ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XBreakIterator > CreateBreakIterator();
+VCL_DLLPUBLIC ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XCharacterClassification> CreateCharacterClassification();
+VCL_DLLPUBLIC ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XCollator > CreateCollator();
+VCL_DLLPUBLIC ::rtl::OUString CreateLibraryName( const sal_Char* pModName, sal_Bool bSUPD );
+VCL_DLLPUBLIC void NotifyAccessibleStateEventGlobally( const ::com::sun::star::accessibility::AccessibleEventObject& rEventObject );
 }}	// namespace vcl::unohelper
 
 #endif  // _VCL_UNOHELP_HXX
commit 954f4e6538ed516848d955b1088788265aeb738c
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Feb 14 20:48:04 2011 +0000

    squeeze these down in case of StringCompare casting

diff --git a/comphelper/source/misc/string.cxx b/comphelper/source/misc/string.cxx
index 97389ab..aa4efaa 100644
--- a/comphelper/source/misc/string.cxx
+++ b/comphelper/source/misc/string.cxx
@@ -160,7 +160,7 @@ sal_Int32 compareNatural( const ::rtl::OUString & rLHS, const ::rtl::OUString &
         nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos,
             nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen);
         if (nRet != 0)
-            return nRet;
+            break;
 
         //Compare digit block as one number vs another
         nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos,
@@ -182,9 +182,15 @@ sal_Int32 compareNatural( const ::rtl::OUString & rLHS, const ::rtl::OUString &
 
         nRet = nLHS-nRHS;
         if (nRet != 0)
-            return nRet;
+            break;
     }
 
+    //Squeeze these down to -1, 0, 1 in case it gets casted to a StringCompare
+    if (nRet > 0)
+        nRet = 1;
+    else if (nRet < 0)
+        nRet = -1;
+
     return nRet;
 }
 
commit 182be9f9bc4153aba729bb3c64146ff13203d98c
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Feb 14 16:17:55 2011 +0000

    we can make this const

diff --git a/comphelper/inc/comphelper/string.hxx b/comphelper/inc/comphelper/string.hxx
index dcffafa..62f3d83 100644
--- a/comphelper/inc/comphelper/string.hxx
+++ b/comphelper/inc/comphelper/string.hxx
@@ -166,7 +166,7 @@ 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)
+    sal_Int32 compare(const rtl::OUString &rLHS, const rtl::OUString &rRHS) const
     {
         return compareNatural(rLHS, rRHS, m_xCollator, m_xBI, m_aLocale);
     }
commit efb85252da68b4820d7e05e9519c49bcbc874c41
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Feb 14 15:37:58 2011 +0000

    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.

diff --git a/comphelper/inc/comphelper/string.hxx b/comphelper/inc/comphelper/string.hxx
index ca08e82..dcffafa 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 ab13c88..aa733cf 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 63d93dd..97389ab 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);
 }
 
 } }


More information about the Libreoffice-commits mailing list