26 template<
typename Concrete>
27 struct StringNaNOperators
31 return std::numeric_limits<double>::quiet_NaN();
36 return std::numeric_limits<double>::quiet_NaN();
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());
61 static constexpr double op(
double lhs,
double rhs) {
return lhs + rhs; }
62 static bool opOverflow(
int lhs,
int rhs,
int *
result)
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)
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)
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;
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:
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(); }
225 case Null:
return false;
226 case Boolean:
return asBoolean();
227 case Integer:
return asInteger() != 0;
229 const double v = asDouble();
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({});
289 const double result = asDouble();
292 if (std::isfinite(
result))
298 case String:
return asString();
301 Q_UNREACHABLE_RETURN(
QString());
308 case Null:
return QVariant::fromValue<std::nullptr_t>(
nullptr);
321 return operate<AddOperators>(lhs, rhs);
327 return operate<SubOperators>(lhs, rhs);
333 return operate<MulOperators>(lhs, rhs);
339 return operate<DivOperators>(lhs, rhs);
345 switch (lhs.
type()) {
349 switch (rhs.
type()) {
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))
443 return asString() ==
other.asString();
455 if (myType == otherType)
460 return otherType ==
Null;
472 return other.equals(*
this);
474 return fromString(asString()).parsedEquals(
other);
495 switch (lhs.
type()) {
499 switch (rhs.
type()) {
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();
510 switch (rhs.
type()) {
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();
521 switch (rhs.
type()) {
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();
532 switch (rhs.
type()) {
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();
543 switch (rhs.
type()) {
549 case String:
return lhs.asString() < rhs.asString();
565 if (lhs.
type() == String) {
566 if (rhs.
type() == String)
567 return lhs.asString() <= rhs.asString();
569 return fromString(lhs.asString()) <= rhs;
571 if (rhs.
type() == String)
572 return lhs <= fromString(rhs.asString());
574 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
581 if (lhs.
type() == String) {
582 if (rhs.
type() == String)
583 return lhs.asString() >= rhs.asString();
585 return fromString(lhs.asString()) >= rhs;
587 if (rhs.
type() == String)
588 return lhs >= fromString(rhs.asString());
590 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
600 constexpr bool asBoolean()
const {
return d.getBool(); }
601 constexpr int asInteger()
const {
return d.getInt(); }
602 constexpr double asDouble()
const {
return d.getDouble(); }
613 const int intValue =
string.toInt(&
ok);
617 const double doubleValue =
string.toDouble(&
ok);
621 return std::numeric_limits<double>::infinity();
623 return -std::numeric_limits<double>::infinity();
625 return std::numeric_limits<double>::quiet_NaN();
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>
644 switch (lhs.
type()) {
646 switch (rhs.
type()) {
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();
656 switch (rhs.
type()) {
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());
666 switch (rhs.
type()) {
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());
676 switch (rhs.
type()) {
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());
686 switch (rhs.
type()) {
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());
696 switch (rhs.
type()) {
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 {}
736 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
bool b) noexcept
738 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
int i) noexcept
740 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
double d) noexcept
741 : m_double(d), m_type(
Double) {}
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))
753 constexpr QJSPrimitiveValuePrivate(QJSPrimitiveValuePrivate &&
other) noexcept
754 : m_type(
other.m_type)
757 if (!assignSimple(
other))
761 constexpr QJSPrimitiveValuePrivate &operator=(
const QJSPrimitiveValuePrivate &
other)
noexcept
766 if (m_type == String) {
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))
781 constexpr QJSPrimitiveValuePrivate &operator=(QJSPrimitiveValuePrivate &&
other)
noexcept
786 if (m_type == String) {
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))
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 {
815 if constexpr (std::is_same_v<T, QJSPrimitiveUndefined>)
817 else if constexpr (std::is_same_v<T, QJSPrimitiveNull>)
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)
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);
944 QJSPrimitiveValuePrivate d;