From d7cb21ac085117f879a8aa1d7727b2ca52d3353d Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 15 Nov 2019 21:46:32 +0100 Subject: QDom: use QLocale::C when converting a double to a xml attribute QDomElement::setAttribute(QString, double) did not use QString::setNum() but qsnprintf(). This is wrong because qsnprintf() is using the current locale instead QLocale::C. It was also inconsistent to QDomElement::setAttributeNS() which was already using QString::setNum(). Also fix the documentation which stated that all QDomElement::setAttribute() format the values according the current locale. Fixes: QTBUG-80068 Change-Id: Iabb0b39c0d0723060527542c283a5435f26f31ca Reviewed-by: Thiago Macieira --- src/xml/dom/qdom.cpp | 19 ++++------ tests/auto/xml/dom/qdom/tst_qdom.cpp | 69 ++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 8d232237bf..04151c3f31 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -4818,20 +4818,20 @@ void QDomElement::setAttribute(const QString& name, const QString& value) \fn void QDomElement::setAttribute(const QString& name, int value) \overload - The number is formatted according to the current locale. + The formatting always uses QLocale::C. */ /*! \fn void QDomElement::setAttribute(const QString& name, uint value) \overload - The number is formatted according to the current locale. + The formatting always uses QLocale::C. */ /*! \overload - The number is formatted according to the current locale. + The formatting always uses QLocale::C. */ void QDomElement::setAttribute(const QString& name, qlonglong value) { @@ -4845,7 +4845,7 @@ void QDomElement::setAttribute(const QString& name, qlonglong value) /*! \overload - The number is formatted according to the current locale. + The formatting always uses QLocale::C. */ void QDomElement::setAttribute(const QString& name, qulonglong value) { @@ -4859,7 +4859,7 @@ void QDomElement::setAttribute(const QString& name, qulonglong value) /*! \overload - The number is formatted according to the current locale. + The formatting always uses QLocale::C. */ void QDomElement::setAttribute(const QString& name, float value) { @@ -4873,19 +4873,14 @@ void QDomElement::setAttribute(const QString& name, float value) /*! \overload - The number is formatted according to the current locale. + The formatting always uses QLocale::C. */ void QDomElement::setAttribute(const QString& name, double value) { if (!impl) return; QString x; - char buf[256]; - int count = qsnprintf(buf, sizeof(buf), "%.16g", value); - if (count > 0) - x = QString::fromLatin1(buf, count); - else - x.setNum(value); // Fallback + x.setNum(value); IMPL->setAttribute(name, x); } diff --git a/tests/auto/xml/dom/qdom/tst_qdom.cpp b/tests/auto/xml/dom/qdom/tst_qdom.cpp index b09a3447e3..99639df5b0 100644 --- a/tests/auto/xml/dom/qdom/tst_qdom.cpp +++ b/tests/auto/xml/dom/qdom/tst_qdom.cpp @@ -57,6 +57,7 @@ private slots: void toString_02(); void hasAttributes_data(); void hasAttributes(); + void setGetAttributes(); void save_data(); void save(); void saveWithSerialization() const; @@ -392,6 +393,74 @@ void tst_QDom::hasAttributes() QTEST( visitedNodes, "visitedNodes" ); } +void tst_QDom::setGetAttributes() +{ + QDomDocument doc; + QDomElement rootNode = doc.createElement("Root"); + doc.appendChild(rootNode); + + const QLocale oldLocale = QLocale(); + QLocale::setDefault(QLocale::German); // decimal separator != '.' + + const QString qstringVal("QString"); + const qlonglong qlonglongVal = std::numeric_limits::min(); + const qulonglong qulonglongVal = std::numeric_limits::max(); + const int intVal = std::numeric_limits::min(); + const uint uintVal = std::numeric_limits::max(); + const float floatVal = 0.1234f; + const double doubleVal = 0.1234; + + rootNode.setAttribute("qstringVal", qstringVal); + rootNode.setAttribute("qlonglongVal", qlonglongVal); + rootNode.setAttribute("qulonglongVal", qulonglongVal); + rootNode.setAttribute("intVal", intVal); + rootNode.setAttribute("uintVal", uintVal); + rootNode.setAttribute("floatVal", floatVal); + rootNode.setAttribute("doubleVal", doubleVal); + + QDomElement nsNode = doc.createElement("NS"); + rootNode.appendChild(nsNode); + nsNode.setAttributeNS("namespace", "qstringVal", qstringVal); + nsNode.setAttributeNS("namespace", "qlonglongVal", qlonglongVal); + nsNode.setAttributeNS("namespace", "qulonglongVal", qulonglongVal); + nsNode.setAttributeNS("namespace", "intVal", intVal); + nsNode.setAttributeNS("namespace", "uintVal", uintVal); + nsNode.setAttributeNS("namespace", "floatVal", floatVal); // not available atm + nsNode.setAttributeNS("namespace", "doubleVal", doubleVal); + + bool bOk; + QCOMPARE(rootNode.attribute("qstringVal"), qstringVal); + QCOMPARE(rootNode.attribute("qlonglongVal").toLongLong(&bOk), qlonglongVal); + QVERIFY(bOk); + QCOMPARE(rootNode.attribute("qulonglongVal").toULongLong(&bOk), qulonglongVal); + QVERIFY(bOk); + QCOMPARE(rootNode.attribute("intVal").toInt(&bOk), intVal); + QVERIFY(bOk); + QCOMPARE(rootNode.attribute("uintVal").toUInt(&bOk), uintVal); + QVERIFY(bOk); + QCOMPARE(rootNode.attribute("floatVal").toFloat(&bOk), floatVal); + QVERIFY(bOk); + QCOMPARE(rootNode.attribute("doubleVal").toDouble(&bOk), doubleVal); + QVERIFY(bOk); + + QCOMPARE(nsNode.attributeNS("namespace", "qstringVal"), qstringVal); + QCOMPARE(nsNode.attributeNS("namespace", "qlonglongVal").toLongLong(&bOk), qlonglongVal); + QVERIFY(bOk); + QCOMPARE(nsNode.attributeNS("namespace", "qulonglongVal").toULongLong(&bOk), qulonglongVal); + QVERIFY(bOk); + QCOMPARE(nsNode.attributeNS("namespace", "intVal").toInt(&bOk), intVal); + QVERIFY(bOk); + QCOMPARE(nsNode.attributeNS("namespace", "uintVal").toUInt(&bOk), uintVal); + QVERIFY(bOk); + QCOMPARE(nsNode.attributeNS("namespace", "floatVal").toFloat(&bOk), floatVal); + QVERIFY(bOk); + QCOMPARE(nsNode.attributeNS("namespace", "doubleVal").toDouble(&bOk), doubleVal); + QVERIFY(bOk); + + QLocale::setDefault(oldLocale); +} + + int tst_QDom::hasAttributesHelper( const QDomNode& node ) { int visitedNodes = 1; -- cgit v1.2.3