From f60588237b230923c6a27f60669fa0230138f1ca Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 17 Feb 2012 13:08:21 +1000 Subject: [PATCH] Implement String.localeCompare() using QString::localeAwareCompare() v8's localeCompare() implementation is not locale aware, so we use Qt's locale aware compare. Change-Id: Ia9092b3d6754545bb797adac26080ac7a29dcd92 Reviewed-by: Glenn Watson --- src/declarative/qml/qdeclarativelocale.cpp | 30 ++++++++++++++ src/declarative/qml/qdeclarativelocale_p.h | 4 ++ src/declarative/qml/v8/qv8engine.cpp | 1 + .../qdeclarativelocale/data/localeCompare.qml | 7 +++ .../qdeclarativelocale/tst_qdeclarativelocale.cpp | 41 ++++++++++++++++++++ 5 files changed, 83 insertions(+), 0 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativelocale/data/localeCompare.qml diff --git a/src/declarative/qml/qdeclarativelocale.cpp b/src/declarative/qml/qdeclarativelocale.cpp index 8ec51b0..39d0f6c 100644 --- a/src/declarative/qml/qdeclarativelocale.cpp +++ b/src/declarative/qml/qdeclarativelocale.cpp @@ -834,6 +834,36 @@ v8::Handle QDeclarativeLocale::locale(QV8Engine *v8engine, const QStr return v8Value; } +static const char *localeCompareFunction = + "(function(localeCompareFunc) { " + " var orig_localeCompare;" + " orig_localeCompare = String.prototype.localeCompare;" + " String.prototype.localeCompare = (function() {" + " var val = localeCompareFunc.apply(this, arguments);" + " if (val == undefined) val = orig_localeCompare.call(this);" + " return val;" + " })" + "})"; + +void QDeclarativeLocale::registerStringLocaleCompare(QV8Engine *engine) +{ + registerFunction(engine, localeCompareFunction, localeCompare); +} + +v8::Handle QDeclarativeLocale::localeCompare(const v8::Arguments &args) +{ + if (args.Length() != 1 || (!args[0]->IsString() && !args[0]->IsStringObject())) + return v8::Undefined(); + + if (!args.This()->IsString() && !args.This()->IsStringObject()) + return v8::Undefined(); + + QString thisString = QJSConverter::toString(args.This()->ToString()); + QString thatString = QJSConverter::toString(args[0]->ToString()); + + return v8::Integer::New(QString::localeAwareCompare(thisString, thatString)); +} + /*! \enum QtQuick2::Locale::FormatType diff --git a/src/declarative/qml/qdeclarativelocale_p.h b/src/declarative/qml/qdeclarativelocale_p.h index 904e4e6..98370fb 100644 --- a/src/declarative/qml/qdeclarativelocale_p.h +++ b/src/declarative/qml/qdeclarativelocale_p.h @@ -119,8 +119,12 @@ public: static v8::Handle locale(QV8Engine *v8engine, const QString &lang); + static void registerStringLocaleCompare(QV8Engine *engine); + private: QDeclarativeLocale(); + + static v8::Handle localeCompare(const v8::Arguments &args); }; diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index 92cd336..04589fe 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -636,6 +636,7 @@ void QV8Engine::initializeGlobal(v8::Handle global) #undef STRING_ARG } + QDeclarativeLocale::registerStringLocaleCompare(this); QDeclarativeDateExtension::registerExtension(this); QDeclarativeNumberExtension::registerExtension(this); diff --git a/tests/auto/declarative/qdeclarativelocale/data/localeCompare.qml b/tests/auto/declarative/qdeclarativelocale/data/localeCompare.qml new file mode 100644 index 0000000..6851af6 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelocale/data/localeCompare.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 + +QtObject { + property var string1: "a" + property var string2: "a" + property var comparison: string1.localeCompare(string2) +} diff --git a/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp b/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp index 5afc235..bf5c8c7 100644 --- a/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp +++ b/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp @@ -106,6 +106,9 @@ private slots: void numberFromLocaleString(); void numberConstToLocaleString(); + void stringLocaleCompare_data(); + void stringLocaleCompare(); + private: void addPropertyData(const QString &l); QVariant getProperty(QObject *obj, const QString &locale, const QString &property); @@ -1137,6 +1140,44 @@ void tst_qdeclarativelocale::numberConstToLocaleString() QCOMPARE(obj->property("const2").toString(), l.toString(1234., 'f', 2)); } +void tst_qdeclarativelocale::stringLocaleCompare_data() +{ + QTest::addColumn("string1"); + QTest::addColumn("string2"); + + QTest::newRow("before") << "a" << "b"; + QTest::newRow("equal") << "a" << "a"; + QTest::newRow("after") << "b" << "a"; + + // Copied from QString::localeAwareCompare tests + // We don't actually change locale - we just care that String.localeCompare() + // matches QString::localeAwareCompare(); + QTest::newRow("swedish1") << QString("\xe5") << QString("\xe4"); + QTest::newRow("swedish2") << QString("\xe4") << QString("\xf6"); + QTest::newRow("swedish3") << QString("\xe5") << QString("\xf6"); + QTest::newRow("swedish4") << QString("z") << QString("\xe5"); + + QTest::newRow("german1") << QString("z") << QString("\xe4"); + QTest::newRow("german2") << QString("\xe4") << QString("\xf6"); + QTest::newRow("german3") << QString("z") << QString("\xf6"); +} + +void tst_qdeclarativelocale::stringLocaleCompare() +{ + QFETCH(QString, string1); + QFETCH(QString, string2); + + QDeclarativeComponent c(&engine, testFileUrl("localeCompare.qml")); + + QObject *obj = c.create(); + QVERIFY(obj); + + obj->setProperty("string1", string1); + obj->setProperty("string2", string2); + + QCOMPARE(obj->property("comparison").toInt(), QString::localeAwareCompare(string1, string2)); +} + QTEST_MAIN(tst_qdeclarativelocale) #include "tst_qdeclarativelocale.moc" -- 1.7.2.5