QString: toward UTF-8 arg() support [3/4]: add Q{Any,Utf8}StringView::arg()

This is the public API for the functionality already implemented in
pt.2 of this patch series.

We can now use UTF-8 format strings, but there's still no way to
interpolate UTF-8 strings into them.

[ChangeLog][QtCore][QUtf8StringView/QAnyStringView] Added
(multi-)arg() support a la QStringView/QLatin1StringView.

Task-number: QTBUG-124365
Change-Id: Ie887e3e89eee6cb997b41e381f143befaad1e08f
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2024-05-21 16:56:39 +02:00
parent bac7f20acd
commit b8500f3efc
8 changed files with 196 additions and 1 deletions

View File

@ -696,5 +696,13 @@ QDebug operator<<(QDebug d, QAnyStringView s)
return d;
}
/*!
\fn template <typename...Args> QString QAnyStringView::arg(Args &&...args) const
\since 6.9
\include qstringview.cpp qstring-multi-arg
\sa QString::arg(Args&&...)
*/
QT_END_NAMESPACE

View File

@ -279,6 +279,8 @@ public:
constexpr void chop(qsizetype n)
{ verify(0, n); setSize(size() - n); }
template <typename...Args>
[[nodiscard]] inline QString arg(Args &&...args) const;
[[nodiscard]] inline QString toString() const; // defined in qstring.h

View File

@ -1621,6 +1621,19 @@ QString QLatin1StringView::arg(Args &&...args) const
return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
}
template <bool HasChar8T>
template <typename...Args>
QString QBasicUtf8StringView<HasChar8T>::arg(Args &&...args) const
{
return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
}
template <typename...Args>
QString QAnyStringView::arg(Args &&...args) const
{
return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
}
template <typename T>
qsizetype erase(QString &s, const T &t)
{

View File

@ -505,6 +505,7 @@ QT_BEGIN_NAMESPACE
\fn template <typename...Args> QString QString::arg(Args &&...args) const
\since 5.14
//![qstring-multi-arg]
Replaces occurrences of \c{%N} in this string with the corresponding
argument from \a args. The arguments are not positional: the first of
the \a args replaces the \c{%N} with the lowest \c{N} (all of them), the
@ -514,6 +515,7 @@ QT_BEGIN_NAMESPACE
QStringView or QLatin1StringView.
In addition, the following types are also supported: QChar, QLatin1Char.
//![qstring-multi-arg]
\sa QString::arg()
*/

View File

@ -215,6 +215,9 @@ public:
[[nodiscard]] constexpr storage_type at(qsizetype n) const { return (*this)[n]; }
template <typename...Args>
[[nodiscard]] inline QString arg(Args &&...args) const;
[[nodiscard]]
constexpr QBasicUtf8StringView mid(qsizetype pos, qsizetype n = -1) const
{

View File

@ -761,3 +761,12 @@
Returns maxSize().
*/
/*!
\fn template <typename...Args> QString QUtf8StringView::arg(Args &&...args) const
\since 6.9
\include qstringview.cpp qstring-multi-arg
\sa QString::arg(Args&&...)
*/

View File

@ -399,6 +399,8 @@ private Q_SLOTS:
void comparison_data();
void comparison();
void arg() const;
private:
template <typename StringBuilder>
void fromQStringBuilder(StringBuilder &&sb, QStringView expected) const;
@ -962,5 +964,61 @@ void tst_QAnyStringView::comparison()
}
}
void tst_QAnyStringView::arg() const
{
// nullness checks
QCOMPARE(QAnyStringView().arg(QStringView()), "");
QCOMPARE(QAnyStringView(u"%1").arg(QStringView()), "");
#define CHECK1IMPL(pattern, arg1, expected) \
do { \
auto p = QAnyStringView(pattern); \
QCOMPARE(p.arg(QLatin1StringView(arg1)), expected); \
QCOMPARE(p.arg(u"" arg1), expected); \
QCOMPARE(p.arg(QStringLiteral(arg1)), expected); \
QCOMPARE(p.arg(QString(QLatin1StringView(arg1))), expected); \
} while (false) \
/*end*/
#define CHECK1(pattern, arg1, expected) \
do { \
CHECK1IMPL("" pattern, arg1, expected); \
CHECK1IMPL(u8"" pattern, arg1, expected); \
CHECK1IMPL(pattern ""_L1, arg1, expected); \
CHECK1IMPL(u"" pattern, arg1, expected); \
} while (false) \
/*end*/
#define CHECK2(pattern, arg1, arg2, expected) \
do { \
auto p = QAnyStringView(pattern); \
QCOMPARE(p.arg(QLatin1StringView(arg1), QLatin1StringView(arg2)), expected); \
QCOMPARE(p.arg(u"" arg1, QLatin1StringView(arg2)), expected); \
QCOMPARE(p.arg(QLatin1StringView(arg1), u"" arg2), expected); \
QCOMPARE(p.arg(u"" arg1, u"" arg2), expected); \
} while (false) \
/*end*/
CHECK1("", "World", "");
CHECK1("%1", "World", "World");
CHECK1("!%1?", "World", "!World?");
CHECK1("%1%1", "World", "WorldWorld");
CHECK1("%1%2", "World", "World%2");
CHECK1("%2%1", "World", "%2World");
CHECK2("", "Hello", "World", "");
CHECK2("%1", "Hello", "World", "Hello");
CHECK2("!%1, %2?", "Hello", "World", "!Hello, World?");
CHECK2("%1%1", "Hello", "World", "HelloHello");
CHECK2("%1%2", "Hello", "World", "HelloWorld");
CHECK2("%2%1", "Hello", "World", "WorldHello");
#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);
}
QTEST_APPLESS_MAIN(tst_QAnyStringView)
#include "tst_qanystringview.moc"

