Long live QString::asprintf()!
asprintf() is a GNU extension that prints into a string it allocates internally. Arguably, that's a better name for QString::sprintf() since it also allocates memory internally. The main problem with QString::sprintf() isn't that it's dangerous to use (it is), but that it's not static. It also returns a reference instead of by-value, breaking RVO. There is a comment about removing this function completely in Qt 6.0, but it remains the only printf-style function in Qt that can allocate the target string, so it's vital for logging, e.g., and the recommended replacement code (http://linux.die.net/man/3/vsnprintf) is a nightmare. So this patch adds static (v)asprintf() methods to replace it. Further patches will fix up all in-tree callers and finally deprecate the old (v)sprintf(). Test coverage is provided through the existing tests of sprintf(), which is implemented in terms of asprintf(). Arguably, the in-tree callers show that QByteArray would benefit from having an asprintf(), too, as most of the in-tree code works around its lack with calls to to{Latin1,Local8Bit}() after using the QString version. [ChangeLog][QtCore][QString] Added asprintf(), vasprintf(). Change-Id: I8510f8d67c22230653ec0f1c252c01bc95f3c386 Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
63114f4d3c
commit
d251cae7b7
|
|
@ -5661,9 +5661,22 @@ QString QString::toUpper_helper(QString &str)
|
|||
return QUnicodeTables::convertCase<QUnicodeTables::UppercaseTraits>(str);
|
||||
}
|
||||
|
||||
/*!
|
||||
\obsolete Use asprintf(), arg() or QTextStream instead.
|
||||
*/
|
||||
QString &QString::sprintf(const char *cformat, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, cformat);
|
||||
*this = vasprintf(cformat, ap);
|
||||
va_end(ap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ### Qt 6: Consider whether this function shouldn't be removed See task 202871.
|
||||
/*!
|
||||
\since 5.5
|
||||
|
||||
Safely builds a formatted string from the format string \a cformat
|
||||
and an arbitrary list of arguments.
|
||||
|
||||
|
|
@ -5680,7 +5693,7 @@ QString QString::toUpper_helper(QString &str)
|
|||
a \c{wchar_t*}, and might also produce compiler warnings on platforms
|
||||
where the size of \c {wchar_t} is not 16 bits.
|
||||
|
||||
\warning We do not recommend using QString::sprintf() in new Qt
|
||||
\warning We do not recommend using QString::asprintf() in new Qt
|
||||
code. Instead, consider using QTextStream or arg(), both of
|
||||
which support Unicode strings seamlessly and are type-safe.
|
||||
Here's an example that uses QTextStream:
|
||||
|
|
@ -5695,32 +5708,42 @@ QString QString::toUpper_helper(QString &str)
|
|||
\sa arg()
|
||||
*/
|
||||
|
||||
QString &QString::sprintf(const char *cformat, ...)
|
||||
QString QString::asprintf(const char *cformat, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, cformat);
|
||||
QString &s = vsprintf(cformat, ap);
|
||||
const QString s = vasprintf(cformat, ap);
|
||||
va_end(ap);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*!
|
||||
Equivalent method to sprintf(), but takes a va_list \a ap
|
||||
instead a list of variable arguments. See the sprintf()
|
||||
\obsolete Use vasprintf(), arg() or QTextStream instead.
|
||||
*/
|
||||
QString &QString::vsprintf(const char *cformat, va_list ap)
|
||||
{
|
||||
return *this = vasprintf(cformat, ap);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QString::vasprintf(const char *cformat, va_list ap)
|
||||
\since 5.5
|
||||
|
||||
Equivalent method to asprintf(), but takes a va_list \a ap
|
||||
instead a list of variable arguments. See the asprintf()
|
||||
documentation for an explanation of \a cformat.
|
||||
|
||||
This method does not call the va_end macro, the caller
|
||||
is responsible to call va_end on \a ap.
|
||||
|
||||
\sa sprintf()
|
||||
\sa asprintf()
|
||||
*/
|
||||
|
||||
QString &QString::vsprintf(const char* cformat, va_list ap)
|
||||
QString QString::vasprintf(const char *cformat, va_list ap)
|
||||
{
|
||||
if (!cformat || !*cformat) {
|
||||
// Qt 1.x compat
|
||||
*this = fromLatin1("");
|
||||
return *this;
|
||||
return fromLatin1("");
|
||||
}
|
||||
|
||||
// Parse cformat
|
||||
|
|
@ -6036,9 +6059,7 @@ QString &QString::vsprintf(const char* cformat, va_list ap)
|
|||
result.append(subst.rightJustified(width));
|
||||
}
|
||||
|
||||
*this = result;
|
||||
|
||||
return *this;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -7167,7 +7188,7 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
|
|||
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 sprintf() is that the order of the
|
||||
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
|
||||
|
|
|
|||
|
|
@ -300,6 +300,8 @@ public:
|
|||
|
||||
QString &vsprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(2, 0);
|
||||
QString &sprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
|
||||
static QString vasprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(1, 0);
|
||||
static QString asprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
|
||||
|
||||
int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
|
|
|
|||
|
|
@ -58,10 +58,10 @@ QT_BEGIN_NAMESPACE
|
|||
platforms, you should not rely on the return value or on the fact
|
||||
that you will always get a 0 terminated string back.
|
||||
|
||||
Ideally, you should never call this function but use QString::sprintf()
|
||||
Ideally, you should never call this function but use QString::asprintf()
|
||||
instead.
|
||||
|
||||
\sa qsnprintf(), QString::sprintf()
|
||||
\sa qsnprintf(), QString::asprintf()
|
||||
*/
|
||||
|
||||
int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
||||
|
|
@ -107,9 +107,9 @@ int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
|||
|
||||
\warning Call this function only when you know what you are doing
|
||||
since it shows different behavior on certain platforms.
|
||||
Use QString::sprintf() to format a string instead.
|
||||
Use QString::asprintf() to format a string instead.
|
||||
|
||||
\sa qvsnprintf(), QString::sprintf()
|
||||
\sa qvsnprintf(), QString::asprintf()
|
||||
*/
|
||||
|
||||
int qsnprintf(char *str, size_t n, const char *fmt, ...)
|
||||
|
|
|
|||
|
|
@ -975,7 +975,7 @@ QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVar
|
|||
return qvariant_cast<QPixmap>(variant);
|
||||
}
|
||||
|
||||
// hacky but faster version of "QString::sprintf("%d-%d", i, enabled)"
|
||||
// hacky but faster version of "QString::asprintf("%d-%d", i, enabled)"
|
||||
static QString qPixmapSerial(quint64 i, bool enabled)
|
||||
{
|
||||
ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', ushort('0' + enabled) };
|
||||
|
|
|
|||
Loading…
Reference in New Issue