QStringConverter: port encodingForName() to QAnyStringView

These kinds of lookup functions are no-brainers for QAnyStringView.

This is required to replace the QStringEncoder/Decoder constructors
from QString, newly added for 6.8, and found in API review to be
better written using QAnyStringView.

Because this is API-Review-relevant, keep the QStringView case
pessimized. It's not worse than the code that it replaces (toLatin1()
on an unshared QString performs in-place conversion), and can be
improved later.

[ChangeLog][QtCore][QStringConverter] The encodingForName() function
now takes QAnyStringView (was: const char*).

Pick-to: 6.8
Task-number: QTBUG-126108
Change-Id: I02cc53bfbc8f1eebe539816487a10b39e96fac2d
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2024-06-05 20:55:22 +02:00
parent 776982a14e
commit b3edce58e5
3 changed files with 35 additions and 6 deletions

View File

@ -1138,6 +1138,13 @@ bool QtPrivate::ResultIteratorBase::operator!=(const QtPrivate::ResultIteratorBa
#include "qstring.h" // inlined API
#include "qstringconverter.h"
auto QStringConverter::encodingForName(const char *name) noexcept -> std::optional<Encoding>
{
return encodingForName(QAnyStringView{name});
}
#if QT_CONFIG(thread)
# include "qthreadpool.h" // inlined API
#endif

View File

@ -1910,20 +1910,37 @@ const QStringConverter::Interface QStringConverter::encodingInterfaces[QStringCo
};
// match names case insensitive and skipping '-' and '_'
static bool nameMatch(const char *a, const char *b)
static bool nameMatch_impl(const char *a, QLatin1StringView rhs)
{
const char *b = rhs.data();
const char *b_end = rhs.end();
do {
while (*a == '-' || *a == '_')
++a;
while (*b == '-' || *b == '_')
while (b != b_end && (*b == '-' || *b == '_'))
++b;
if (!*a && !*b) // end of both strings
if (!*a && b == b_end) // end of both strings
return true;
} while (QtMiscUtils::toAsciiLower(*a++) == QtMiscUtils::toAsciiLower(*b++));
return false;
}
static bool nameMatch_impl(const char *a, QUtf8StringView b)
{
return nameMatch_impl(a, QLatin1StringView{QByteArrayView{b}});
}
static bool nameMatch_impl(const char *a, QStringView b)
{
return nameMatch_impl(a, QLatin1StringView{b.toString().toLatin1()}); // ### optimize
}
static bool nameMatch(const char *a, QAnyStringView b)
{
return b.visit([a](auto b) { return nameMatch_impl(a, b); });
}
/*!
\fn constexpr QStringConverter::QStringConverter()
@ -2237,11 +2254,12 @@ const char *QStringConverter::name() const noexcept
the QStringConverter constructor when Qt is built with ICU, if ICU provides a
converter with the given name.
\a name is expected to be UTF-8 encoded.
\note In Qt versions prior to 6.8, this function took only a \c{const char *},
which was expected to be UTF-8-encoded.
*/
std::optional<QStringConverter::Encoding> QStringConverter::encodingForName(const char *name) noexcept
std::optional<QStringConverter::Encoding> QStringConverter::encodingForName(QAnyStringView name) noexcept
{
if (!name)
if (name.isEmpty())
return std::nullopt;
for (qsizetype i = 0; i < LastEncoding + 1; ++i) {
if (nameMatch(encodingInterfaces[i].name, name))

View File

@ -14,6 +14,7 @@
#include <QtCore/qglobal.h> // QT_{BEGIN,END}_NAMESPACE
#include <QtCore/qflags.h> // Q_DECLARE_FLAGS
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qstringfwd.h>
#include <cstring>
@ -156,7 +157,10 @@ public:
Q_CORE_EXPORT const char *name() const noexcept;
#if QT_CORE_REMOVED_SINCE(6, 8)
Q_CORE_EXPORT static std::optional<Encoding> encodingForName(const char *name) noexcept;
#endif
Q_CORE_EXPORT static std::optional<Encoding> encodingForName(QAnyStringView name) noexcept;
Q_CORE_EXPORT static const char *nameForEncoding(Encoding e);
Q_CORE_EXPORT static std::optional<Encoding>
encodingForData(QByteArrayView data, char16_t expectedFirstCharacter = 0) noexcept;