aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-02-22 17:13:36 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-02-25 12:49:13 +0000
commitb959074afb43d25c1a8818e0528004f8cf073ae2 (patch)
tree9c00bb615057b51ded5f26795c8b7e02cf706dc0 /src/qml/jsruntime
parentcdb8eb988e572411030486ad2834ae54e4567bf3 (diff)
Unify and fix number to string conversion with radix
Previously, the loop that generated the string could fail to terminate with certain numbers as input. Also, the algorithm was duplicated in two places. Change-Id: Ie2075148d931e7cfcedb5bcd23af61e2e8afc232 Fixes: QTBUG-73999 Reviewed-by: Robert Loehning <robert.loehning@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp38
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp17
2 files changed, 16 insertions, 39 deletions
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index d26e888069..13f6912371 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -223,41 +223,9 @@ ReturnedValue NumberPrototype::method_toString(const FunctionObject *b, const Va
return v4->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix").arg(radix));
}
- if (std::isnan(num)) {
- return Encode(v4->newString(QStringLiteral("NaN")));
- } else if (qt_is_inf(num)) {
- return Encode(v4->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity")));
- }
-
- if (radix != 10) {
- QString str;
- bool negative = false;
- if (num < 0) {
- negative = true;
- num = -num;
- }
- double frac = num - std::floor(num);
- num = Value::toInteger(num);
- do {
- char c = (char)std::fmod(num, radix);
- c = (c < 10) ? (c + '0') : (c - 10 + 'a');
- str.prepend(QLatin1Char(c));
- num = std::floor(num / radix);
- } while (num != 0);
- if (frac != 0) {
- str.append(QLatin1Char('.'));
- do {
- frac = frac * radix;
- char c = (char)std::floor(frac);
- c = (c < 10) ? (c + '0') : (c - 10 + 'a');
- str.append(QLatin1Char(c));
- frac = frac - std::floor(frac);
- } while (frac != 0);
- }
- if (negative)
- str.prepend(QLatin1Char('-'));
- return Encode(v4->newString(str));
- }
+ QString str;
+ RuntimeHelpers::numberToString(&str, num, radix);
+ return Encode(v4->newString(str));
}
return Encode(Value::fromDouble(num).toString(v4));
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 13244fdd95..424103cb08 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -298,13 +298,22 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
if (frac != 0) {
result->append(QLatin1Char('.'));
+ double magnitude = 1;
+ double next = frac;
do {
- frac = frac * radix;
- char c = (char)::floor(frac);
+ next *= radix;
+ const int floored = ::floor(next);
+ char c = char(floored);
c = (c < 10) ? (c + '0') : (c - 10 + 'a');
result->append(QLatin1Char(c));
- frac = frac - ::floor(frac);
- } while (frac != 0);
+ magnitude /= radix;
+ frac -= double(floored) * magnitude;
+ next -= double(floored);
+
+ // The next digit still makes a difference
+ // if a value of "radix" for it would change frac.
+ // Otherwise we've reached the limit of numerical precision.
+ } while (frac > 0 && frac - magnitude != frac);
}
if (negative)