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.lu...@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.lu...@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.lu...@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.lu...@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.lu...@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.lu...@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.lu...@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.lu...@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.lu...@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(); } };
_______________________________________________ Libreoffice-commits mailing list Libreoffice-commits@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits