summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2017-03-31 12:47:33 +0200
committerMarc Mutz <marc.mutz@kdab.com>2017-04-06 12:06:18 +0000
commite1e6506c8dec6d0fc0fdbb15cfde43e7c0277403 (patch)
treee9e3602783a576ca9c8d1e867098fd2024677635
parent0a5b6106799b25cfd1ab9de2e74098e99a8b13cb (diff)
QString: add QStringView/QLatin1String overload of (non-multi) arg()
Use the new overload directly in QXmlStream*. Saves 129B in QtCore text size on optimized GCC 6.1 Linux AMD64 builds, even though we added two more functions. [ChangeLog][QtCore][QString] Added arg(QStringView), arg(QLatin1String) overloads. Change-Id: Idf7236dcab763824593f34182e4e0b16b5ed4321 Reviewed-by: Anton Kudryavtsev <antkudr@mail.ru> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
-rw-r--r--src/corelib/doc/snippets/qstring/main.cpp11
-rw-r--r--src/corelib/tools/qstring.cpp94
-rw-r--r--src/corelib/tools/qstring.h6
-rw-r--r--src/corelib/xml/qxmlstream.cpp8
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp12
5 files changed, 109 insertions, 22 deletions
diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp
index dd65fad4e3..3a6f6483fb 100644
--- a/src/corelib/doc/snippets/qstring/main.cpp
+++ b/src/corelib/doc/snippets/qstring/main.cpp
@@ -262,6 +262,17 @@ void Widget::argFunction()
.arg(i).arg(total).arg(fileName);
//! [11]
+ {
+ //! [11]
+ int i; // current file's number
+ int total; // number of files to process
+ QStringView fileName; // current file's name
+
+ QString status = QString("Processing file %1 of %2: %3")
+ .arg(i).arg(total).arg(fileName);
+ //! [11]
+ }
+
//! [12] //! [13]
QString str;
//! [12]
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 6c97e2563c..672dda804f 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -7363,10 +7363,10 @@ struct ArgEscapeData
int escape_len; // total length of escape sequences which will be replaced
};
-static ArgEscapeData findArgEscapes(const QString &s)
+static ArgEscapeData findArgEscapes(QStringView s)
{
- const QChar *uc_begin = s.unicode();
- const QChar *uc_end = uc_begin + s.length();
+ const QChar *uc_begin = s.begin();
+ const QChar *uc_end = s.end();
ArgEscapeData d;
@@ -7425,11 +7425,11 @@ static ArgEscapeData findArgEscapes(const QString &s)
return d;
}
-static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int field_width,
- const QString &arg, const QString &larg, QChar fillChar = QLatin1Char(' '))
+static QString replaceArgEscapes(QStringView s, const ArgEscapeData &d, int field_width,
+ QStringView arg, QStringView larg, QChar fillChar)
{
- const QChar *uc_begin = s.unicode();
- const QChar *uc_end = uc_begin + s.length();
+ const QChar *uc_begin = s.begin();
+ const QChar *uc_end = s.end();
int abs_field_width = qAbs(field_width);
int result_len = s.length()
@@ -7493,11 +7493,11 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
}
if (locale_arg) {
- memcpy(rc, larg.unicode(), larg.length()*sizeof(QChar));
+ memcpy(rc, larg.data(), larg.length()*sizeof(QChar));
rc += larg.length();
}
else {
- memcpy(rc, arg.unicode(), arg.length()*sizeof(QChar));
+ memcpy(rc, arg.data(), arg.length()*sizeof(QChar));
rc += arg.length();
}
@@ -7519,6 +7519,7 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
return result;
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a copy of this string with the lowest numbered place marker
replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
@@ -7550,17 +7551,86 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
*/
QString QString::arg(const QString &a, int fieldWidth, QChar fillChar) const
{
+ return arg(QStringView(a), fieldWidth, fillChar);
+}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ \overload
+ \since 5.10
+
+ Returns a copy of this string with the lowest-numbered place-marker
+ replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
+
+ \a fieldWidth specifies the minimum amount of space that \a a
+ shall occupy. If \a a requires less space than \a fieldWidth, it
+ is padded to \a fieldWidth with character \a fillChar. A positive
+ \a fieldWidth produces right-aligned text. A negative \a fieldWidth
+ produces left-aligned text.
+
+ This example shows how we might create a \c status string for
+ reporting progress while processing a list of files:
+
+ \snippet qstring/main.cpp 11-qstringview
+
+ First, \c arg(i) replaces \c %1. Then \c arg(total) replaces \c
+ %2. Finally, \c arg(fileName) replaces \c %3.
+
+ One advantage of using arg() over asprintf() is that the order of the
+ numbered place markers can change, if the application's strings are
+ translated into other languages, but each arg() will still replace
+ the lowest-numbered unreplaced place-marker, no matter where it
+ appears. Also, if place-marker \c %i appears more than once in the
+ string, arg() replaces all of them.
+
+ If there is no unreplaced place-marker remaining, a warning message
+ is printed and the result is undefined. Place-marker numbers must be
+ in the range 1 to 99.
+*/
+QString QString::arg(QStringView a, int fieldWidth, QChar fillChar) const
+{
ArgEscapeData d = findArgEscapes(*this);
- if (d.occurrences == 0) {
- qWarning("QString::arg: Argument missing: %s, %s", toLocal8Bit().data(),
- a.toLocal8Bit().data());
+ if (Q_UNLIKELY(d.occurrences == 0)) {
+ qWarning("QString::arg: Argument missing: %ls, %ls", qUtf16Printable(*this),
+ qUtf16Printable(a.toString()));
return *this;
}
return replaceArgEscapes(*this, d, fieldWidth, a, a, fillChar);
}
/*!
+ \overload
+ \since 5.10
+
+ Returns a copy of this string with the lowest-numbered place-marker
+ replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
+
+ \a fieldWidth specifies the minimum amount of space that \a a
+ shall occupy. If \a a requires less space than \a fieldWidth, it
+ is padded to \a fieldWidth with character \a fillChar. A positive
+ \a fieldWidth produces right-aligned text. A negative \a fieldWidth
+ produces left-aligned text.
+
+ One advantage of using arg() over asprintf() is that the order of the
+ numbered place markers can change, if the application's strings are
+ translated into other languages, but each arg() will still replace
+ the lowest-numbered unreplaced place-marker, no matter where it
+ appears. Also, if place-marker \c %i appears more than once in the
+ string, arg() replaces all of them.
+
+ If there is no unreplaced place-marker remaining, a warning message
+ is printed and the result is undefined. Place-marker numbers must be
+ in the range 1 to 99.
+*/
+QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
+{
+ QVarLengthArray<ushort> utf16(a.size());
+ qt_from_latin1(utf16.data(), a.data(), a.size());
+ return arg(QStringView(utf16.data(), utf16.size()), fieldWidth, fillChar);
+}
+
+/*!
\fn QString QString::arg(const QString& a1, const QString& a2) const
\overload arg()
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 5110487889..87e88d74bd 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -319,8 +319,14 @@ public:
QChar fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
QString arg(QChar a, int fieldWidth = 0,
QChar fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+#if QT_STRINGVIEW_LEVEL < 2
QString arg(const QString &a, int fieldWidth = 0,
QChar fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+#endif
+ QString arg(QStringView a, int fieldWidth = 0,
+ QChar fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(QLatin1String a, int fieldWidth = 0,
+ QChar fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
QString arg(const QString &a1, const QString &a2) const Q_REQUIRED_RESULT;
QString arg(const QString &a1, const QString &a2, const QString &a3) const Q_REQUIRED_RESULT;
QString arg(const QString &a1, const QString &a2, const QString &a3,
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index af35193b13..ecca5569f8 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -1558,7 +1558,7 @@ QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
#if 1
if (namespaceProcessing && !prefix.isEmpty())
- raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix.toString()));
+ raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix));
#endif
return QStringRef();
@@ -1636,7 +1636,7 @@ void QXmlStreamReaderPrivate::resolveTag()
if (attributes[j].name() == attribute.name()
&& attributes[j].namespaceUri() == attribute.namespaceUri()
&& (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
- raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName().toString()));
+ raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName()));
}
}
@@ -1804,14 +1804,14 @@ void QXmlStreamReaderPrivate::startDocument()
if(hasStandalone)
err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
if(!QXmlUtils::isEncName(name))
- err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name);
+ err = QXmlStream::tr("%1 is an invalid encoding name.").arg(value);
else {
#ifdef QT_NO_TEXTCODEC
readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
#else
QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1());
if (!newCodec)
- err = QXmlStream::tr("Encoding %1 is unsupported").arg(name);
+ err = QXmlStream::tr("Encoding %1 is unsupported").arg(value);
else if (newCodec != codec && !lockEncoding) {
codec = newCodec;
delete decoder;
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 3f118d04ce..4a82d952ab 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -4726,8 +4726,8 @@ void tst_QString::arg()
QString s14( "%1%2%3" );
QCOMPARE( s4.arg("foo"), QLatin1String("[foo]") );
- QCOMPARE( s5.arg("foo"), QLatin1String("[foo]") );
- QCOMPARE( s6.arg("foo"), QLatin1String("[foo]") );
+ QCOMPARE( s5.arg(QLatin1String("foo")), QLatin1String("[foo]") );
+ QCOMPARE( s6.arg(QStringViewLiteral("foo")), QLatin1String("[foo]") );
QCOMPARE( s7.arg("foo"), QLatin1String("[foo]") );
QCOMPARE( s8.arg("foo"), QLatin1String("[foo %1]") );
QCOMPARE( s8.arg("foo").arg("bar"), QLatin1String("[foo bar]") );
@@ -4788,11 +4788,11 @@ void tst_QString::arg()
QCOMPARE( QString("%%%1%%%2").arg("foo").arg("bar"), QLatin1String("%%foo%%bar") );
QCOMPARE( QString("%1").arg("hello", -10), QLatin1String("hello ") );
- QCOMPARE( QString("%1").arg("hello", -5), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg("hello", -2), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QLatin1String("hello"), -5), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), -2), QLatin1String("hello") );
QCOMPARE( QString("%1").arg("hello", 0), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg("hello", 2), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg("hello", 5), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QLatin1String("hello"), 2), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), 5), QLatin1String("hello") );
QCOMPARE( QString("%1").arg("hello", 10), QLatin1String(" hello") );
QCOMPARE( QString("%1%1").arg("hello"), QLatin1String("hellohello") );
QCOMPARE( QString("%2%1").arg("hello"), QLatin1String("%2hello") );