Long live qUtf16Printable()

QString::asprintf() has the ability to take a ushort* array as
obtained from QString::utf16() and insert that into the output
with an %ls conversion.

But no-one ever used this, because just passing QString::utf16()
to QString::asprintf() creates a warning about wchar_t* expected,
but ushort* provided.

The new qUtf16Printable() macro adds the necessary casts (via void*
to prevent any "type-punned pointer" warnings) to make
passing QString::utf16() to QString::asprintf() work silently.

This should greatly reduce the need to do a round-trip via utf-8
just to print the contents of a QString.

[ChangeLog][QtCore] Added qUtf16Printable().

Change-Id: I7ddd8d2b2a2191c9faa26aca95d49850d94b287c
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Marc Mutz 2015-11-12 09:59:37 +01:00
parent 226ce6020e
commit 1005b7a0de
4 changed files with 46 additions and 9 deletions

View File

@ -439,6 +439,11 @@ qWarning("%s: %s", qUtf8Printable(key), qUtf8Printable(value));
//! [37]
//! [qUtf16Printable]
qWarning("%ls: %ls", qUtf16Printable(key), qUtf16Printable(value));
//! [qUtf16Printable]
//! [38]
struct Point2D
{

View File

@ -3824,6 +3824,29 @@ int qrand()
\sa qPrintable(), qDebug(), qInfo(), qWarning(), qCritical(), qFatal()
*/
/*!
\macro const wchar_t *qUtf16Printable(const QString &str)
\relates <QtGlobal>
\since 5.7
Returns \a str as a \c{const ushort *}, but cast to a \c{const wchar_t *}
to avoid warnings. This is equivalent to \a{str}.utf16() plus some casting.
The only useful thing you can do with the return value of this macro is to
pass it to QString::asprintf() for use in a \c{%ls} conversion. In particular,
the return value is \e{not} a valid \c{const wchar_t*}!
In general, the pointer will be invalid after the statement in which
qUtf16Printable() is used. This is because the pointer may have been
obtained from a temporary expression, which will fall out of scope.
Example:
\snippet code/src_corelib_global_qglobal.cpp qUtf16Printable
\sa qPrintable(), qDebug(), qInfo(), qWarning(), qCritical(), qFatal()
*/
/*!
\macro Q_DECLARE_TYPEINFO(Type, Flags)
\relates <QtGlobal>

View File

@ -687,6 +687,15 @@ Q_CORE_EXPORT bool qSharedBuild() Q_DECL_NOTHROW;
# define qUtf8Printable(string) QString(string).toUtf8().constData()
#endif
/*
Wrap QString::utf16() with enough casts to allow passing it
to QString::asprintf("%ls") without warnings.
*/
#ifndef qUtf16Printable
# define qUtf16Printable(string) \
static_cast<const wchar_t*>(static_cast<const void*>(QString(string).utf16()))
#endif
class QString;
Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);

View File

@ -1279,21 +1279,21 @@ void tst_QString::sprintfS()
QCOMPARE(a, QString("foobarwhiz"));
{ // %ls
QCOMPARE(a.sprintf("%.3ls", QString("Hello").utf16() ), QLatin1String("Hel"));
QCOMPARE(a.sprintf("%10.3ls", QString("Hello").utf16() ), QLatin1String(" Hel"));
QCOMPARE(a.sprintf("%.10ls", QString("Hello").utf16() ), QLatin1String("Hello"));
QCOMPARE(a.sprintf("%10.10ls", QString("Hello").utf16() ), QLatin1String(" Hello"));
QCOMPARE(a.sprintf("%-10.10ls", QString("Hello").utf16() ), QLatin1String("Hello "));
QCOMPARE(a.sprintf("%-10.3ls", QString("Hello").utf16() ), QLatin1String("Hel "));
QCOMPARE(a.sprintf("%-5.5ls", QString("Hello").utf16() ), QLatin1String("Hello"));
QCOMPARE(a.sprintf("%.3ls", qUtf16Printable("Hello")), QLatin1String("Hel"));
QCOMPARE(a.sprintf("%10.3ls", qUtf16Printable("Hello")), QLatin1String(" Hel"));
QCOMPARE(a.sprintf("%.10ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
QCOMPARE(a.sprintf("%10.10ls", qUtf16Printable("Hello")), QLatin1String(" Hello"));
QCOMPARE(a.sprintf("%-10.10ls", qUtf16Printable("Hello")), QLatin1String("Hello "));
QCOMPARE(a.sprintf("%-10.3ls", qUtf16Printable("Hello")), QLatin1String("Hel "));
QCOMPARE(a.sprintf("%-5.5ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
// Check utf16 is preserved for %ls
QCOMPARE(a.sprintf("%ls",
QString::fromUtf8("\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205").utf16()),
qUtf16Printable("\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205")),
QLatin1String("\366\344\374\326\304\334\370\346\345\330\306\305"));
int n;
a.sprintf("%ls%n%s", QString("hello").utf16(), &n, "goodbye");
a.sprintf("%ls%n%s", qUtf16Printable("hello"), &n, "goodbye");
QCOMPARE(n, 5);
QCOMPARE(a, QLatin1String("hellogoodbye"));
}