[Libreoffice-commits] .: 8 commits - sal/inc sal/Package_inc.mk sal/qa

Lubos Lunak llunak at kemper.freedesktop.org
Wed Mar 28 14:01:24 PDT 2012


 sal/Package_inc.mk                                  |    1 
 sal/inc/rtl/oustringostreaminserter.hxx             |   13 
 sal/inc/rtl/strbuf.hxx                              |   70 +++
 sal/inc/rtl/string.hxx                              |   81 ----
 sal/inc/rtl/stringutils.hxx                         |  133 +++++++
 sal/inc/rtl/ustrbuf.hxx                             |   66 ++-
 sal/inc/rtl/ustring.hxx                             |  354 +++++++-------------
 sal/qa/rtl/strings/test_ostring_stringliterals.cxx  |   32 +
 sal/qa/rtl/strings/test_oustring_stringliterals.cxx |   43 +-
 9 files changed, 461 insertions(+), 332 deletions(-)

New commits:
commit ef87e804ec80451ff1517482c1b70e7dccb961ce
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 22:58:11 2012 +0200

    string literal overloads for OStringBuffer

diff --git a/sal/inc/rtl/strbuf.hxx b/sal/inc/rtl/strbuf.hxx
index 62250f3..54428d3 100644
--- a/sal/inc/rtl/strbuf.hxx
+++ b/sal/inc/rtl/strbuf.hxx
@@ -373,11 +373,31 @@ public:
         @param   str   the characters to be appended.
         @return  this string buffer.
      */
-    OStringBuffer & append( const sal_Char * str )
+    template< typename T >
+    typename internal::CharPtrDetector< T, OStringBuffer& >::Type append( const T& str )
     {
         return append( str, rtl_str_getLength( str ) );
     }
 
+    template< typename T >
+    typename internal::NonConstCharArrayDetector< T, OStringBuffer& >::Type append( T& str )
+    {
+        return append( str, rtl_str_getLength( str ) );
+    }
+
+    /**
+     @overload
+     This function accepts an ASCII string literal as its argument.
+     @since LibreOffice 3.6
+    */
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OStringBuffer& >::Type append( T& literal )
+    {
+        RTL_STRING_CONST_FUNCTION
+        rtl_stringbuffer_insert( &pData, &nCapacity, getLength(), literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
+        return *this;
+    }
+
     /**
         Appends the string representation of the <code>char</code> array
         argument to this string buffer.
@@ -535,11 +555,31 @@ public:
         @param      str      a character array.
         @return     this string buffer.
      */
-    OStringBuffer & insert( sal_Int32 offset, const sal_Char * str )
+    template< typename T >
+    typename internal::CharPtrDetector< T, OStringBuffer& >::Type insert( sal_Int32 offset, const T& str )
     {
         return insert( offset, str, rtl_str_getLength( str ) );
     }
 
+    template< typename T >
+    typename internal::NonConstCharArrayDetector< T, OStringBuffer& >::Type insert( sal_Int32 offset, T& str )
+    {
+        return insert( offset, str, rtl_str_getLength( str ) );
+    }
+
+    /**
+     @overload
+     This function accepts an ASCII string literal as its argument.
+     @since LibreOffice 3.6
+    */
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OStringBuffer& >::Type insert( sal_Int32 offset, T& literal )
+    {
+        RTL_STRING_CONST_FUNCTION
+        rtl_stringbuffer_insert( &pData, &nCapacity, offset, literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
+        return *this;
+    }
+
     /**
         Inserts the string representation of the <code>char</code> array
         argument into this string buffer.
diff --git a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
index 462385e..3f2ed84 100644
--- a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
@@ -40,6 +40,7 @@ bool rtl_string_unittest_non_const_literal_function;
 #include <cppunit/extensions/HelperMacros.h>
 #include "rtl/string.h"
 #include "rtl/string.hxx"
+#include "rtl/strbuf.hxx"
 
 namespace rtlunittest {
 
@@ -61,6 +62,7 @@ private:
     void checkCtors();
     void checkUsage();
     void checkNonConstUsage();
+    void checkBuffer();
 
     void testcall( const char str[] );
 
@@ -68,6 +70,7 @@ CPPUNIT_TEST_SUITE(StringLiterals);
 CPPUNIT_TEST(checkCtors);
 CPPUNIT_TEST(checkUsage);
 CPPUNIT_TEST(checkNonConstUsage);
+CPPUNIT_TEST(checkBuffer);
 CPPUNIT_TEST_SUITE_END();
 };
 
@@ -247,6 +250,34 @@ void test::ostring::StringLiterals::checkNonConstUsage()
 //    CPPUNIT_ASSERT( foobarfoo.lastIndexOf( (const char*)foo_c ) == 6 );
 //    CPPUNIT_ASSERT( foobarfoo.lastIndexOf( foo_c ) == 6 );
     // if this is not true, some of the calls above used const variants
+    CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
+    CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == false );
+}
+
+void test::ostring::StringLiterals::checkBuffer()
+{
+    rtl::OStringBuffer buf;
+    rtl_string_unittest_const_literal_function = false;
+    buf.append( "foo" );
+    CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
+    CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OString( "foo" ));
+    rtl_string_unittest_const_literal_function = false;
+    buf.append( "bar" );
+    CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
+    CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OString( "foobar" ));
+    rtl_string_unittest_const_literal_function = false;
+    buf.insert( 3, "baz" );
+    CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
+    CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OString( "foobazbar" ));
+
+    rtl::OString foobazbard( "foobazbard" );
+    rtl::OString foodbazbard( "foodbazbard" );
+    rtl_string_unittest_const_literal = false; // start checking for OString conversions
+    rtl_string_unittest_const_literal_function = false; // and check for const variants
+    char d[] = "d";
+    CPPUNIT_ASSERT_EQUAL( buf.append( d ).toString(), foobazbard );
+    CPPUNIT_ASSERT_EQUAL( buf.insert( 3, d ).toString(), foodbazbard );
+    CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
     CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == false );
 }
 
commit b741f7fb1ea7b62c9cf2988a64e07cbbb8db904a
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 22:52:37 2012 +0200

    make unittest check also for invalid conversions with OUStringBuffer

diff --git a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
index ddac4d6..2070698 100644
--- a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
@@ -180,6 +180,9 @@ void test::oustring::StringLiterals::checkBuffer()
     CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OUString( "foobar" ));
     buf.insert( 3, "baz" );
     CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OUString( "foobazbar" ));
+    char d[] = "d";
+    CPPUNIT_ASSERT( !VALID_CONVERSION( buf.append( d )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( buf.insert( 0, d )));
 }
 
 }} // namespace
commit bd577aa7f8252f3f95276cd17c93beae1902fd96
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 22:31:25 2012 +0200

    string literal overload for OUStringBuffer::insert()

diff --git a/sal/inc/rtl/ustrbuf.hxx b/sal/inc/rtl/ustrbuf.hxx
index ee17f77..99afe44 100644
--- a/sal/inc/rtl/ustrbuf.hxx
+++ b/sal/inc/rtl/ustrbuf.hxx
@@ -635,6 +635,19 @@ public:
     }
 
     /**
+        @overload
+        This function accepts an ASCII string literal as its argument.
+        @since LibreOffice 3.6
+     */
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OUStringBuffer& >::Type insert( sal_Int32 offset, T& literal )
+    {
+        rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, offset, literal,
+            internal::ConstCharArrayDetector< T, void >::size - 1 );
+        return *this;
+    }
+
+    /**
         Inserts the string representation of the <code>sal_Bool</code>
         argument into this string buffer.
 
diff --git a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
index 2783571..ddac4d6 100644
--- a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
@@ -178,6 +178,8 @@ void test::oustring::StringLiterals::checkBuffer()
     CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OUString( "foo" ));
     buf.append( "bar" );
     CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OUString( "foobar" ));
+    buf.insert( 3, "baz" );
+    CPPUNIT_ASSERT_EQUAL( buf.toString(), rtl::OUString( "foobazbar" ));
 }
 
 }} // namespace
commit bf68985627a7e0520674a8eb0d0f037e71f432fe
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 22:27:53 2012 +0200

    string literal overload in the right place

diff --git a/sal/inc/rtl/ustrbuf.hxx b/sal/inc/rtl/ustrbuf.hxx
index a89d877..ee17f77 100644
--- a/sal/inc/rtl/ustrbuf.hxx
+++ b/sal/inc/rtl/ustrbuf.hxx
@@ -375,6 +375,19 @@ public:
     }
 
     /**
+        @overload
+        This function accepts an ASCII string literal as its argument.
+        @since LibreOffice 3.6
+     */
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OUStringBuffer& >::Type append( T& literal )
+    {
+        rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), literal,
+            internal::ConstCharArrayDetector< T, void >::size - 1 );
+        return *this;
+    }
+
+    /**
         Appends a 8-Bit ASCII character string to this string buffer.
 
        Since this method is optimized for performance. the ASCII
@@ -420,19 +433,6 @@ public:
     }
 
     /**
-        @overload
-        This function accepts an ASCII string literal as its argument.
-        @since LibreOffice 3.6
-     */
-    template< typename T >
-    typename internal::ConstCharArrayDetector< T, OUStringBuffer& >::Type append( T& literal )
-    {
-        rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), literal,
-            internal::ConstCharArrayDetector< T, void >::size - 1 );
-        return *this;
-    }
-
-    /**
         Appends the string representation of the <code>sal_Bool</code>
         argument to the string buffer.
 
commit 60573363d87bb1335ff8ac0c0623f0ec3e0dc319
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 22:24:48 2012 +0200

    clean up string literal overloads in OUStringBuffer

diff --git a/sal/inc/rtl/ustrbuf.hxx b/sal/inc/rtl/ustrbuf.hxx
index 15bbe67..a89d877 100644
--- a/sal/inc/rtl/ustrbuf.hxx
+++ b/sal/inc/rtl/ustrbuf.hxx
@@ -52,10 +52,6 @@ namespace rtl
 
 #ifdef RTL_STRING_UNITTEST
 #undef rtl
-// helper macro to make functions appear more readable
-#define RTL_STRING_CONST_FUNCTION rtl_string_unittest_const_literal_function = true;
-#else
-#define RTL_STRING_CONST_FUNCTION
 #endif
 
 /** A string buffer implements a mutable sequence of characters.
@@ -428,21 +424,15 @@ public:
         This function accepts an ASCII string literal as its argument.
         @since LibreOffice 3.6
      */
