Implement String.localeCompare() using QString::localeAwareCompare()
authorMartin Jones <martin.jones@nokia.com>
Fri, 17 Feb 2012 03:08:21 +0000 (13:08 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 21 Feb 2012 23:03:53 +0000 (00:03 +0100)
v8's localeCompare() implementation is not locale aware, so we use
Qt's locale aware compare.

Change-Id: Ia9092b3d6754545bb797adac26080ac7a29dcd92
Reviewed-by: Glenn Watson <glenn.watson@nokia.com>
src/declarative/qml/qdeclarativelocale.cpp
src/declarative/qml/qdeclarativelocale_p.h
src/declarative/qml/v8/qv8engine.cpp
tests/auto/declarative/qdeclarativelocale/data/localeCompare.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp

index 8ec51b0..39d0f6c 100644 (file)
@@ -834,6 +834,36 @@ v8::Handle<v8::Value> 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<v8::Value> 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
 
index 904e4e6..98370fb 100644 (file)
@@ -119,8 +119,12 @@ public:
 
     static v8::Handle<v8::Value> locale(QV8Engine *v8engine, const QString &lang);
 
+    static void registerStringLocaleCompare(QV8Engine *engine);
+
 private:
     QDeclarativeLocale();
+
+    static v8::Handle<v8::Value> localeCompare(const v8::Arguments &args);
 };
 
 
index 92cd336..04589fe 100644 (file)
@@ -636,6 +636,7 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> 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 (file)
index 0000000..6851af6
--- /dev/null
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+QtObject {
+    property var string1: "a"
+    property var string2: "a"
+    property var comparison: string1.localeCompare(string2)
+}
index 5afc235..bf5c8c7 100644 (file)
@@ -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<QString>("string1");
+    QTest::addColumn<QString>("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"