From db991cb4e12bca2e4ae72e03c8f078b27517f4e9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 8 Nov 2023 10:44:39 -0800 Subject: [PATCH] QBitArray: replace the member operator~ with a hidden friend Which takes the array to be inverted by value, so we get free move semantics and allowing us to perform the negation in-place. [ChangeLog][Potentially Source-Incompatible Changes] The bitwise AND, OR, XOR, and NOT operator functions on QBitArray are now hidden friends. This may cause source-incompatibility in unusual coding styles (like 'array.operator~()') or with classes that have a casting 'operator QBitArray()'. Change-Id: I85b3fc2dd45c4693be13fffd1795ba1fbaf23769 Reviewed-by: Marc Mutz --- src/corelib/compat/removed_api.cpp | 7 +++++++ src/corelib/tools/qbitarray.cpp | 20 +++++++++++++------ src/corelib/tools/qbitarray.h | 6 ++++++ .../corelib/tools/qbitarray/tst_qbitarray.cpp | 1 + 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index efffb1b9bd0..ac4aea9ef3e 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -618,6 +618,13 @@ QStringView QXmlStreamAttributes::value(QLatin1StringView qualifiedName) const #if QT_CORE_REMOVED_SINCE(6, 7) +#include "qbitarray.h" + +QBitArray QBitArray::operator~() const +{ + return QBitArray(*this).inverted_inplace(); +} + #include "qbytearray.h" QByteArray QByteArray::left(qsizetype len) const diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index 4a3e929909f..54d587517ec 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -583,8 +583,9 @@ QBitArray &QBitArray::operator^=(const QBitArray &other) } /*! - Returns a bit array that contains the inverted bits of this bit - array. + \fn QBitArray QBitArray::operator~(QBitArray a) + Returns a bit array that contains the inverted bits of the bit + array \a a. Example: \snippet code/src_corelib_tools_qbitarray.cpp 11 @@ -592,12 +593,19 @@ QBitArray &QBitArray::operator^=(const QBitArray &other) \sa operator&(), operator|(), operator^() */ -QBitArray QBitArray::operator~() const +Q_NEVER_INLINE QBitArray QBitArray::inverted_inplace() && { qsizetype n = d.size(); - QBitArray result(QByteArrayData(n, n)); - const uchar *src = reinterpret_cast(data_ptr().data()); - uchar *dst = reinterpret_cast(result.data_ptr().data()); + uchar *dst = reinterpret_cast(data_ptr().data()); + const uchar *src = dst; + QBitArray result([&] { + if (d.isDetached() || n == 0) + return std::move(d.data_ptr()); // invert in-place + + QByteArrayData tmp(n, n); + dst = reinterpret_cast(tmp.data()); + return tmp; + }()); uchar bitdiff = 8; if (n) diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h index a1dde3934c3..01afe29eaa8 100644 --- a/src/corelib/tools/qbitarray.h +++ b/src/corelib/tools/qbitarray.h @@ -16,6 +16,8 @@ class Q_CORE_EXPORT QBitArray friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &); #endif friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept; + friend QBitArray operator~(QBitArray a) + { return std::move(a).inverted_inplace(); } QByteArray d; QBitArray(QByteArrayData &&dd) : d(std::move(dd)) {} @@ -32,6 +34,8 @@ class Q_CORE_EXPORT QBitArray return R{ ba.d[1 + byteIdx], uchar(1U << bitIdx) }; } + QBitArray inverted_inplace() &&; + public: inline QBitArray() noexcept {} explicit QBitArray(qsizetype size, bool val = false); @@ -78,7 +82,9 @@ public: QBitArray &operator&=(const QBitArray &); QBitArray &operator|=(const QBitArray &); QBitArray &operator^=(const QBitArray &); +#if QT_CORE_REMOVED_SINCE(6, 7) QBitArray operator~() const; +#endif inline bool operator==(const QBitArray &other) const { return d == other.d; } inline bool operator!=(const QBitArray &other) const { return d != other.d; } diff --git a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp index b205bb76eea..1431221fd5e 100644 --- a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp +++ b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp @@ -454,6 +454,7 @@ void tst_QBitArray::operator_neg() input = ~input; QCOMPARE(input, res); + QCOMPARE(~~input, res); // performs two in-place negations } void tst_QBitArray::datastream_data()