27 template<
typename Concrete>
28 struct StringNaNOperators
32 return std::numeric_limits<
double>::quiet_NaN();
37 return std::numeric_limits<
double>::quiet_NaN();
40 static double op(
const QString &lhs,
QJSPrimitiveNull) {
return op(lhs, 0); }
41 static double op(
QJSPrimitiveNull,
const QString &rhs) {
return op(0, rhs); }
44 static double op(
const QString &lhs, T rhs)
46 return Concrete::op(numberFromString(lhs).toDouble(), rhs);
50 static double op(T lhs,
const QString &rhs)
52 return Concrete::op(lhs, numberFromString(rhs).toDouble());
55 static double op(
const QString &lhs,
const QString &rhs)
57 return Concrete::op(numberFromString(lhs).toDouble(), numberFromString(rhs).toDouble());
62 static constexpr double op(
double lhs,
double rhs) {
return lhs + rhs; }
63 static bool opOverflow(
int lhs,
int rhs,
int *result)
65 return qAddOverflow(lhs, rhs, result);
69 static QString op(
const QString &lhs, T rhs)
75 static QString op(T lhs,
const QString &rhs)
80 static QString op(
const QString &lhs,
const QString &rhs) {
return lhs + rhs; }
83 struct SubOperators :
private StringNaNOperators<SubOperators> {
84 static constexpr double op(
double lhs,
double rhs) {
return lhs - rhs; }
85 static bool opOverflow(
int lhs,
int rhs,
int *result)
87 return qSubOverflow(lhs, rhs, result);
90 using StringNaNOperators::op;
93 struct MulOperators :
private StringNaNOperators<MulOperators> {
94 static constexpr double op(
double lhs,
double rhs) {
return lhs * rhs; }
95 static bool opOverflow(
int lhs,
int rhs,
int *result)
98 auto hadOverflow = qMulOverflow(lhs, rhs, result);
99 if (((lhs < 0) ^ (rhs < 0)) && (*result == 0))
104 using StringNaNOperators::op;
107 struct DivOperators :
private StringNaNOperators<DivOperators> {
108 static constexpr double op(
double lhs,
double rhs) {
110#ifndef Q_OS_INTEGRITY
111 static_assert(
std::numeric_limits<
double>::is_iec559);
115 QT_WARNING_DISABLE_MSVC(4723)
119 static constexpr bool opOverflow(
int,
int,
int *)
124 using StringNaNOperators::op;
153 case QMetaType::UnknownType:
156 case QMetaType::Nullptr:
159 case QMetaType::Bool:
160 d = *
static_cast<
const bool *>(value);
163 d = *
static_cast<
const int *>(value);
165 case QMetaType::Double:
166 d = *
static_cast<
const double *>(value);
168 case QMetaType::QString:
169 d = *
static_cast<
const QString *>(value);
180 case QMetaType::UnknownType:
183 case QMetaType::Nullptr:
186 case QMetaType::Bool:
192 case QMetaType::Double:
195 case QMetaType::QString:
210 constexpr void *
data() {
return d.data(); }
211 constexpr const void *
data()
const {
return d.data(); }
212 constexpr const void *
constData()
const {
return d.data(); }
218 if constexpr (type ==
Null)
224 if constexpr (type ==
Double)
226 if constexpr (type == String)
236 case Null:
return false;
237 case Boolean:
return asBoolean();
238 case Integer:
return asInteger() != 0;
240 const double v = asDouble();
241 return !QJSNumberCoercion::equals(v, 0) && !std::isnan(v);
243 case String:
return !asString().isEmpty();
247 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
248 Q_UNREACHABLE_RETURN(
false);
259 case Boolean:
return asBoolean();
260 case Integer:
return asInteger();
261 case Double:
return QJSNumberCoercion::toInteger(asDouble());
262 case String:
return numberFromString(asString()).toInteger();
266 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
267 Q_UNREACHABLE_RETURN(0);
276 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
278 case Boolean:
return asBoolean();
279 case Integer:
return asInteger();
280 case Double:
return asDouble();
281 case String:
return numberFromString(asString()).toDouble();
285 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
286 Q_UNREACHABLE_RETURN({});
295 case Undefined:
return QStringLiteral(
"undefined");
296 case Null:
return QStringLiteral(
"null");
297 case Boolean:
return asBoolean() ? QStringLiteral(
"true") : QStringLiteral(
"false");
298 case Integer:
return QString::number(asInteger());
300 const double result = asDouble();
301 if (
std::isnan(result))
302 return QStringLiteral(
"NaN");
303 if (std::isfinite(result))
304 return toString(result);
306 return QStringLiteral(
"Infinity");
307 return QStringLiteral(
"-Infinity");
309 case String:
return asString();
312 Q_UNREACHABLE_RETURN(QString());
319 case Null:
return QVariant::fromValue<std::nullptr_t>(
nullptr);
320 case Boolean:
return QVariant(asBoolean());
321 case Integer:
return QVariant(asInteger());
322 case Double:
return QVariant(asDouble());
323 case String:
return QVariant(asString());
326 Q_UNREACHABLE_RETURN(QVariant());
332 return operate<AddOperators>(lhs, rhs);
338 return operate<SubOperators>(lhs, rhs);
344 return operate<MulOperators>(lhs, rhs);
350 return operate<DivOperators>(lhs, rhs);
365 if (leftInt >= 0 && rightInt > 0)
366 return leftInt % rightInt;
388 return (*
this = operate<SubOperators>(*
this, -1));
395 std::swap(other, *
this);
401 return (*
this = operate<SubOperators>(*
this, 1));
407 std::swap(other, *
this);
414 return (*
this = operate<SubOperators>(*
this, 0));
419 return (*
this = operate<MulOperators>(*
this, -1));
427 if (myType != otherType) {
441 return asBoolean() == other.asBoolean();
443 return asInteger() == other.asInteger();
445 const double l = asDouble();
446 const double r = other.asDouble();
447 if (
std::isnan(l) ||
std::isnan(r))
449 if (qIsNull(l) && qIsNull(r))
451 return QJSNumberCoercion::equals(l, r);
454 return asString() == other.asString();
466 if (myType == otherType)
471 return otherType ==
Null;
475 return QJSPrimitiveValue(
int(asBoolean()))
.equals(other
);
479 ? QJSPrimitiveValue(asInteger())
.equals(
int(other.asBoolean()))
480 : QJSPrimitiveValue(
double(asInteger()))
.equals(other
);
485 return numberFromString(asString()).parsedEquals(other);
512 case Null:
return false;
513 case Boolean:
return 0 <
int(rhs.asBoolean());
514 case Integer:
return 0 < rhs.asInteger();
515 case Double:
return double(0) < rhs.asDouble();
523 case Null:
return int(lhs.asBoolean()) < 0;
524 case Boolean:
return lhs.asBoolean() < rhs.asBoolean();
525 case Integer:
return int(lhs.asBoolean()) < rhs.asInteger();
526 case Double:
return double(lhs.asBoolean()) < rhs.asDouble();
534 case Null:
return lhs.asInteger() < 0;
535 case Boolean:
return lhs.asInteger() <
int(rhs.asBoolean());
536 case Integer:
return lhs.asInteger() < rhs.asInteger();
537 case Double:
return double(lhs.asInteger()) < rhs.asDouble();
545 case Null:
return lhs.asDouble() <
double(0);
546 case Boolean:
return lhs.asDouble() <
double(rhs.asBoolean());
547 case Integer:
return lhs.asDouble() <
double(rhs.asInteger());
548 case Double:
return lhs.asDouble() < rhs.asDouble();
560 case String:
return lhs.asString() < rhs.asString();
578 return lhs.asString() <= rhs.asString();
580 return numberFromString(lhs.asString()) <= rhs;
583 return lhs <= numberFromString(rhs.asString());
585 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
594 return lhs.asString() >= rhs.asString();
596 return numberFromString(lhs.asString()) >= rhs;
599 return lhs >= numberFromString(rhs.asString());
601 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
607 friend class QJSManagedValue;
608 friend class QJSValue;
609 friend struct QV4::ExecutionEngine;
611 constexpr bool asBoolean()
const {
return d.getBool(); }
612 constexpr int asInteger()
const {
return d.getInt(); }
613 constexpr double asDouble()
const {
return d.getDouble(); }
614 QString asString()
const {
return d.getString(); }
624 const int intValue = string.toInt(&ok);
628 const double doubleValue = string.toDouble(&ok);
631 if (string.isEmpty())
633 if (string == QStringLiteral(
"Infinity"))
634 return std::numeric_limits<
double>::infinity();
635 if (string == QStringLiteral(
"-Infinity"))
636 return -
std::numeric_limits<
double>::infinity();
637 if (string == QStringLiteral(
"NaN"))
638 return std::numeric_limits<
double>::quiet_NaN();
642 static Q_QML_EXPORT QString
toString(
double d);
644 template<
typename Operators,
typename Lhs,
typename Rhs>
649 if (Operators::opOverflow(lhs.d.get<Lhs>(), rhs.d.get<Rhs>(), &result))
650 return Operators::op(lhs.d.get<Lhs>(), rhs.d.get<Rhs>());
654 template<
typename Operators>
660 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
661 case Null:
return std::numeric_limits<
double>::quiet_NaN();
662 case Boolean:
return std::numeric_limits<
double>::quiet_NaN();
663 case Integer:
return std::numeric_limits<
double>::quiet_NaN();
664 case Double:
return std::numeric_limits<
double>::quiet_NaN();
670 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
671 case Null:
return operateOnIntegers<Operators,
int,
int>(0, 0);
672 case Boolean:
return operateOnIntegers<Operators,
int,
bool>(0, rhs);
673 case Integer:
return operateOnIntegers<Operators,
int,
int>(0, rhs);
674 case Double:
return Operators::op(0, rhs.asDouble());
680 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
681 case Null:
return operateOnIntegers<Operators,
bool,
int>(lhs, 0);
682 case Boolean:
return operateOnIntegers<Operators,
bool,
bool>(lhs, rhs);
683 case Integer:
return operateOnIntegers<Operators,
bool,
int>(lhs, rhs);
684 case Double:
return Operators::op(lhs.asBoolean(), rhs.asDouble());
685 case String:
return Operators::op(lhs.asBoolean(), rhs.asString());
690 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
691 case Null:
return operateOnIntegers<Operators,
int,
int>(lhs, 0);
692 case Boolean:
return operateOnIntegers<Operators,
int,
bool>(lhs, rhs);
693 case Integer:
return operateOnIntegers<Operators,
int,
int>(lhs, rhs);
694 case Double:
return Operators::op(lhs.asInteger(), rhs.asDouble());
695 case String:
return Operators::op(lhs.asInteger(), rhs.asString());
700 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
701 case Null:
return Operators::op(lhs.asDouble(), 0);
702 case Boolean:
return Operators::op(lhs.asDouble(), rhs.asBoolean());
703 case Integer:
return Operators::op(lhs.asDouble(), rhs.asInteger());
704 case Double:
return Operators::op(lhs.asDouble(), rhs.asDouble());
705 case String:
return Operators::op(lhs.asDouble(), rhs.asString());
712 case Boolean:
return Operators::op(lhs.asString(), rhs.asBoolean());
713 case Integer:
return Operators::op(lhs.asString(), rhs.asInteger());
714 case Double:
return Operators::op(lhs.asString(), rhs.asDouble());
715 case String:
return Operators::op(lhs.asString(), rhs.asString());
723 constexpr bool isNanOrUndefined()
const
727 case Null:
return false;
730 case Double:
return std::isnan(asDouble());
731 case String:
return false;
734 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
735 Q_UNREACHABLE_RETURN(
false);
741 struct QJSPrimitiveValuePrivate
744 constexpr QJSPrimitiveValuePrivate()
noexcept {}
746 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(QJSPrimitiveUndefined)
noexcept {}
747 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(QJSPrimitiveNull)
noexcept
749 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
bool b)
noexcept
750 : m_bool(b), m_type(Boolean) {}
751 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
int i)
noexcept
752 : m_int(i), m_type(Integer) {}
753 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
double d)
noexcept
754 : m_double(d), m_type(Double) {}
755 Q_IMPLICIT QJSPrimitiveValuePrivate(QString s)
noexcept
756 : m_string(std::move(s)), m_type(String) {}
758 constexpr QJSPrimitiveValuePrivate(
const QJSPrimitiveValuePrivate &other)
noexcept
759 : m_type(other.m_type)
762 if (!assignSimple(other))
763 new (&m_string) QString(other.m_string);
766 constexpr QJSPrimitiveValuePrivate(QJSPrimitiveValuePrivate &&other)
noexcept
767 : m_type(other.m_type)
770 if (!assignSimple(other))
771 new (&m_string) QString(std::move(other.m_string));
774 constexpr QJSPrimitiveValuePrivate &operator=(
const QJSPrimitiveValuePrivate &other)
noexcept
780 if (other.m_type ==
String) {
781 m_type = other.m_type;
782 m_string = other.m_string;
788 m_type = other.m_type;
789 if (!assignSimple(other))
790 new (&m_string) QString(other.m_string);
794 constexpr QJSPrimitiveValuePrivate &operator=(QJSPrimitiveValuePrivate &&other)
noexcept
800 if (other.m_type ==
String) {
801 m_type = other.m_type;
802 m_string = std::move(other.m_string);
808 m_type = other.m_type;
809 if (!assignSimple(other))
810 new (&m_string) QString(std::move(other.m_string));
814 ~QJSPrimitiveValuePrivate()
816 if (m_type == String)
820 constexpr Type type()
const noexcept {
return m_type; }
821 constexpr bool getBool()
const noexcept {
return m_bool; }
822 constexpr int getInt()
const noexcept {
return m_int; }
823 constexpr double getDouble()
const noexcept {
return m_double; }
824 QString getString()
const noexcept {
return m_string; }
827 constexpr T get()
const noexcept {
832 else if constexpr (std::is_same_v<T,
bool>)
834 else if constexpr (std::is_same_v<T,
int>)
836 else if constexpr (std::is_same_v<T,
double>)
838 else if constexpr (std::is_same_v<T, QString>)
842 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
843 Q_UNREACHABLE_RETURN(T());
849 constexpr QMetaType metaType()
const noexcept {
854 return QMetaType::fromType<std::nullptr_t>();
856 return QMetaType::fromType<
bool>();
858 return QMetaType::fromType<
int>();
860 return QMetaType::fromType<
double>();
862 return QMetaType::fromType<QString>();
866 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
867 Q_UNREACHABLE_RETURN(QMetaType());
873 constexpr void *data()
noexcept {
889 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
890 Q_UNREACHABLE_RETURN(
nullptr);
896 constexpr const void *data()
const noexcept {
912 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
913 Q_UNREACHABLE_RETURN(
nullptr);
920 constexpr bool assignSimple(
const QJSPrimitiveValuePrivate &other)
noexcept
922 switch (other.m_type) {
927 m_bool = other.m_bool;
933 m_double = other.m_double;
940 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
941 Q_UNREACHABLE_RETURN(
false);
955 std::byte m_zeroInitialize[
sizeof(QString)] = {};
961 QJSPrimitiveValuePrivate d;