26 template<
typename Concrete>
27 struct StringNaNOperators
31 return std::numeric_limits<
double>::quiet_NaN();
36 return std::numeric_limits<
double>::quiet_NaN();
39 static double op(
const QString &lhs,
QJSPrimitiveNull) {
return op(lhs, 0); }
40 static double op(
QJSPrimitiveNull,
const QString &rhs) {
return op(0, rhs); }
43 static double op(
const QString &lhs, T rhs)
45 return Concrete::op(fromString(lhs).toDouble(), rhs);
49 static double op(T lhs,
const QString &rhs)
51 return Concrete::op(lhs, fromString(rhs).toDouble());
54 static double op(
const QString &lhs,
const QString &rhs)
56 return Concrete::op(fromString(lhs).toDouble(), fromString(rhs).toDouble());
61 static constexpr double op(
double lhs,
double rhs) {
return lhs + rhs; }
62 static bool opOverflow(
int lhs,
int rhs,
int *result)
64 return qAddOverflow(lhs, rhs, result);
68 static QString op(
const QString &lhs, T rhs)
74 static QString op(T lhs,
const QString &rhs)
79 static QString op(
const QString &lhs,
const QString &rhs) {
return lhs + rhs; }
82 struct SubOperators :
private StringNaNOperators<SubOperators> {
83 static constexpr double op(
double lhs,
double rhs) {
return lhs - rhs; }
84 static bool opOverflow(
int lhs,
int rhs,
int *result)
86 return qSubOverflow(lhs, rhs, result);
89 using StringNaNOperators::op;
92 struct MulOperators :
private StringNaNOperators<MulOperators> {
93 static constexpr double op(
double lhs,
double rhs) {
return lhs * rhs; }
94 static bool opOverflow(
int lhs,
int rhs,
int *result)
97 auto hadOverflow = qMulOverflow(lhs, rhs, result);
98 if (((lhs < 0) ^ (rhs < 0)) && (*result == 0))
103 using StringNaNOperators::op;
106 struct DivOperators :
private StringNaNOperators<DivOperators> {
107 static constexpr double op(
double lhs,
double rhs) {
return lhs / rhs; }
108 static constexpr bool opOverflow(
int,
int,
int *)
113 using StringNaNOperators::op;
142 case QMetaType::UnknownType:
145 case QMetaType::Nullptr:
148 case QMetaType::Bool:
149 d = *
static_cast<
const bool *>(value);
152 d = *
static_cast<
const int *>(value);
154 case QMetaType::Double:
155 d = *
static_cast<
const double *>(value);
157 case QMetaType::QString:
158 d = *
static_cast<
const QString *>(value);
169 case QMetaType::UnknownType:
172 case QMetaType::Nullptr:
175 case QMetaType::Bool:
181 case QMetaType::Double:
184 case QMetaType::QString:
199 constexpr void *
data() {
return d.data(); }
200 constexpr const void *
data()
const {
return d.data(); }
201 constexpr const void *
constData()
const {
return d.data(); }
207 if constexpr (type ==
Null)
213 if constexpr (type ==
Double)
215 if constexpr (type == String)
225 case Null:
return false;
226 case Boolean:
return asBoolean();
227 case Integer:
return asInteger() != 0;
229 const double v = asDouble();
230 return !QJSNumberCoercion::equals(v, 0) && !std::isnan(v);
232 case String:
return !asString().isEmpty();
236 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
237 Q_UNREACHABLE_RETURN(
false);
248 case Boolean:
return asBoolean();
249 case Integer:
return asInteger();
250 case Double:
return QJSNumberCoercion::toInteger(asDouble());
251 case String:
return fromString(asString()).toInteger();
255 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
256 Q_UNREACHABLE_RETURN(0);
265 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
267 case Boolean:
return asBoolean();
268 case Integer:
return asInteger();
269 case Double:
return asDouble();
270 case String:
return fromString(asString()).toDouble();
274 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
275 Q_UNREACHABLE_RETURN({});
284 case Undefined:
return QStringLiteral(
"undefined");
285 case Null:
return QStringLiteral(
"null");
286 case Boolean:
return asBoolean() ? QStringLiteral(
"true") : QStringLiteral(
"false");
287 case Integer:
return QString::number(asInteger());
289 const double result = asDouble();
290 if (
std::isnan(result))
291 return QStringLiteral(
"NaN");
292 if (std::isfinite(result))
293 return toString(result);
295 return QStringLiteral(
"Infinity");
296 return QStringLiteral(
"-Infinity");
298 case String:
return asString();
301 Q_UNREACHABLE_RETURN(QString());
308 case Null:
return QVariant::fromValue<std::nullptr_t>(
nullptr);
309 case Boolean:
return QVariant(asBoolean());
310 case Integer:
return QVariant(asInteger());
311 case Double:
return QVariant(asDouble());
312 case String:
return QVariant(asString());
315 Q_UNREACHABLE_RETURN(QVariant());
321 return operate<AddOperators>(lhs, rhs);
327 return operate<SubOperators>(lhs, rhs);
333 return operate<MulOperators>(lhs, rhs);
339 return operate<DivOperators>(lhs, rhs);
354 if (leftInt >= 0 && rightInt > 0)
355 return leftInt % rightInt;
377 return (*
this = operate<SubOperators>(*
this, -1));
384 std::swap(other, *
this);
390 return (*
this = operate<SubOperators>(*
this, 1));
396 std::swap(other, *
this);
403 return (*
this = operate<SubOperators>(*
this, 0));
408 return (*
this = operate<MulOperators>(*
this, -1));
416 if (myType != otherType) {
430 return asBoolean() == other.asBoolean();
432 return asInteger() == other.asInteger();
434 const double l = asDouble();
435 const double r = other.asDouble();
436 if (
std::isnan(l) ||
std::isnan(r))
438 if (qIsNull(l) && qIsNull(r))
440 return QJSNumberCoercion::equals(l, r);
443 return asString() == other.asString();
455 if (myType == otherType)
460 return otherType ==
Null;
464 return QJSPrimitiveValue(
int(asBoolean()))
.equals(other
);
468 ? QJSPrimitiveValue(asInteger())
.equals(
int(other.asBoolean()))
469 : QJSPrimitiveValue(
double(asInteger()))
.equals(other
);
474 return fromString(asString()).parsedEquals(other);
501 case Null:
return false;
502 case Boolean:
return 0 <
int(rhs.asBoolean());
503 case Integer:
return 0 < rhs.asInteger();
504 case Double:
return double(0) < rhs.asDouble();
512 case Null:
return int(lhs.asBoolean()) < 0;
513 case Boolean:
return lhs.asBoolean() < rhs.asBoolean();
514 case Integer:
return int(lhs.asBoolean()) < rhs.asInteger();
515 case Double:
return double(lhs.asBoolean()) < rhs.asDouble();
523 case Null:
return lhs.asInteger() < 0;
524 case Boolean:
return lhs.asInteger() <
int(rhs.asBoolean());
525 case Integer:
return lhs.asInteger() < rhs.asInteger();
526 case Double:
return double(lhs.asInteger()) < rhs.asDouble();
534 case Null:
return lhs.asDouble() <
double(0);
535 case Boolean:
return lhs.asDouble() <
double(rhs.asBoolean());
536 case Integer:
return lhs.asDouble() <
double(rhs.asInteger());
537 case Double:
return lhs.asDouble() < rhs.asDouble();
549 case String:
return lhs.asString() < rhs.asString();
567 return lhs.asString() <= rhs.asString();
569 return fromString(lhs.asString()) <= rhs;
572 return lhs <= fromString(rhs.asString());
574 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
583 return lhs.asString() >= rhs.asString();
585 return fromString(lhs.asString()) >= rhs;
588 return lhs >= fromString(rhs.asString());
590 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
596 friend class QJSManagedValue;
597 friend class QJSValue;
598 friend struct QV4::ExecutionEngine;
600 constexpr bool asBoolean()
const {
return d.getBool(); }
601 constexpr int asInteger()
const {
return d.getInt(); }
602 constexpr double asDouble()
const {
return d.getDouble(); }
603 QString asString()
const {
return d.getString(); }
613 const int intValue = string.toInt(&ok);
617 const double doubleValue = string.toDouble(&ok);
620 if (string == QStringLiteral(
"Infinity"))
621 return std::numeric_limits<
double>::infinity();
622 if (string == QStringLiteral(
"-Infinity"))
623 return -
std::numeric_limits<
double>::infinity();
624 if (string == QStringLiteral(
"NaN"))
625 return std::numeric_limits<
double>::quiet_NaN();
629 static Q_QML_EXPORT QString
toString(
double d);
631 template<
typename Operators,
typename Lhs,
typename Rhs>
636 if (Operators::opOverflow(lhs.d.get<Lhs>(), rhs.d.get<Rhs>(), &result))
637 return Operators::op(lhs.d.get<Lhs>(), rhs.d.get<Rhs>());
641 template<
typename Operators>
647 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
648 case Null:
return std::numeric_limits<
double>::quiet_NaN();
649 case Boolean:
return std::numeric_limits<
double>::quiet_NaN();
650 case Integer:
return std::numeric_limits<
double>::quiet_NaN();
651 case Double:
return std::numeric_limits<
double>::quiet_NaN();
657 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
658 case Null:
return operateOnIntegers<Operators,
int,
int>(0, 0);
659 case Boolean:
return operateOnIntegers<Operators,
int,
bool>(0, rhs);
660 case Integer:
return operateOnIntegers<Operators,
int,
int>(0, rhs);
661 case Double:
return Operators::op(0, rhs.asDouble());
667 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
668 case Null:
return operateOnIntegers<Operators,
bool,
int>(lhs, 0);
669 case Boolean:
return operateOnIntegers<Operators,
bool,
bool>(lhs, rhs);
670 case Integer:
return operateOnIntegers<Operators,
bool,
int>(lhs, rhs);
671 case Double:
return Operators::op(lhs.asBoolean(), rhs.asDouble());
672 case String:
return Operators::op(lhs.asBoolean(), rhs.asString());
677 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
678 case Null:
return operateOnIntegers<Operators,
int,
int>(lhs, 0);
679 case Boolean:
return operateOnIntegers<Operators,
int,
bool>(lhs, rhs);
680 case Integer:
return operateOnIntegers<Operators,
int,
int>(lhs, rhs);
681 case Double:
return Operators::op(lhs.asInteger(), rhs.asDouble());
682 case String:
return Operators::op(lhs.asInteger(), rhs.asString());
687 case Undefined:
return std::numeric_limits<
double>::quiet_NaN();
688 case Null:
return Operators::op(lhs.asDouble(), 0);
689 case Boolean:
return Operators::op(lhs.asDouble(), rhs.asBoolean());
690 case Integer:
return Operators::op(lhs.asDouble(), rhs.asInteger());
691 case Double:
return Operators::op(lhs.asDouble(), rhs.asDouble());
692 case String:
return Operators::op(lhs.asDouble(), rhs.asString());
699 case Boolean:
return Operators::op(lhs.asString(), rhs.asBoolean());
700 case Integer:
return Operators::op(lhs.asString(), rhs.asInteger());
701 case Double:
return Operators::op(lhs.asString(), rhs.asDouble());
702 case String:
return Operators::op(lhs.asString(), rhs.asString());
710 constexpr bool isNanOrUndefined()
const
714 case Null:
return false;
717 case Double:
return std::isnan(asDouble());
718 case String:
return false;
721 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
722 Q_UNREACHABLE_RETURN(
false);
728 struct QJSPrimitiveValuePrivate
731 constexpr QJSPrimitiveValuePrivate()
noexcept {}
733 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(QJSPrimitiveUndefined)
noexcept {}
734 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(QJSPrimitiveNull)
noexcept
736 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
bool b)
noexcept
737 : m_bool(b), m_type(Boolean) {}
738 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
int i)
noexcept
739 : m_int(i), m_type(Integer) {}
740 Q_IMPLICIT
constexpr QJSPrimitiveValuePrivate(
double d)
noexcept
741 : m_double(d), m_type(Double) {}
742 Q_IMPLICIT QJSPrimitiveValuePrivate(QString s)
noexcept
743 : m_string(std::move(s)), m_type(String) {}
745 constexpr QJSPrimitiveValuePrivate(
const QJSPrimitiveValuePrivate &other)
noexcept
746 : m_type(other.m_type)
749 if (!assignSimple(other))
750 new (&m_string) QString(other.m_string);
753 constexpr QJSPrimitiveValuePrivate(QJSPrimitiveValuePrivate &&other)
noexcept
754 : m_type(other.m_type)
757 if (!assignSimple(other))
758 new (&m_string) QString(std::move(other.m_string));
761 constexpr QJSPrimitiveValuePrivate &operator=(
const QJSPrimitiveValuePrivate &other)
noexcept
767 if (other.m_type ==
String) {
768 m_type = other.m_type;
769 m_string = other.m_string;
775 m_type = other.m_type;
776 if (!assignSimple(other))
777 new (&m_string) QString(other.m_string);
781 constexpr QJSPrimitiveValuePrivate &operator=(QJSPrimitiveValuePrivate &&other)
noexcept
787 if (other.m_type ==
String) {
788 m_type = other.m_type;
789 m_string = std::move(other.m_string);
795 m_type = other.m_type;
796 if (!assignSimple(other))
797 new (&m_string) QString(std::move(other.m_string));
801 ~QJSPrimitiveValuePrivate()
803 if (m_type == String)
807 constexpr Type type()
const noexcept {
return m_type; }
808 constexpr bool getBool()
const noexcept {
return m_bool; }
809 constexpr int getInt()
const noexcept {
return m_int; }
810 constexpr double getDouble()
const noexcept {
return m_double; }
811 QString getString()
const noexcept {
return m_string; }
814 constexpr T get()
const noexcept {
819 else if constexpr (std::is_same_v<T,
bool>)
821 else if constexpr (std::is_same_v<T,
int>)
823 else if constexpr (std::is_same_v<T,
double>)
825 else if constexpr (std::is_same_v<T, QString>)
829 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
830 Q_UNREACHABLE_RETURN(T());
836 constexpr QMetaType metaType()
const noexcept {
841 return QMetaType::fromType<std::nullptr_t>();
843 return QMetaType::fromType<
bool>();
845 return QMetaType::fromType<
int>();
847 return QMetaType::fromType<
double>();
849 return QMetaType::fromType<QString>();
853 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
854 Q_UNREACHABLE_RETURN(QMetaType());
860 constexpr void *data()
noexcept {
876 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
877 Q_UNREACHABLE_RETURN(
nullptr);
883 constexpr const void *data()
const noexcept {
899 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
900 Q_UNREACHABLE_RETURN(
nullptr);
907 constexpr bool assignSimple(
const QJSPrimitiveValuePrivate &other)
noexcept
909 switch (other.m_type) {
914 m_bool = other.m_bool;
920 m_double = other.m_double;
927 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900
)
928 Q_UNREACHABLE_RETURN(
false);
942 std::byte m_zeroInitialize[
sizeof(QString)] = {};
948 QJSPrimitiveValuePrivate d;