4#ifndef QJSPRIMITIVEVALUE_H
5#define QJSPRIMITIVEVALUE_H
7#include <QtQml/qtqmlglobal.h>
8#include <QtQml/qjsnumbercoercion.h>
10#include <QtCore/qstring.h>
11#include <QtCore/qnumeric.h>
12#include <QtCore/qvariant.h>
19namespace QV4 {
struct ExecutionEngine; }
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();
233 default: Q_UNREACHABLE();
244 case Boolean:
return asBoolean();
245 case Integer:
return asInteger();
246 case Double:
return QJSNumberCoercion::toInteger(asDouble());
248 default: Q_UNREACHABLE();
257 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
259 case Boolean:
return asBoolean();
260 case Integer:
return asInteger();
261 case Double:
return asDouble();
263 default: Q_UNREACHABLE();
277 const double result = asDouble();
280 if (std::isfinite(
result))
286 case String:
return asString();
289 Q_UNREACHABLE_RETURN(
QString());
296 case Null:
return QVariant::fromValue<std::nullptr_t>(
nullptr);
309 return operate<AddOperators>(lhs, rhs);
315 return operate<SubOperators>(lhs, rhs);
321 return operate<MulOperators>(lhs, rhs);
327 return operate<DivOperators>(lhs, rhs);
333 switch (lhs.
type()) {
337 switch (rhs.
type()) {
342 if (leftInt >= 0 && rightInt > 0)
343 return leftInt % rightInt;
360 return (*
this = operate<SubOperators>(*
this, -1));
367 std::swap(
other, *
this);
373 return (*
this = operate<SubOperators>(*
this, 1));
379 std::swap(
other, *
this);
386 return (*
this = operate<SubOperators>(*
this, 0));
391 return (*
this = operate<MulOperators>(*
this, -1));
399 if (myType != otherType) {
413 return asBoolean() ==
other.asBoolean();
415 return asInteger() ==
other.asInteger();
417 const double l = asDouble();
418 const double r =
other.asDouble();
419 if (std::isnan(l) || std::isnan(
r))
426 return asString() ==
other.asString();
438 if (myType == otherType)
443 return otherType ==
Null;
455 return other.equals(*
this);
457 return fromString(asString()).parsedEquals(
other);
478 switch (lhs.
type()) {
482 switch (rhs.
type()) {
484 case Null:
return false;
485 case Boolean:
return 0 < int(rhs.asBoolean());
486 case Integer:
return 0 < rhs.asInteger();
487 case Double:
return double(0) < rhs.asDouble();
493 switch (rhs.
type()) {
495 case Null:
return int(lhs.asBoolean()) < 0;
496 case Boolean:
return lhs.asBoolean() < rhs.asBoolean();
497 case Integer:
return int(lhs.asBoolean()) < rhs.asInteger();
498 case Double:
return double(lhs.asBoolean()) < rhs.asDouble();
504 switch (rhs.
type()) {
506 case Null:
return lhs.asInteger() < 0;
507 case Boolean:
return lhs.asInteger() < int(rhs.asBoolean());
508 case Integer:
return lhs.asInteger() < rhs.asInteger();
509 case Double:
return double(lhs.asInteger()) < rhs.asDouble();
515 switch (rhs.
type()) {
517 case Null:
return lhs.asDouble() < double(0);
518 case Boolean:
return lhs.asDouble() < double(rhs.asBoolean());
519 case Integer:
return lhs.asDouble() < double(rhs.asInteger());
520 case Double:
return lhs.asDouble() < rhs.asDouble();
526 switch (rhs.
type()) {
532 case String:
return lhs.asString() < rhs.asString();
550 return lhs.asString() <= rhs.asString();
552 return fromString(lhs.asString()) <= rhs;
555 return lhs <= fromString(rhs.asString());
557 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
566 return lhs.asString() >= rhs.asString();
568 return fromString(lhs.asString()) >= rhs;
571 return lhs >= fromString(rhs.asString());
573 if (lhs.isNanOrUndefined() || rhs.isNanOrUndefined())
583 constexpr bool asBoolean()
const {
return d.getBool(); }
584 constexpr int asInteger()
const {
return d.getInt(); }
585 constexpr double asDouble()
const {
return d.getDouble(); }
586 QString asString()
const {
return d.getString(); }
596 const int intValue =
string.toInt(&
ok);
600 const double doubleValue =
string.toDouble(&
ok);
604 return std::numeric_limits<double>::infinity();
606 return -std::numeric_limits<double>::infinity();
608 return std::numeric_limits<double>::quiet_NaN();
614 template<
typename Operators,
typename Lhs,
typename Rhs>
619 if (Operators::opOverflow(lhs.d.get<Lhs>(), rhs.d.get<Rhs>(), &
result))
620 return Operators::op(lhs.d.get<Lhs>(), rhs.d.get<Rhs>());
624 template<
typename Operators>
627 switch (lhs.
type()) {
629 switch (rhs.
type()) {
630 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
631 case Null:
return std::numeric_limits<double>::quiet_NaN();
632 case Boolean:
return std::numeric_limits<double>::quiet_NaN();
633 case Integer:
return std::numeric_limits<double>::quiet_NaN();
634 case Double:
return std::numeric_limits<double>::quiet_NaN();
639 switch (rhs.
type()) {
640 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
641 case Null:
return operateOnIntegers<Operators, int, int>(0, 0);
642 case Boolean:
return operateOnIntegers<Operators, int, bool>(0, rhs);
643 case Integer:
return operateOnIntegers<Operators, int, int>(0, rhs);
644 case Double:
return Operators::op(0, rhs.asDouble());
649 switch (rhs.
type()) {
650 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
651 case Null:
return operateOnIntegers<Operators, bool, int>(lhs, 0);
652 case Boolean:
return operateOnIntegers<Operators, bool, bool>(lhs, rhs);
653 case Integer:
return operateOnIntegers<Operators, bool, int>(lhs, rhs);
654 case Double:
return Operators::op(lhs.asBoolean(), rhs.asDouble());
655 case String:
return Operators::op(lhs.asBoolean(), rhs.asString());
659 switch (rhs.
type()) {
660 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
661 case Null:
return operateOnIntegers<Operators, int, int>(lhs, 0);
662 case Boolean:
return operateOnIntegers<Operators, int, bool>(lhs, rhs);
663 case Integer:
return operateOnIntegers<Operators, int, int>(lhs, rhs);
664 case Double:
return Operators::op(lhs.asInteger(), rhs.asDouble());
665 case String:
return Operators::op(lhs.asInteger(), rhs.asString());
669 switch (rhs.
type()) {
670 case Undefined:
return std::numeric_limits<double>::quiet_NaN();
671 case Null:
return Operators::op(lhs.asDouble(), 0);
672 case Boolean:
return Operators::op(lhs.asDouble(), rhs.asBoolean());
673 case Integer:
return Operators::op(lhs.asDouble(), rhs.asInteger());
674 case Double:
return Operators::op(lhs.asDouble(), rhs.asDouble());
675 case String:
return Operators::op(lhs.asDouble(), rhs.asString());
679 switch (rhs.
type()) {
682 case Boolean:
return Operators::op(lhs.asString(), rhs.asBoolean());
683 case Integer:
return Operators::op(lhs.asString(), rhs.asInteger());
684 case Double:
return Operators::op(lhs.asString(), rhs.asDouble());
685 case String:
return Operators::op(lhs.asString(), rhs.asString());
693 constexpr bool isNanOrUndefined()
const
697 case Double:
return std::isnan(asDouble());
698 default:
return false;
702 struct QJSPrimitiveValuePrivate
705 constexpr QJSPrimitiveValuePrivate() noexcept {}
710 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
bool b) noexcept
712 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
int i) noexcept
714 Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(
double d) noexcept
715 : m_double(d), m_type(
Double) {}
717 : m_string(std::move(
s)), m_type(
String) {}
719 constexpr QJSPrimitiveValuePrivate(
const QJSPrimitiveValuePrivate &
other) noexcept
720 : m_type(
other.m_type)
723 if (!assignSimple(
other))
727 constexpr QJSPrimitiveValuePrivate(QJSPrimitiveValuePrivate &&
other) noexcept
728 : m_type(
other.m_type)
731 if (!assignSimple(
other))
735 constexpr QJSPrimitiveValuePrivate &operator=(
const QJSPrimitiveValuePrivate &
other)
noexcept
742 m_type =
other.m_type;
743 m_string =
other.m_string;
749 m_type =
other.m_type;
750 if (!assignSimple(
other))
755 constexpr QJSPrimitiveValuePrivate &operator=(QJSPrimitiveValuePrivate &&
other)
noexcept
762 m_type =
other.m_type;
763 m_string = std::move(
other.m_string);
769 m_type =
other.m_type;
770 if (!assignSimple(
other))
775 ~QJSPrimitiveValuePrivate()
781 constexpr Type type() const noexcept {
return m_type; }
782 constexpr bool getBool() const noexcept {
return m_bool; }
783 constexpr int getInt() const noexcept {
return m_int; }
784 constexpr double getDouble() const noexcept {
return m_double; }
785 QString getString() const noexcept {
return m_string; }
788 constexpr T
get() const noexcept {
789 if constexpr (std::is_same_v<T, QJSPrimitiveUndefined>)
791 else if constexpr (std::is_same_v<T, QJSPrimitiveNull>)
793 else if constexpr (std::is_same_v<T, bool>)
795 else if constexpr (std::is_same_v<T, int>)
797 else if constexpr (std::is_same_v<T, double>)
799 else if constexpr (std::is_same_v<T, QString>)
803 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
810 constexpr QMetaType metaType() const noexcept {
815 return QMetaType::fromType<std::nullptr_t>();
817 return QMetaType::fromType<bool>();
819 return QMetaType::fromType<int>();
821 return QMetaType::fromType<double>();
823 return QMetaType::fromType<QString>();
827 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
834 constexpr void *
data() noexcept {
850 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
857 constexpr const void *
data() const noexcept {
873 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
881 constexpr bool assignSimple(
const QJSPrimitiveValuePrivate &
other)
noexcept
883 switch (
other.m_type) {
888 m_bool =
other.m_bool;
894 m_double =
other.m_double;
914 QJSPrimitiveValuePrivate d;
921 constexpr double qNaN = std::numeric_limits<double>::quiet_NaN();
922 constexpr double inf = std::numeric_limits<double>::infinity();
936 if (std::copysign(1.0,
base) > 0.0)
943 ? std::copysign(0, -1.0)
static constexpr bool equals(double lhs, double rhs)
The QJSPrimitiveValue class operates on primitive types in JavaScript semantics.
friend QJSPrimitiveValue operator+(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
friend QJSPrimitiveValue operator*(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
QJSPrimitiveValue(Type)=delete
constexpr QMetaType metaType() const
friend constexpr bool operator<=(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
Q_IMPLICIT constexpr QJSPrimitiveValue(bool value) noexcept
Creates a QJSPrimitiveValue of value value and type Boolean.
friend constexpr bool operator!=(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
QJSPrimitiveValue(QMetaType type) noexcept
Q_IMPLICIT constexpr QJSPrimitiveValue(QJSPrimitiveNull null) noexcept
Creates a QJSPrimitiveValue of value null and type Null.
constexpr const void * data() const
friend constexpr bool operator>(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
QJSPrimitiveValue operator++(int)
QJSPrimitiveValue operator+()
QVariant toVariant() const
friend QJSPrimitiveValue operator-(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
QJSPrimitiveValue(const QVariant &variant) noexcept
Creates a QJSPrimitiveValue from the contents of value if those contents can be stored in QJSPrimtive...
QJSPrimitiveValue operator--(int)
Q_IMPLICIT constexpr QJSPrimitiveValue(int value) noexcept
Creates a QJSPrimitiveValue of value value and type Integer.
friend constexpr bool operator<(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
constexpr const void * constData() const
constexpr double toDouble() const
Returns the value coerced to a JavaScript Number by JavaScript rules.
constexpr Type type() const
Returns the type of the QJSPrimitiveValue.
Type
This enum speicifies the types a QJSPrimitiveValue might contain.
QJSPrimitiveValue & operator--()
QJSPrimitiveValue(const QMetaType type, const void *value) noexcept
friend QJSPrimitiveValue operator/(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
constexpr int toInteger() const
Returns the value coerced to an integral 32bit number by the rules JavaScript would apply when prepar...
QString toString() const
Returns the value coerced to a JavaScript String by JavaScript rules.
QJSPrimitiveValue & operator++()
constexpr bool toBoolean() const
Returns the value coerced a boolean by JavaScript rules.
QJSPrimitiveValue operator-()
constexpr bool strictlyEquals(const QJSPrimitiveValue &other) const
Performs the JavaScript '===' operation on this QJSPrimitiveValue and other, and returns the result.
constexpr bool equals(const QJSPrimitiveValue &other) const
Performs the JavaScript '==' operation on this QJSPrimitiveValue and other, and returns the result.
Q_IMPLICIT constexpr QJSPrimitiveValue(double value) noexcept
Creates a QJSPrimitiveValue of value value and type Double.
friend QJSPrimitiveValue operator%(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
friend constexpr bool operator>=(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
QJSPrimitiveValue to() const
friend constexpr bool operator==(const QJSPrimitiveValue &lhs, const QJSPrimitiveValue &rhs)
Q_IMPLICIT QJSPrimitiveValue(QString string) noexcept
Creates a QJSPrimitiveValue of value value and type String.
Q_IMPLICIT constexpr QJSPrimitiveValue() noexcept=default
Creates a QJSPrimitiveValue of type Undefined.
The QJSValue class acts as a container for Qt/JavaScript data types.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
~QString()
Destroys the string.
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
QMetaType metaType() const
double jsExponentiate(double base, double exponent)
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qIsNull(qfloat16 f) noexcept
std::enable_if_t< std::is_unsigned_v< T >, bool > qAddOverflow(T v1, T v2, T *r)
std::enable_if_t< std::is_unsigned_v< T >, bool > qSubOverflow(T v1, T v2, T *r)
std::enable_if_t< std::is_unsigned_v< T >||std::is_signed_v< T >, bool > qMulOverflow(T v1, T v2, T *r)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
static bool fromString(const QMetaObject *mo, QString s, Allocate &&allocate)
#define QStringLiteral(str)
manager get(QNetworkRequest(QUrl("http://qt-project.org")))
An empty marker type to signify the JavaScript null value. \inmodule QtQml.
An empty marker type to signify the JavaScript Undefined type and its single value....