-    template< int N >
-    OUStringBuffer& append( const char (&literal)[ N ] )
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OUStringBuffer& >::Type append( T& literal )
     {
-        rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), literal, N - 1 );
+        rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), literal,
+            internal::ConstCharArrayDetector< T, void >::size - 1 );
         return *this;
     }
 
     /**
-        It is an error to call this overload. Strings cannot directly use non-const char[].
-        @internal
-     */
-    template< int N >
-    OUStringBuffer& append( char (&literal)[ N ] );
-
-    /**
         Appends the string representation of the <code>sal_Bool</code>
         argument to the string buffer.
 
@@ -889,7 +879,6 @@ namespace rtl
 {
 typedef rtlunittest::OUStringBuffer OUStringBuffer;
 }
-#undef RTL_STRING_CONST_FUNCTION
 #endif
 
 #endif  /* _RTL_USTRBUF_HXX_ */
commit 8594c4c52a38f34d1ccb4541dae2e29f08546151
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 22:22:39 2012 +0200

    OUString does not have any non-const char functions, no need to check for it

diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx
index a95abd1..ad6fad2 100644
--- a/sal/inc/rtl/ustring.hxx
+++ b/sal/inc/rtl/ustring.hxx
@@ -60,10 +60,6 @@ namespace rtl
 
 #ifdef RTL_STRING_UNITTEST
 #undef rtl
-// helper macro to make functions appear more readable
-#define RTL_STRING_CONST_FUNCTION rtl_string_unittest_const_literal_function = true;
-#else
-#define RTL_STRING_CONST_FUNCTION
 #endif
 
 /* ======================================================================= */
@@ -2028,7 +2024,6 @@ namespace rtl
 {
 typedef rtlunittest::OUString OUString;
 }
-#undef RTL_STRING_CONST_FUNCTION
 #endif
 
 namespace rtl
commit 8a654fe9a5efc609bcbbfe8864a0748687798930
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 22:21:03 2012 +0200

    use SFINAE to remove non-const char[N] OUString overloads

diff --git a/sal/inc/rtl/stringutils.hxx b/sal/inc/rtl/stringutils.hxx
index 866bf23..55326ce 100644
--- a/sal/inc/rtl/stringutils.hxx
+++ b/sal/inc/rtl/stringutils.hxx
@@ -101,7 +101,30 @@ struct ConstCharArrayDetector< const char[ N ], T >
     typedef T Type;
     static const int size = N;
 };