View File

@ -549,7 +549,7 @@ private:
template <typename Format, typename Argument> void arg1_impl() const;
private Q_SLOTS:
// let Formats = {QString, QStringView, QLatin1String}
// 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}
// test Formats × Arguments:
void arg1_QString_QString_data() { arg1_data(); }
@ -631,6 +631,106 @@ private Q_SLOTS:
void arg1_QLatin1StringView_char16_t_data() { arg1_data(false); }
void arg1_QLatin1StringView_char16_t() { arg1_impl<QLatin1StringView, char16_t>(); }
void arg1_QUtf8StringView_QString_data() { arg1_data(); }
void arg1_QUtf8StringView_QString() { arg1_impl<QUtf8StringView, QString>(); }
void arg1_QUtf8StringView_QStringView_data() { arg1_data(); }
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_QByteArray_data() { arg1_data(); }
void arg1_QUtf8StringView_QByteArray() { arg1_impl<QUtf8StringView, QByteArray>(); }
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(); }
void arg1_QUtf8StringView_const_char8_t_star() { IF_CHAR8T((arg1_impl<QUtf8StringView, const char8_t*>())); }
void arg1_QUtf8StringView_const_char16_t_star_data() { arg1_data(); }
void arg1_QUtf8StringView_const_char16_t_star() { arg1_impl<QUtf8StringView, const char16_t*>(); }
void arg1_QUtf8StringView_stdu16string_data() { arg1_data(); }
void arg1_QUtf8StringView_stdu16string() { arg1_impl<QUtf8StringView, std::u16string>(); }
void arg1_QUtf8StringView_char_data() { arg1_data(false); }
void arg1_QUtf8StringView_char() { arg1_impl<QUtf8StringView, char>(); }
void arg1_QUtf8StringView_QChar_data() { arg1_data(false); }
void arg1_QUtf8StringView_QChar() { arg1_impl<QUtf8StringView, QChar>(); }
void arg1_QUtf8StringView_QLatin1Char_data() { arg1_data(false); }
void arg1_QUtf8StringView_QLatin1Char() { arg1_impl<QUtf8StringView, QLatin1Char>(); }
void arg1_QUtf8StringView_char16_t_data() { arg1_data(false); }
void arg1_QUtf8StringView_char16_t() { arg1_impl<QUtf8StringView, char16_t>(); }
void arg1_QAnyStringViewUsingL1_QString_data() { arg1_data(); }
void arg1_QAnyStringViewUsingL1_QString() { arg1_impl<QAnyStringViewUsingL1, QString>(); }
void arg1_QAnyStringViewUsingL1_QStringView_data() { arg1_data(); }
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_QByteArray_data() { arg1_data(); }
void arg1_QAnyStringViewUsingL1_QByteArray() { arg1_impl<QAnyStringViewUsingL1, QByteArray>(); }
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(); }
void arg1_QAnyStringViewUsingL1_const_char8_t_star() { IF_CHAR8T((arg1_impl<QAnyStringViewUsingL1, const char8_t*>())); }
void arg1_QAnyStringViewUsingL1_const_char16_t_star_data() { arg1_data(); }
void arg1_QAnyStringViewUsingL1_const_char16_t_star() { arg1_impl<QAnyStringViewUsingL1, const char16_t*>(); }
void arg1_QAnyStringViewUsingL1_stdu16string_data() { arg1_data(); }
void arg1_QAnyStringViewUsingL1_stdu16string() { arg1_impl<QAnyStringViewUsingL1, std::u16string>(); }
void arg1_QAnyStringViewUsingL1_char_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingL1_char() { arg1_impl<QAnyStringViewUsingL1, char>(); }
void arg1_QAnyStringViewUsingL1_QChar_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingL1_QChar() { arg1_impl<QAnyStringViewUsingL1, QChar>(); }
void arg1_QAnyStringViewUsingL1_QLatin1Char_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingL1_QLatin1Char() { arg1_impl<QAnyStringViewUsingL1, QLatin1Char>(); }
void arg1_QAnyStringViewUsingL1_char16_t_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingL1_char16_t() { arg1_impl<QAnyStringViewUsingL1, char16_t>(); }
void arg1_QAnyStringViewUsingU8_QString_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU8_QString() { arg1_impl<QAnyStringViewUsingU8, QString>(); }
void arg1_QAnyStringViewUsingU8_QStringView_data() { arg1_data(); }
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_QByteArray_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU8_QByteArray() { arg1_impl<QAnyStringViewUsingU8, QByteArray>(); }
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(); }
void arg1_QAnyStringViewUsingU8_const_char8_t_star() { IF_CHAR8T((arg1_impl<QAnyStringViewUsingU8, const char8_t*>())); }
void arg1_QAnyStringViewUsingU8_const_char16_t_star_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU8_const_char16_t_star() { arg1_impl<QAnyStringViewUsingU8, const char16_t*>(); }
void arg1_QAnyStringViewUsingU8_stdu16string_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU8_stdu16string() { arg1_impl<QAnyStringViewUsingU8, std::u16string>(); }
void arg1_QAnyStringViewUsingU8_char_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU8_char() { arg1_impl<QAnyStringViewUsingU8, char>(); }
void arg1_QAnyStringViewUsingU8_QChar_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU8_QChar() { arg1_impl<QAnyStringViewUsingU8, QChar>(); }
void arg1_QAnyStringViewUsingU8_QLatin1Char_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU8_QLatin1Char() { arg1_impl<QAnyStringViewUsingU8, QLatin1Char>(); }
void arg1_QAnyStringViewUsingU8_char16_t_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU8_char16_t() { arg1_impl<QAnyStringViewUsingU8, char16_t>(); }
void arg1_QAnyStringViewUsingU16_QString_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU16_QString() { arg1_impl<QAnyStringViewUsingU16, QString>(); }
void arg1_QAnyStringViewUsingU16_QStringView_data() { arg1_data(); }
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_QByteArray_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU16_QByteArray() { arg1_impl<QAnyStringViewUsingU16, QByteArray>(); }
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(); }
void arg1_QAnyStringViewUsingU16_const_char8_t_star() { IF_CHAR8T((arg1_impl<QAnyStringViewUsingU16, const char8_t*>())); }
void arg1_QAnyStringViewUsingU16_const_char16_t_star_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU16_const_char16_t_star() { arg1_impl<QAnyStringViewUsingU16, const char16_t*>(); }
void arg1_QAnyStringViewUsingU16_stdu16string_data() { arg1_data(); }
void arg1_QAnyStringViewUsingU16_stdu16string() { arg1_impl<QAnyStringViewUsingU16, std::u16string>(); }
void arg1_QAnyStringViewUsingU16_char_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU16_char() { arg1_impl<QAnyStringViewUsingU16, char>(); }
void arg1_QAnyStringViewUsingU16_QChar_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU16_QChar() { arg1_impl<QAnyStringViewUsingU16, QChar>(); }
void arg1_QAnyStringViewUsingU16_QLatin1Char_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU16_QLatin1Char() { arg1_impl<QAnyStringViewUsingU16, QLatin1Char>(); }
void arg1_QAnyStringViewUsingU16_char16_t_data() { arg1_data(false); }
void arg1_QAnyStringViewUsingU16_char16_t() { arg1_impl<QAnyStringViewUsingU16, char16_t>(); }
private:
void split_data(bool rhsHasVariableLength = true);
template <typename Haystack, typename Needle> void split_impl() const;