[Libreoffice-commits] .: sal/inc sal/qa sal/rtl sal/util

Cédric Bosdonnat cbosdo at kemper.freedesktop.org
Thu Feb 10 08:04:27 PST 2011


 sal/inc/rtl/string.h                         |   23 ++++++++++
 sal/inc/rtl/string.hxx                       |   22 ++++++++++
 sal/inc/rtl/ustring.h                        |   23 ++++++++++
 sal/inc/rtl/ustring.hxx                      |   22 ++++++++++
 sal/qa/rtl/strings/test_oustring_compare.cxx |   58 +++++++++++++++++++++++++++
 sal/rtl/source/strtmpl.c                     |   47 +++++++++++++++++++++
 sal/util/sal.map                             |    2 
 7 files changed, 197 insertions(+)

New commits:
commit 5cb80049f5a9472260947056a25d89fef31d86b1
Author: Sébastien Le Ray <sebastien-libreoffice at orniz.org>
Date:   Thu Feb 10 16:54:04 2011 +0100

    Add compareToNumeric to OUString & Co

diff --git a/sal/inc/rtl/string.h b/sal/inc/rtl/string.h
index 2a7a2d9..0051fc3 100644
--- a/sal/inc/rtl/string.h
+++ b/sal/inc/rtl/string.h
@@ -73,6 +73,29 @@ sal_Int32 SAL_CALL rtl_str_getLength( const sal_Char * str ) SAL_THROW_EXTERN_C(
  */
 sal_Int32 SAL_CALL rtl_str_compare( const sal_Char * first, const sal_Char * second ) SAL_THROW_EXTERN_C();
 
+/** Compare 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 first
+    the first null-terminated string to be compared.
+
+    @param second
+    the second null-terminated string which is compared with the first one.
+
+    @return
+    0 if both strings are equal, a value less than 0 if the first string is
+    less than the second string, and a value greater than 0 if the first
+    string is greater than the second string.
+ */
+sal_Int32 SAL_CALL rtl_str_compare_Numeric( const sal_Char * first, const sal_Char * second ) SAL_THROW_EXTERN_C();
+
 /** Compare two strings.
 
     The comparison is based on the numeric value of each character in the
diff --git a/sal/inc/rtl/string.hxx b/sal/inc/rtl/string.hxx
index 186b515..bd0fa03 100644
--- a/sal/inc/rtl/string.hxx
+++ b/sal/inc/rtl/string.hxx
@@ -283,6 +283,28 @@ public:
     }
 
     /**
+      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
+     */
+    sal_Int32 compareToNumeric( const OString & str ) const SAL_THROW(())
+    {
+        return rtl_str_compare_Numeric( pData->buffer,
+                                            str.pData->buffer );
+    }
+
+    /**
       Compares two strings with an maximum count of characters.
 
       The comparison is based on the numeric value of each character in
diff --git a/sal/inc/rtl/ustring.h b/sal/inc/rtl/ustring.h
index 723117c..0ed0bbf 100644
--- a/sal/inc/rtl/ustring.h
+++ b/sal/inc/rtl/ustring.h
@@ -74,6 +74,29 @@ sal_Int32 SAL_CALL rtl_ustr_getLength( const sal_Unicode * str ) SAL_THROW_EXTER
  */
 sal_Int32 SAL_CALL rtl_ustr_compare( const sal_Unicode * first, const sal_Unicode * second ) SAL_THROW_EXTERN_C();
 
+/** Compare 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 first
+    the first null-terminated string to be compared.
+
+    @param second
+    the second null-terminated string which is compared with the first one.
+
+    @return
+    0 if both strings are equal, a value less than 0 if the first string is
+    less than the second string, and a value greater than 0 if the first
+    string is greater than the second string.
+ */
+sal_Int32 SAL_CALL rtl_ustr_compare_Numeric( const sal_Unicode * first, const sal_Unicode * second ) SAL_THROW_EXTERN_C();
+
 /** Compare two strings.
 
     The comparison is based on the numeric value of each character in the
diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx
index f948a0c..c44603e 100644
--- a/sal/inc/rtl/ustring.hxx
+++ b/sal/inc/rtl/ustring.hxx
@@ -330,6 +330,28 @@ public:
     }
 
     /**
+      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
+    */
+    sal_Int32 compareToNumeric( const OUString & str ) const SAL_THROW(())
+    {
+        return rtl_ustr_compare_Numeric( pData->buffer,
+                                            str.pData->buffer );
+    }
+
+    /**
       Compares two strings with an maximum count of characters.
 
       The comparison is based on the numeric value of each character in
diff --git a/sal/qa/rtl/strings/test_oustring_compare.cxx b/sal/qa/rtl/strings/test_oustring_compare.cxx
index 1d4246d..daa3958 100644
--- a/sal/qa/rtl/strings/test_oustring_compare.cxx
+++ b/sal/qa/rtl/strings/test_oustring_compare.cxx
@@ -40,9 +40,11 @@ class Compare: public CppUnit::TestFixture
 {
 private:
     void equalsIgnoreAsciiCaseAscii();
+    void compareNumeric();
 
 CPPUNIT_TEST_SUITE(Compare);
 CPPUNIT_TEST(equalsIgnoreAsciiCaseAscii);
+CPPUNIT_TEST(compareNumeric);
 CPPUNIT_TEST_SUITE_END();
 };
 
@@ -68,4 +70,60 @@ void test::oustring::Compare::equalsIgnoreAsciiCaseAscii()
                    equalsIgnoreAsciiCaseAscii("abcd"));
 }
 
+void test::oustring::Compare::compareNumeric()
+{
+// --- Some generic tests to ensure we do not alter original behavior
+// outside what we want
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC")))) == 0
+    );
+    // Case sensitivity
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc")))) < 0
+    );
+    // Reverse
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("ABC")))) > 0
+    );
+    // First shorter
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongstring"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongerstring")))) > 0
+    );
+    // Second shorter
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongerstring"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("alongstring")))) < 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(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10")))) < 0
+    );
+    // Original behavior
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9"))).compareTo(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10")))) > 0
+    );
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 10"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("Heading 9")))) > 0
+    );
+    // Harder
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th")))) < 0
+    );
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th"))).compareTo(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th")))) > 0
+    );
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 10th"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("July, the 4th")))) > 0
+    );
+    // Hardest
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010")))) < 0
+    );
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08"))).compareTo(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010")))) > 0
+    );
+    CPPUNIT_ASSERT(
+        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc010"))).compareToNumeric(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(("abc08")))) > 0
+    );
+}
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/rtl/source/strtmpl.c b/sal/rtl/source/strtmpl.c
index 98c09f1..18bc959 100644
--- a/sal/rtl/source/strtmpl.c
+++ b/sal/rtl/source/strtmpl.c
@@ -60,6 +60,8 @@ inline void rtl_str_ImplCopy( IMPL_RTL_STRCODE* pDest,
     }                                                               \
 }
 
+#define IS_DIGIT(CHAR) (((CHAR) >= 48) && ((CHAR <= 57)))
+
 /* ======================================================================= */
 /* C-String functions which could be used without the String-Class         */
 /* ======================================================================= */
@@ -91,6 +93,51 @@ sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare )( const IMPL_RTL_STRCODE* pStr1,
 
 /* ----------------------------------------------------------------------- */
 
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare_Numeric )( const IMPL_RTL_STRCODE* pStr1,
+                                                        const IMPL_RTL_STRCODE* pStr2 )
+{
+    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);
+
+    return nRet;
+}
+
+/* ----------------------------------------------------------------------- */
+
 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
                                                            sal_Int32 nStr1Len,
                                                            const IMPL_RTL_STRCODE* pStr2,
diff --git a/sal/util/sal.map b/sal/util/sal.map
index 8b1c079..a7e3eb6 100755
--- a/sal/util/sal.map
+++ b/sal/util/sal.map
@@ -194,6 +194,7 @@ UDK_3_0_0 {
         rtl_locale_setDefault;
         rtl_str_getLength;
         rtl_str_compare;
+        rtl_str_compare_Numeric;
         rtl_str_compare_WithLength;
         rtl_str_shortenedCompare_WithLength;
         rtl_str_reverseCompare_WithLength;
@@ -251,6 +252,7 @@ UDK_3_0_0 {
         rtl_stringbuffer_newFromStr_WithLength;
         rtl_stringbuffer_newFromStringBuffer;
         rtl_ustr_compare;
+        rtl_ustr_compare_Numeric;
         rtl_ustr_compare_WithLength;
         rtl_ustr_shortenedCompare_WithLength;
         rtl_ustr_reverseCompare_WithLength;


More information about the Libreoffice-commits mailing list