-}
+
+// this one is used to rule out only const char[N]
+template< typename T >
+struct ExceptConstCharArrayDetector
+{
+    typedef Dummy Type;
+};
+template< int N >
+struct ExceptConstCharArrayDetector< const char[ N ] >
+{
+};
+// this one is used to rule out only const char[N]
+// (const will be brought in by 'const T&' in the function call)
+template< typename T >
+struct ExceptCharArrayDetector
+{
+    typedef Dummy Type;
+};
+template< int N >
+struct ExceptCharArrayDetector< char[ N ] >
+{
+};
+
+} /* Namespace */
 
 } /* Namespace */
 
diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx
index dadef0f..a95abd1 100644
--- a/sal/inc/rtl/ustring.hxx
+++ b/sal/inc/rtl/ustring.hxx
@@ -199,6 +199,9 @@ public:
       @exception std::bad_alloc is thrown if an out-of-memory condition occurs
       @since LibreOffice 3.6
     */
+#ifdef HAVE_SFINAE_ANONYMOUS_BROKEN
+    // Old gcc can try to convert anonymous enums to OUString and give compile error.
+    // So instead have a variant for const and non-const char[].
     template< int N >
     OUString( const char (&literal)[ N ] )
     {
@@ -217,15 +220,8 @@ public:
     }
 
     /**
-     * This overload exists only to avoid creating instances directly from (non-const) char[],
-     * which would otherwise be picked up by the optimized const char[] constructor.
-     * Since the non-const array cannot be guaranteed to contain characters in the expected
-     * ASCII encoding, this needs to be prevented.
-     *
-     * It is an error to try to call this overload.
-     *
+     * It is an error to call this overload. Strings cannot directly use non-const char[].
      * @internal
-     * @since LibreOffice 3.6
      */
     template< int N >
     OUString( char (&value)[ N ] )
@@ -236,8 +232,29 @@ public:
         (void) value; // unused
         pData = 0;
         rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10 ); // set to garbage
+        rtl_string_unittest_invalid_conversion = true;
     }
 #endif
+#else // HAVE_SFINAE_ANONYMOUS_BROKEN
+    template< typename T >
+    OUString( T& literal, typename internal::ConstCharArrayDetector< T, internal::Dummy >::Type = internal::Dummy() )
+    {
+        pData = 0;
+        rtl_uString_newFromLiteral( &pData, literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
+        if (pData == 0) {
+#if defined EXCEPTIONS_OFF
+            SAL_WARN("sal", "std::bad_alloc but EXCEPTIONS_OFF");
+#else
+            throw std::bad_alloc();
+#endif
+        }
+#ifdef RTL_STRING_UNITTEST
+        rtl_string_unittest_const_literal = true;
+#endif
+    }
+
+#endif // HAVE_SFINAE_ANONYMOUS_BROKEN
+
 
 #ifdef RTL_STRING_UNITTEST
     /**
@@ -245,10 +262,22 @@ public:
      * @internal
      */
     template< typename T >
-    OUString( T )
+    OUString( T&, typename internal::ExceptConstCharArrayDetector< T >::Type = internal::Dummy() )
+    {
+        pData = 0;
+        rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10 ); // set to garbage
+        rtl_string_unittest_invalid_conversion = true;
+    }
+    /**
+     * Only used by unittests to detect incorrect conversions.
+     * @internal
+     */
+    template< typename T >
+    OUString( const T&, typename internal::ExceptCharArrayDetector< T >::Type = internal::Dummy() )
     {
         pData = 0;
         rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10 ); // set to garbage
+        rtl_string_unittest_invalid_conversion = true;
     }
 #endif
 
@@ -357,10 +386,10 @@ public:
       @exception std::bad_alloc is thrown if an out-of-memory condition occurs
       @since LibreOffice 3.6
     */
