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;
372 return (*
this = operate<SubOperators>(*
this, -1));
379 std::swap(
other, *
this);
385 return (*
this = operate<SubOperators>(*
this, 1));
391 std::swap(
other, *
this);
398 return (*
this = operate<SubOperators>(*
this, 0));
403 return (*
this = operate<MulOperators>(*
this, -1));
411 if (myType != otherType) {
425 return asBoolean() ==
other.asBoolean();
427 return asInteger() ==
other.asInteger();
429 const double l = asDouble();
430 const double r =
other.asDouble();
431 if (std::isnan(l) || std::isnan(
r))
438 return asString() ==
other.asString();
450 if (myType == otherType)
455 return otherType ==
Null;
467 return other.equals(*
this);
469 return fromString(asString()).parsedEquals(
other);
490 switch (lhs.
type()) {
494 switch (rhs.
type()) {
496 case Null:
return false;
497 case Boolean:
return 0 < int(rhs.asBoolean());
498 case Integer:
return 0 < rhs.asInteger();
499 case Double:
return double(0) < rhs.asDouble();
505 switch (rhs.
type()) {
507 case Null:
return int(lhs.asBoolean()) < 0;
508 case Boolean:
return lhs.asBoolean() < rhs.asBoolean();
509 case Integer:
return int(lhs.asBoolean()) < rhs.asInteger();
510 case Double:
return double(lhs.asBoolean()) < rhs.asDouble();
516 switch (rhs.
type()) {
518 case Null:
return lhs.asInteger() < 0;
519 case Boolean:
return lhs.asInteger() < int(rhs.asBoolean());
520 case Integer:
return lhs.asInteger() < rhs.asInteger();
521 case Double:
return double(lhs.asInteger()) < rhs.asDouble();
527 switch (rhs.
type()) {
529 case Null:
return lhs.asDouble() < double(0);
530 case Boolean:
return lhs.asDouble() < double(rhs.asBoolean());
531 case Integer:
return lhs.asDouble() < double(rhs.asInteger());
532 case Double:
return lhs.asDouble() < rhs.asDouble();
538 switch (rhs.
type()) {
544 case String:
return lhs.asString() < rhs.asString();
560 if (lhs.
type() == String) {
561 if (rhs.
type() == String)
562 return lhs.asString() <= rhs.asString();
564 return fromString(lhs.asString()) <= rhs;
566 if (rhs.
type() == String)
567 return lhs <= fromString(rhs.asString());
569 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
576 if (lhs.
type() == String) {
577 if (rhs.
type() == String)
578 return lhs.asString() >= rhs.asString();
580 return fromString(lhs.asString()) >= rhs;
582 if (rhs.
type() == String)
583 return lhs >= fromString(rhs.asString());
585 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
595 constexpr bool asBoolean()
const {
return d.getBool(); }
596 constexpr int asInteger()
const {
return d.getInt(); }
597 constexpr double asDouble()
const {
return d.getDouble(); }
608 const int intValue =
string.toInt(&
ok);
612 const double doubleValue =
string.toDouble(&
ok);
616 return std::numeric_limits<double>::infinity();
618 return -std::numeric_limits<double>::infinity();
620 return std::numeric_limits<double>::quiet_NaN();
626 template<
typename Operators,
typename Lhs,
typename Rhs>
631 if (Operators::opOverflow(lhs.d.get<Lhs>(), rhs.d.get<Rhs>(), &
result))
632 return Operators::op(lhs.d.get<Lhs>(), rhs.d.get<Rhs>());
636 template<
typename Operators>
639 switch (lhs.
type()) {
641 switch (rhs.
type()) {
642 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
643 case Null:
return std::numeric_limits<double>::quiet_NaN();
644 case Boolean:
return std::numeric_limits<double>::quiet_NaN();
645 case Integer:
return std::numeric_limits<double>::quiet_NaN();
646 case Double:
return std::numeric_limits<double>::quiet_NaN();
651 switch (rhs.
type()) {
652 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
653 case Null:
return operateOnIntegers<Operators, int, int>(0, 0);
654 case Boolean:
return operateOnIntegers<Operators, int, bool>(0, rhs);
655 case Integer:
return operateOnIntegers<Operators, int, int>(0, rhs);
656 case Double:
return Operators::op(0, rhs.asDouble());
661 switch (rhs.
type()) {
662 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
663 case Null:
return operateOnIntegers<Operators, bool, int>(lhs, 0);
664 case Boolean:
return operateOnIntegers<Operators, bool, bool>(lhs, rhs);
665 case Integer:
return operateOnIntegers<Operators, bool, int>(lhs, rhs);
666 case Double:
return Operators::op(lhs.asBoolean(), rhs.asDouble());
667 case String:
return Operators::op(lhs.asBoolean(), rhs.asString());
671 switch (rhs.
type()) {
672 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
673 case Null:
return operateOnIntegers<Operators, int, int>(lhs, 0);
674 case Boolean:
return operateOnIntegers<Operators, int, bool>(lhs, rhs);
675 case Integer:
return operateOnIntegers<Operators, int, int>(lhs, rhs);
676 case Double:
return Operators::op(lhs.asInteger(), rhs.asDouble());
677 case String:
return Operators::op(lhs.asInteger(), rhs.asString());
681 switch (rhs.
type()) {
682 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
683 case Null:
return Operators::op(lhs.asDouble(), 0);
684 case Boolean:
return Operators::op(lhs.asDouble(), rhs.asBoolean());
685 case Integer:
return Operators::op(lhs.asDouble(), rhs.asInteger());
686 case Double:
return Operators::op(lhs.asDouble(), rhs.asDouble());
687 case String:
return Operators::op(lhs.asDouble(), rhs.asString());
691 switch (rhs.
type()) {
694 case Boolean:
return Operators::op(lhs.asString(), rhs.asBoolean());
695 case Integer:
return Operators::op(lhs.asString(), rhs.asInteger());
696 case Double:
return Operators::op(lhs.asString(), rhs.asDouble());
697 case String:
return Operators::op(lhs.asString(), rhs.asString());
705 constexpr bool isNanOrUndefined()
const
709 case Double:
return std::isnan(asDouble());
710 default:
return false;
714 struct QJSPrimitiveValuePrivate
717 constexpr QJSPrimitiveValuePrivate() noexcept {}
722 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
bool b) noexcept
724 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
int i) noexcept
726 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
double d) noexcept
727 : m_double(d), m_type(
Double) {}
729 : m_string(std::move(
s)), m_type(String) {}
731 constexpr QJSPrimitiveValuePrivate(
const QJSPrimitiveValuePrivate &
other) noexcept
732 : m_type(
other.m_type)
735 if (!assignSimple(
other))
739 constexpr QJSPrimitiveValuePrivate(QJSPrimitiveValuePrivate &&
other) noexcept
740 : m_type(
other.m_type)
743 if (!assignSimple(
other))
747 constexpr QJSPrimitiveValuePrivate &operator=(
const QJSPrimitiveValuePrivate &
other)
noexcept
752 if (m_type == String) {
753 if (
other.m_type == String) {
754 m_type =
other.m_type;
755 m_string =
other.m_string;
761 m_type =
other.m_type;
762 if (!assignSimple(
other))
767 constexpr QJSPrimitiveValuePrivate &operator=(QJSPrimitiveValuePrivate &&
other)
noexcept
772 if (m_type == String) {
773 if (
other.m_type == String) {
774 m_type =
other.m_type;
775 m_string = std::move(
other.m_string);
781 m_type =
other.m_type;
782 if (!assignSimple(
other))
787 ~QJSPrimitiveValuePrivate()
789 if (m_type == String)
793 constexpr Type type() const noexcept {
return m_type; }
794 constexpr bool getBool() const noexcept {
return m_bool; }
795 constexpr int getInt() const noexcept {
return m_int; }
796 constexpr double getDouble() const noexcept {
return m_double; }
797 QString getString() const noexcept {
return m_string; }
800 constexpr T get() const noexcept {
801 if constexpr (std::is_same_v<T, QJSPrimitiveUndefined>)
803 else if constexpr (std::is_same_v<T, QJSPrimitiveNull>)
805 else if constexpr (std::is_same_v<T, bool>)
807 else if constexpr (std::is_same_v<T, int>)
809 else if constexpr (std::is_same_v<T, double>)
811 else if constexpr (std::is_same_v<T, QString>)
815 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
816 Q_UNREACHABLE_RETURN(T());
822 constexpr QMetaType metaType() const noexcept {
827 return QMetaType::fromType<std::nullptr_t>();
829 return QMetaType::fromType<bool>();
831 return QMetaType::fromType<int>();
833 return QMetaType::fromType<double>();
835 return QMetaType::fromType<QString>();
839 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
846 constexpr void *
data() noexcept {
862 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
863 Q_UNREACHABLE_RETURN(
nullptr);
869 constexpr const void *
data() const noexcept {
885 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
886 Q_UNREACHABLE_RETURN(
nullptr);
893 constexpr bool assignSimple(
const QJSPrimitiveValuePrivate &
other)
noexcept
895 switch (
other.m_type) {
900 m_bool =
other.m_bool;
906 m_double =
other.m_double;
913 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
914 Q_UNREACHABLE_RETURN(
false);
930 QJSPrimitiveValuePrivate d;