QString: toward UTF-8 arg() support [4/4]: accept QAnyStringViews (incl. UTF-8 ones)
This is the public API for the functionality already implemented in pt.1 of this patch series (except the replacement of the remaining Q_UNREACHABLE). I opted to do the minimal change to enable this important functionality: the ArgBase hierarchy stays and gets extended a bit differently than originally envisioned. ArgBase, of course, is just yet another QAnyStringView re-implementation, so eventually, this will go. But the churn to do this in a binary-compatible way would just be too big. Instead of the U8 tag representing UTF-8 arguments, repurpose this up-to-now unused tag to mean QAnyStringView. This allows to get rid of the qStringLikeToArg() overloads, leaving only one accepting QAnyStringView. This is the only one that new code will ever call. But we still need to support L1 and U16 ArgBases for old code. [ChangeLog][QtCore][QString/QStringView/QAnyStringView] Added (multi-)arg() support for UTF-8 (QUtf8StringView) and QAnyStringView arguments. Passing C string literals or QByteArrays to arg() now no longer implicitly converts to QString first. Fixes: QTBUG-124365 Change-Id: I0d710365a45d2c62af26184e8a857c3f4cdeeae2 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
563ed822f8
commit
f7e8e54d7e
@ -9113,8 +9113,8 @@ static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const A
|
||||
case ArgBase::L1:
|
||||
part.reset(static_cast<const QLatin1StringArg&>(arg).string);
|
||||
break;
|
||||
case ArgBase::U8:
|
||||
Q_UNREACHABLE(); // waiting for QUtf8String...
|
||||
case ArgBase::Any:
|
||||
part.reset(static_cast<const QAnyStringArg&>(arg).string);
|
||||
break;
|
||||
case ArgBase::U16:
|
||||
part.reset(static_cast<const QStringViewArg&>(arg).string);
|
||||
|
@ -337,12 +337,6 @@ private:
|
||||
QString arg_impl(double a, int fieldWidth, char format, int precision, QChar fillChar) const;
|
||||
QString arg_impl(QAnyStringView a, int fieldWidth, QChar fillChar) const;
|
||||
|
||||
template <typename T>
|
||||
using is_convertible_to_view_or_qstring = std::disjunction<
|
||||
std::is_convertible<T, QString>,
|
||||
std::is_convertible<T, QStringView>,
|
||||
std::is_convertible<T, QLatin1StringView>
|
||||
>;
|
||||
public:
|
||||
template <typename...Args>
|
||||
[[nodiscard]]
|
||||
@ -350,10 +344,7 @@ public:
|
||||
QString
|
||||
#else
|
||||
typename std::enable_if<
|
||||
sizeof...(Args) >= 2 && std::is_same<
|
||||
QtPrivate::BoolList<is_convertible_to_view_or_qstring<Args>::value..., true>,
|
||||
QtPrivate::BoolList<true, is_convertible_to_view_or_qstring<Args>::value...>
|
||||
>::value,
|
||||
sizeof...(Args) >= 2 && std::conjunction_v<is_string_like<Args>...>,
|
||||
QString
|
||||
>::type
|
||||
#endif
|
||||
@ -1644,7 +1635,7 @@ inline QString &&asString(QString &&s) { return std::move(s); }
|
||||
namespace QtPrivate {
|
||||
|
||||
struct ArgBase {
|
||||
enum Tag : uchar { L1, U8, U16 } tag;
|
||||
enum Tag : uchar { L1, Any, U16 } tag;
|
||||
};
|
||||
|
||||
struct QStringViewArg : ArgBase {
|
||||
@ -1659,6 +1650,12 @@ struct QLatin1StringArg : ArgBase {
|
||||
constexpr explicit QLatin1StringArg(QLatin1StringView v) noexcept : ArgBase{L1}, string{v} {}
|
||||
};
|
||||
|
||||
struct QAnyStringArg : ArgBase {
|
||||
QAnyStringView string;
|
||||
QAnyStringArg() = default;
|
||||
constexpr explicit QAnyStringArg(QAnyStringView v) noexcept : ArgBase{Any}, string{v} {}
|
||||
};
|
||||
|
||||
#if QT_CORE_REMOVED_SINCE(6, 9)
|
||||
[[nodiscard]] Q_CORE_EXPORT QString argToQString(QStringView pattern, size_t n, const ArgBase **args);
|
||||
[[nodiscard]] Q_CORE_EXPORT QString argToQString(QLatin1StringView pattern, size_t n, const ArgBase **args);
|
||||
@ -1672,10 +1669,7 @@ template <typename...Args>
|
||||
return QtPrivate::argToQString(pattern, sizeof...(Args), argBases);
|
||||
}
|
||||
|
||||
inline QStringViewArg qStringLikeToArg(const QString &s) noexcept { return QStringViewArg{qToStringViewIgnoringNull(s)}; }
|
||||
constexpr inline QStringViewArg qStringLikeToArg(QStringView s) noexcept { return QStringViewArg{s}; }
|
||||
inline QStringViewArg qStringLikeToArg(const QChar &c) noexcept { return QStringViewArg{QStringView{&c, 1}}; }
|
||||
constexpr inline QLatin1StringArg qStringLikeToArg(QLatin1StringView s) noexcept { return QLatin1StringArg{s}; }
|
||||
constexpr inline QAnyStringArg qStringLikeToArg(QAnyStringView s) noexcept { return QAnyStringArg{s}; }
|
||||
|
||||
} // namespace QtPrivate
|
||||
|
||||
|
@ -517,12 +517,13 @@ QT_BEGIN_NAMESPACE
|
||||
the \a args replaces the \c{%N} with the lowest \c{N} (all of them), the
|
||||
second of the \a args the \c{%N} with the next-lowest \c{N} etc.
|
||||
|
||||
\c Args can consist of anything that implicitly converts to QString,
|
||||
QStringView or QLatin1StringView.
|
||||
|
||||
In addition, the following types are also supported: QChar, QLatin1Char.
|
||||
\c Args can consist of anything that implicitly converts to QAnyStringView.
|
||||
//![qstring-multi-arg]
|
||||
|
||||
\note In Qt versions prior to 6.9, QAnyStringView and UTF-8 strings
|
||||
(QUtf8StringView, QByteArray, QByteArrayView, \c{const char8_t*}, etc) were
|
||||
not supported as \a args.
|
||||
|
||||
\sa QString::arg()
|
||||
*/
|
||||
|
||||
|
@ -1014,10 +1014,12 @@ void tst_QAnyStringView::arg() const
|
||||
#undef CHECK2
|
||||
#undef CHECK1
|
||||
|
||||
QCOMPARE_EQ(QAnyStringView(u8"ä %2 %2—%1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'),
|
||||
u"ä \r \r—c C "_s);
|
||||
QCOMPARE_EQ(QUtf8StringView(u8"ä %2 %2—%1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'),
|
||||
u"ä \r \r—c C "_s);
|
||||
QCOMPARE_EQ(QAnyStringView(u8"ä %2 %2—%1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u8"Ç"),
|
||||
u"ä \r \r—c Ç "_s);
|
||||
QCOMPARE_EQ(QUtf8StringView(u8"ä %2 %2—%1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, "Ç"),
|
||||
u"ä \r \r—c Ç "_s);
|
||||
QCOMPARE_EQ(QUtf8StringView(u8"ä %2 %2—%1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, "Ç"_ba),
|
||||
u"ä \r \r—c Ç "_s);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QAnyStringView)
|
||||
|
@ -550,7 +550,7 @@ private:
|
||||
|
||||
private Q_SLOTS:
|
||||
// let Formats = {QString, QStringView, QLatin1String, QUtf8StringView, QAnyStringView}
|
||||
// let Arguments = Formats ∪ {QByteArray, const char*, const char8_t*. const char16_t*, std::u16string, char, QChar, QLatin1Char, char16_t}
|
||||
// let Arguments = Formats ∪ {QByteArray/View, const char*, const char8_t*, const char16_t*, std::u16string, char, QChar, QLatin1Char, char16_t}
|
||||
// test Formats × Arguments:
|
||||
void arg1_QString_QString_data() { arg1_data(); }
|
||||
void arg1_QString_QString() { arg1_impl<QString, QString>(); }
|
||||
@ -595,8 +595,18 @@ private Q_SLOTS:
|
||||
void arg1_QStringView_QStringView() { arg1_impl<QStringView, QStringView>(); }
|
||||
void arg1_QStringView_QLatin1StringView_data() { arg1_data(); }
|
||||
void arg1_QStringView_QLatin1StringView() { arg1_impl<QStringView, QLatin1StringView>(); }
|
||||
void arg1_QStringView_QUtf8StringView_data() { arg1_data(); }
|
||||
void arg1_QStringView_QUtf8StringView() { arg1_impl<QStringView, QUtf8StringView>(); }
|
||||
void arg1_QStringView_QAnyStringViewUsingL1_data() { arg1_data(); }
|
||||
void arg1_QStringView_QAnyStringViewUsingL1() { arg1_impl<QStringView, QAnyStringViewUsingL1>(); }
|
||||
void arg1_QStringView_QAnyStringViewUsingU8_data() { arg1_data(); }
|
||||
void arg1_QStringView_QAnyStringViewUsingU8() { arg1_impl<QStringView, QAnyStringViewUsingU8>(); }
|
||||
void arg1_QStringView_QAnyStringViewUsingU16_data() { arg1_data(); }
|
||||
void arg1_QStringView_QAnyStringViewUsingU16() { arg1_impl<QStringView, QAnyStringViewUsingU16>(); }
|
||||
void arg1_QStringView_QByteArray_data() { arg1_data(); }
|
||||
void arg1_QStringView_QByteArray() { arg1_impl<QStringView, QByteArray>(); }
|
||||
void arg1_QStringView_QByteArrayView_data() { arg1_data(); }
|
||||
void arg1_QStringView_QByteArrayView() { arg1_impl<QStringView, QByteArrayView>(); }
|
||||
void arg1_QStringView_const_char_star_data() { arg1_data(); }
|
||||
void arg1_QStringView_const_char_star() { arg1_impl<QStringView, const char*>(); }
|
||||
void arg1_QStringView_const_char8_t_star_data() { arg1_data(); }
|
||||
@ -620,8 +630,18 @@ private Q_SLOTS:
|
||||
void arg1_QLatin1StringView_QStringView() { arg1_impl<QLatin1StringView, QStringView>(); }
|
||||
void arg1_QLatin1StringView_QLatin1StringView_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_QLatin1StringView() { arg1_impl<QLatin1StringView, QLatin1StringView>(); }
|
||||
void arg1_QLatin1StringView_QUtf8StringView_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_QUtf8StringView() { arg1_impl<QLatin1StringView, QUtf8StringView>(); }
|
||||
void arg1_QLatin1StringView_QAnyStringViewUsingL1_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_QAnyStringViewUsingL1() { arg1_impl<QLatin1StringView, QAnyStringViewUsingL1>(); }
|
||||
void arg1_QLatin1StringView_QAnyStringViewUsingU8_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_QAnyStringViewUsingU8() { arg1_impl<QLatin1StringView, QAnyStringViewUsingU8>(); }
|
||||
void arg1_QLatin1StringView_QAnyStringViewUsingU16_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_QAnyStringViewUsingU16() { arg1_impl<QLatin1StringView, QAnyStringViewUsingU16>(); }
|
||||
void arg1_QLatin1StringView_QByteArray_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_QByteArray() { arg1_impl<QLatin1StringView, QByteArray>(); }
|
||||
void arg1_QLatin1StringView_QByteArrayView_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_QByteArrayView() { arg1_impl<QLatin1StringView, QByteArrayView>(); }
|
||||
void arg1_QLatin1StringView_const_char_star_data() { arg1_data(); }
|
||||
void arg1_QLatin1StringView_const_char_star() { arg1_impl<QLatin1StringView, const char*>(); }
|
||||
void arg1_QLatin1StringView_const_char8_t_star_data() { arg1_data(); }
|
||||
@ -645,8 +665,18 @@ private Q_SLOTS:
|
||||
void arg1_QUtf8StringView_QStringView() { arg1_impl<QUtf8StringView, QStringView>(); }
|
||||
void arg1_QUtf8StringView_QLatin1StringView_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_QLatin1StringView() { arg1_impl<QUtf8StringView, QLatin1StringView>(); }
|
||||
void arg1_QUtf8StringView_QUtf8StringView_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_QUtf8StringView() { arg1_impl<QUtf8StringView, QUtf8StringView>(); }
|
||||
void arg1_QUtf8StringView_QAnyStringViewUsingL1_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_QAnyStringViewUsingL1() { arg1_impl<QUtf8StringView, QAnyStringViewUsingL1>(); }
|
||||
void arg1_QUtf8StringView_QAnyStringViewUsingU8_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_QAnyStringViewUsingU8() { arg1_impl<QUtf8StringView, QAnyStringViewUsingU8>(); }
|
||||
void arg1_QUtf8StringView_QAnyStringViewUsingU16_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_QAnyStringViewUsingU16() { arg1_impl<QUtf8StringView, QAnyStringViewUsingU16>(); }
|
||||
void arg1_QUtf8StringView_QByteArray_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_QByteArray() { arg1_impl<QUtf8StringView, QByteArray>(); }
|
||||
void arg1_QUtf8StringView_QByteArrayView_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_QByteArrayView() { arg1_impl<QUtf8StringView, QByteArrayView>(); }
|
||||
void arg1_QUtf8StringView_const_char_star_data() { arg1_data(); }
|
||||
void arg1_QUtf8StringView_const_char_star() { arg1_impl<QUtf8StringView, const char*>(); }
|
||||
void arg1_QUtf8StringView_const_char8_t_star_data() { arg1_data(); }
|
||||
@ -670,8 +700,18 @@ private Q_SLOTS:
|
||||
void arg1_QAnyStringViewUsingL1_QStringView() { arg1_impl<QAnyStringViewUsingL1, QStringView>(); }
|
||||
void arg1_QAnyStringViewUsingL1_QLatin1StringView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_QLatin1StringView() { arg1_impl<QAnyStringViewUsingL1, QLatin1StringView>(); }
|
||||
void arg1_QAnyStringViewUsingL1_QUtf8StringView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_QUtf8StringView() { arg1_impl<QAnyStringViewUsingL1, QUtf8StringView>(); }
|
||||
void arg1_QAnyStringViewUsingL1_QAnyStringViewUsingL1_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_QAnyStringViewUsingL1() { arg1_impl<QAnyStringViewUsingL1, QAnyStringViewUsingL1>(); }
|
||||
void arg1_QAnyStringViewUsingL1_QAnyStringViewUsingU8_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_QAnyStringViewUsingU8() { arg1_impl<QAnyStringViewUsingL1, QAnyStringViewUsingU8>(); }
|
||||
void arg1_QAnyStringViewUsingL1_QAnyStringViewUsingU16_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_QAnyStringViewUsingU16() { arg1_impl<QAnyStringViewUsingL1, QAnyStringViewUsingU16>(); }
|
||||
void arg1_QAnyStringViewUsingL1_QByteArray_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_QByteArray() { arg1_impl<QAnyStringViewUsingL1, QByteArray>(); }
|
||||
void arg1_QAnyStringViewUsingL1_QByteArrayView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_QByteArrayView() { arg1_impl<QAnyStringViewUsingL1, QByteArrayView>(); }
|
||||
void arg1_QAnyStringViewUsingL1_const_char_star_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingL1_const_char_star() { arg1_impl<QAnyStringViewUsingL1, const char*>(); }
|
||||
void arg1_QAnyStringViewUsingL1_const_char8_t_star_data() { arg1_data(); }
|
||||
@ -695,8 +735,18 @@ private Q_SLOTS:
|
||||
void arg1_QAnyStringViewUsingU8_QStringView() { arg1_impl<QAnyStringViewUsingU8, QStringView>(); }
|
||||
void arg1_QAnyStringViewUsingU8_QLatin1StringView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_QLatin1StringView() { arg1_impl<QAnyStringViewUsingU8, QLatin1StringView>(); }
|
||||
void arg1_QAnyStringViewUsingU8_QUtf8StringView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_QUtf8StringView() { arg1_impl<QAnyStringViewUsingU8, QUtf8StringView>(); }
|
||||
void arg1_QAnyStringViewUsingU8_QAnyStringViewUsingL1_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_QAnyStringViewUsingL1() { arg1_impl<QAnyStringViewUsingU8, QAnyStringViewUsingL1>(); }
|
||||
void arg1_QAnyStringViewUsingU8_QAnyStringViewUsingU8_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_QAnyStringViewUsingU8() { arg1_impl<QAnyStringViewUsingU8, QAnyStringViewUsingU8>(); }
|
||||
void arg1_QAnyStringViewUsingU8_QAnyStringViewUsingU16_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_QAnyStringViewUsingU16() { arg1_impl<QAnyStringViewUsingU8, QAnyStringViewUsingU16>(); }
|
||||
void arg1_QAnyStringViewUsingU8_QByteArray_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_QByteArray() { arg1_impl<QAnyStringViewUsingU8, QByteArray>(); }
|
||||
void arg1_QAnyStringViewUsingU8_QByteArrayView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_QByteArrayView() { arg1_impl<QAnyStringViewUsingU8, QByteArrayView>(); }
|
||||
void arg1_QAnyStringViewUsingU8_const_char_star_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU8_const_char_star() { arg1_impl<QAnyStringViewUsingU8, const char*>(); }
|
||||
void arg1_QAnyStringViewUsingU8_const_char8_t_star_data() { arg1_data(); }
|
||||
@ -720,8 +770,18 @@ private Q_SLOTS:
|
||||
void arg1_QAnyStringViewUsingU16_QStringView() { arg1_impl<QAnyStringViewUsingU16, QStringView>(); }
|
||||
void arg1_QAnyStringViewUsingU16_QLatin1StringView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_QLatin1StringView() { arg1_impl<QAnyStringViewUsingU16, QLatin1StringView>(); }
|
||||
void arg1_QAnyStringViewUsingU16_QUtf8StringView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_QUtf8StringView() { arg1_impl<QAnyStringViewUsingU16, QUtf8StringView>(); }
|
||||
void arg1_QAnyStringViewUsingU16_QAnyStringViewUsingL1_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_QAnyStringViewUsingL1() { arg1_impl<QAnyStringViewUsingU16, QAnyStringViewUsingL1>(); }
|
||||
void arg1_QAnyStringViewUsingU16_QAnyStringViewUsingU8_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_QAnyStringViewUsingU8() { arg1_impl<QAnyStringViewUsingU16, QAnyStringViewUsingU8>(); }
|
||||
void arg1_QAnyStringViewUsingU16_QAnyStringViewUsingU16_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_QAnyStringViewUsingU16() { arg1_impl<QAnyStringViewUsingU16, QAnyStringViewUsingU16>(); }
|
||||
void arg1_QAnyStringViewUsingU16_QByteArray_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_QByteArray() { arg1_impl<QAnyStringViewUsingU16, QByteArray>(); }
|
||||
void arg1_QAnyStringViewUsingU16_QByteArrayView_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_QByteArrayView() { arg1_impl<QAnyStringViewUsingU16, QByteArrayView>(); }
|
||||
void arg1_QAnyStringViewUsingU16_const_char_star_data() { arg1_data(); }
|
||||
void arg1_QAnyStringViewUsingU16_const_char_star() { arg1_impl<QAnyStringViewUsingU16, const char*>(); }
|
||||
void arg1_QAnyStringViewUsingU16_const_char8_t_star_data() { arg1_data(); }
|
||||
|
@ -495,7 +495,7 @@ void tst_QStringView::arg() const
|
||||
{
|
||||
// nullness checks
|
||||
QCOMPARE(QStringView().arg(QStringView()), "");
|
||||
QCOMPARE(QStringView(u"%1").arg(QStringView()), "");
|
||||
QCOMPARE(QStringView(u"%1").arg(nullptr), "");
|
||||
|
||||
#define CHECK1(pattern, arg1, expected) \
|
||||
do { \
|
||||
|
Loading…
x
Reference in New Issue
Block a user