From 8b7dbfe1e0c0d4b8d0984fb381f1a0bb6b566e76 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 19 Aug 2016 10:13:45 +0200 Subject: 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 --- src/qml/jsruntime/qv4numberobject.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src') 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(); } -- cgit v1.2.3