O[U]String literals (unusable for now, C++20 only)

Change-Id: I0ecd1a8b60a01aefdf0139e3777dc006532764fd
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154434
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
diff --git a/include/rtl/string.hxx b/include/rtl/string.hxx
index 091f224..aae291f 100644
--- a/include/rtl/string.hxx
+++ b/include/rtl/string.hxx
@@ -88,8 +88,6 @@ This class is not part of public API and is meant to be used only in LibreOffice
template<std::size_t N> class SAL_WARN_UNUSED OStringLiteral {
    static_assert(N != 0);
    static_assert(N - 1 <= std::numeric_limits<sal_Int32>::max(), "literal too long");
    friend class OString;
    friend class OStringConstExpr;

public:
#if HAVE_CPP_CONSTEVAL
@@ -146,6 +144,9 @@ private:
        char buffer[N] = {}; //TODO: drop initialization for C++20 (P1331R2)
    };

public:
    // (Data members must be public so that OStringLiteral is a structural type that can be used as
    // a non-type template parameter type for rtl::detail::OStringHolder:)
    union {
        rtl_String str;
        Data more = {};
@@ -2274,6 +2275,18 @@ inline bool operator !=(StringConcatenation<char> const & lhs, OString const & r

#ifdef LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"

#if __cplusplus >= 202002L

namespace detail {

template<OStringLiteral L> struct OStringHolder {
    static constexpr auto & literal = L;
};

}

#endif

/**
 @internal
*/
@@ -2374,6 +2387,30 @@ using ::rtl::OStringHash;
using ::rtl::OStringLiteral;
#endif

#if defined LIBO_INTERNAL_ONLY && __cplusplus >= 202002L

template<
#if defined RTL_STRING_UNITTEST
    rtlunittest::
#endif
    OStringLiteral L>
constexpr
#if defined RTL_STRING_UNITTEST
    rtlunittest::
#endif
    OString
operator ""_ostr() {
    return
#if defined RTL_STRING_UNITTEST
        rtlunittest
#else
        rtl
#endif
        ::detail::OStringHolder<L>::literal;
}

#endif

/// @cond INTERNAL
/**
  Make OString hashable by default for use in STL containers.
diff --git a/include/rtl/ustring.hxx b/include/rtl/ustring.hxx
index c4869f4..67275ee 100644
--- a/include/rtl/ustring.hxx
+++ b/include/rtl/ustring.hxx
@@ -86,8 +86,6 @@ This class is not part of public API and is meant to be used only in LibreOffice
template<std::size_t N> class SAL_WARN_UNUSED OUStringLiteral {
    static_assert(N != 0);
    static_assert(N - 1 <= std::numeric_limits<sal_Int32>::max(), "literal too long");
    friend class OUString;
    friend class OUStringConstExpr;

public:
#if HAVE_CPP_CONSTEVAL
@@ -128,6 +126,9 @@ private:
        sal_Unicode buffer[N] = {}; //TODO: drop initialization for C++20 (P1331R2)
    };

public:
    // (Data members must be public so that OUStringLiteral is a structural type that can be used as
    // a non-type template parameter type for rtl::detail::OUStringHolder:)
    union {
        rtl_uString str;
        Data more = {};
@@ -3413,6 +3414,18 @@ inline bool operator !=(StringConcatenation<char16_t> const & lhs, OUString cons
#if defined LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"
/// @cond INTERNAL

#if __cplusplus >= 202002L

namespace detail {

template<OUStringLiteral L> struct OUStringHolder {
    static constexpr auto & literal = L;
};

}

#endif

/**
 @internal
*/
@@ -3576,6 +3589,30 @@ using ::rtl::OUStringChar;
using ::rtl::Concat2View;
#endif

#if defined LIBO_INTERNAL_ONLY && __cplusplus >= 202002L

template<
#if defined RTL_STRING_UNITTEST
    rtlunittest::
#endif
    OUStringLiteral L>
constexpr
#if defined RTL_STRING_UNITTEST
    rtlunittest::
#endif
    OUString
operator ""_ostr() {
    return
#if defined RTL_STRING_UNITTEST
        rtlunittest
#else
        rtl
#endif
        ::detail::OUStringHolder<L>::literal;
}

#endif

/// @cond INTERNAL
/**
  Make OUString hashable by default for use in STL containers.
diff --git a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
index ec0faec..8cfc3a6 100644
--- a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
@@ -31,6 +31,7 @@ private:
    void checkUsage();
    void checkNonConstUsage();
    void checkBuffer();
    void checkOstr();

    void testcall( const char str[] );

@@ -46,6 +47,7 @@ CPPUNIT_TEST(checkConstexprCtor);
CPPUNIT_TEST(checkUsage);
CPPUNIT_TEST(checkNonConstUsage);
CPPUNIT_TEST(checkBuffer);
CPPUNIT_TEST(checkOstr);
CPPUNIT_TEST_SUITE_END();
};

@@ -273,6 +275,14 @@ void test::ostring::StringLiterals::checkBuffer()
    CPPUNIT_ASSERT( !rtl_string_unittest_const_literal_function );
}

void test::ostring::StringLiterals::checkOstr() {
#if __cplusplus >= 202002L
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ""_ostr.getLength());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), "foobar"_ostr.getLength());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), "foo\0bar"_ostr.getLength());
#endif
}

#undef CONST_CTOR_USED

} // namespace
diff --git a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
index 0caa3fc..d2f471b 100644
--- a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx
@@ -41,6 +41,7 @@ private:
    void checkOUStringChar();
    void checkUtf16();
    void checkEmbeddedNul();
    void checkOstr();

    void testcall( const char str[] );

@@ -56,6 +57,7 @@ CPPUNIT_TEST(checkOUStringLiteral);
CPPUNIT_TEST(checkOUStringChar);
CPPUNIT_TEST(checkUtf16);
CPPUNIT_TEST(checkEmbeddedNul);
CPPUNIT_TEST(checkOstr);
CPPUNIT_TEST_SUITE_END();
};

@@ -425,6 +427,14 @@ void test::oustring::StringLiterals::checkEmbeddedNul() {
/*TODO*/
}

void test::oustring::StringLiterals::checkOstr() {
#if __cplusplus >= 202002L
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), u""_ostr.getLength());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), u"foobar"_ostr.getLength());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), u"foo\0bar"_ostr.getLength());
#endif
}

} // namespace

CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringLiterals);