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) {
return lhs / rhs; }
109 static constexpr bool opOverflow(
int,
int,
int *)
114 using StringNaNOperators::op;
143 case QMetaType::UnknownType:
146 case QMetaType::Nullptr:
149 case QMetaType::Bool:
150 d = *
static_cast<
const bool *>(value);
153 d = *
static_cast<
const int *>(value);
155 case QMetaType::Double:
156 d = *
static_cast<
const double *>(value);
158 case QMetaType::QString:
159 d = *
static_cast<
const QString *>(value);
170 case QMetaType::UnknownType:
173 case QMetaType::Nullptr:
176 case QMetaType::Bool:
182 case QMetaType::Double:
185 case QMetaType::QString:
200 constexpr void *
data() {
return d.data(); }
201 constexpr const void *
data()
const {
return d.data(); }
202 constexpr const void *
constData()
const {
return d.data(); }
208 if constexpr (type ==
Null)
214 if constexpr (type ==
Double)
216 if constexpr (type == String)
226 case Null:
return false;
227 case Boolean:
return asBoolean();
228 case Integer:
return asInteger() != 0;
230 const double v = asDouble();
231 return !QJSNumberCoercion::equals(v, 0) && !std::isnan(v);
233 case String:
return !asString().isEmpty();
237 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
238 Q_UNREACHABLE_RETURN(
false);
249 case Boolean:
return asBoolean();
250 case Integer:
return asInteger();
251 case Double:
return QJSNumberCoercion::toInteger(asDouble());
252 case String:
return numberFromString(asString()).toInteger();
256 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
257 Q_UNREACHABLE_RETURN(0);
266 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
268 case Boolean:
return asBoolean();
269 case Integer:
return asInteger();
270 case Double:
return asDouble();
271 case String:
return numberFromString(asString()).toDouble();
275 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
276 Q_UNREACHABLE_RETURN({});
285 case Undefined:
return QStringLiteral(
"undefined");
286 case Null:
return QStringLiteral(
"null");
287 case Boolean:
return asBoolean() ? QStringLiteral(
"true") : QStringLiteral(
"false");
288 case Integer:
return QString::number(asInteger());
290 const double result = asDouble();
291 if (
std::isnan(result))
292 return QStringLiteral(
"NaN");
293 if (std::isfinite(result))
294 return toString(result);
296 return QStringLiteral(
"Infinity");
297 return QStringLiteral(
"-Infinity");
299 case String:
return asString();
302 Q_UNREACHABLE_RETURN(QString());
309 case Null:
return QVariant::fromValue<std::nullptr_t>(
nullptr);
310 case Boolean:
return QVariant(asBoolean());
311 case Integer:
return QVariant(asInteger());
312 case Double:
return QVariant(asDouble());
313 case String:
return QVariant(asString());
316 Q_UNREACHABLE_RETURN(QVariant());
322 return operate<AddOperators>(lhs, rhs);
328 return operate<SubOperators>(lhs, rhs);
334 return operate<MulOperators>(lhs, rhs);
340 return operate<DivOperators>(lhs, rhs);
355 if (leftInt >= 0 && rightInt > 0)
356 return leftInt % rightInt;
378 return (*
this = operate<SubOperators>(*
this, -1));
385 std::swap(other, *
this);
391 return (*
this = operate<SubOperators>(*
this, 1));
397 std::swap(other, *
this);
404 return (*
this = operate<SubOperators>(*
this, 0));
409 return (*
this = operate<MulOperators>(*
this, -1));
417 if (myType != otherType) {
431 return asBoolean() == other.asBoolean();
433 return asInteger() == other.asInteger();
435 const double l = asDouble();
436 const double r = other.asDouble();
437 if (
std::isnan(l) ||
std::isnan(r))
439 if (qIsNull(l) && qIsNull(r))
441 return QJSNumberCoercion::equals(l, r);
444 return asString() == other.asString();
456 if (myType == otherType)
461 return otherType ==
Null;
465 return QJSPrimitiveValue(
int(asBoolean()))
.equals(other
);
469 ? QJSPrimitiveValue(asInteger())
.equals(
int(other.asBoolean()))
470 : QJSPrimitiveValue(
double(asInteger()))
.equals(other
);
475 return numberFromString(asString()).parsedEquals(other);
502 case Null:
return false;
503 case Boolean:
return 0 <
int(rhs.asBoolean());
504 case Integer:
return 0 < rhs.asInteger();
505 case Double:
return double(0) < rhs.asDouble();
513 case Null:
return int(lhs.asBoolean()) < 0;
514 case Boolean:
return lhs.asBoolean() < rhs.asBoolean();
515 case Integer:
return int(lhs.asBoolean()) < rhs.asInteger();
516 case Double:
return double(lhs.asBoolean()) < rhs.asDouble();
524 case Null:
return lhs.asInteger() < 0;
525 case Boolean:
return lhs.asInteger() <
int(rhs.asBoolean());
526 case Integer:
return lhs.asInteger() < rhs.asInteger();
527 case Double:
return double(lhs.asInteger()) < rhs.asDouble();
535 case Null:
return lhs.asDouble() <
double(0);
536 case Boolean:
return lhs.asDouble() <
double(rhs.asBoolean());
537 case Integer:
return lhs.asDouble() <
double(rhs.asInteger());
538 case Double:
return lhs.asDouble() < rhs.asDouble();
550 case String:
return lhs.asString() < rhs.asString();
568 return lhs.asString() <= rhs.asString();
570 return numberFromString(lhs.asString()) <= rhs;
573 return lhs <= numberFromString(rhs.asString());
575 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
584 return lhs.asString() >= rhs.asString();
586 return numberFromString(lhs.asString()) >= rhs;
589 return lhs >= numberFromString(rhs.asString());
591 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
597 friend class QJSManagedValue;
598 friend class QJSValue;
599 friend struct QV4::ExecutionEngine;
601 constexpr bool asBoolean()
const {
return d.getBool(); }
602 constexpr int asInteger()
const {
return d.getInt(); }
603 constexpr double asDouble()
const {
return d.getDouble(); }
604 QString asString()
const {
return d.getString(); }
614 const int intValue = string.toInt(&ok);
618 const double doubleValue = string.toDouble(&ok);
621 if (string.isEmpty())
623 if (string == QStringLiteral(
"Infinity"))
624 return std::numeric_limits<
double>::infinity();
625 if (string == QStringLiteral(
"-Infinity"))
626 return -
std::numeric_limits<
double>::infinity();
627 if (string == QStringLiteral(
"NaN"))
628 return std::numeric_limits<
double>::quiet_NaN();
632 static Q_QML_EXPORT QString
toString(
double d);
634 template<
typename Operators,
typename Lhs,
typename Rhs>
639 if (Operators::opOverflow(lhs.d.get<Lhs>(), rhs.d.get<Rhs>(), &result))
640 return Operators::op(lhs.d.get<Lhs>(), rhs.d.get<Rhs>());
644 template<
typename Operators>
650 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
651 case Null:
return std::numeric_limits<
double>::quiet_NaN();
652 case Boolean:
return std::numeric_limits<
double>::quiet_NaN();
653 case Integer:
return std::numeric_limits<
double>::quiet_NaN();
654 case Double:
return std::numeric_limits<
double>::quiet_NaN();
660 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
661 case Null:
return operateOnIntegers<Operators,
int,
int>(0, 0);
662 case Boolean:
return operateOnIntegers<Operators,
int,
bool>(0, rhs);
663 case Integer:
return operateOnIntegers<Operators,
int,
int>(0, rhs);
664 case Double:
return Operators::op(0, rhs.asDouble());
670 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
671 case Null:
return operateOnIntegers<Operators,
bool,
int>(lhs, 0);
672 case Boolean:
return operateOnIntegers<Operators,
bool,
bool>(lhs, rhs);
673 case Integer:
return operateOnIntegers<Operators,
bool,
int>(lhs, rhs);
674 case Double:
return Operators::op(lhs.asBoolean(), rhs.asDouble());
675 case String:
return Operators::op(lhs.asBoolean(), rhs.asString());
680 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
681 case Null:
return operateOnIntegers<Operators,
int,
int>(lhs, 0);
682 case Boolean:
return operateOnIntegers<Operators,
int,
bool>(lhs, rhs);
683 case Integer:
return operateOnIntegers<Operators,
int,
int>(lhs, rhs);
684 case Double:
return Operators::op(lhs.asInteger(), rhs.asDouble());
685 case String:
return Operators::op(lhs.asInteger(), rhs.asString());
690 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
691 case Null:
return Operators::op(lhs.asDouble(), 0);
692 case Boolean:
return Operators::op(lhs.asDouble(), rhs.asBoolean());
693 case Integer:
return Operators::op(lhs.asDouble(), rhs.asInteger());
694 case Double:
return Operators::op(lhs.asDouble(), rhs.asDouble());
695 case String:
return Operators::op(lhs.asDouble(), rhs.asString());
702 case Boolean:
return Operators::op(lhs.asString(), rhs.asBoolean());
703 case Integer:
return Operators::op(lhs.asString(), rhs.asInteger());
704 case Double:
return Operators::op(lhs.asString(), rhs.asDouble());
705 case String:
return Operators::op(lhs.asString(), rhs.asString());
713 constexpr bool isNanOrUndefined()
const
717 case Null:
return false;
720 case Double:
return std::isnan(asDouble());
721 case String:
return false;
724 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
725 Q_UNREACHABLE_RETURN(
false);
731 struct QJSPrimitiveValuePrivate
734 constexpr QJSPrimitiveValuePrivate()
noexcept {}
736 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(QJSPrimitiveUndefined)
noexcept {}
737 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(QJSPrimitiveNull)
noexcept
739 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
bool b)
noexcept
740 : m_bool(b), m_type(Boolean) {}
741 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
int i)
noexcept
742 : m_int(i), m_type(Integer) {}
743 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
double d)
noexcept
744 : m_double(d), m_type(Double) {}
745 Q_IMPLICIT QJSPrimitiveValuePrivate(QString s)
noexcept
746 : m_string(std::move(s)), m_type(String) {}
748 constexpr QJSPrimitiveValuePrivate(
const QJSPrimitiveValuePrivate &other)
noexcept
749 : m_type(other.m_type)
752 if (!assignSimple(other))
753 new (&m_string) QString(other.m_string);
756 constexpr QJSPrimitiveValuePrivate(QJSPrimitiveValuePrivate &&other)
noexcept
757 : m_type(other.m_type)
760 if (!assignSimple(other))
761 new (&m_string) QString(std::move(other.m_string));
764 constexpr QJSPrimitiveValuePrivate &operator=(
const QJSPrimitiveValuePrivate &other)
noexcept
770 if (other.m_type ==
String) {
771 m_type = other.m_type;
772 m_string = other.m_string;
778 m_type = other.m_type;
779 if (!assignSimple(other))
780 new (&m_string) QString(other.m_string);
784 constexpr QJSPrimitiveValuePrivate &operator=(QJSPrimitiveValuePrivate &&other)
noexcept
790 if (other.m_type ==
String) {
791 m_type = other.m_type;
792 m_string = std::move(other.m_string);
798 m_type = other.m_type;
799 if (!assignSimple(other))
800 new (&m_string) QString(std::move(other.m_string));
804 ~QJSPrimitiveValuePrivate()
806 if (m_type == String)
810 constexpr Type type()
const noexcept {
return m_type; }
811 constexpr bool getBool()
const noexcept {
return m_bool; }
812 constexpr int getInt()
const noexcept {
return m_int; }
813 constexpr double getDouble()
const noexcept {
return m_double; }
814 QString getString()
const noexcept {
return m_string; }
817 constexpr T get()
const noexcept {
822 else if constexpr (std::is_same_v<T,
bool>)
824 else if constexpr (std::is_same_v<T,
int>)
826 else if constexpr (std::is_same_v<T,
double>)
828 else if constexpr (std::is_same_v<T, QString>)
832 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
833 Q_UNREACHABLE_RETURN(T());
839 constexpr QMetaType metaType()
const noexcept {
844 return QMetaType::fromType<std::nullptr_t>();
846 return QMetaType::fromType<
bool>();
848 return QMetaType::fromType<
int>();
850 return QMetaType::fromType<
double>();
852 return QMetaType::fromType<QString>();
856 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
857 Q_UNREACHABLE_RETURN(QMetaType());
863 constexpr void *data()
noexcept {
879 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
880 Q_UNREACHABLE_RETURN(
nullptr);
886 constexpr const void *data()
const noexcept {
902 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
903 Q_UNREACHABLE_RETURN(
nullptr);
910 constexpr bool assignSimple(
const QJSPrimitiveValuePrivate &other)
noexcept
912 switch (other.m_type) {
917 m_bool = other.m_bool;
923 m_double = other.m_double;
930 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
931 Q_UNREACHABLE_RETURN(
false);
945 std::byte m_zeroInitialize[
sizeof(QString)] = {};
951 QJSPrimitiveValuePrivate d;