Introduce qUtf8Printable() macro to qglobal.h

This macro is equivalent to arg.toUtf8().constData().
It is usable for "%s" arguments of qDebug(), qWarning(), qFatal(),
qCritical().

Change-Id: I2d9956e6651271e1e2183dce9c835511cf923bf3
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Takumi Asaki 2014-03-06 16:56:52 +09:00 committed by Kai Koehne
parent 7638c0d783
commit 71c6fdf871
4 changed files with 93 additions and 11 deletions

View File

@ -305,7 +305,7 @@ void load(const QString &fileName)
{
QFile file(fileName);
if (!file.exists())
qCritical("File '%s' does not exist!", qPrintable(fileName));
qCritical("File '%s' does not exist!", qUtf8Printable(fileName));
}
//! [28]
@ -424,7 +424,7 @@ void TheClass::addLabels()
//! [37]
qWarning("%s: %s", qPrintable(key), qPrintable(value));
qWarning("%s: %s", qUtf8Printable(key), qUtf8Printable(value));
//! [37]

View File

@ -580,8 +580,8 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
64-bit integer literals in a platform-independent way. The
Q_CHECK_PTR() macro prints a warning containing the source code's
file name and line number, saying that the program ran out of
memory, if the pointer is 0. The qPrintable() macro represent an
easy way of printing text.
memory, if the pointer is 0. The qPrintable() and qUtf8Printable()
macros represent an easy way of printing text.
Finally, the QT_POINTER_SIZE macro expands to the size of a
pointer in bytes, and the QT_VERSION and QT_VERSION_STR macros
@ -3356,17 +3356,31 @@ int qrand()
qPrintable() is used. This is because the array returned by
QString::toLocal8Bit() will fall out of scope.
\note qDebug(), qWarning(), qCritical(), qFatal() expect %s
arguments to be UTF-8 encoded, while qPrintable() converts to
local 8-bit encoding. Therefore qUtf8Printable() should be used
for logging strings instead of qPrintable().
\sa qUtf8Printable()
*/
/*!
\macro const char *qUtf8Printable(const QString &str)
\relates <QtGlobal>
\since 5.4
Returns \a str as a \c{const char *}. This is equivalent to
\a{str}.toUtf8().constData().
The char pointer will be invalid after the statement in which
qUtf8Printable() is used. This is because the array returned by
QString::toUtf8() will fall out of scope.
Example:
\snippet code/src_corelib_global_qglobal.cpp 37
\note qDebug(), qWarning(), qCritical(), qFatal() expect %s
arguments to be UTF-8 encoded, while qPrintable() converts to
local 8-bit encoding. Therefore using qPrintable for logging
strings is only safe if the argument contains only ASCII
characters.
\sa qDebug(), qWarning(), qCritical(), qFatal()
\sa qPrintable(), qDebug(), qWarning(), qCritical(), qFatal()
*/
/*!

View File

@ -645,6 +645,10 @@ inline void qUnused(T &x) { (void)x; }
# define qPrintable(string) QString(string).toLocal8Bit().constData()
#endif
#ifndef qUtf8Printable
# define qUtf8Printable(string) QString(string).toUtf8().constData()
#endif
class QString;
Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);

View File

@ -43,6 +43,9 @@
#include <QtTest/QtTest>
#include <QtCore/qtypetraits.h>
#include <QPair>
#include <QTextCodec>
class tst_QGlobal: public QObject
{
Q_OBJECT
@ -60,6 +63,8 @@ private slots:
void isEnum();
void qAlignOf();
void integerForSize();
void qprintable();
void qprintable_data();
};
void tst_QGlobal::qIsNull()
@ -588,5 +593,64 @@ void tst_QGlobal::integerForSize()
Q_STATIC_ASSERT(sizeof(QIntegerForSize<8>::Unsigned) == 8);
}
typedef QPair<const char *, const char *> stringpair;
Q_DECLARE_METATYPE(stringpair)
void tst_QGlobal::qprintable()
{
QFETCH(QList<stringpair>, localestrings);
QFETCH(int, utf8index);
QVERIFY(utf8index >= 0 && utf8index < localestrings.count());
if (utf8index < 0 || utf8index >= localestrings.count())
return;
const char *const utf8string = localestrings.at(utf8index).second;
QString string = QString::fromUtf8(utf8string);
foreach (const stringpair &pair, localestrings) {
QTextCodec *codec = QTextCodec::codecForName(pair.first);
if (!codec)
continue;
QTextCodec::setCodecForLocale(codec);
// test qPrintable()
QVERIFY(qstrcmp(qPrintable(string), pair.second) == 0);
foreach (const stringpair &pair2, localestrings) {
if (pair2.second == pair.second)
continue;
QVERIFY(qstrcmp(qPrintable(string), pair2.second) != 0);
}
// test qUtf8Printable()
QVERIFY(qstrcmp(qUtf8Printable(string), utf8string) == 0);
foreach (const stringpair &pair2, localestrings) {
if (qstrcmp(pair2.second, utf8string) == 0)
continue;
QVERIFY(qstrcmp(qUtf8Printable(string), pair2.second) != 0);
}
}
QTextCodec::setCodecForLocale(0);
}
void tst_QGlobal::qprintable_data()
{
QTest::addColumn<QList<stringpair> >("localestrings");
QTest::addColumn<int>("utf8index"); // index of utf8 string
// Unicode: HIRAGANA LETTER A, I, U, E, O (U+3442, U+3444, U+3446, U+3448, U+344a)
static const char *const utf8string = "\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a";
static const char *const eucjpstring = "\xa4\xa2\xa4\xa4\xa4\xa6\xa4\xa8\xa4\xaa";
static const char *const sjisstring = "\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8";
QList<stringpair> japanesestrings;
japanesestrings << stringpair("UTF-8", utf8string)
<< stringpair("EUC-JP", eucjpstring)
<< stringpair("Shift_JIS", sjisstring);
QTest::newRow("Japanese") << japanesestrings << 0;
}
QTEST_APPLESS_MAIN(tst_QGlobal)
#include "tst_qglobal.moc"