QString: de-inline toStdString() so we can avoid a QByteArray temporary

We can simply write the UTF-8 string into the std::string buffer,
bypassing our temporary. And when Qt is compiled with C++23, we even get
resize_and_overwrite() support, removing the unnecessary memset() -
though the compiler might have been smart enough to suppress it (GCC and
Clang currently aren't that smart; in fact, GCC even generates code to
deal with a default-constructed std::string not being empty).

Change-Id: I3883268b30a9065757dcfffd6da4705a4aa44d7a
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
This commit is contained in:
Thiago Macieira 2025-01-27 14:02:44 -08:00
parent f846754663
commit 3b73bc463d
4 changed files with 31 additions and 9 deletions

View File

@ -9374,6 +9374,26 @@ QString::iterator QString::erase(QString::const_iterator first, QString::const_i
\sa toLatin1(), toUtf8(), toLocal8Bit(), QByteArray::toStdString()
*/
std::string QString::toStdString() const
{
std::string result;
if (isEmpty())
return result;
auto writeToBuffer = [this](char *out, size_t) {
char *last = QUtf8::convertFromUnicode(out, *this);
return last - out;
};
size_t maxSize = size() * 3; // worst case for UTF-8
#ifdef __cpp_lib_string_resize_and_overwrite
// C++23
result.resize_and_overwrite(maxSize, writeToBuffer);
#else
result.resize(maxSize);
result.resize(writeToBuffer(result.data(), result.size()));
#endif
return result;
}
/*!
\fn QString QString::fromRawData(const char16_t *unicode, qsizetype size)

View File

@ -1086,7 +1086,7 @@ public:
}
static inline QString fromStdString(const std::string &s);
inline std::string toStdString() const;
std::string toStdString() const;
static inline QString fromStdWString(const std::wstring &s);
inline std::wstring toStdWString() const;
@ -1573,9 +1573,6 @@ QT_ASCII_CAST_WARN inline QString operator+(QString &&lhs, const QByteArray &rhs
# endif // QT_NO_CAST_FROM_ASCII
#endif // QT_USE_QSTRINGBUILDER
std::string QString::toStdString() const
{ return toUtf8().toStdString(); }
QString QString::fromStdString(const std::string &s)
{ return fromUtf8(s.data(), qsizetype(s.size())); }

View File

@ -691,6 +691,14 @@ char *QUtf8::convertFromUnicode(char *out, QStringView in, OnErrorLambda &&onErr
return reinterpret_cast<char *>(dst);
}
char *QUtf8::convertFromUnicode(char *dst, QStringView in) noexcept
{
return convertFromUnicode(dst, in, [](auto *dst, ...) {
// encoding error - append '?'
*dst++ = '?';
});
}
QByteArray QUtf8::convertFromUnicode(QStringView in)
{
qsizetype len = in.size();
@ -698,11 +706,7 @@ QByteArray QUtf8::convertFromUnicode(QStringView in)
// create a QByteArray with the worst case scenario size
QByteArray result(len * 3, Qt::Uninitialized);
char *dst = const_cast<char *>(result.constData());
dst = convertFromUnicode(dst, in, [](auto *dst, ...) {
// encoding error - append '?'
*dst++ = '?';
});
dst = convertFromUnicode(dst, in);
result.truncate(dst - result.constData());
return result;
}

View File

@ -320,6 +320,7 @@ struct QUtf8
static char16_t *convertToUnicode(char16_t *dst, QByteArrayView in, QStringConverter::State *state);
static char *convertFromUnicode(char *dst, QStringView in) noexcept;
Q_CORE_EXPORT static QByteArray convertFromUnicode(QStringView in);
Q_CORE_EXPORT static QByteArray convertFromUnicode(QStringView in, QStringConverter::State *state);
static char *convertFromUnicode(char *out, QStringView in, QStringConverter::State *state);