diff options
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp | 4 | ||||
-rw-r--r-- | src/corelib/global/qglobal.cpp | 32 | ||||
-rw-r--r-- | src/corelib/global/qglobal.h | 4 | ||||
-rw-r--r-- | tests/auto/corelib/global/qglobal/tst_qglobal.cpp | 64 |
4 files changed, 93 insertions, 11 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp index b907c9acb1..5befebc982 100644 --- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp @@ -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] diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index fb95a1966f..98460481ca 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -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() */ /*! diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a9621e744c..80c9992e25 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -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); diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 4eb3e4fc98..0389ae7976 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -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" |