diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2016-08-19 10:13:45 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2016-08-23 13:46:22 +0000 |
commit | 8b7dbfe1e0c0d4b8d0984fb381f1a0bb6b566e76 (patch) | |
tree | 3438c6ec351cc6cadbbacdfd170affd8605e6a44 /src/qml/jsruntime/qv4numberobject.cpp | |
parent | 4f0988c3907406087dbfdc193abfbf767678d814 (diff) |
V4: Correctly format on Number.toPrecision(n)
The ecmascript standard mandates that we add trailing zeroes if the
given precision is greater than the number of digits available. The
only way to request this from QLocale is currently QString::asprintf(),
which adds a few other incompatibilities that are easier to 'fix' by
editing the resulting string. Thus we use it as a stop gap measure
until we can expose better API from qtbase.
Task-number: QTBUG-55358
Change-Id: Iafc11f21abb341fbe458ad75b46b4222ae5bc1db
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4numberobject.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4numberobject.cpp | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index ab3e03b183..0e653c18cb 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -263,12 +263,30 @@ ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx) if (!ctx->argc() || ctx->args()[0].isUndefined()) return RuntimeHelpers::toString(scope.engine, v); - double precision = ctx->args()[0].toInt32(); + int precision = ctx->args()[0].toInt32(); if (precision < 1 || precision > 21) { ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range"))); return ctx->engine()->throwRangeError(error); } - QString result = NumberLocale::instance()->toString(v->asDouble(), 'g', precision); + // TODO: Once we get a NumberOption to retain trailing zeroes, replace the code below with: + // QString result = NumberLocale::instance()->toString(v->asDouble(), 'g', precision); + QByteArray format = "%#." + QByteArray::number(precision) + "g"; + QString result = QString::asprintf(format.constData(), v->asDouble()); + if (result.endsWith(QLatin1Char('.'))) { + // This is 'f' notation, not 'e'. + result.chop(1); + } else { + int ePos = result.indexOf(QLatin1Char('e')); + if (ePos != -1) { + Q_ASSERT(ePos + 2 < result.length()); // always '+' or '-', and number, after 'e' + Q_ASSERT(ePos > 0); // 'e' is not the first character + + if (result.at(ePos + 2) == QLatin1Char('0')) // Drop leading zeroes in exponent + result = result.remove(ePos + 2, 1); + if (result.at(ePos - 1) == QLatin1Char('.')) // Drop trailing dots before 'e' + result = result.remove(ePos - 1, 1); + } + } return scope.engine->newString(result)->asReturnedValue(); } |