-    template< int N >
-    OUString& operator=( const char (&literal)[ N ] )
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OUString& >::Type operator=( T& literal )
     {
-        rtl_uString_newFromLiteral( &pData, literal, N - 1 );
+        rtl_uString_newFromLiteral( &pData, literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
         if (pData == 0) {
 #if defined EXCEPTIONS_OFF
             SAL_WARN("sal", "std::bad_alloc but EXCEPTIONS_OFF");
@@ -372,13 +401,6 @@ public:
     }
 
     /**
-     * It is an error to call this overload. Strings cannot be directly assigned non-const char[].
-     * @internal
-     */
-    template< int N >
-    OUString& operator=( char (&value)[ N ] ); // intentionally not implemented
-
-    /**
       Append a string to this string.
 
       @param    str         a OUString.
@@ -542,22 +564,15 @@ public:
      This function accepts an ASCII string literal as its argument.
      @since LibreOffice 3.6
     */
-    template< int N >
-    sal_Bool equalsIgnoreAsciiCase( const char (&literal)[ N ] ) const SAL_THROW(())
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, bool >::Type equalsIgnoreAsciiCase( T& literal ) const SAL_THROW(())
     {
-        if ( pData->length != N - 1 )
+        if ( pData->length != internal::ConstCharArrayDetector< T, void >::size - 1 )
             return sal_False;
 
         return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, literal ) == 0;
     }
 
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    sal_Bool equalsIgnoreAsciiCase( char (&literal)[ N ] ) const SAL_THROW(());
-
    /**
       Match against a substring appearing in this string.
 
@@ -584,21 +599,14 @@ public:
      This function accepts an ASCII string literal as its argument.
      @since LibreOffice 3.6
     */
-    template< int N >
-    sal_Bool match( const char (&literal)[ N ], sal_Int32 fromIndex = 0 ) const SAL_THROW(())
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, bool >::Type match( T& literal, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
     {
         return rtl_ustr_ascii_shortenedCompare_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
-                                                           literal, N - 1 ) == 0;
+            literal, internal::ConstCharArrayDetector< T, void >::size - 1 ) == 0;
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    sal_Bool match( char (&literal)[ N ], sal_Int32 fromIndex = 0 ) const SAL_THROW(());
-
-    /**
       Match against a substring appearing in this string, ignoring the case of
       ASCII letters.
 
@@ -628,21 +636,14 @@ public:
      This function accepts an ASCII string literal as its argument.
      @since LibreOffice 3.6
     */
-    template< int N >
-    sal_Bool matchIgnoreAsciiCase( const char (&literal)[ N ], sal_Int32 fromIndex = 0 ) const SAL_THROW(())
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, bool >::Type matchIgnoreAsciiCase( T& literal, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
     {
         return rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
-                                                                          literal, N - 1 ) == 0;
+            literal, internal::ConstCharArrayDetector< T, void >::size - 1 ) == 0;
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    sal_Bool matchIgnoreAsciiCase( char (&literal)[ N ], sal_Int32 fromIndex = 0 ) const SAL_THROW(());
-
-    /**
       Compares two strings.
 
       The comparison is based on the numeric value of each character in
@@ -926,23 +927,16 @@ public:
      This function accepts an ASCII string literal as its argument.
      @since LibreOffice 3.6
     */
-    template< int N >
-    bool endsWith( const char (&literal)[ N ] ) const
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, bool >::Type endsWith( T& literal ) const
     {
-        return N - 1 <= pData->length
+        return internal::ConstCharArrayDetector< T, void >::size - 1 <= pData->length
             && rtl_ustr_asciil_reverseEquals_WithLength(
-                pData->buffer + pData->length - ( N - 1 ), literal,
-                N - 1);
+                pData->buffer + pData->length - ( internal::ConstCharArrayDetector< T, void >::size - 1 ), literal,
+                internal::ConstCharArrayDetector< T, void >::size - 1);
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    bool endsWith( char (&literal)[ N ] ) const;
-
-    /**
       Check whether this string ends with a given ASCII string.
 
       @param asciiStr a sequence of at least asciiStrLength ASCII characters
@@ -986,23 +980,18 @@ public:
      This function accepts an ASCII string literal as its argument.
      @since LibreOffice 3.6
     */
-    template< int N >
-    sal_Bool endsWithIgnoreAsciiCase( const char (&literal)[ N ] ) const SAL_THROW(())
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, bool >::Type endsWithIgnoreAsciiCase( T& literal ) const SAL_THROW(())
     {
-        return N - 1 <= pData->length
+        return internal::ConstCharArrayDetector< T, void >::size - 1 <= pData->length
             && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
-                    pData->buffer + pData->length - ( N - 1 ),
-                    N - 1, literal, N - 1)
+                    pData->buffer + pData->length - ( internal::ConstCharArrayDetector< T, void >::size - 1 ),
+                    internal::ConstCharArrayDetector< T, void >::size - 1, literal,
+                    internal::ConstCharArrayDetector< T, void >::size - 1)
                 == 0);
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    sal_Bool endsWithIgnoreAsciiCase( char (&literal)[ N ] ) const SAL_THROW(());
-    /**
       Check whether this string ends with a given ASCII string, ignoring the
       case of ASCII letters.
 
@@ -1052,10 +1041,10 @@ public:
      *
      * @since LibreOffice 3.6
      */
-    template< int N >
-    friend inline bool operator==( const OUString& string, const char (&literal)[ N ] )
+    template< typename T >
+    friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator==( const OUString& string, T& literal )
     {
-        return string.equalsAsciiL( literal, N - 1 );
+        return string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
     }
     /**
      * Compare string to an ASCII string literal.
@@ -1064,10 +1053,10 @@ public:
      *
      * @since LibreOffice 3.6
      */
-    template< int N >
-    friend inline bool operator==( const char (&literal)[ N ], const OUString& string )
+    template< typename T >
+    friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator==( T& literal, const OUString& string )
     {
-        return string.equalsAsciiL( literal, N - 1 );
+        return string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
     }
     /**
      * Compare string to an ASCII string literal.
@@ -1076,10 +1065,10 @@ public:
      *
      * @since LibreOffice 3.6
      */
-    template< int N >
-    friend inline bool operator!=( const OUString& string, const char (&literal)[ N ] )
+    template< typename T >
+    friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator!=( const OUString& string, T& literal )
     {
-        return !string.equalsAsciiL( literal, N - 1 );
+        return !string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
     }
     /**
      * Compare string to an ASCII string literal.
@@ -1088,35 +1077,11 @@ public:
      *
      * @since LibreOffice 3.6
      */
-    template< int N >
-    friend inline bool operator!=( const char (&literal)[ N ], const OUString& string )
+    template< typename T >
+    friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator!=( T& literal, const OUString& string )
     {
-        return !string.equalsAsciiL( literal, N - 1 );
+        return !string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
     }
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    friend inline bool operator==( const OUString& string, char (&literal)[ N ] ); // not implemented
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    friend inline bool operator==( char (&literal)[ N ], const OUString& string ); // not implemented
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    friend inline bool operator!=( const OUString& string, char (&literal)[ N ] ); // not implemented
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    friend inline bool operator!=( char (&literal)[ N ], const OUString& string ); // not implemented
 
     /**
       Returns a hashcode for this string.
@@ -1207,22 +1172,16 @@ public:
      This function accepts an ASCII string literal as its argument.
      @since LibreOffice 3.6
     */
