From da0e1e101bb4c44c25b6523357fa81ad1b2d6539 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 12 Jul 2011 10:22:33 +0200 Subject: Add QLocale::toUpper/Lower The toUpper/Lower() methods in QString should not be locale dependent, as this can lead to rather hard to find bugs in at least a turkish locale. Rather have explicit, locale dependend case conversions available in QLocale. Reviewed-by: Denis Dzyubenko --- src/corelib/tools/qlocale.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/corelib/tools/qlocale.h | 3 +++ src/corelib/tools/qstring.cpp | 30 ++++++++---------------------- tests/auto/qstring/tst_qstring.cpp | 20 ++++++++++++-------- 4 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index d791529..8640c8b 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -88,6 +88,8 @@ Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate) #ifdef QT_USE_ICU extern bool qt_initIcu(const QString &localeName); +extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale); +extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale); #endif /****************************************************************************** @@ -2180,6 +2182,42 @@ Qt::LayoutDirection QLocale::textDirection() const return Qt::LeftToRight; } +/*! + \since 4.8 + + Returns an uppercase copy of \a str. +*/ +QString QLocale::toUpper(const QString &str) const +{ +#ifdef QT_USE_ICU + { + QString result; + if (qt_u_strToUpper(str, &result, *this)) + return result; + // else fall through and use Qt's toUpper + } +#endif + return str.toUpper(); +} + +/*! + \since 4.8 + + Returns a lowercase copy of \a str. +*/ +QString QLocale::toLower(const QString &str) const +{ +#ifdef QT_USE_ICU + { + QString result; + if (qt_u_strToLower(str, &result, *this)) + return result; + // else fall through and use Qt's toUpper + } +#endif + return str.toLower(); +} + /*! \since 4.5 diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index 8a5d526..55dd55b 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -724,6 +724,9 @@ public: Qt::LayoutDirection textDirection() const; + QString toUpper(const QString &str) const; + QString toLower(const QString &str) const; + QString currencySymbol(CurrencySymbolFormat = CurrencySymbol) const; QString toCurrencyString(qlonglong, const QString &symbol = QString()) const; QString toCurrencyString(qulonglong, const QString &symbol = QString()) const; diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ee45cfd..c303c00 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -109,8 +109,6 @@ static QHash *asciiCache = 0; #ifdef QT_USE_ICU // qlocale_icu.cpp extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result); -extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale); -extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale); #endif @@ -5012,7 +5010,10 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const \snippet doc/src/snippets/qstring/main.cpp 75 - \sa toUpper() + The case conversion will always happen in the 'C' locale. For locale dependent + case folding use QLocale::toLower() + + \sa toUpper(), QLocale::toLower() */ QString QString::toLower() const @@ -5023,15 +5024,6 @@ QString QString::toLower() const if (!d->size) return *this; -#ifdef QT_USE_ICU - { - QString result; - if (qt_u_strToLower(*this, &result, QLocale())) - return result; - // else fall through and use Qt's toUpper - } -#endif - const ushort *e = d->data + d->size; // this avoids one out of bounds check in the loop @@ -5112,7 +5104,10 @@ QString QString::toCaseFolded() const \snippet doc/src/snippets/qstring/main.cpp 81 - \sa toLower() + The case conversion will always happen in the 'C' locale. For locale dependent + case folding use QLocale::toUpper() + + \sa toLower(), QLocale::toLower() */ QString QString::toUpper() const @@ -5123,15 +5118,6 @@ QString QString::toUpper() const if (!d->size) return *this; -#ifdef QT_USE_ICU - { - QString result; - if (qt_u_strToUpper(*this, &result, QLocale())) - return result; - // else fall through and use Qt's toUpper - } -#endif - const ushort *e = d->data + d->size; // this avoids one out of bounds check in the loop diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp index b26121c..214b2f3 100644 --- a/tests/auto/qstring/tst_qstring.cpp +++ b/tests/auto/qstring/tst_qstring.cpp @@ -5103,24 +5103,28 @@ void tst_QString::toUpperLower_icu() QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); + QCOMPARE(s.toUpper(), QString::fromLatin1("I")); + QCOMPARE(s.toLower(), QString::fromLatin1("i")); + // turkish locale has a capital I with a dot (U+0130, utf8 c4b0) + QLocale l; - QCOMPARE(s.toUpper(), QString::fromUtf8("\xc4\xb0")); - QCOMPARE(QString::fromUtf8("\xc4\xb0").toLower(), s); + QCOMPARE(l.toUpper(s), QString::fromUtf8("\xc4\xb0")); + QCOMPARE(l.toLower(QString::fromUtf8("\xc4\xb0")), s); // nothing should happen here - QCOMPARE(s.toLower(), s); - QCOMPARE(QString::fromLatin1("I").toUpper(), QString::fromLatin1("I")); + QCOMPARE(l.toLower(s), s); + QCOMPARE(l.toUpper(QString::fromLatin1("I")), QString::fromLatin1("I")); // U+0131, utf8 c4b1 is the lower-case i without a dot QString sup = QString::fromUtf8("\xc4\xb1"); - QCOMPARE(sup.toUpper(), QString::fromLatin1("I")); - QCOMPARE(QString::fromLatin1("I").toLower(), sup); + QCOMPARE(l.toUpper(sup), QString::fromLatin1("I")); + QCOMPARE(l.toLower(QString::fromLatin1("I")), sup); // nothing should happen here - QCOMPARE(sup.toLower(), sup); - QCOMPARE(QString::fromLatin1("i").toLower(), QString::fromLatin1("i")); + QCOMPARE(l.toLower(sup), sup); + QCOMPARE(l.toLower(QString::fromLatin1("i")), QString::fromLatin1("i")); // the cleanup function will restore the default locale } -- cgit v0.12