diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2022-01-12 12:49:02 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2022-01-17 19:56:41 -0800 |
commit | 86b346823e114ac0b6b1c2ab6065ce53b1393de0 (patch) | |
tree | 567c2eb6c50caca1c438d855b14f53de0b9ab8bd /src/corelib/text/qstring.cpp | |
parent | a59e7361714d50687d82a2d9abae9e95825a23b6 (diff) |
QString::toLatin1_helper_inplace: simplify the code
Hot function, so help the compiler out. In particular, this removes any
touch to the ref count, so there are no atomic operations or dead code
leading to memory allocations and deallocations.
Change-Id: I0e5f6bec596a4a78bd3bfffd16c9a0fbd8dd2c12
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'src/corelib/text/qstring.cpp')
-rw-r--r-- | src/corelib/text/qstring.cpp | 34 |
1 files changed, 17 insertions, 17 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 23927b0e84..57bed1240f 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -5269,6 +5269,7 @@ QByteArray QtPrivate::convertToLatin1(QStringView string) return qt_convert_to_latin1(string); } +Q_NEVER_INLINE static QByteArray qt_convert_to_latin1(QStringView string) { if (Q_UNLIKELY(string.isNull())) @@ -5290,27 +5291,26 @@ QByteArray QString::toLatin1_helper_inplace(QString &s) // We can return our own buffer to the caller. // Conversion to Latin-1 always shrinks the buffer by half. - const char16_t *data = s.d.data(); - qsizetype length = s.d.size; - - // Move the d pointer over to the bytearray. - // Kids, avert your eyes. Don't try this at home. + // This relies on the fact that we use QArrayData for everything behind the scenes - // this relies on the fact that we use QArrayData for everything behind the scenes which has the same layout - static_assert(sizeof(QByteArray::DataPointer) == sizeof(QString::DataPointer), "sizes have to be equal"); - QByteArray::DataPointer ba_d(reinterpret_cast<QByteArray::Data *>(s.d.d_ptr()), reinterpret_cast<char *>(s.d.data()), length); - ba_d.ref(); - s.clear(); + // First, do the in-place conversion. Since isDetached() == true, the data + // was allocated by QArrayData, so the null terminator must be there. + qsizetype length = s.size(); + char16_t *sdata = s.d->data(); + Q_ASSERT(sdata[length] == u'\0'); + qt_to_latin1(reinterpret_cast<uchar *>(sdata), sdata, length + 1); - char *ddata = ba_d.data(); + // Move the internals over to the byte array. + // Kids, avert your eyes. Don't try this at home. + auto ba_d = std::move(s.d).reinterpreted<char>(); - // multiply the allocated capacity by sizeof(char16_t) - ba_d.d_ptr()->alloc *= sizeof(char16_t); + // Some sanity checks + Q_ASSERT(ba_d.d->allocatedCapacity() >= ba_d.size); + Q_ASSERT(s.isNull()); + Q_ASSERT(s.isEmpty()); + Q_ASSERT(s.constData() == QString().constData()); - // do the in-place conversion - qt_to_latin1(reinterpret_cast<uchar *>(ddata), data, length); - ddata[length] = '\0'; - return QByteArray(ba_d); + return QByteArray(std::move(ba_d)); } /*! |