1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QJSNUMBERCOERCION_H
5#define QJSNUMBERCOERCION_H
6
7#include <QtCore/qglobal.h>
8#include <cstring>
9
10QT_BEGIN_NAMESPACE
11
12class QJSNumberCoercion
13{
14public:
15
16 static constexpr bool isInteger(double d)
17 {
18 // Comparing d with itself checks for NaN and comparing d with the min and max values
19 // for int also covers infinities.
20 if (!equals(lhs: d, rhs: d) || d < (std::numeric_limits<int>::min)()
21 || d > (std::numeric_limits<int>::max)()) {
22 return false;
23 }
24
25 return equals(lhs: static_cast<int>(d), rhs: d);
26 }
27
28 static constexpr bool isArrayIndex(double d)
29 {
30 return d >= 0
31 && equals(lhs: d, rhs: d)
32 && d <= (std::numeric_limits<uint>::max)()
33 && equals(lhs: static_cast<uint>(d), rhs: d);
34 }
35
36 static constexpr bool isArrayIndex(qint64 i)
37 {
38 return i >= 0 && i <= (std::numeric_limits<uint>::max)();
39 }
40
41 static constexpr bool isArrayIndex(quint64 i)
42 {
43 return i <= (std::numeric_limits<uint>::max)();
44 }
45
46 static constexpr int toInteger(double d) {
47 // Check for NaN
48 if (!equals(lhs: d, rhs: d))
49 return 0;
50
51 if (d >= (std::numeric_limits<int>::min)() && d <= (std::numeric_limits<int>::max)()) {
52 const int i = static_cast<int>(d);
53 if (equals(lhs: i, rhs: d))
54 return i;
55 }
56
57 return QJSNumberCoercion(d).toInteger();
58 }
59
60 static constexpr bool equals(double lhs, double rhs)
61 {
62 QT_WARNING_PUSH
63 QT_WARNING_DISABLE_FLOAT_COMPARE
64 return lhs == rhs;
65 QT_WARNING_POP
66 }
67
68private:
69 constexpr QJSNumberCoercion(double dbl)
70 {
71 // the dbl == 0 path is guaranteed constexpr. The other one may or may not be, depending
72 // on whether and how the compiler inlines the memcpy.
73 // In order to declare the ctor constexpr we need one guaranteed constexpr path.
74 if (!equals(lhs: dbl, rhs: 0))
75 memcpy(dest: &d, src: &dbl, n: sizeof(double));
76 }
77
78 constexpr int sign() const
79 {
80 return (d >> 63) ? -1 : 1;
81 }
82
83 constexpr bool isDenormal() const
84 {
85 return static_cast<int>((d << 1) >> 53) == 0;
86 }
87
88 constexpr int exponent() const
89 {
90 return static_cast<int>((d << 1) >> 53) - 1023;
91 }
92
93 constexpr quint64 significant() const
94 {
95 quint64 m = (d << 12) >> 12;
96 if (!isDenormal())
97 m |= (static_cast<quint64>(1) << 52);
98 return m;
99 }
100
101 constexpr int toInteger()
102 {
103 int e = exponent() - 52;
104 if (e < 0) {
105 if (e <= -53)
106 return 0;
107 return sign() * static_cast<int>(significant() >> -e);
108 } else {
109 if (e > 31)
110 return 0;
111 return sign() * (static_cast<int>(significant()) << e);
112 }
113 }
114
115 quint64 d = 0;
116};
117
118QT_END_NAMESPACE
119
120#endif // QJSNUMBERCOERCION_H
121

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtdeclarative/src/qml/common/qjsnumbercoercion.h