summaryrefslogtreecommitdiffstats
path: root/sal/qa/rtl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'sal/qa/rtl/strings')
-rw-r--r--sal/qa/rtl/strings/compile-oustring.cxx45
-rw-r--r--sal/qa/rtl/strings/nonconstarray.cxx94
-rw-r--r--sal/qa/rtl/strings/test_ostring.cxx123
-rw-r--r--sal/qa/rtl/strings/test_ostring_concat.cxx206
-rw-r--r--sal/qa/rtl/strings/test_ostring_stringliterals.cxx282
-rw-r--r--sal/qa/rtl/strings/test_ostringbuffer.cxx56
-rw-r--r--sal/qa/rtl/strings/test_oustring_compare.cxx97
-rw-r--r--sal/qa/rtl/strings/test_oustring_concat.cxx213
-rw-r--r--sal/qa/rtl/strings/test_oustring_convert.cxx177
-rw-r--r--sal/qa/rtl/strings/test_oustring_endswith.cxx113
-rw-r--r--sal/qa/rtl/strings/test_oustring_startswith.cxx38
-rw-r--r--sal/qa/rtl/strings/test_oustring_stringliterals.cxx432
-rw-r--r--sal/qa/rtl/strings/test_strings_defaultstringview.cxx118
-rw-r--r--sal/qa/rtl/strings/test_strings_replace.cxx339
-rw-r--r--sal/qa/rtl/strings/test_strings_toint.cxx72
-rw-r--r--sal/qa/rtl/strings/test_strings_valuex.cxx115
16 files changed, 2520 insertions, 0 deletions
diff --git a/sal/qa/rtl/strings/compile-oustring.cxx b/sal/qa/rtl/strings/compile-oustring.cxx
new file mode 100644
index 000000000..667a52324
--- /dev/null
+++ b/sal/qa/rtl/strings/compile-oustring.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <rtl/string.h>
+#include <rtl/ustring.hxx>
+
+// expected-note@rtl/ustring.hxx:* 1+ {{}}
+
+void checkExtraIntArgument()
+{
+ // This makes sure that using by mistake RTL_CONSTASCII_STRINGPARAM does not trigger a different
+ // overload, i.e. the second argument to match() in this case is the indexFrom argument,
+ // but with the macro it would contain the length of the string. Therefore
+ // match( RTL_CONSTASCII_STRINGPARAM( "bar" )) would be match( "bar", 3 ), which would be
+ // true when called for OUString( "foobar" ). But this should not happen because of the
+ // &foo[0] trick in the RTL_CONSTASCII_STRINGPARAM macro.
+ // expected-error@+1 {{}}
+ OUString("foobar").match(RTL_CONSTASCII_STRINGPARAM("bar"));
+}
+
+void checkNonconstChar()
+{
+ // check that non-const char[] data do not trigger string literal overloads
+ char test[] = "test";
+ char bar[] = "bar";
+ const char consttest[] = "test";
+ const char constbar[] = "bar";
+ // expected-error@+1 {{}}
+ (void)OUString("footest").replaceAll(test, bar);
+ // expected-error@+1 {{}}
+ (void)OUString("footest").replaceAll(consttest, bar);
+ // expected-error@+1 {{}}
+ (void)OUString("footest").replaceAll(test, constbar);
+ (void)OUString("footest").replaceAll(consttest, constbar);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sal/qa/rtl/strings/nonconstarray.cxx b/sal/qa/rtl/strings/nonconstarray.cxx
new file mode 100644
index 000000000..4b66e4e31
--- /dev/null
+++ b/sal/qa/rtl/strings/nonconstarray.cxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+
+namespace
+{
+class Test : public CppUnit::TestFixture
+{
+private:
+ void testOString()
+ {
+ struct S
+ {
+ char a[4];
+ };
+ S s{ "x\0y" };
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OString(s.a).getLength());
+ // Ideally, the below would work the same as the above. However, the const reference makes
+ // the ConstCharArrayDetector instead of the NonConstCharArrayDetector kick in, so that the
+ // call to OString(r.a) would fire the ConstCharArrayDetector<T>::isValid assert (and in
+ // NDEBUG builds the CPPUNIT_ASSERT_EQUAL would fail with 3 != 1):
+ if ((false))
+ {
+ S const& r = s;
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OString(r.a).getLength());
+ }
+ }
+
+ void testOUStringChar()
+ {
+ struct S
+ {
+ char a[4];
+ };
+ S s{ "x\0y" };
+ // This would fail to compile, as there is no OUString ctor taking a
+ // NonConstCharArrayDetector char array:
+#if 0
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(s.a).getLength());
+#endif
+ // Ideally, the below would fail to compile the same as the above. However, the const
+ // reference makes the ConstCharArrayDetector instead of the NonConstCharArrayDetector kick
+ // in, so that the call to OUString(r.a) would fire the ConstCharArrayDetector<T>::isValid
+ // assert (and in NDEBUG builds the CPPUNIT_ASSERT_EQUAL would fail with 3 != 1):
+ if ((false))
+ {
+ S const& r = s;
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(r.a).getLength());
+ }
+ }
+
+ void testOUStringChar16t()
+ {
+ struct S
+ {
+ char16_t a[4];
+ };
+ S s{ u"x\0y" };
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(s.a).getLength());
+ // Ideally, the below would work the same as the above. However, the const reference makes
+ // the ConstCharArrayDetector instead of the NonConstCharArrayDetector kick in, so that the
+ // call to OUString(r.a) would fire the ConstCharArrayDetector<T>::isValid assert (and in
+ // NDEBUG builds the CPPUNIT_ASSERT_EQUAL would fail with 3 != 1)::
+ if ((false))
+ {
+ S const& r = s;
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(r.a).getLength());
+ }
+ }
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testOString);
+ CPPUNIT_TEST(testOUStringChar);
+ CPPUNIT_TEST(testOUStringChar16t);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sal/qa/rtl/strings/test_ostring.cxx b/sal/qa/rtl/strings/test_ostring.cxx
new file mode 100644
index 000000000..b4fb201ca
--- /dev/null
+++ b/sal/qa/rtl/strings/test_ostring.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/string.hxx>
+
+namespace {
+
+class Test: public CppUnit::TestFixture {
+private:
+ void testStartsWithIgnoreAsciiCase();
+ void testCompareTo();
+ void testUtf8StringLiterals();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testStartsWithIgnoreAsciiCase);
+ CPPUNIT_TEST(testCompareTo);
+ CPPUNIT_TEST(testUtf8StringLiterals);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testStartsWithIgnoreAsciiCase() {
+ {
+ OString r;
+ CPPUNIT_ASSERT(OString().startsWithIgnoreAsciiCase(std::string_view(), &r));
+ CPPUNIT_ASSERT(r.isEmpty());
+ }
+ {
+ OString r;
+ CPPUNIT_ASSERT(OString("foo").startsWithIgnoreAsciiCase(std::string_view(), &r));
+ CPPUNIT_ASSERT_EQUAL(OString("foo"), r);
+ }
+ {
+ OString r;
+ CPPUNIT_ASSERT(
+ OString("foo").startsWithIgnoreAsciiCase("F", &r));
+ CPPUNIT_ASSERT_EQUAL(OString("oo"), r);
+ }
+ {
+ OString r("other");
+ CPPUNIT_ASSERT(
+ !OString("foo").startsWithIgnoreAsciiCase("bar", &r));
+ CPPUNIT_ASSERT_EQUAL(OString("other"), r);
+ }
+ {
+ OString r("other");
+ CPPUNIT_ASSERT(
+ !OString("foo").startsWithIgnoreAsciiCase("foobar", &r));
+ CPPUNIT_ASSERT_EQUAL(OString("other"), r);
+ }
+
+ {
+ OString r;
+ CPPUNIT_ASSERT(OString().startsWithIgnoreAsciiCase("", &r));
+ CPPUNIT_ASSERT(r.isEmpty());
+ }
+ {
+ OString r;
+ CPPUNIT_ASSERT(OString("foo").startsWithIgnoreAsciiCase("", &r));
+ CPPUNIT_ASSERT_EQUAL(OString("foo"), r);
+ }
+ {
+ OString r;
+ CPPUNIT_ASSERT(
+ OString("foo").startsWithIgnoreAsciiCase("F", &r));
+ CPPUNIT_ASSERT_EQUAL(OString("oo"), r);
+ }
+ {
+ OString r("other");
+ CPPUNIT_ASSERT(
+ !OString("foo").startsWithIgnoreAsciiCase("bar", &r));
+ CPPUNIT_ASSERT_EQUAL(OString("other"), r);
+ }
+ {
+ OString r("other");
+ CPPUNIT_ASSERT(
+ !OString("foo").startsWithIgnoreAsciiCase("foobar", &r));
+ CPPUNIT_ASSERT_EQUAL(OString("other"), r);
+ }
+}
+
+void Test::testCompareTo()
+{
+ // test that embedded NUL does not stop the compare
+ char str1[2] = { '\0', 'x' };
+ char str2[2] = { '\0', 'y' };
+
+ OString s1(str1, 2);
+ OString s2(str2, 2);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s1.compareTo(s1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s2.compareTo(s2));
+ CPPUNIT_ASSERT(s1.compareTo(s2) < 0);
+ CPPUNIT_ASSERT(s2.compareTo(s1) > 0);
+ CPPUNIT_ASSERT(s1.compareTo(OString(s2 + "y")) < 0);
+ CPPUNIT_ASSERT(s2.compareTo(OString(s1 + "x")) > 0);
+ CPPUNIT_ASSERT(OString(s1 + "x").compareTo(s2) < 0);
+ CPPUNIT_ASSERT(OString(s2 + "y").compareTo(s1) > 0);
+}
+
+void Test::testUtf8StringLiterals()
+{
+ const OString sIn(u8"ßa");
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), sIn.getLength());
+ CPPUNIT_ASSERT_EQUAL(195, int(static_cast<unsigned char>(sIn[0])));
+ CPPUNIT_ASSERT_EQUAL(159, int(static_cast<unsigned char>(sIn[1])));
+ CPPUNIT_ASSERT_EQUAL(97, int(static_cast<unsigned char>(sIn[2])));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_ostring_concat.cxx b/sal/qa/rtl/strings/test_ostring_concat.cxx
new file mode 100644
index 000000000..853f97564
--- /dev/null
+++ b/sal/qa/rtl/strings/test_ostring_concat.cxx
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// activate support for detecting errors instead of getting compile errors
+#define RTL_STRING_UNITTEST_CONCAT
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <rtl/string.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <string>
+#include <typeinfo>
+
+bool rtl_string_unittest_invalid_concat = false;
+
+using namespace rtl;
+
+namespace CppUnit
+{
+template<> struct assertion_traits<std::type_info>
+{
+ static bool equal(std::type_info const & x, std::type_info const & y) { return x == y; }
+
+ static std::string toString(std::type_info const & x) { return x.name(); }
+};
+} // namespace
+
+namespace test::ostring {
+
+class StringConcat : public CppUnit::TestFixture
+{
+private:
+ void checkConcat();
+ void checkEnsureCapacity();
+ void checkAppend();
+ void checkInvalid();
+
+CPPUNIT_TEST_SUITE(StringConcat);
+CPPUNIT_TEST(checkConcat);
+CPPUNIT_TEST(checkEnsureCapacity);
+CPPUNIT_TEST(checkAppend);
+CPPUNIT_TEST(checkInvalid);
+CPPUNIT_TEST_SUITE_END();
+};
+
+void test::ostring::StringConcat::checkConcat()
+{
+// All the extra () are to protect commas against being treated as separators of macro arguments.
+ CPPUNIT_ASSERT_EQUAL( OString(), OString(OString() + OString()));
+ CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OString( "foo" ) + OString( "bar" )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OString > )), typeid( OString( "foo" ) + OString( "bar" )));
+ CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OString( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, const char[ 4 ] > )), typeid( OString( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OString( "foobarbaz" ), OString( OString( "foo" ) + "bar" + "baz" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OString, const char[ 4 ] >, const char[ 4 ] > )), typeid( OString( "foo" ) + "bar" + "baz" ));
+ CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringBuffer( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringBuffer, const char[ 4 ] > )), typeid( OStringBuffer( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringLiteral( "foo" ) + "bar" ));
+#if defined __GNUC__ && __GNUC__ <= 11 && !defined __clang__
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char[ 4 ] > )), typeid( OStringLiteral<4>( "foo" ) + "bar" ));
+ // the explicit OStringLiteral<4> template argument in the unevaluated typeid context
+ // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878>
+ // "Failed class template argument deduction in unevaluated, parenthesized context"
+#else
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char[ 4 ] > )), typeid( OStringLiteral( "foo" ) + "bar" ));
+#endif
+ CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringLiteral( "foo" ) + static_cast<const char*>("bar") ));
+#if defined __GNUC__ && __GNUC__ <= 11 && !defined __clang__
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char* > )), typeid( OStringLiteral<4>( "foo" ) + static_cast<const char*>("bar") ));
+ // the explicit OStringLiteral<4> template argument in the unevaluated typeid context
+ // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878>
+ // "Failed class template argument deduction in unevaluated, parenthesized context"
+#else
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char* > )), typeid( OStringLiteral( "foo" ) + static_cast<const char*>("bar") ));
+#endif
+ const char d1[] = "xyz";
+ char d2[] = "abc";
+ const char* d3 = d1;
+ char* d4 = d2;
+ CPPUNIT_ASSERT_EQUAL( OString( "fooxyz" ), OString( OString( "foo" ) + d1 ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, const char[ 4 ] > )), typeid( OString( "foo" ) + d1 ));
+ CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d2 ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char[ 4 ] > )), typeid( OString( "foo" ) + d2 ));
+ CPPUNIT_ASSERT_EQUAL( OString( "fooxyz" ), OString( OString( "foo" ) + d3 ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, const char* > )), typeid( OString( "foo" ) + d3 ));
+ CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d4 ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char* > )), typeid( OString( "foo" ) + d4 ));
+ CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d4 ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char* > )), typeid( OString( "foo" ) + d4 ));
+ CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OString::Concat( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OString::Concat( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OString( "xyzbar" ), OString( OString::Concat( d1 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OString::Concat( d1 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OString( "abcbar" ), OString( OString::Concat( d2 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, char[ 4 ] >, const char[ 4 ] > )), typeid( OString::Concat( d2 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OString( "xyzbar" ), OString( OString::Concat( d3 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, const char* >, const char[ 4 ] > )), typeid( OString::Concat( d3 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OString( "abcbar" ), OString( OString::Concat( d4 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, char* >, const char[ 4 ] > )), typeid( OString::Concat( d4 ) + "bar" ));
+
+ CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10 )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< int > > )), typeid( OString( "num" ) + OString::number( 10 )));
+ CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10L )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< long long > > )), typeid( OString( "num" ) + OString::number( 10L )));
+ CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10ULL )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< unsigned long long > > )), typeid( OString( "num" ) + OString::number( 10ULL )));
+ CPPUNIT_ASSERT_EQUAL( OString( "num10.5" ), OString( OString( "num" ) + OString::number( 10.5f )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< float > > )), typeid( OString( "num" ) + OString::number( 10.5f )));
+ CPPUNIT_ASSERT_EQUAL( OString( "num10.5" ), OString( OString( "num" ) + OString::number( 10.5 )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< double > > )), typeid( OString( "num" ) + OString::number( 10.5 )));
+}
+
+void test::ostring::StringConcat::checkEnsureCapacity()
+{
+ rtl_String* str = nullptr;
+ rtl_string_newFromLiteral( &str, "test", strlen( "test" ), 0 );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+
+ rtl_String* oldStr = str;
+ rtl_string_ensureCapacity( &str, 4 ); // should be no-op
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+ CPPUNIT_ASSERT_EQUAL( str, oldStr );
+
+ rtl_string_acquire( oldStr );
+ CPPUNIT_ASSERT_EQUAL( 2, int( str->refCount ));
+ rtl_string_ensureCapacity( &str, 4 );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+ // a copy was forced because of refcount
+ CPPUNIT_ASSERT( oldStr != str );
+ CPPUNIT_ASSERT_EQUAL( 0, strcmp( oldStr->buffer, str->buffer ) );
+ CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount ));
+ rtl_string_release( str );
+ str = oldStr;
+
+ rtl_string_acquire( oldStr );
+ rtl_string_ensureCapacity( &str, 1024 );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); // size is still 4
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+ CPPUNIT_ASSERT( oldStr != str );
+ CPPUNIT_ASSERT_EQUAL( 0, strcmp( oldStr->buffer, str->buffer ) );
+ CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount ));
+ strcpy( str->buffer, "01234567890123456789" ); // but there should be extra capacity
+ str->length += 20;
+ rtl_string_release( str );
+ rtl_string_release( oldStr );
+}
+
+void test::ostring::StringConcat::checkAppend()
+{
+ OString str( "foo" );
+ str += OStringLiteral( "bar" ) + "baz";
+ CPPUNIT_ASSERT_EQUAL( OString( "foobarbaz" ), str );
+ OStringBuffer buf( "foo" );
+ buf.append( OStringLiteral( "bar" ) + "baz" );
+ CPPUNIT_ASSERT_EQUAL( OString( "foobarbaz" ), buf.makeStringAndClear());
+}
+
+#define INVALID_CONCAT( expression ) \
+ ( \
+ rtl_string_unittest_invalid_concat = false, \
+ ( void ) OString( expression ), \
+ rtl_string_unittest_invalid_concat )
+
+void test::ostring::StringConcat::checkInvalid()
+{
+ CPPUNIT_ASSERT( !INVALID_CONCAT( OString() + OString()));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUString( "b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUStringBuffer( "b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUStringLiteral( u"b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUString::Concat( u"b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + 1 ));
+ rtl_String* rs = nullptr;
+ rtl_uString* rus = nullptr;
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs ));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus ));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUString::number( 10 )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OString::number( 0 ) + OUString::number( 10 )));
+
+#if 0
+ // Should fail to compile, to avoid use of OStringConcat lvalues that
+ // contain dangling references to temporaries:
+ auto const conc = OStringLiteral("foo") + "bar";
+ (void) OString(conc);
+#endif
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringConcat);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
new file mode 100644
index 000000000..ec0faec94
--- /dev/null
+++ b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// activate the extra needed ctor
+#define RTL_STRING_UNITTEST
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/strbuf.hxx>
+
+bool rtl_string_unittest_const_literal;
+bool rtl_string_unittest_const_literal_function;
+static bool rtl_string_unittest_non_const_literal_function;
+
+namespace test::ostring {
+
+class StringLiterals: public CppUnit::TestFixture
+{
+private:
+ void checkCtors();
+ void checkConstexprCtor();
+ void checkUsage();
+ void checkNonConstUsage();
+ void checkBuffer();
+
+ void testcall( const char str[] );
+
+ static const char bad5[];
+ static char bad6[];
+
+ // Check that OStringLiteral ctor is actually constexpr:
+ static constexpr rtlunittest::OStringLiteral dummy{"dummy"};
+
+CPPUNIT_TEST_SUITE(StringLiterals);
+CPPUNIT_TEST(checkCtors);
+CPPUNIT_TEST(checkConstexprCtor);
+CPPUNIT_TEST(checkUsage);
+CPPUNIT_TEST(checkNonConstUsage);
+CPPUNIT_TEST(checkBuffer);
+CPPUNIT_TEST_SUITE_END();
+};
+
+// reset the flag, call OString ctor with the given argument and return
+// whether the string literal ctor was used
+#define CONST_CTOR_USED( argument ) \
+ ( \
+ rtl_string_unittest_const_literal = false, \
+ ( void ) rtl::OString( argument ), \
+ result_tmp = rtl_string_unittest_const_literal, \
+ rtl_string_unittest_const_literal = false, \
+ ( void ) rtl::OStringBuffer( argument ), \
+ rtl_string_unittest_const_literal && result_tmp )
+
+void test::ostring::StringLiterals::checkCtors()
+{
+ bool result_tmp;
+ CPPUNIT_ASSERT( CONST_CTOR_USED( "test" ));
+ const char good1[] = "test";
+ CPPUNIT_ASSERT( CONST_CTOR_USED( good1 ));
+
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( static_cast<const char*>("test") ));
+ const char* bad1 = good1;
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( bad1 ));
+ char bad2[] = "test";
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( bad2 ));
+ char* bad3 = bad2;
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( bad3 ));
+ const char* bad4[] = { "test1" };
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( bad4[ 0 ] ));
+ testcall( good1 );
+#ifndef _MSC_VER
+ // this is actually not supposed to work (see discussion in stringutils.hxx),
+ // but gcc and clang somehow manage, so keep it used, just in case some other problem
+ // shows up somewhen in the future
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( bad5 )); // size is not known here
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( bad6 ));
+#endif
+
+// 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 assert()).
+// RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
+ const char bad7[][ 6 ] = { "test", "test2" };
+// CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 0 ] ));
+ CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 1 ] ));
+
+// Check that contents are correct and equal to the case when const char* ctor is used.
+ CPPUNIT_ASSERT_EQUAL( rtl::OString( "" ), rtl::OString( static_cast<const char*>("") ) );
+ CPPUNIT_ASSERT_EQUAL( rtl::OString( "ab" ), rtl::OString( static_cast<const char*>("ab") ) );
+
+// Check that contents are correct and equal to the case when RTL_CONSTASCII_STRINGPARAM is used.
+ CPPUNIT_ASSERT_EQUAL( rtl::OString( "" ), rtl::OString( RTL_CONSTASCII_STRINGPARAM( "" )) );
+ CPPUNIT_ASSERT_EQUAL( rtl::OString( "ab" ), rtl::OString( RTL_CONSTASCII_STRINGPARAM( "ab" )) );
+}
+
+const char test::ostring::StringLiterals::bad5[] = "test";
+char test::ostring::StringLiterals::bad6[] = "test";
+
+void test::ostring::StringLiterals::testcall( const char str[] )
+{
+#ifndef _MSC_VER
+ bool result_tmp;
+ CPPUNIT_ASSERT( !CONST_CTOR_USED( str ));
+#else
+ // MSVC just errors out on this for some reason, which is fine as well
+ (void)str;
+#endif
+}
+
+void test::ostring::StringLiterals::checkConstexprCtor()
+{
+#if __cplusplus >= 202002L
+ static constinit
+#endif
+ rtl::OString s(dummy);
+ CPPUNIT_ASSERT_EQUAL(oslInterlockedCount(0x40000000), s.pData->refCount);
+ // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx)
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), s.getLength());
+ CPPUNIT_ASSERT_EQUAL(rtl::OString("dummy"), s);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast<void const *>(dummy.getStr()), static_cast<void const *>(s.getStr()));
+}
+
+void test::ostring::StringLiterals::checkUsage()
+{
+// simply check that all string literal based calls work as expected
+// also check that they really use string literal overload and do not convert to OString
+ rtl::OString foo( "foo" );
+ rtl::OString FoO( "FoO" );
+ rtl::OString foobarfoo( "foobarfoo" );
+ rtl::OString foobar( "foobar" );
+ rtl::OString FooBaRfoo( "FooBaRfoo" );
+ rtl::OString FooBaR( "FooBaR" );
+ rtl::OString bar( "bar" );
+
+ rtl_string_unittest_const_literal = false; // start checking for OString conversions
+ rtl_string_unittest_non_const_literal_function = false; // and check for non-const variants
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = "foo" );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( "fOo" ));
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( foobarfoo.match( "bar", 3 ));
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( foobar.match( "foo" ));
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( "bAr", 3 ));
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( "fOo" ));
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( foobar.startsWith( "foo" ));
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( foobar.endsWith( "bar" ));
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+// rtl_string_unittest_const_literal_function = false;
+// CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" ));
+// CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( bool(foo == "foo") );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( bool("foo" == foo) );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( foo != "bar" );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT( "foo" != bar );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ rtl_string_unittest_const_literal_function = false;
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( "foo", 1 ) );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+// rtl_string_unittest_const_literal_function = false;
+// CPPUNIT_ASSERT( foobarfoo.lastIndexOf( "foo" ) == 6 );
+// CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
+ // if this is not true, some of the calls above converted to OString
+ CPPUNIT_ASSERT( !rtl_string_unittest_const_literal );
+ // if this is not true, some of the calls above used non-const variants
+ CPPUNIT_ASSERT( !rtl_string_unittest_non_const_literal_function );
+}
+
+void test::ostring::StringLiterals::checkNonConstUsage()
+{
+// check that (non-const) char[] overloads work and do not use const char[] overloads
+ rtl::OString foo( "foo" );
+ rtl::OString FoO( "FoO" );
+ rtl::OString foobarfoo( "foobarfoo" );
+ rtl::OString foobar( "foobar" );
+ rtl::OString FooBaRfoo( "FooBaRfoo" );
+ rtl::OString FooBaR( "FooBaR" );
+ rtl::OString bar( "bar" );
+ char foo_c[] = "foo";
+ char bar_c[] = "bar";
+ char fOo_c[] = "fOo";
+ char bAr_c[] = "bAr";
+
+ rtl_string_unittest_const_literal = false; // start checking for OString conversions
+ rtl_string_unittest_const_literal_function = false; // and check for const variants
+ CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = static_cast<const char*>(foo_c) );
+ CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = foo_c );
+ CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( static_cast<const char*>(fOo_c) ));
+ CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( fOo_c ));
+ CPPUNIT_ASSERT( foobarfoo.match( static_cast<const char*>(bar_c), 3 ));
+ CPPUNIT_ASSERT( foobarfoo.match( bar_c, 3 ));
+ CPPUNIT_ASSERT( foobar.match( static_cast<const char*>(foo_c) ));
+ CPPUNIT_ASSERT( foobar.match( foo_c ));
+ CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( static_cast<const char*>(bAr_c), 3 ));
+ CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( bAr_c, 3 ));
+ CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( static_cast<const char*>(fOo_c) ));
+ CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( fOo_c ));
+ CPPUNIT_ASSERT( foobar.startsWith( static_cast<const char*>(foo_c) ));
+ CPPUNIT_ASSERT( foobar.startsWith( foo_c ));
+ CPPUNIT_ASSERT( foobar.endsWith( static_cast<const char*>(bar_c) ));
+ CPPUNIT_ASSERT( foobar.endsWith( bar_c ));
+// CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( (const char*)bar_c ));
+// CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( bar_c ));
+ CPPUNIT_ASSERT( bool(foo == static_cast<const char*>(foo_c)) );
+ CPPUNIT_ASSERT( bool(foo == foo_c) );
+ CPPUNIT_ASSERT( bool(static_cast<const char*>(foo_c) == foo) );
+ CPPUNIT_ASSERT( bool(foo_c == foo) );
+ CPPUNIT_ASSERT( foo != static_cast<const char*>(bar_c) );
+ CPPUNIT_ASSERT( foo != bar_c );
+ CPPUNIT_ASSERT( static_cast<const char*>(foo_c) != bar );
+ CPPUNIT_ASSERT( foo_c != bar );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( static_cast<const char*>(foo_c), 1 ) );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( foo_c, 1 ) );
+// 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 );
+ CPPUNIT_ASSERT( !rtl_string_unittest_const_literal_function );
+}
+
+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 );
+ CPPUNIT_ASSERT_EQUAL( rtl::OString( "foo" ), buf.toString());
+ rtl_string_unittest_const_literal_function = false;
+ buf.append( "bar" );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobar" ), buf.toString());
+ rtl_string_unittest_const_literal_function = false;
+ buf.insert( 3, "baz" );
+ CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function );
+ CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobazbar" ), buf.toString());
+
+ 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( foobazbard, buf.append( d ).toString());
+ CPPUNIT_ASSERT_EQUAL( foodbazbard, buf.insert( 3, d ).toString() );
+ CPPUNIT_ASSERT( !rtl_string_unittest_const_literal );
+ CPPUNIT_ASSERT( !rtl_string_unittest_const_literal_function );
+}
+
+#undef CONST_CTOR_USED
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringLiterals);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_ostringbuffer.cxx b/sal/qa/rtl/strings/test_ostringbuffer.cxx
new file mode 100644
index 000000000..292e24310
--- /dev/null
+++ b/sal/qa/rtl/strings/test_ostringbuffer.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <rtl/strbuf.hxx>
+#include <rtl/stringutils.hxx>
+#include <sal/types.h>
+
+namespace
+{
+class Test : public CppUnit::TestFixture
+{
+private:
+ void testStringView()
+ {
+ OStringBuffer b("foobar");
+ b = std::string_view("abc").substr(
+ 0, 2); // avoid the string_view accidentally being NUL-terminated
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), b.getLength());
+ CPPUNIT_ASSERT_EQUAL('a', b.getStr()[0]);
+ CPPUNIT_ASSERT_EQUAL('b', b.getStr()[1]);
+ CPPUNIT_ASSERT_EQUAL('\0', b.getStr()[2]);
+ }
+
+ void testOStringChar()
+ {
+ OStringBuffer b("foobar");
+ b = OStringChar('a');
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), b.getLength());
+ CPPUNIT_ASSERT_EQUAL('a', b.getStr()[0]);
+ CPPUNIT_ASSERT_EQUAL('\0', b.getStr()[1]);
+ }
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testStringView);
+ CPPUNIT_TEST(testOStringChar);
+ CPPUNIT_TEST_SUITE_END();
+};
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sal/qa/rtl/strings/test_oustring_compare.cxx b/sal/qa/rtl/strings/test_oustring_compare.cxx
new file mode 100644
index 000000000..e55d4d3d9
--- /dev/null
+++ b/sal/qa/rtl/strings/test_oustring_compare.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/string.h>
+#include <rtl/ustring.hxx>
+
+namespace test::oustring {
+
+class Compare: public CppUnit::TestFixture
+{
+private:
+ void equalsIgnoreAsciiCaseAscii();
+ void compareToIgnoreAsciiCase();
+ void compareTo();
+
+CPPUNIT_TEST_SUITE(Compare);
+CPPUNIT_TEST(equalsIgnoreAsciiCaseAscii);
+CPPUNIT_TEST(compareToIgnoreAsciiCase);
+CPPUNIT_TEST(compareTo);
+CPPUNIT_TEST_SUITE_END();
+};
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::Compare);
+
+void test::oustring::Compare::equalsIgnoreAsciiCaseAscii()
+{
+ const char* const abc = "abc";
+ const char* const abcd = "abcd";
+ const char* const empty = "";
+ CPPUNIT_ASSERT(!OUString().equalsIgnoreAsciiCaseAscii(abc));
+ CPPUNIT_ASSERT(!OUString().equalsIgnoreAsciiCaseAsciiL(abc,3));
+ CPPUNIT_ASSERT(!OUString("abc").
+ equalsIgnoreAsciiCaseAscii(empty));
+ CPPUNIT_ASSERT(!OUString("abc").
+ equalsIgnoreAsciiCaseAsciiL(empty,0));
+
+ CPPUNIT_ASSERT(OUString("abc").
+ equalsIgnoreAsciiCaseAscii(abc));
+ CPPUNIT_ASSERT(!OUString("abcd").
+ equalsIgnoreAsciiCaseAscii(abc));
+ CPPUNIT_ASSERT(!OUString("abc").
+ equalsIgnoreAsciiCaseAscii(abcd));
+}
+
+void test::oustring::Compare::compareToIgnoreAsciiCase()
+{
+ CPPUNIT_ASSERT_EQUAL(
+ sal_Int32(0),
+ OUString("abc").compareToIgnoreAsciiCase(u"ABC"));
+ CPPUNIT_ASSERT(
+ OUString("ABC").compareToIgnoreAsciiCase(u"abcdef")
+ < 0);
+ CPPUNIT_ASSERT(
+ OUString("A").compareToIgnoreAsciiCase(u"_") > 0);
+}
+
+void test::oustring::Compare::compareTo()
+{
+ // test that embedded NUL does not stop the compare
+ // this sort of thing is how we assign shape ids in oox
+ sal_Unicode str1[2] = { '\0', 'x' };
+ sal_Unicode str2[2] = { '\0', 'y' };
+
+ OUString s1(str1, 2);
+ OUString s2(str2, 2);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s1.compareTo(s1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s2.compareTo(s2));
+ CPPUNIT_ASSERT(s1.compareTo(s2) < 0);
+ CPPUNIT_ASSERT(s2.compareTo(s1) > 0);
+ CPPUNIT_ASSERT(s1.compareTo(OUStringConcatenation(s2 + "y")) < 0);
+ CPPUNIT_ASSERT(s2.compareTo(OUStringConcatenation(s1 + "x")) > 0);
+ CPPUNIT_ASSERT(OUString(s1 + "x").compareTo(s2) < 0);
+ CPPUNIT_ASSERT(OUString(s2 + "y").compareTo(s1) > 0);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_oustring_concat.cxx b/sal/qa/rtl/strings/test_oustring_concat.cxx
new file mode 100644
index 000000000..5a11da892
--- /dev/null
+++ b/sal/qa/rtl/strings/test_oustring_concat.cxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// activate support for detecting errors instead of getting compile errors
+#define RTL_STRING_UNITTEST_CONCAT
+extern bool rtl_string_unittest_invalid_concat;
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/string.hxx>
+#include <rtl/strbuf.hxx>
+
+#include <string>
+#include <typeinfo>
+
+using namespace rtl;
+
+namespace CppUnit
+{
+template<> struct assertion_traits<std::type_info>
+{
+ static bool equal(std::type_info const & x, std::type_info const & y) { return x == y; }
+
+ static std::string toString(std::type_info const & x) { return x.name(); }
+};
+} // namespace
+
+namespace test::oustring {
+
+class StringConcat : public CppUnit::TestFixture
+{
+private:
+ void checkConcat();
+ void checkConcatAsciiL();
+ void checkEnsureCapacity();
+ void checkAppend();
+ void checkInvalid();
+
+CPPUNIT_TEST_SUITE(StringConcat);
+CPPUNIT_TEST(checkConcat);
+CPPUNIT_TEST(checkConcatAsciiL);
+CPPUNIT_TEST(checkEnsureCapacity);
+CPPUNIT_TEST(checkAppend);
+CPPUNIT_TEST(checkInvalid);
+CPPUNIT_TEST_SUITE_END();
+};
+
+void test::oustring::StringConcat::checkConcat()
+{
+// All the extra () are to protect commas against being treated as separators of macro arguments.
+ CPPUNIT_ASSERT_EQUAL( OUString(), OUString(OUString() + OUString()));
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString( "foo" ) + OUString( "bar" )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUString > )), typeid( OUString( "foo" ) + OUString( "bar" )));
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const char[ 4 ] > )), typeid( OUString( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobarbaz" ), OUString( OUString( "foo" ) + "bar" + "baz" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< OUString, const char[ 4 ] >, const char[ 4 ] > )), typeid( OUString( "foo" ) + "bar" + "baz" ));
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUStringBuffer( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringBuffer, const char[ 4 ] > )), typeid( OUStringBuffer( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUStringLiteral( u"foo" ) + "bar" ));
+#if defined __GNUC__ && __GNUC__ <= 11 && !defined __clang__
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringLiteral<4>, const char[ 4 ] > )), typeid( OUStringLiteral<4>( u"foo" ) + "bar" ));
+ // the explicit OUStringLiteral<4> template argument in the unevaluated typeid context
+ // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878>
+ // "Failed class template argument deduction in unevaluated, parenthesized context"
+#else
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringLiteral<4>, const char[ 4 ] > )), typeid( OUStringLiteral( u"foo" ) + "bar" ));
+#endif
+ const char d1[] = "xyz";
+ CPPUNIT_ASSERT_EQUAL( OUString( "fooxyz" ), OUString( OUString( "foo" ) + d1 ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const char[ 4 ] > )), typeid( OUString( "foo" ) + d1 ));
+ const sal_Unicode* d2 = u"xyz";
+ CPPUNIT_ASSERT_EQUAL( OUString( "fooxyz" ), OUString( OUString( "foo" ) + d2 ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const sal_Unicode* > )), typeid( OUString( "foo" ) + d2 ));
+ const sal_Unicode d3[] = u"xyz";
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString::Concat( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OUString( "xyzbar" ), OUString( OUString::Concat( d1 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( d1 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString::Concat( u"foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const sal_Unicode[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( u"foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OUString( "xyzbar" ), OUString( OUString::Concat( d2 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const sal_Unicode* >, const char[ 4 ] > )), typeid( OUString::Concat( d2 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL( OUString( "xyzbar" ), OUString( OUString::Concat( d3 ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const sal_Unicode[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( d3 ) + "bar" ));
+
+ CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10 )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< int > > )), typeid( OUString( "num" ) + OUString::number( 10 )));
+ CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10L )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< long long > > )), typeid( OUString( "num" ) + OUString::number( 10L )));
+ CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10ULL )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< unsigned long long > > )), typeid( OUString( "num" ) + OUString::number( 10ULL )));
+ CPPUNIT_ASSERT_EQUAL( OUString( "num10.5" ), OUString( OUString( "num" ) + OUString::number( 10.5f )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< float > > )), typeid( OUString( "num" ) + OUString::number( 10.5f )));
+ CPPUNIT_ASSERT_EQUAL( OUString( "num10.5" ), OUString( OUString( "num" ) + OUString::number( 10.5 )));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< double > > )), typeid( OUString( "num" ) + OUString::number( 10.5 )));
+}
+
+void test::oustring::StringConcat::checkConcatAsciiL()
+{
+ {
+ OUString s("foo");
+ s += "";
+ CPPUNIT_ASSERT_EQUAL(OUString("foo"), s);
+ }
+ {
+ OUString s("foo");
+ s += "bar";
+ CPPUNIT_ASSERT_EQUAL(OUString("foobar"), s);
+ }
+}
+
+void test::oustring::StringConcat::checkEnsureCapacity()
+{
+ rtl_uString* str = nullptr;
+ rtl_uString_newFromLiteral( &str, "test", strlen( "test" ), 0 );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+
+ rtl_uString* oldStr = str;
+ rtl_uString_ensureCapacity( &str, 4 ); // should be no-op
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+ CPPUNIT_ASSERT_EQUAL( str, oldStr );
+
+ rtl_uString_acquire( oldStr );
+ CPPUNIT_ASSERT_EQUAL( 2, int( str->refCount ));
+ rtl_uString_ensureCapacity( &str, 4 );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+ // a copy was forced because of refcount
+ CPPUNIT_ASSERT( oldStr != str );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(0), rtl_ustr_compare( oldStr->buffer, str->buffer ) );
+ CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount ));
+ rtl_uString_release( str );
+ str = oldStr;
+
+ rtl_uString_acquire( oldStr );
+ rtl_uString_ensureCapacity( &str, 1024 );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); // size is still 4
+ CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount ));
+ CPPUNIT_ASSERT( oldStr != str );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(0), rtl_ustr_compare( oldStr->buffer, str->buffer ) );
+ CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount ));
+ // but there should be extra capacity
+ for( int i = 0;
+ i < 20;
+ ++i )
+ str->buffer[ str->length + i ] = '0';
+ str->length += 20;
+ rtl_uString_release( str );
+ rtl_uString_release( oldStr );
+}
+
+void test::oustring::StringConcat::checkAppend()
+{
+ OUString str( "foo" );
+ str += OUStringLiteral( u"bar" ) + "baz";
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobarbaz" ), str );
+ OUStringBuffer buf( "foo" );
+ buf.append( OUStringLiteral( u"bar" ) + "baz" );
+ CPPUNIT_ASSERT_EQUAL( OUString( "foobarbaz" ), buf.makeStringAndClear());
+}
+
+#define INVALID_CONCAT( expression ) \
+ ( \
+ rtl_string_unittest_invalid_concat = false, \
+ ( void ) OUString( expression ), \
+ rtl_string_unittest_invalid_concat )
+
+void test::oustring::StringConcat::checkInvalid()
+{
+ CPPUNIT_ASSERT( !INVALID_CONCAT( OUString() + OUString()));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OString( "b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OStringBuffer( "b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + static_cast<const char*>("b") ));
+ char d[] = "b";
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + d ));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + static_cast<char*>(d) ));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OStringLiteral( "b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OString::Concat( "b" )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + 1 ));
+ rtl_String* rs = nullptr;
+ rtl_uString* rus = nullptr;
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs ));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus ));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OString::number( 10 )));
+ CPPUNIT_ASSERT( INVALID_CONCAT( OUString::number( 0 ) + OString::number( 10 )));
+
+#if 0
+ // Should fail to compile, to avoid use of OUStringConcat lvalues that
+ // contain dangling references to temporaries:
+ auto const conc = OUStringLiteral("foo") + "bar";
+ (void) OUString(conc);
+#endif
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringConcat);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_oustring_convert.cxx b/sal/qa/rtl/strings/test_oustring_convert.cxx
new file mode 100644
index 000000000..da930a03f
--- /dev/null
+++ b/sal/qa/rtl/strings/test_oustring_convert.cxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/macros.h>
+
+namespace test::oustring {
+
+class Convert: public CppUnit::TestFixture
+{
+private:
+ void convertToString();
+
+ CPPUNIT_TEST_SUITE(Convert);
+ CPPUNIT_TEST(convertToString);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::Convert);
+
+namespace {
+
+struct TestConvertToString
+{
+ sal_Unicode aSource[100];
+ sal_Int32 nLength;
+ rtl_TextEncoding nEncoding;
+ sal_uInt32 nFlags;
+ char const * pStrict;
+ char const * pRelaxed;
+};
+
+void testConvertToString(TestConvertToString const & rTest)
+{
+ const OUString aSource(rTest.aSource, rTest.nLength);
+ OString aStrict(RTL_CONSTASCII_STRINGPARAM("12345"));
+ bool bSuccess = aSource.convertToString(&aStrict, rTest.nEncoding,
+ rTest.nFlags);
+ OString aRelaxed(OUStringToOString(aSource, rTest.nEncoding,
+ rTest.nFlags));
+
+ OStringBuffer aPrefix;
+ aPrefix.append("{");
+ for (sal_Int32 i = 0; i < rTest.nLength; ++i)
+ {
+ aPrefix.append("U+");
+ aPrefix.append(static_cast< sal_Int32 >(rTest.aSource[i]), 16);
+ if (i + 1 < rTest.nLength)
+ aPrefix.append(",");
+ }
+ aPrefix.append("}, ");
+ aPrefix.append(static_cast< sal_Int32 >(rTest.nEncoding));
+ aPrefix.append(", 0x");
+ aPrefix.append(static_cast< sal_Int32 >(rTest.nFlags), 16);
+ aPrefix.append(" -> ");
+
+ if (bSuccess)
+ {
+ if (rTest.pStrict == nullptr || aStrict != rTest.pStrict)
+ {
+ OStringBuffer aMessage(aPrefix);
+ aMessage.append("strict = \"");
+ aMessage.append(aStrict);
+ aMessage.append("\"");
+ CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false);
+ }
+ }
+ else
+ {
+ if (aStrict != "12345")
+ {
+ OStringBuffer aMessage(aPrefix);
+ aMessage.append("modified output");
+ CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false);
+ }
+ if (rTest.pStrict != nullptr)
+ {
+ OStringBuffer aMessage(aPrefix);
+ aMessage.append("failed");
+ CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false);
+ }
+ }
+ if (aRelaxed != rTest.pRelaxed)
+ {
+ OStringBuffer aMessage(aPrefix);
+ aMessage.append("relaxed = \"");
+ aMessage.append(aRelaxed);
+ aMessage.append("\"");
+ CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false);
+ }
+}
+
+}
+
+void test::oustring::Convert::convertToString()
+{
+ TestConvertToString const aTests[]
+ = { { { 0 },
+ 0,
+ RTL_TEXTENCODING_ASCII_US,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR,
+ "",
+ "" },
+ { { 0 },
+ 0,
+ RTL_TEXTENCODING_ASCII_US,
+ OUSTRING_TO_OSTRING_CVTFLAGS,
+ "",
+ "" },
+ { { 0x0041,0x0042,0x0043 },
+ 3,
+ RTL_TEXTENCODING_ASCII_US,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR,
+ "ABC",
+ "ABC" },
+ { { 0x0041,0x0042,0x0043 },
+ 3,
+ RTL_TEXTENCODING_ASCII_US,
+ OUSTRING_TO_OSTRING_CVTFLAGS,
+ "ABC",
+ "ABC" },
+ { { 0xB800 },
+ 1,
+ RTL_TEXTENCODING_ISO_2022_JP,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR,
+ nullptr,
+ "" },
+ { { 0x3001, 0xB800 },
+ 2,
+ RTL_TEXTENCODING_ISO_2022_JP,
+ OUSTRING_TO_OSTRING_CVTFLAGS,
+ "\x1b\x24\x42\x21\x22\x1b\x28\x42\x3f",
+ "\x1b\x24\x42\x21\x22\x1b\x28\x42\x3f" },
+ { { 0x0041,0x0100,0x0042 },
+ 3,
+ RTL_TEXTENCODING_ISO_8859_1,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR,
+ nullptr,
+ "A" },
+ { { 0x0041,0x0100,0x0042 },
+ 3,
+ RTL_TEXTENCODING_ISO_8859_1,
+ OUSTRING_TO_OSTRING_CVTFLAGS,
+ "A?B",
+ "A?B" } };
+ for (size_t i = 0; i < SAL_N_ELEMENTS(aTests); ++i)
+ testConvertToString(aTests[i]);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_oustring_endswith.cxx b/sal/qa/rtl/strings/test_oustring_endswith.cxx
new file mode 100644
index 000000000..bf01577e2
--- /dev/null
+++ b/sal/qa/rtl/strings/test_oustring_endswith.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/textenc.h>
+#include <rtl/ustring.hxx>
+#include <sal/macros.h>
+
+namespace test::oustring {
+
+class EndsWith: public CppUnit::TestFixture
+{
+private:
+ void endsWith();
+
+ CPPUNIT_TEST_SUITE(EndsWith);
+ CPPUNIT_TEST(endsWith);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::EndsWith);
+
+namespace {
+
+void appendString(OStringBuffer & buffer, OString const & string)
+{
+ buffer.append('"');
+ for (int i = 0; i < string.getLength(); ++i) {
+ char c = string[i];
+ if (c < ' ' || c == '"' || c == '\\' || c > '~') {
+ buffer.append('\\');
+ sal_Int32 n = static_cast< sal_Int32 >(
+ static_cast< unsigned char >(c));
+ if (n < 16) {
+ buffer.append('0');
+ }
+ buffer.append(n, 16);
+ } else {
+ buffer.append(c);
+ }
+ }
+ buffer.append('"');
+}
+
+}
+
+void test::oustring::EndsWith::endsWith()
+{
+ struct Data {
+ char const * str1;
+ sal_Int32 str1Len;
+ char const * str2;
+ sal_Int32 str2Len;
+ bool endsWith;
+ };
+ Data const data[] = {
+ { RTL_CONSTASCII_STRINGPARAM(""), RTL_CONSTASCII_STRINGPARAM(""),
+ true },
+ { RTL_CONSTASCII_STRINGPARAM("abc"), RTL_CONSTASCII_STRINGPARAM(""),
+ true },
+ { RTL_CONSTASCII_STRINGPARAM(""), RTL_CONSTASCII_STRINGPARAM("abc"),
+ false },
+ { RTL_CONSTASCII_STRINGPARAM("ABC"), RTL_CONSTASCII_STRINGPARAM("abc"),
+ true },
+ { RTL_CONSTASCII_STRINGPARAM("abcd"), RTL_CONSTASCII_STRINGPARAM("bcd"),
+ true },
+ { RTL_CONSTASCII_STRINGPARAM("bcd"), RTL_CONSTASCII_STRINGPARAM("abcd"),
+ false },
+ { RTL_CONSTASCII_STRINGPARAM("a\0b\0c"),
+ RTL_CONSTASCII_STRINGPARAM("b\0c"), true },
+ { RTL_CONSTASCII_STRINGPARAM("a\0b\0c"),
+ RTL_CONSTASCII_STRINGPARAM("b"), false } };
+ for (size_t i = 0; i < SAL_N_ELEMENTS(data); ++i) {
+ OStringBuffer msg;
+ appendString(msg, OString(data[i].str1, data[i].str1Len));
+ msg.append(".endsWithIgnoreAsciiCaseAsciiL(");
+ appendString(msg, OString(data[i].str2, data[i].str2Len));
+ msg.append(") == ");
+ msg.append(data[i].endsWith);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ msg.getStr(),
+ data[i].endsWith,
+ OUString(
+ data[i].str1, data[i].str1Len,
+ RTL_TEXTENCODING_ASCII_US).endsWithIgnoreAsciiCaseAsciiL(
+ data[i].str2, data[i].str2Len));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_oustring_startswith.cxx b/sal/qa/rtl/strings/test_oustring_startswith.cxx
new file mode 100644
index 000000000..a74671e6e
--- /dev/null
+++ b/sal/qa/rtl/strings/test_oustring_startswith.cxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/ustring.hxx>
+
+namespace test::oustring {
+
+class StartsWith: public CppUnit::TestFixture
+{
+private:
+ void startsWith();
+
+ CPPUNIT_TEST_SUITE(StartsWith);
+ CPPUNIT_TEST(startsWith);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StartsWith);
+
+void test::oustring::StartsWith::startsWith()
+{
+ CPPUNIT_ASSERT( OUString( "foobar" ).startsWith( "foo" ));
+ CPPUNIT_ASSERT( !OUString( "foo" ).startsWith( "foobar" ));
+ CPPUNIT_ASSERT( !OUString( "foobar" ).startsWith( "oo" ));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
new file mode 100644
index 000000000..0caa3fc03
--- /dev/null
+++ b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
@@ -0,0 +1,432 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// activate the extra needed ctor
+#define RTL_STRING_UNITTEST
+
+#include <sal/config.h>
+
+#include <string>
+#include <string_view>
+#include <utility>
+
+#include <o3tl/cppunittraitshelper.hxx>
+#include <sal/types.h>
+#include <config_global.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/string.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+extern bool rtl_string_unittest_const_literal;
+bool rtl_string_unittest_invalid_conversion;
+
+namespace test::oustring {
+
+class StringLiterals: public CppUnit::TestFixture
+{
+private:
+ void checkCtors();
+ void checkConstexprCtor();
+ void checkUsage();
+ void checkBuffer();
+ void checkOUStringLiteral();
+ void checkOUStringChar();
+ void checkUtf16();
+ void checkEmbeddedNul();
+
+ void testcall( const char str[] );
+
+ // Check that OUStringLiteral ctor is actually constexpr:
+ static constexpr rtlunittest::OUStringLiteral dummy{u"dummy"};
+
+CPPUNIT_TEST_SUITE(StringLiterals);
+CPPUNIT_TEST(checkCtors);
+CPPUNIT_TEST(checkConstexprCtor);
+CPPUNIT_TEST(checkUsage);
+CPPUNIT_TEST(checkBuffer);
+CPPUNIT_TEST(checkOUStringLiteral);
+CPPUNIT_TEST(checkOUStringChar);
+CPPUNIT_TEST(checkUtf16);
+CPPUNIT_TEST(checkEmbeddedNul);
+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)
+template<typename T> static bool VALID_CONVERSION( T && expression )
+{
+ rtl_string_unittest_invalid_conversion = false;
+ // OK to std::forward expression twice; what is relevant in both ctor calls
+ // is not the content of the passed argument (which is ignored anyway by the
+ // special RTL_STRING_UNITTEST ctors) but only its type:
+ ( void ) rtl::OUString( std::forward<T>(expression) );
+ ( void ) rtl::OUStringBuffer( std::forward<T>(expression) );
+ return !rtl_string_unittest_invalid_conversion;
+}
+template<typename T> static bool VALID_CONVERSION_CALL( T f )
+{
+ rtl_string_unittest_invalid_conversion = false;
+ ( void ) rtl::OUString( f() );
+ ( void ) rtl::OUStringBuffer( f() );
+ return !rtl_string_unittest_invalid_conversion;
+}
+
+void test::oustring::StringLiterals::checkCtors()
+{
+ CPPUNIT_ASSERT( VALID_CONVERSION( "test" ));
+ const char good1[] = "test";
+ CPPUNIT_ASSERT( VALID_CONVERSION( good1 ));
+
+ CPPUNIT_ASSERT( !VALID_CONVERSION( static_cast<const char*>("test") ));
+ const char* bad1 = good1;
+ CPPUNIT_ASSERT( !VALID_CONVERSION( bad1 ));
+ char bad2[] = "test";
+ CPPUNIT_ASSERT( !VALID_CONVERSION( bad2 ));
+ char* bad3 = bad2;
+ CPPUNIT_ASSERT( !VALID_CONVERSION( bad3 ));
+ const char* bad4[] = { "test1" };
+ CPPUNIT_ASSERT( !VALID_CONVERSION( 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 assert()).
+// RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
+ const char bad5[][ 6 ] = { "test", "test2" };
+// CPPUNIT_ASSERT( VALID_CONVERSION( bad5[ 0 ] ));
+ CPPUNIT_ASSERT( VALID_CONVERSION( bad5[ 1 ] ));
+
+// Check that contents are correct and equal to the case when RTL_CONSTASCII_USTRINGPARAM is used.
+ CPPUNIT_ASSERT_EQUAL( rtl::OUString( "" ), rtl::OUString( "" ));
+ CPPUNIT_ASSERT_EQUAL( rtl::OUString( "ab" ), rtl::OUString( "ab" ));
+#if 0
+// Also check that embedded \0 is included.
+// In fact, allowing this is probably just trouble, so this now asserts.
+ CPPUNIT_ASSERT_EQUAL( rtl::OUString( "\0" ), rtl::OUString( "\0" ));
+ CPPUNIT_ASSERT_EQUAL( rtl::OUString( "a\0b" ), rtl::OUString( "a\0b" ));
+#endif
+}
+
+void test::oustring::StringLiterals::testcall( const char str[] )
+{
+ CPPUNIT_ASSERT(
+ !VALID_CONVERSION_CALL([&str]() { return rtl::OUString(str); }));
+}
+
+void test::oustring::StringLiterals::checkConstexprCtor()
+{
+#if __cplusplus >= 202002L
+ static constinit
+#endif
+ rtl::OUString s(dummy);
+ CPPUNIT_ASSERT_EQUAL(oslInterlockedCount(0x40000000), s.pData->refCount);
+ // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx)
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), s.getLength());
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("dummy"), s);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast<void const *>(dummy.getStr()), static_cast<void const *>(s.getStr()));
+}
+
+void test::oustring::StringLiterals::checkUsage()
+{
+// simply check that all string literal based calls work as expected
+// also check that they really use string literal overload and do not convert to OUString
+ rtl::OUString foo( "foo" );
+ rtl::OUString FoO( "FoO" );
+ rtl::OUString foobarfoo( "foobarfoo" );
+ rtl::OUString foobar( "foobar" );
+ rtl::OUString FooBaRfoo( "FooBaRfoo" );
+ rtl::OUString FooBaR( "FooBaR" );
+ rtl::OUString bar( "bar" );
+ rtl::OUString test( "test" );
+
+ rtl_string_unittest_const_literal = false; // start checking for OUString conversions
+ CPPUNIT_ASSERT_EQUAL( foo, rtl::OUString() = "foo" );
+ CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( "fOo" ));
+ CPPUNIT_ASSERT( foobarfoo.match( "bar", 3 ));
+ CPPUNIT_ASSERT( foobar.match( "foo" ));
+ CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( "bAr", 3 ));
+ CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( "fOo" ));
+ CPPUNIT_ASSERT( foobar.startsWith( "foo" ));
+ CPPUNIT_ASSERT( FooBaR.startsWithIgnoreAsciiCase( "foo" ));
+ CPPUNIT_ASSERT( foobar.endsWith( "bar" ));
+ CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" ));
+ CPPUNIT_ASSERT( bool(foo == "foo") );
+ CPPUNIT_ASSERT( bool("foo" == foo) );
+ CPPUNIT_ASSERT( foo != "bar" );
+ CPPUNIT_ASSERT( "foo" != bar );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( "foo", 1 ) );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.lastIndexOf( "foo" ) );
+ CPPUNIT_ASSERT( bool(foobarfoo.replaceFirst( "foo", test ) == "testbarfoo") );
+ CPPUNIT_ASSERT( bool(foobarfoo.replaceFirst( "foo", "test" ) == "testbarfoo") );
+ CPPUNIT_ASSERT( bool(foobarfoo.replaceAll( "foo", test ) == "testbartest") );
+ CPPUNIT_ASSERT( bool(foobarfoo.replaceAll( "foo", "test" ) == "testbartest") );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(0), foo.reverseCompareTo( "foo" ) );
+ // if this is not true, some of the calls above converted to OUString
+ CPPUNIT_ASSERT( !rtl_string_unittest_const_literal );
+}
+
+void test::oustring::StringLiterals::checkBuffer()
+{
+ rtl::OUStringBuffer buf;
+ buf.append( "foo" );
+ CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foo" ), buf.toString());
+ buf.append( "bar" );
+ CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobar" ), buf.toString());
+ buf.insert( 3, "baz" );
+ CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobazbar" ), buf.toString());
+ char d[] = "d";
+ CPPUNIT_ASSERT( !VALID_CONVERSION( buf.append( rtl::OUString( d ))));
+ CPPUNIT_ASSERT( !VALID_CONVERSION( buf.append( rtl::OUStringBuffer( d ))));
+}
+
+namespace {
+
+rtl::OUString conditional(bool flag) {
+ return rtl::OUString::Concat(flag ? std::u16string_view(u"a") : std::u16string_view(u"bb"))
+ + "c";
+}
+
+}
+
+void test::oustring::StringLiterals::checkOUStringLiteral()
+{
+ CPPUNIT_ASSERT(bool(conditional(true) == "ac"));
+ CPPUNIT_ASSERT(bool(conditional(false) == "bbc"));
+
+ static constexpr rtlunittest::OUStringLiteral s1lit(u"abc");
+ rtl::OUString s1(s1lit);
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), s1);
+ static constexpr rtlunittest::OUStringLiteral de(u"de");
+ s1 = de;
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("de"), s1);
+ s1 += rtlunittest::OUStringLiteral(u"fde");
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("defde"), s1);
+ CPPUNIT_ASSERT_EQUAL(
+ sal_Int32(0),
+ s1.reverseCompareTo(rtlunittest::OUStringLiteral(u"defde")));
+ CPPUNIT_ASSERT(
+ s1.equalsIgnoreAsciiCase(rtlunittest::OUStringLiteral(u"DEFDE")));
+ CPPUNIT_ASSERT(s1.match(rtlunittest::OUStringLiteral(u"fde"), 2));
+ CPPUNIT_ASSERT(
+ s1.matchIgnoreAsciiCase(rtlunittest::OUStringLiteral(u"FDE"), 2));
+ rtl::OUString s2;
+ CPPUNIT_ASSERT(s1.startsWith(rtlunittest::OUStringLiteral(u"de"), &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("fde"), s2);
+ CPPUNIT_ASSERT(
+ s1.startsWithIgnoreAsciiCase(
+ rtlunittest::OUStringLiteral(u"DEFD"), &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("e"), s2);
+ CPPUNIT_ASSERT(s1.endsWith(rtlunittest::OUStringLiteral(u"de"), &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("def"), s2);
+ CPPUNIT_ASSERT(
+ s1.endsWithIgnoreAsciiCase(rtlunittest::OUStringLiteral(u"EFDE"), &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("d"), s2);
+ static constexpr rtlunittest::OUStringLiteral defde(u"defde");
+ CPPUNIT_ASSERT(bool(s1 == defde));
+ CPPUNIT_ASSERT(bool(defde == s1));
+ static constexpr rtlunittest::OUStringLiteral abc(u"abc");
+ CPPUNIT_ASSERT(s1 != abc);
+ CPPUNIT_ASSERT(abc != s1);
+ CPPUNIT_ASSERT_EQUAL(
+ sal_Int32(3), s1.indexOf(rtlunittest::OUStringLiteral(u"de"), 1));
+ CPPUNIT_ASSERT_EQUAL(
+ sal_Int32(3), s1.lastIndexOf(rtlunittest::OUStringLiteral(u"de")));
+ sal_Int32 i = 0;
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfde"),
+ s1.replaceFirst(
+ rtlunittest::OUStringLiteral(u"de"), rtl::OUString("abc"), &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfde"),
+ s1.replaceFirst(
+ rtl::OUString("de"), rtlunittest::OUStringLiteral(u"abc"), &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfde"),
+ s1.replaceFirst(
+ rtlunittest::OUStringLiteral(u"de"),
+ rtlunittest::OUStringLiteral(u"abc"), &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfde"),
+ s1.replaceFirst(rtlunittest::OUStringLiteral(u"de"), "abc", &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfde"),
+ s1.replaceFirst("de", rtlunittest::OUStringLiteral(u"abc"), &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfabc"),
+ s1.replaceAll(
+ rtlunittest::OUStringLiteral(u"de"), rtl::OUString("abc")));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfabc"),
+ s1.replaceAll(
+ rtl::OUString("de"), rtlunittest::OUStringLiteral(u"abc")));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfabc"),
+ s1.replaceAll(
+ rtlunittest::OUStringLiteral(u"de"),
+ rtlunittest::OUStringLiteral(u"abc")));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfabc"),
+ s1.replaceAll(rtlunittest::OUStringLiteral(u"de"), "abc"));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcfabc"),
+ s1.replaceAll("de", rtlunittest::OUStringLiteral(u"abc")));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcdef"),
+ rtl::OUString(
+ rtl::OUString("abc") + rtlunittest::OUStringLiteral(u"def")));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcdef"),
+ rtl::OUString(
+ rtlunittest::OUStringLiteral(u"abc") + rtl::OUString("def")));
+ rtl::OUStringBuffer b(rtlunittest::OUStringLiteral(u"abc"));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), b.toString());
+ b.append(rtlunittest::OUStringLiteral(u"def"));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abcdef"), b.toString());
+ b.insert(2, rtlunittest::OUStringLiteral(u"gabab"));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abgababcdef"), b.toString());
+ CPPUNIT_ASSERT_EQUAL(
+ sal_Int32(3), b.indexOf(rtlunittest::OUStringLiteral(u"ab"), 1));
+ CPPUNIT_ASSERT_EQUAL(
+ sal_Int32(5), b.lastIndexOf(rtlunittest::OUStringLiteral(u"ab")));
+}
+
+void test::oustring::StringLiterals::checkOUStringChar()
+{
+ auto l1 = rtlunittest::OUStringChar('A');
+ CPPUNIT_ASSERT_EQUAL(u'A', l1.c);
+
+ char const c2 = 'A';
+ auto l2 = rtlunittest::OUStringChar(c2);
+ CPPUNIT_ASSERT_EQUAL(u'A', l2.c);
+
+ char c3 = 'A'; auto l3 = rtlunittest::OUStringChar(c3);
+ CPPUNIT_ASSERT_EQUAL(u'A', l3.c);
+
+ auto l4 = rtlunittest::OUStringChar(u'A');
+ CPPUNIT_ASSERT_EQUAL(u'A', l4.c);
+
+ sal_Unicode const c5 = 0x100;
+ auto l5 = rtlunittest::OUStringChar(c5);
+ CPPUNIT_ASSERT_EQUAL(c5, l5.c);
+
+ rtl::OUString s1{rtlunittest::OUStringChar('A')};
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), s1.getLength());
+ CPPUNIT_ASSERT_EQUAL(u'A', s1[0]);
+
+ CPPUNIT_ASSERT_EQUAL(
+ true, rtl::OUString("A") == rtlunittest::OUStringChar('A'));
+ CPPUNIT_ASSERT_EQUAL(
+ false, rtl::OUString("AB") == rtlunittest::OUStringChar('A'));
+ CPPUNIT_ASSERT_EQUAL(
+ false, rtl::OUString("A") != rtlunittest::OUStringChar('A'));
+ CPPUNIT_ASSERT_EQUAL(
+ true, rtl::OUString("AB") != rtlunittest::OUStringChar('A'));
+
+ rtl::OUString s2("A" + rtlunittest::OUStringChar('b'));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), s2.getLength());
+ CPPUNIT_ASSERT_EQUAL(u'A', s2[0]);
+ CPPUNIT_ASSERT_EQUAL(u'b', s2[1]);
+}
+
+void test::oustring::StringLiterals::checkUtf16() {
+ rtl::OUString s1(u"abc");
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), s1);
+ s1 = u"de";
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("de"), s1);
+ s1 += u"fde";
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("defde"), s1);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), s1.reverseCompareTo(u"defde"));
+ CPPUNIT_ASSERT(s1.equalsIgnoreAsciiCase(u"DEFDE"));
+ CPPUNIT_ASSERT(s1.match(u"fde", 2));
+ CPPUNIT_ASSERT(s1.matchIgnoreAsciiCase(u"FDE", 2));
+ rtl::OUString s2;
+ CPPUNIT_ASSERT(s1.startsWith(u"de", &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"fde"), s2);
+ CPPUNIT_ASSERT(s1.startsWithIgnoreAsciiCase(u"DEFD", &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"e"), s2);
+ CPPUNIT_ASSERT(s1.endsWith(u"de", &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"def"), s2);
+ CPPUNIT_ASSERT(s1.endsWithIgnoreAsciiCase(u"EFDE", &s2));
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"d"), s2);
+ CPPUNIT_ASSERT(bool(s1 == u"defde"));
+ CPPUNIT_ASSERT(bool(u"defde" == s1));
+ CPPUNIT_ASSERT(s1 != u"abc");
+ CPPUNIT_ASSERT(u"abc" != s1);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), s1.indexOf(u"de", 1));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), s1.lastIndexOf(u"de"));
+ sal_Int32 i = 0;
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfde"),
+ s1.replaceFirst(u"de", rtl::OUString("abc"), &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfde"),
+ s1.replaceFirst(rtl::OUString("de"), u"abc", &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfde"), s1.replaceFirst(u"de", u"abc", &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfde"), s1.replaceFirst(u"de", "abc", &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfde"), s1.replaceFirst("de", u"abc", &i));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i);
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfabc"), s1.replaceAll(u"de", rtl::OUString("abc")));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfabc"), s1.replaceAll(rtl::OUString("de"), u"abc"));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfabc"), s1.replaceAll(u"de", u"abc"));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfabc"), s1.replaceAll(u"de", "abc"));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString(u"abcfabc"), s1.replaceAll("de", u"abc"));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcdef"), rtl::OUString(rtl::OUString("abc") + u"def"));
+ CPPUNIT_ASSERT_EQUAL(
+ rtl::OUString("abcdef"), rtl::OUString(u"abc" + rtl::OUString("def")));
+ rtl::OUStringBuffer b(u"abc");
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), b.toString());
+ b.append(u"def");
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abcdef"), b.toString());
+ b.insert(2, u"gabab");
+ CPPUNIT_ASSERT_EQUAL(rtl::OUString("abgababcdef"), b.toString());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), b.indexOf(u"ab", 1));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), b.lastIndexOf(u"ab"));
+}
+
+void test::oustring::StringLiterals::checkEmbeddedNul() {
+ using namespace std::literals;
+ rtl::OUString const s("foobar");
+ constexpr char16_t const a[] = u"foo\0hidden";
+ char16_t const * const p = a;
+ CPPUNIT_ASSERT(s.startsWith(a));
+ CPPUNIT_ASSERT(s.startsWith(p));
+ CPPUNIT_ASSERT(s.startsWith(u"foo\0hidden"));
+ CPPUNIT_ASSERT(!s.startsWith(u"foo\0hidden"s));
+ CPPUNIT_ASSERT(!s.startsWith(u"foo\0hidden"sv));
+/*TODO:*/
+ CPPUNIT_ASSERT(!s.startsWith(rtlunittest::OUStringLiteral(a)));
+ CPPUNIT_ASSERT(!s.startsWith(rtlunittest::OUStringLiteral(u"foo\0hidden")));
+/*TODO*/
+}
+
+} // namespace
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringLiterals);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_strings_defaultstringview.cxx b/sal/qa/rtl/strings/test_strings_defaultstringview.cxx
new file mode 100644
index 000000000..591688b31
--- /dev/null
+++ b/sal/qa/rtl/strings/test_strings_defaultstringview.cxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <rtl/string.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+
+namespace
+{
+class Test : public CppUnit::TestFixture
+{
+ void string() { CPPUNIT_ASSERT_EQUAL(OString(), OString(std::string_view())); }
+
+ void stringbuffer()
+ {
+ // No functions related to OStringBuffer that take a std::string_view or std::u16string_view
+ // argument.
+ }
+
+ void ustring()
+ {
+ CPPUNIT_ASSERT_EQUAL(OUString(), OUString(std::u16string_view()));
+ OUString s1("foo");
+ s1 = std::u16string_view();
+ CPPUNIT_ASSERT_EQUAL(OUString(), s1);
+ OUString s2("foo");
+ s2 += std::u16string_view();
+ CPPUNIT_ASSERT_EQUAL(OUString("foo"), s2);
+ CPPUNIT_ASSERT_GREATER(sal_Int32(0),
+ OUString("foo").reverseCompareTo(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(false, OUString("foo").equalsIgnoreAsciiCase(std::u16string_view()));
+ CPPUNIT_ASSERT_GREATER(sal_Int32(0),
+ OUString("foo").compareToIgnoreAsciiCase(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(true, OUString("foo").match(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(true, OUString("foo").matchIgnoreAsciiCase(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(true, OUString("foo").startsWith(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(true,
+ OUString("foo").startsWithIgnoreAsciiCase(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(true, OUString("foo").endsWith(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(true, OUString("foo").endsWithIgnoreAsciiCase(std::u16string_view()));
+ OUString const foo("foo"); // avoid loplugin:stringconstant, loplugin:stringview
+ CPPUNIT_ASSERT_EQUAL(false, foo == std::u16string_view());
+ CPPUNIT_ASSERT_EQUAL(true, foo != std::u16string_view());
+ CPPUNIT_ASSERT_EQUAL(false, foo < std::u16string_view());
+ CPPUNIT_ASSERT_EQUAL(false, foo <= std::u16string_view());
+ CPPUNIT_ASSERT_EQUAL(true, foo > std::u16string_view());
+ CPPUNIT_ASSERT_EQUAL(true, foo >= std::u16string_view());
+ CPPUNIT_ASSERT_EQUAL(false, std::u16string_view() == foo);
+ CPPUNIT_ASSERT_EQUAL(true, std::u16string_view() != foo);
+ CPPUNIT_ASSERT_EQUAL(true, std::u16string_view() < foo);
+ CPPUNIT_ASSERT_EQUAL(true, std::u16string_view() <= foo);
+ CPPUNIT_ASSERT_EQUAL(false, std::u16string_view() > foo);
+ CPPUNIT_ASSERT_EQUAL(false, std::u16string_view() >= foo);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), OUString("foo").indexOf(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), OUString("foo").lastIndexOf(std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), OUString("foo").lastIndexOf(std::u16string_view(), 3));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst(std::u16string_view(), std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("barfoo"),
+ OUString("foobarfoo").replaceFirst(std::u16string_view(u"foo"), std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst(std::u16string_view(), std::u16string_view(u"baz")));
+ CPPUNIT_ASSERT_EQUAL(OUString("barfoo"),
+ OUString("foobarfoo").replaceFirst("foo", std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst(std::u16string_view(), "baz"));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceAll(std::u16string_view(), std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("bar"),
+ OUString("foobarfoo").replaceAll(std::u16string_view(u"foo"), std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceAll(std::u16string_view(), std::u16string_view(u"baz")));
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"),
+ OUString("foobarfoo").replaceAll("foo", std::u16string_view()));
+ CPPUNIT_ASSERT_EQUAL(OUString("foobarfoo"),
+ OUString("foobarfoo").replaceAll(std::u16string_view(), "baz"));
+ CPPUNIT_ASSERT_EQUAL(OUString(), OUString::createFromAscii(std::string_view()));
+ }
+
+ void ustringbuffer()
+ {
+ OUStringBuffer b("foo");
+ b.append(std::u16string_view());
+ CPPUNIT_ASSERT_EQUAL(OUString("foo"), b.toString());
+ }
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(string);
+ CPPUNIT_TEST(stringbuffer);
+ CPPUNIT_TEST(ustring);
+ CPPUNIT_TEST(ustringbuffer);
+ CPPUNIT_TEST_SUITE_END();
+};
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sal/qa/rtl/strings/test_strings_replace.cxx b/sal/qa/rtl/strings/test_strings_replace.cxx
new file mode 100644
index 000000000..3be6e176a
--- /dev/null
+++ b/sal/qa/rtl/strings/test_strings_replace.cxx
@@ -0,0 +1,339 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+
+namespace {
+
+OUString s_empty;
+OUString s_bar("bar");
+OUString s_bars("bars");
+OUString s_foo("foo");
+OUString s_other("other");
+OUString s_xa("xa");
+OUString s_xx("xx");
+
+class Test: public CppUnit::TestFixture {
+private:
+ void stringReplaceFirst();
+
+ void stringReplaceAll();
+
+ void ustringReplaceFirst();
+
+ void ustringReplaceFirstAsciiL();
+
+ void ustringReplaceFirstToAsciiL();
+
+ void ustringReplaceFirstAsciiLAsciiL();
+
+ void ustringReplaceAll();
+
+ void ustringReplaceAllAsciiL();
+
+ void ustringReplaceAllToAsciiL();
+
+ void ustringReplaceAllAsciiLAsciiL();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(stringReplaceFirst);
+ CPPUNIT_TEST(stringReplaceAll);
+ CPPUNIT_TEST(ustringReplaceFirst);
+ CPPUNIT_TEST(ustringReplaceFirstAsciiL);
+ CPPUNIT_TEST(ustringReplaceFirstToAsciiL);
+ CPPUNIT_TEST(ustringReplaceFirstAsciiLAsciiL);
+ CPPUNIT_TEST(ustringReplaceAll);
+ CPPUNIT_TEST(ustringReplaceAllAsciiL);
+ CPPUNIT_TEST(ustringReplaceAllToAsciiL);
+ CPPUNIT_TEST(ustringReplaceAllAsciiLAsciiL);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::stringReplaceFirst() {
+ CPPUNIT_ASSERT_EQUAL(
+ OString("otherbarfoo"),
+ OString("foobarfoo").replaceFirst("foo", "other"));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OString("foobarfoo"),
+ OString("foobarfoo").replaceFirst("bars", "other"));
+
+ {
+ sal_Int32 n = 0;
+ CPPUNIT_ASSERT_EQUAL(
+ OString("otherbarfoo"),
+ OString("foobarfoo").replaceFirst("foo", "other", &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n);
+ }
+
+ {
+ sal_Int32 n = 1;
+ CPPUNIT_ASSERT_EQUAL(
+ OString("foobarother"),
+ OString("foobarfoo").replaceFirst("foo", "other", &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n);
+ }
+
+ {
+ sal_Int32 n = 4;
+ CPPUNIT_ASSERT_EQUAL(
+ OString("foobarfoo"),
+ OString("foobarfoo").replaceFirst("bar", "other", &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n);
+ }
+}
+
+void Test::stringReplaceAll() {
+ CPPUNIT_ASSERT_EQUAL(
+ OString("otherbarother"),
+ OString("foobarfoo").replaceAll("foo", "other"));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OString("foobarfoo"),
+ OString("foobarfoo").replaceAll("bars", "other"));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OString("xxa"), OString("xaa").replaceAll("xa", "xx"));
+}
+
+void Test::ustringReplaceFirst() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ OUString("foobarfoo").replaceFirst(s_foo, s_other));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst(s_bars, s_other));
+
+ {
+ sal_Int32 n = 0;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ OUString("foobarfoo").replaceFirst(s_foo, s_other, &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n);
+ }
+
+ {
+ sal_Int32 n = 1;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarother"),
+ OUString("foobarfoo").replaceFirst(s_foo, s_other, &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n);
+ }
+
+ {
+ sal_Int32 n = 4;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst(s_bar, s_other, &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n);
+ }
+}
+
+void Test::ustringReplaceFirstAsciiL() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ OUString("foobarfoo").replaceFirst("foo", s_other));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst("bars", s_other));
+
+ {
+ sal_Int32 n = 0;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ OUString("foobarfoo").replaceFirst("foo", s_other, &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n);
+ }
+
+ {
+ sal_Int32 n = 1;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarother"),
+ OUString("foobarfoo").replaceFirst("foo", s_other, &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n);
+ }
+
+ {
+ sal_Int32 n = 4;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst("bar", s_other, &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(), OUString("xa").replaceFirst("xa", s_empty));
+}
+
+void Test::ustringReplaceFirstToAsciiL() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ OUString("foobarfoo").replaceFirst(s_foo, "other"));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst(s_bars, "other"));
+
+ {
+ sal_Int32 n = 0;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ OUString("foobarfoo").replaceFirst(s_foo, "other", &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n);
+ }
+
+ {
+ sal_Int32 n = 1;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarother"),
+ OUString("foobarfoo").replaceFirst(s_foo, "other", &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n);
+ }
+
+ {
+ sal_Int32 n = 4;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceFirst(s_bar, "other", &n));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(), OUString("xa").replaceFirst(s_xa, ""));
+}
+
+void Test::ustringReplaceFirstAsciiLAsciiL() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ (OUString("foobarfoo").
+ replaceFirst("foo", "other")));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ (OUString("foobarfoo").
+ replaceFirst("bars", "other")));
+
+ {
+ sal_Int32 n = 0;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarfoo"),
+ (OUString("foobarfoo").
+ replaceFirst("foo", "other", &n)));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n);
+ }
+
+ {
+ sal_Int32 n = 1;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarother"),
+ (OUString("foobarfoo").
+ replaceFirst("foo", "other", &n)));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n);
+ }
+
+ {
+ sal_Int32 n = 4;
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ (OUString("foobarfoo").
+ replaceFirst("bar", "other", &n)));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(), OUString("xa").replaceFirst("xa", ""));
+}
+
+void Test::ustringReplaceAll() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarother"),
+ OUString("foobarfoo").replaceAll(s_foo, s_other));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceAll(s_bars, s_other));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("xxa"),
+ OUString("xaa").replaceAll(s_xa, s_xx));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarbaz"), OUString("foobarfoo").replaceAll(u"foo", u"baz", 1));
+}
+
+void Test::ustringReplaceAllAsciiL() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarother"),
+ OUString("foobarfoo").replaceAll("foo", s_other));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceAll("bars", s_other));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("xxa"),
+ OUString("xaa").replaceAll("xa", s_xx));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(), OUString("xa").replaceAll("xa", s_empty));
+}
+
+void Test::ustringReplaceAllToAsciiL() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarother"),
+ OUString("foobarfoo").replaceAll(s_foo, "other"));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ OUString("foobarfoo").replaceAll(s_bars, "other"));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("xxa"),
+ OUString("xaa").replaceAll(s_xa, "xx"));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(), OUString("xa").replaceAll(s_xa, ""));
+}
+
+void Test::ustringReplaceAllAsciiLAsciiL() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("otherbarother"),
+ (OUString("foobarfoo").
+ replaceAll("foo", "other")));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("foobarfoo"),
+ (OUString("foobarfoo").
+ replaceAll("bars", "other")));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("xxa"),
+ (OUString("xaa").
+ replaceAll("xa", "xx")));
+
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(), OUString("xa").replaceAll("xa", ""));
+}
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_strings_toint.cxx b/sal/qa/rtl/strings/test_strings_toint.cxx
new file mode 100644
index 000000000..d81525b94
--- /dev/null
+++ b/sal/qa/rtl/strings/test_strings_toint.cxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+namespace {
+
+template< typename T > class Test: public CppUnit::TestFixture {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testToInt32Overflow);
+ CPPUNIT_TEST(testToUInt32Overflow);
+ CPPUNIT_TEST(testToInt64Overflow);
+ CPPUNIT_TEST(testToUInt64Overflow);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testToInt32Overflow() {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), T("-2147483649").toInt32());
+ CPPUNIT_ASSERT_EQUAL(SAL_MIN_INT32, T("-2147483648").toInt32());
+ CPPUNIT_ASSERT_EQUAL(SAL_MIN_INT32 + 1, T("-2147483647").toInt32());
+ CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT32 - 1, T("2147483646").toInt32());
+ CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT32, T("2147483647").toInt32());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), T("2147483648").toInt32());
+ }
+
+ void testToUInt32Overflow() {
+ CPPUNIT_ASSERT_EQUAL(SAL_MAX_UINT32 - 1, T("4294967294").toUInt32());
+ CPPUNIT_ASSERT_EQUAL(SAL_MAX_UINT32, T("4294967295").toUInt32());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), T("4294967296").toUInt32());
+ }
+
+ void testToInt64Overflow() {
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(0), T("-9223372036854775809").toInt64());
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MIN_INT64, T("-9223372036854775808").toInt64());
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MIN_INT64 + 1, T("-9223372036854775807").toInt64());
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_INT64 - 1, T("9223372036854775806").toInt64());
+ CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT64, T("9223372036854775807").toInt64());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(0), T("9223372036854775808").toInt64());
+ }
+
+ void testToUInt64Overflow() {
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_UINT64 - 1, T("18446744073709551614").toUInt64());
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_UINT64, T("18446744073709551615").toUInt64());
+ CPPUNIT_ASSERT_EQUAL(
+ sal_uInt64(0), T("18446744073709551616").toUInt64());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test< OString >);
+CPPUNIT_TEST_SUITE_REGISTRATION(Test< OUString >);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/rtl/strings/test_strings_valuex.cxx b/sal/qa/rtl/strings/test_strings_valuex.cxx
new file mode 100644
index 000000000..6c9c83644
--- /dev/null
+++ b/sal/qa/rtl/strings/test_strings_valuex.cxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <rtl/ustring.hxx>
+#include <iostream>
+
+namespace test::strings {
+
+class valueX : public CppUnit::TestFixture {
+public:
+ void testOBoolean();
+ void testOUBoolean();
+ void testOUInt();
+ void testOInt();
+ void testOUFloat();
+ void testOFloat();
+
+ CPPUNIT_TEST_SUITE(valueX);
+ CPPUNIT_TEST(testOBoolean);
+ CPPUNIT_TEST(testOUBoolean);
+ CPPUNIT_TEST(testOUInt);
+ CPPUNIT_TEST(testOInt);
+ CPPUNIT_TEST(testOUFloat);
+ CPPUNIT_TEST(testOFloat);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test::strings::valueX);
+
+namespace {
+
+template< typename T >
+void testBoolean() {
+ CPPUNIT_ASSERT_EQUAL( T( "false" ), T::boolean( false ) );
+ CPPUNIT_ASSERT_EQUAL( T( "true" ), T::boolean( true ) );
+}
+
+}
+
+void test::strings::valueX::testOBoolean() {
+ testBoolean<OString>();
+}
+
+void test::strings::valueX::testOUBoolean() {
+ testBoolean<OUString>();
+}
+
+template< typename T >
+static void testInt() {
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( 30039062 )));
+
+ // test the overloading resolution
+
+ CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< signed char >( 30 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< unsigned char >( 30 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< short >( 30039 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< unsigned short >( 30039 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< int >( 30039062 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned int >( 30039062 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< long >( 30039062 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned long >( 30039062 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< long long >( 30039062 ))));
+ // The highest bit set in unsigned long long may not actually work.
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned long long >( 30039062 ))));
+
+ CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< sal_Int8 >( 30 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< sal_uInt8 >( 30 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< sal_Int16 >( 30039 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< sal_uInt16 >( 30039 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_Int32 >( 30039062 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_uInt32 >( 30039062 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_Int64 >( 30039062 ))));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_uInt64 >( 30039062 ))));
+
+ // The implementation internally uses sal_Int64 etc. types, so check ranges.
+ assert( sizeof( int ) <= sizeof( sal_Int32 ));
+ assert( sizeof( long ) <= sizeof( sal_Int64 ));
+ assert( sizeof( long long ) <= sizeof( sal_Int64 ));
+ assert( sizeof( unsigned int ) < sizeof( sal_Int64 ));
+}
+
+void test::strings::valueX::testOUInt() {
+ testInt<OUString>();
+}
+
+void test::strings::valueX::testOInt() {
+ testInt<OString>();
+}
+
+template< typename T >
+static void testFloat() {
+ CPPUNIT_ASSERT_EQUAL( T( "39062.2" ), T( T::number( 39062.2f )));
+ CPPUNIT_ASSERT_EQUAL( T( "30039062.2" ), T( T::number( 30039062.2 )));
+ // long double not supported
+}
+
+void test::strings::valueX::testOUFloat() {
+ testFloat<OUString>();
+}
+
+void test::strings::valueX::testOFloat() {
+ testFloat<OString>();
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */