summaryrefslogtreecommitdiffstats
path: root/include/rtl
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2021-04-19 11:41:47 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2021-04-20 15:30:50 +0200
commit21584b304b21bfe6b99b6f29018c6b754ea28fc0 (patch)
tree34dad49f040259e005422902b10cf1d8d9b81096 /include/rtl
parentsw bibliography table, text generator: handle relative URLs (diff)
downloadcore-21584b304b21bfe6b99b6f29018c6b754ea28fc0.tar.gz
core-21584b304b21bfe6b99b6f29018c6b754ea28fc0.zip
make OUString(OUStringLiteral) constructor constexpr
with the intent that we can declare static const OUStringLiteral FOO = "bar"; static const struct { OUString s; } xxx = { FOO }; and have the xxx laid out at compile time. Kudos to mikekaganski for coming up with the idea of using the rtl_uString struct inside OUStringLiteral. We are using a union to defeat the array bounds checking that the compiler does when it evaluates constexpr values, so this might be brittle. Change-Id: I9a6247a17afab2eb28df139d532a8d864c49cd62 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114196 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'include/rtl')
-rw-r--r--include/rtl/ustring.hxx52
1 files changed, 31 insertions, 21 deletions
diff --git a/include/rtl/ustring.hxx b/include/rtl/ustring.hxx
index bb3390c19985..e1ae2d38f2d9 100644
--- a/include/rtl/ustring.hxx
+++ b/include/rtl/ustring.hxx
@@ -83,6 +83,7 @@ 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;
public:
#if HAVE_CPP_CONSTEVAL
@@ -95,35 +96,44 @@ public:
assert(literal[N - 1] == '\0');
//TODO: Use C++20 constexpr std::copy_n (P0202R3):
for (std::size_t i = 0; i != N; ++i) {
- buffer[i] = literal[i];
+ more.buffer[i] = literal[i];
}
}
- constexpr sal_Int32 getLength() const { return length; }
+ constexpr sal_Int32 getLength() const { return more.length; }
- constexpr sal_Unicode const * getStr() const SAL_RETURNS_NONNULL { return buffer; }
+ constexpr sal_Unicode const * getStr() const SAL_RETURNS_NONNULL { return more.buffer; }
- constexpr operator std::u16string_view() const { return {buffer, sal_uInt32(length)}; }
+ constexpr operator std::u16string_view() const { return {more.buffer, sal_uInt32(more.length)}; }
private:
static constexpr void assertLayout() {
// These static_asserts verifying the layout compatibility with rtl_uString cannot be class
// member declarations, as offsetof requires a complete type, so defer them to here:
- static_assert(offsetof(OUStringLiteral, refCount) == offsetof(rtl_uString, refCount));
- static_assert(std::is_same_v<decltype(refCount), decltype(rtl_uString::refCount)>);
- static_assert(offsetof(OUStringLiteral, length) == offsetof(rtl_uString, length));
- static_assert(std::is_same_v<decltype(length), decltype(rtl_uString::length)>);
- static_assert(offsetof(OUStringLiteral, buffer) == offsetof(rtl_uString, buffer));
- static_assert(
- std::is_same_v<
- std::remove_extent_t<decltype(buffer)>,
- std::remove_extent_t<decltype(rtl_uString::buffer)>>);
- }
-
- // Same layout as rtl_uString (include/rtl/ustring.h):
- oslInterlockedCount refCount = 0x40000000; // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx)
- sal_Int32 length = N - 1;
- sal_Unicode buffer[N] = {}; //TODO: drop initialization for C++20 (P1331R2)
+ static_assert(offsetof(OUStringLiteral, str.refCount) == offsetof(OUStringLiteral, more.refCount));
+ static_assert(offsetof(OUStringLiteral, str.length) == offsetof(OUStringLiteral, more.length));
+ static_assert(offsetof(OUStringLiteral, str.buffer) == offsetof(OUStringLiteral, more.buffer));
+ }
+
+#if defined(_WIN32)
+#pragma pack(push, 4)
+#endif
+ union {
+ rtl_uString str;
+ struct {
+ oslInterlockedCount refCount;
+ sal_Int32 length;
+ sal_Unicode buffer[N];
+ } more =
+ {
+ 0x40000000, // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx)
+ N - 1,
+ {} //TODO: drop initialization for C++20 (P1331R2)
+ };
+ };
+#if defined(_WIN32)
+#pragma pack(pop)
+#endif
};
#if defined RTL_STRING_UNITTEST
@@ -385,8 +395,8 @@ public:
@since LibreOffice 5.0
*/
- template<std::size_t N> OUString(OUStringLiteral<N> const & literal):
- pData(const_cast<rtl_uString *>(reinterpret_cast<rtl_uString const *>(&literal))) {}
+ template<std::size_t N> constexpr OUString(OUStringLiteral<N> const & literal):
+ pData(const_cast<rtl_uString *>(&literal.str)) {}
template<std::size_t N> OUString(OUStringLiteral<N> &&) = delete;
/// @endcond
#endif