-    template< int N >
-    sal_Int32 indexOf( const char (&literal)[ N ], sal_Int32 fromIndex = 0 ) const SAL_THROW(())
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, sal_Int32 >::Type indexOf( T& literal, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
     {
         sal_Int32 ret = rtl_ustr_indexOfAscii_WithLength(
-            pData->buffer + fromIndex, pData->length - fromIndex, literal, N - 1);
+            pData->buffer + fromIndex, pData->length - fromIndex, literal,
+            internal::ConstCharArrayDetector< T, void >::size - 1);
         return ret < 0 ? ret : ret + fromIndex;
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    sal_Int32 indexOf( char (&literal)[ N ], sal_Int32 fromIndex = 0 ) const SAL_THROW(());
-
-    /**
        Returns the index within this string of the first occurrence of the
        specified ASCII substring, starting at the specified index.
 
@@ -1311,21 +1270,14 @@ public:
      This function accepts an ASCII string literal as its argument.
      @since LibreOffice 3.6
     */
-    template< int N >
-    sal_Int32 lastIndexOf( const char (&literal)[ N ] ) const SAL_THROW(())
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, sal_Int32 >::Type lastIndexOf( T& literal ) const SAL_THROW(())
     {
         return rtl_ustr_lastIndexOfAscii_WithLength(
-            pData->buffer, pData->length, literal, N - 1);
+            pData->buffer, pData->length, literal, internal::ConstCharArrayDetector< T, void >::size - 1);
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    sal_Int32 lastIndexOf( char (&literal)[ N ] ) const SAL_THROW(());
-
-    /**
        Returns the index within this string of the last occurrence of the
        specified ASCII substring.
 
@@ -1503,26 +1455,18 @@ public:
 
       @since LibreOffice 3.6
     */
-    template< int N >
-    OUString replaceFirst( const char (&from)[ N ], OUString const & to,
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OUString >::Type replaceFirst( T& from, OUString const & to,
                            sal_Int32 * index = 0) const
     {
         rtl_uString * s = 0;
         sal_Int32 i = 0;
         rtl_uString_newReplaceFirstAsciiL(
-            &s, pData, from, N - 1, to.pData, index == 0 ? &i : index);
+            &s, pData, from, internal::ConstCharArrayDetector< T, void >::size - 1, to.pData, index == 0 ? &i : index);
         return OUString(s, SAL_NO_ACQUIRE);
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    OUString replaceFirst( char (&literal)[ N ], OUString const & to,
-                           sal_Int32 * index = 0) const;
-
-    /**
       Returns a new string resulting from replacing the first occurrence of a
       given substring with another substring.
 
@@ -1540,40 +1484,19 @@ public:
 
       @since LibreOffice 3.6
     */
-    template< int N1, int N2 >
-    OUString replaceFirst( const char (&from)[ N1 ], const char (&to)[ N2 ],
-                           sal_Int32 * index = 0) const
+    template< typename T1, typename T2 >
+    typename internal::ConstCharArrayDetector< T1, typename internal::ConstCharArrayDetector< T2, OUString >::Type >::Type
+        replaceFirst( T1& from, T2& to, sal_Int32 * index = 0) const
     {
         rtl_uString * s = 0;
         sal_Int32 i = 0;
         rtl_uString_newReplaceFirstAsciiLAsciiL(
-            &s, pData, from, N1 - 1, to, N2 - 1, index == 0 ? &i : index);
+            &s, pData, from, internal::ConstCharArrayDetector< T1, void >::size - 1, to,
+            internal::ConstCharArrayDetector< T2, void >::size - 1, index == 0 ? &i : index);
         return OUString(s, SAL_NO_ACQUIRE);
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N1, int N2 >
-    OUString replaceFirst( char (&from)[ N1 ], char (&to)[ N2 ],
-                           sal_Int32 * index = 0) const;
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N1, int N2 >
-    OUString replaceFirst( const char (&from)[ N1 ], char (&to)[ N2 ],
-                           sal_Int32 * index = 0) const;
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N1, int N2 >
-    OUString replaceFirst( char (&from)[ N1 ], const char (&to)[ N2 ],
-                           sal_Int32 * index = 0) const;
-
-    /**
       Returns a new string resulting from replacing all occurrences of a given
       substring with another substring.
 
@@ -1605,22 +1528,15 @@ public:
 
       @since LibreOffice 3.6
     */
-    template< int N >
-    OUString replaceAll( const char (&from)[ N ], OUString const & to) const
+    template< typename T >
+    typename internal::ConstCharArrayDetector< T, OUString >::Type replaceAll( T& from, OUString const & to) const
     {
         rtl_uString * s = 0;
-        rtl_uString_newReplaceAllAsciiL(&s, pData, from, N - 1, to.pData);
+        rtl_uString_newReplaceAllAsciiL(&s, pData, from, internal::ConstCharArrayDetector< T, void >::size - 1, to.pData);
         return OUString(s, SAL_NO_ACQUIRE);
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N >
-    OUString replaceAll( char (&literal)[ N ], OUString const & to) const;
-
-    /**
       Returns a new string resulting from replacing all occurrences of a given
       substring with another substring.
 
@@ -1633,65 +1549,18 @@ public:
 
       @since LibreOffice 3.6
     */
-    template< int N1, int N2 >
-    OUString replaceAll( const char (&from)[ N1 ], const char (&to)[ N2 ] ) const
+    template< typename T1, typename T2 >
+    typename internal::ConstCharArrayDetector< T1, typename internal::ConstCharArrayDetector< T2, OUString >::Type >::Type
+        replaceAll( T1& from, T2& to ) const
     {
         rtl_uString * s = 0;
         rtl_uString_newReplaceAllAsciiLAsciiL(
-            &s, pData, from, N1 - 1, to, N2 - 1);
+            &s, pData, from, internal::ConstCharArrayDetector< T1, void >::size - 1,
+            to, internal::ConstCharArrayDetector< T2, void >::size - 1);
         return OUString(s, SAL_NO_ACQUIRE);
     }
 
     /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N1, int N2 >
-    OUString replaceAll( char (&from)[ N1 ], char (&to)[ N2 ] ) const
-#ifndef RTL_STRING_UNITTEST
-        ; // intentionally not implemented
-#else
-    {
-        (void) from; // unused
-        (void) to; // unused
-        rtl_uString_newFromLiteral( &const_cast<OUString*>(this)->pData, "!!br0ken!!", 10 ); // set to garbage
-        return *this;
-    }
-#endif
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N1, int N2 >
-    OUString replaceAll( char (&from)[ N1 ], const char (&to)[ N2 ] ) const
-#ifndef RTL_STRING_UNITTEST
-        ; // intentionally not implemented
-#else
-    {
-        (void) from; // unused
-        (void) to; // unused
-        rtl_uString_newFromLiteral( &const_cast<OUString*>(this)->pData, "!!br0ken!!", 10 ); // set to garbage
-        return *this;
-    }
-#endif
-    /**
-     * It is an error to call this overload. Strings cannot directly use non-const char[].
-     * @internal
-     */
-    template< int N1, int N2 >
-    OUString replaceAll( const char (&from)[ N1 ], char (&to)[ N2 ] ) const
-#ifndef RTL_STRING_UNITTEST
-        ; // intentionally not implemented
-#else
-    {
-        (void) from; // unused
-        (void) to; // unused
-        rtl_uString_newFromLiteral( &const_cast<OUString*>(this)->pData, "!!br0ken!!", 10 ); // set to garbage
-        return *this;
-    }
-#endif
-
-    /**
       Converts from this string all ASCII uppercase characters (65-90)
       to ASCII lowercase characters (97-122).
 
diff --git a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
index 930b038..462385e 100644
--- a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
@@ -29,6 +29,7 @@
 // activate the extra needed ctor
 #define RTL_STRING_UNITTEST
 bool rtl_string_unittest_const_literal;
+bool rtl_string_unittest_invalid_conversion;
 bool rtl_string_unittest_const_literal_function;
 bool rtl_string_unittest_non_const_literal_function;
 
diff --git a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
index fb0e21e..2783571 100644
--- a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
@@ -29,6 +29,7 @@
 // activate the extra needed ctor
 #define RTL_STRING_UNITTEST
 extern bool rtl_string_unittest_const_literal;
+extern bool rtl_string_unittest_invalid_conversion;
 extern bool rtl_string_unittest_const_literal_function;
 extern bool rtl_string_unittest_non_const_literal_function;
 
@@ -54,9 +55,6 @@ private:
     void checkBuffer();
 
     void testcall( const char str[] );
-    // invalid conversions will trigger templated OUString ctor that creates an empty string
-    // (see RTL_STRING_UNITTEST)
-    bool validConversion( const rtl::OUString& str ) { return str != "!!br0ken!!"; }
 
 CPPUNIT_TEST_SUITE(StringLiterals);
 CPPUNIT_TEST(checkCtors);
@@ -67,29 +65,37 @@ CPPUNIT_TEST(checkBuffer);
 CPPUNIT_TEST_SUITE_END();
 };
 
+// reset the flag, evaluate the expression and return
+// whether the string literal ctor was used (i.e. whether the conversion was valid)
+#define VALID_CONVERSION( expression ) \
+    ( \
+    rtl_string_unittest_invalid_conversion = false, \
+    ( void ) ( expression ), \
+    !rtl_string_unittest_invalid_conversion )
+
 void test::oustring::StringLiterals::checkCtors()
 {
-    CPPUNIT_ASSERT( validConversion( rtl::OUString( "test" )));
+    CPPUNIT_ASSERT( VALID_CONVERSION( rtl::OUString( "test" )));
     const char good1[] = "test";
-    CPPUNIT_ASSERT( validConversion( rtl::OUString( good1 )));
+    CPPUNIT_ASSERT( VALID_CONVERSION( rtl::OUString( good1 )));
 
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( (const char*) "test" )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( (const char*) "test" )));
     const char* bad1 = good1;
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad1 )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( bad1 )));
     char bad2[] = "test";
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad2 )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( bad2 )));
     char* bad3 = bad2;
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad3 )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( bad3 )));
     const char* bad4[] = { "test1" };
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad4[ 0 ] )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( bad4[ 0 ] )));
     testcall( good1 );
 
 // This one is technically broken, since the first element is 6 characters test\0\0,
 // but there does not appear a way to detect this by compile time (runtime will complain).
 // RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
     const char bad5[][ 6 ] = { "test", "test2" };
-//    CPPUNIT_ASSERT( validConversion( rtl::OUString( bad5[ 0 ] )));
-    CPPUNIT_ASSERT( validConversion( rtl::OUString( bad5[ 1 ] )));
+//    CPPUNIT_ASSERT( VALID_CONVERSION( rtl::OUString( bad5[ 0 ] )));
+    CPPUNIT_ASSERT( VALID_CONVERSION( rtl::OUString( bad5[ 1 ] )));
 
 // Check that contents are correct and equal to the case when RTL_CONSTASCII_USTRINGPARAM is used.
 // Also check that embedded \0 is included.
@@ -101,7 +107,7 @@ void test::oustring::StringLiterals::checkCtors()
 
 void test::oustring::StringLiterals::testcall( const char str[] )
 {
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( str )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( str )));
 }
 
 void test::oustring::StringLiterals::checkUsage()
@@ -159,9 +165,9 @@ void test::oustring::StringLiterals::checkNonconstChar()
     char bar[] = "bar";
     const char consttest[] = "test";
     const char constbar[] = "bar";
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( "footest" ).replaceAll( test, bar )));
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( "footest" ).replaceAll( consttest, bar )));
-    CPPUNIT_ASSERT( !validConversion( rtl::OUString( "footest" ).replaceAll( test, constbar )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( "footest" ).replaceAll( test, bar )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( "footest" ).replaceAll( consttest, bar )));
+    CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( "footest" ).replaceAll( test, constbar )));
     CPPUNIT_ASSERT( rtl::OUString( "foobar" ) == rtl::OUString( "footest" ).replaceAll( consttest, constbar ));
 }
 
commit 81e7364f52b6135776d4999be287524d508a7d08
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Mar 28 21:33:11 2012 +0200

    move string helper types to stringutils.hxx

diff --git a/sal/Package_inc.mk b/sal/Package_inc.mk
index 3ac23bc..5350faf 100644
--- a/sal/Package_inc.mk
+++ b/sal/Package_inc.mk
@@ -92,6 +92,7 @@ $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/strbuf.h,rtl/strbuf.h))
 $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/strbuf.hxx,rtl/strbuf.hxx))
 $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/string.h,rtl/string.h))
 $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/string.hxx,rtl/string.hxx))
+$(eval $(call gb_Package_add_file,sal_inc,inc/rtl/stringutils.hxx,rtl/stringutils.hxx))
 $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/tencinfo.h,rtl/tencinfo.h))
 $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/textcvt.h,rtl/textcvt.h))
 $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/textenc.h,rtl/textenc.h))
diff --git a/sal/inc/rtl/oustringostreaminserter.hxx b/sal/inc/rtl/oustringostreaminserter.hxx
index 579ffa0..632bc23 100644
--- a/sal/inc/rtl/oustringostreaminserter.hxx
+++ b/sal/inc/rtl/oustringostreaminserter.hxx
@@ -42,8 +42,21 @@
     @since LibreOffice 3.5.
 */
 
+// The unittest uses slightly different code to help check that the proper
+// calls are made. The class is put into a different namespace to make
+// sure the compiler generates a different (if generating also non-inline)
+// copy of the function and does not merge them together. The class
+// is "brought" into the proper rtl namespace by a typedef below.
+#ifdef RTL_STRING_UNITTEST
+#define rtl rtlunittest
+#endif
+
 namespace rtl {
 
+#ifdef RTL_STRING_UNITTEST
+#undef rtl
+#endif
+
 template< typename charT, typename traits > std::basic_ostream<charT, traits> &
 operator <<(
     std::basic_ostream<charT, traits> & stream, rtl::OUString const & string)
diff --git a/sal/inc/rtl/strbuf.hxx b/sal/inc/rtl/strbuf.hxx
index a92ea1d..62250f3 100644
--- a/sal/inc/rtl/strbuf.hxx
+++ b/sal/inc/rtl/strbuf.hxx
@@ -35,12 +35,30 @@
 
 #include <rtl/strbuf.h>
 #include <rtl/string.hxx>
+#include <rtl/stringutils.hxx>
 
 #ifdef __cplusplus
 
+// The unittest uses slightly different code to help check that the proper
+// calls are made. The class is put into a different namespace to make
+// sure the compiler generates a different (if generating also non-inline)
+// copy of the function and does not merge them together. The class
+// is "brought" into the proper rtl namespace by a typedef below.
+#ifdef RTL_STRING_UNITTEST
+#define rtl rtlunittest
+#endif
+
 namespace rtl
 {
 
+#ifdef RTL_STRING_UNITTEST
+#undef rtl
+// helper macro to make functions appear more readable
+#define RTL_STRING_CONST_FUNCTION rtl_string_unittest_const_literal_function = true;
+#else
+#define RTL_STRING_CONST_FUNCTION
+#endif
+
 /** A string buffer implements a mutable sequence of characters.
     <p>
     String buffers are safe for use by multiple threads. The methods
@@ -715,6 +733,14 @@ private:
 
 }
 
+#ifdef RTL_STRING_UNITTEST
+namespace rtl
+{
+typedef rtlunittest::OStringBuffer OStringBuffer;
+}
+#undef RTL_STRING_CONST_FUNCTION
+#endif
+
 #endif  /* __cplusplus */
 #endif  /* _RTL_STRBUF_HXX_ */
 
diff --git a/sal/inc/rtl/string.hxx b/sal/inc/rtl/string.hxx
index 68f41bd..72af04e 100644
--- a/sal/inc/rtl/string.hxx
+++ b/sal/inc/rtl/string.hxx
@@ -37,6 +37,8 @@
 #include <rtl/memory.h>
 #include <rtl/textenc.h>
 #include <rtl/string.h>
+#include <rtl/stringutils.hxx>
+
 #include "sal/log.hxx"
 
 #if !defined EXCEPTIONS_OFF
@@ -89,65 +91,6 @@ namespace rtl
   use this class.
 */
 
-namespace internal
-{
-/*
-These templates use SFINAE (Substitution failure is not an error) to help distinguish the various
-plain C string types: char*, const char*, char[N] and const char[N]. There are 2 cases:
-1) Only string literal (i.e. const char[N]) is wanted, not any of the others.
-    In this case it is necessary to distinguish between const char[N] and char[N], as the latter
-    would be automatically converted to the const variant, which is not wanted (not a string literal
-    with known size of the content). In this case ConstCharArrayDetector is used to ensure the function
-    is called only with const char[N] arguments. There's no other plain C string type overload.
-2) All plain C string types are wanted, and const char[N] needs to be handled differently.
-    In this case const char[N] would match const char* argument type (not exactly sure why, but it's
-    consistent in all of gcc, clang and msvc). Using a template with a reference to const of the type
-    avoids this problem, and CharPtrDetector ensures that the function is called only with char pointer
-    arguments. The const in the argument is necessary to handle the case when something is explicitly
-    cast to const char*. Additionally (non-const) char[N] needs to be handled, but with the reference
-    being const, it would also match const char[N], so another overload with a reference to non-const
-    and NonConstCharArrayDetector are used to ensure the function is called only with (non-const) char[N].
-*/
-struct Dummy {};
-template< typename T1, typename T2 >
-struct CharPtrDetector
-{
-};
-template< typename T >
-struct CharPtrDetector< const char*, T >
-{
-    typedef T Type;
-};
-template< typename T >
-struct CharPtrDetector< char*, T >
-{
-    typedef T Type;
-};
-
-template< typename T1, typename T2 >
-struct NonConstCharArrayDetector
-{
-};
-template< typename T, int N >
-struct NonConstCharArrayDetector< char[ N ], T >
-{
-    typedef T Type;
-};
-// This is similar, only it helps to detect const char[]. Without using a template,
-// (non-const) char[] would be automatically converted to const char[], which is unwanted
-// here (size of the content is not known).
-template< typename T1, typename T2 >
-struct ConstCharArrayDetector
-{
-};
-template< int N, typename T >
-struct ConstCharArrayDetector< const char[ N ], T >
-{
-    typedef T Type;
-    static const int size = N;
-};
-}
-
 class OString
 {
 public:
@@ -1486,6 +1429,19 @@ public:
 
 /* ======================================================================= */
 
+} /* Namespace */
+
+#ifdef RTL_STRING_UNITTEST
+namespace rtl
+{
+typedef rtlunittest::OString OString;
+}
+#undef RTL_STRING_CONST_FUNCTION
+#endif
+
+namespace rtl
+{
+
 /** A helper to use OStrings with hash maps.
 
     Instances of this class are unary function objects that can be used as
@@ -1510,13 +1466,6 @@ struct OStringHash
 
 } /* Namespace */
 
-#ifdef RTL_STRING_UNITTEST
-namespace rtl
-{
-typedef rtlunittest::OString OString;
-}
-#endif
-
 #endif /* _RTL_STRING_HXX_ */
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/inc/rtl/stringutils.hxx b/sal/inc/rtl/stringutils.hxx
new file mode 100644
index 0000000..866bf23
--- /dev/null
+++ b/sal/inc/rtl/stringutils.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * [ Copyright (C) 2012 Lubos Lunak <l.lunak at suse.cz> (initial developer) ]
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#ifndef _RTL_STRINGUTILS_HXX_
+#define _RTL_STRINGUTILS_HXX_
+
+#include "sal/config.h"
+
+// The unittest uses slightly different code to help check that the proper
+// calls are made. The class is put into a different namespace to make
+// sure the compiler generates a different (if generating also non-inline)
+// copy of the function and does not merge them together. The class
+// is "brought" into the proper rtl namespace by a typedef below.
+#ifdef RTL_STRING_UNITTEST
+#define rtl rtlunittest
+#endif
+
+namespace rtl
+{
+
+#ifdef RTL_STRING_UNITTEST
+#undef rtl
+#endif
+namespace internal
+{
+/*
+These templates use SFINAE (Substitution failure is not an error) to help distinguish the various
+plain C string types: char*, const char*, char[N] and const char[N]. There are 2 cases:
+1) Only string literal (i.e. const char[N]) is wanted, not any of the others.
+    In this case it is necessary to distinguish between const char[N] and char[N], as the latter
+    would be automatically converted to the const variant, which is not wanted (not a string literal
+    with known size of the content). In this case ConstCharArrayDetector is used to ensure the function
+    is called only with const char[N] arguments. There's no other plain C string type overload.
+2) All plain C string types are wanted, and const char[N] needs to be handled differently.
+    In this case const char[N] would match const char* argument type (not exactly sure why, but it's
+    consistent in all of gcc, clang and msvc). Using a template with a reference to const of the type
+    avoids this problem, and CharPtrDetector ensures that the function is called only with char pointer
+    arguments. The const in the argument is necessary to handle the case when something is explicitly
+    cast to const char*. Additionally (non-const) char[N] needs to be handled, but with the reference
+    being const, it would also match const char[N], so another overload with a reference to non-const
+    and NonConstCharArrayDetector are used to ensure the function is called only with (non-const) char[N].
+*/
+struct Dummy {};
+template< typename T1, typename T2 >
+struct CharPtrDetector
+{
+};
+template< typename T >
+struct CharPtrDetector< const char*, T >
+{
+    typedef T Type;
+};
+template< typename T >
+struct CharPtrDetector< char*, T >
+{
+    typedef T Type;
+};
+
+template< typename T1, typename T2 >
+struct NonConstCharArrayDetector
+{
+};
+template< typename T, int N >
+struct NonConstCharArrayDetector< char[ N ], T >
+{
+    typedef T Type;
+};
+
+template< typename T1, typename T2 >
+struct ConstCharArrayDetector
+{
+};
+template< int N, typename T >
+struct ConstCharArrayDetector< const char[ N ], T >
+{
+    typedef T Type;
+    static const int size = N;
+};
+}
+
+} /* Namespace */
+
+#endif /* _RTL_STRINGUTILS_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/inc/rtl/ustrbuf.hxx b/sal/inc/rtl/ustrbuf.hxx
index adb1761..15bbe67 100644
--- a/sal/inc/rtl/ustrbuf.hxx
+++ b/sal/inc/rtl/ustrbuf.hxx
@@ -36,10 +36,28 @@
 #include <osl/diagnose.h>
 #include <rtl/ustrbuf.h>
 #include <rtl/ustring.hxx>
+#include <rtl/stringutils.hxx>
+
+// The unittest uses slightly different code to help check that the proper
+// calls are made. The class is put into a different namespace to make
+// sure the compiler generates a different (if generating also non-inline)
+// copy of the function and does not merge them together. The class
+// is "brought" into the proper rtl namespace by a typedef below.
+#ifdef RTL_STRING_UNITTEST
+#define rtl rtlunittest
+#endif
 
 namespace rtl
 {
 
+#ifdef RTL_STRING_UNITTEST
+#undef rtl
+// helper macro to make functions appear more readable
+#define RTL_STRING_CONST_FUNCTION rtl_string_unittest_const_literal_function = true;
+#else
+#define RTL_STRING_CONST_FUNCTION
+#endif
+
 /** A string buffer implements a mutable sequence of characters.
     <p>
     String buffers are safe for use by multiple threads. The methods
@@ -866,6 +884,14 @@ private:
 
 }
 
+#ifdef RTL_STRING_UNITTEST
+namespace rtl
+{
+typedef rtlunittest::OUStringBuffer OUStringBuffer;
+}
+#undef RTL_STRING_CONST_FUNCTION
+#endif
+
 #endif  /* _RTL_USTRBUF_HXX_ */
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx
index ef47be6..dadef0f 100644
--- a/sal/inc/rtl/ustring.hxx
+++ b/sal/inc/rtl/ustring.hxx
@@ -36,6 +36,7 @@
 #include "osl/diagnose.h"
 #include <rtl/ustring.h>
 #include <rtl/string.hxx>
+#include <rtl/stringutils.hxx>
 #include <rtl/memory.h>
 #include "sal/log.hxx"
 
@@ -45,8 +46,26 @@
 #include <new>
 #endif
 
+// The unittest uses slightly different code to help check that the proper
+// calls are made. The class is put into a different namespace to make
+// sure the compiler generates a different (if generating also non-inline)
+// copy of the function and does not merge them together. The class
+// is "brought" into the proper rtl namespace by a typedef below.
+#ifdef RTL_STRING_UNITTEST
+#define rtl rtlunittest
+#endif
+
 namespace rtl
 {
+
+#ifdef RTL_STRING_UNITTEST
+#undef rtl
+// helper macro to make functions appear more readable
+#define RTL_STRING_CONST_FUNCTION rtl_string_unittest_const_literal_function = true;
+#else
+#define RTL_STRING_CONST_FUNCTION
+#endif
+
 /* ======================================================================= */
 
 /**
@@ -897,7 +916,7 @@ public:
 
       @since LibreOffice 3.6
     */
-    bool endsWith(rtl::OUString const & str) const {
+    bool endsWith(OUString const & str) const {
         return str.getLength() <= getLength()
             && match(str, getLength() - str.getLength());
     }
@@ -1485,7 +1504,7 @@ public:
       @since LibreOffice 3.6
     */
     template< int N >
-    OUString replaceFirst( const char (&from)[ N ], rtl::OUString const & to,
+    OUString replaceFirst( const char (&from)[ N ], OUString const & to,
                            sal_Int32 * index = 0) const
     {
         rtl_uString * s = 0;
@@ -1500,7 +1519,7 @@ public:
      * @internal
      */
     template< int N >
-    OUString replaceFirst( char (&literal)[ N ], rtl::OUString const & to,
+    OUString replaceFirst( char (&literal)[ N ], OUString const & to,
                            sal_Int32 * index = 0) const;
 
     /**
@@ -2133,6 +2152,19 @@ public:
 
 /* ======================================================================= */
 
+} /* Namespace */
+
+#ifdef RTL_STRING_UNITTEST
+namespace rtl
+{
+typedef rtlunittest::OUString OUString;
+}
+#undef RTL_STRING_CONST_FUNCTION
+#endif
+
+namespace rtl
+{
+
 /** A helper to use OUStrings with hash maps.
 
     Instances of this class are unary function objects that can be used as
@@ -2149,7 +2181,7 @@ struct OUStringHash
         a hash code for the string.  This hash code should not be stored
         persistently, as its computation may change in later revisions.
      */
-    size_t operator()(const rtl::OUString& rString) const
+    size_t operator()(const OUString& rString) const
         { return (size_t)rString.hashCode(); }
 };
 


More information about the Libreoffice-commits mailing list