1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | #ifndef QV4DATEOBJECT_P_H |
4 | #define QV4DATEOBJECT_P_H |
5 | |
6 | // |
7 | // W A R N I N G |
8 | // ------------- |
9 | // |
10 | // This file is not part of the Qt API. It exists purely as an |
11 | // implementation detail. This header file may change from version to |
12 | // version without notice, or even be removed. |
13 | // |
14 | // We mean it. |
15 | // |
16 | |
17 | #include "qv4object_p.h" |
18 | #include "qv4functionobject_p.h" |
19 | #include "qv4referenceobject_p.h" |
20 | #include <QtCore/private/qnumeric_p.h> |
21 | #include <QtCore/qdatetime.h> |
22 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | class QDateTime; |
26 | |
27 | namespace QV4 { |
28 | |
29 | struct Date |
30 | { |
31 | static constexpr quint64 MaxDateVal = 8.64e15; |
32 | |
33 | void init() { storage = InvalidDateVal; } |
34 | void init(double value); |
35 | void init(const QDateTime &dateTime); |
36 | void init(QDate date); |
37 | void init(QTime time, ExecutionEngine *engine); |
38 | |
39 | Date &operator=(double value) |
40 | { |
41 | storage = (storage & (HasQDate | HasQTime)) | encode(value); |
42 | return *this; |
43 | } |
44 | |
45 | operator double() const |
46 | { |
47 | const quint64 raw = (storage & ~(HasQDate | HasQTime)); |
48 | if (raw == 0) |
49 | return qt_qnan(); |
50 | |
51 | if (raw > MaxDateVal) |
52 | return double(raw - MaxDateVal - Extra); |
53 | |
54 | return double(raw) - double(MaxDateVal) - double(Extra); |
55 | } |
56 | |
57 | QDate toQDate() const; |
58 | QTime toQTime() const; |
59 | QDateTime toQDateTime() const; |
60 | QVariant toVariant() const; |
61 | |
62 | template<typename Function> |
63 | bool withStoragePointer(Function function) |
64 | { |
65 | switch (storage & (HasQDate | HasQTime)) { |
66 | case HasQDate: { |
67 | QDate date = toQDate(); |
68 | return function(&date); |
69 | } |
70 | case HasQTime: { |
71 | QTime time = toQTime(); |
72 | return function(&time); |
73 | } |
74 | case (HasQTime | HasQDate): { |
75 | QDateTime dateTime = toQDateTime(); |
76 | return function(&dateTime); |
77 | } |
78 | default: |
79 | return false; |
80 | } |
81 | } |
82 | |
83 | private: |
84 | static constexpr quint64 InvalidDateVal = 0; |
85 | static constexpr quint64 = 1; |
86 | static constexpr quint64 HasQDate = 1ull << 63; |
87 | static constexpr quint64 HasQTime = 1ull << 62; |
88 | |
89 | // Make all our dates fit into quint64, leaving space for the flags |
90 | static_assert(((MaxDateVal * 2 + Extra) & (HasQDate | HasQTime)) == 0ull); |
91 | |
92 | static quint64 encode(double value); |
93 | static quint64 encode(const QDateTime &dateTime); |
94 | |
95 | quint64 storage; |
96 | }; |
97 | |
98 | namespace Heap { |
99 | |
100 | #define DateObjectMembers(class, Member) |
101 | DECLARE_HEAP_OBJECT(DateObject, ReferenceObject) { |
102 | DECLARE_MARKOBJECTS(DateObject); |
103 | |
104 | void doSetLocation() |
105 | { |
106 | if (CppStackFrame *frame = internalClass->engine->currentStackFrame) |
107 | setLocation(function: frame->v4Function, statement: frame->statementNumber()); |
108 | } |
109 | |
110 | void init() |
111 | { |
112 | ReferenceObject::init(object: nullptr, property: -1, flags: {}); |
113 | m_date.init(); |
114 | } |
115 | |
116 | void init(double dateTime) |
117 | { |
118 | ReferenceObject::init(object: nullptr, property: -1, flags: {}); |
119 | m_date.init(value: dateTime); |
120 | } |
121 | |
122 | void init(const QDateTime &dateTime) |
123 | { |
124 | ReferenceObject::init(object: nullptr, property: -1, flags: {}); |
125 | m_date.init(dateTime); |
126 | } |
127 | |
128 | void init(const QDateTime &dateTime, Heap::Object *parent, int property, Flags flags) |
129 | { |
130 | ReferenceObject::init(object: parent, property, flags: flags | EnforcesLocation); |
131 | doSetLocation(); |
132 | m_date.init(dateTime); |
133 | }; |
134 | |
135 | void init(QDate date, Heap::Object *parent, int property, Flags flags) |
136 | { |
137 | ReferenceObject::init(object: parent, property, flags: flags | EnforcesLocation); |
138 | doSetLocation(); |
139 | m_date.init(date); |
140 | }; |
141 | |
142 | void init(QTime time, Heap::Object *parent, int property, Flags flags) |
143 | { |
144 | ReferenceObject::init(object: parent, property, flags: flags | EnforcesLocation); |
145 | doSetLocation(); |
146 | m_date.init(time, engine: internalClass->engine); |
147 | }; |
148 | |
149 | void setDate(double newDate) |
150 | { |
151 | m_date = newDate; |
152 | if (isAttachedToProperty()) |
153 | writeBack(); |
154 | } |
155 | |
156 | double date() const |
157 | { |
158 | return m_date; |
159 | } |
160 | |
161 | QVariant toVariant() const { return m_date.toVariant(); } |
162 | QDateTime toQDateTime() const { return m_date.toQDateTime(); } |
163 | |
164 | private: |
165 | bool writeBack() |
166 | { |
167 | if (!object() || !canWriteBack()) |
168 | return false; |
169 | |
170 | QV4::Scope scope(internalClass->engine); |
171 | QV4::ScopedObject o(scope, object()); |
172 | |
173 | int flags = 0; |
174 | int status = -1; |
175 | if (isVariant()) { |
176 | QVariant variant = toVariant(); |
177 | void *a[] = { &variant, nullptr, &status, &flags }; |
178 | return o->metacall(call: QMetaObject::WriteProperty, index: property(), a); |
179 | } |
180 | |
181 | return m_date.withStoragePointer(function: [&](void *storagePointer) { |
182 | void *a[] = { storagePointer, nullptr, &status, &flags }; |
183 | return o->metacall(call: QMetaObject::WriteProperty, index: property(), a); |
184 | }); |
185 | } |
186 | |
187 | Date m_date; |
188 | }; |
189 | |
190 | |
191 | struct DateCtor : FunctionObject { |
192 | void init(QV4::ExecutionContext *scope); |
193 | }; |
194 | |
195 | } |
196 | |
197 | struct DateObject: ReferenceObject { |
198 | V4_OBJECT2(DateObject, ReferenceObject) |
199 | Q_MANAGED_TYPE(DateObject) |
200 | V4_PROTOTYPE(datePrototype) |
201 | |
202 | void setDate(double date) { d()->setDate(date); } |
203 | double date() const { return d()->date(); } |
204 | |
205 | Q_QML_PRIVATE_EXPORT QDateTime toQDateTime() const; |
206 | QString toString() const; |
207 | |
208 | static QString dateTimeToString(const QDateTime &dateTime, ExecutionEngine *engine); |
209 | static QDate dateTimeToDate(const QDateTime &dateTime); |
210 | static QDateTime stringToDateTime(const QString &string, ExecutionEngine *engine); |
211 | }; |
212 | |
213 | template<> |
214 | inline const DateObject *Value::as() const { |
215 | return isManaged() && m()->internalClass->vtable->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : nullptr; |
216 | } |
217 | |
218 | struct DateCtor: FunctionObject |
219 | { |
220 | V4_OBJECT2(DateCtor, FunctionObject) |
221 | |
222 | static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *); |
223 | static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int); |
224 | }; |
225 | |
226 | struct DatePrototype: Object |
227 | { |
228 | V4_PROTOTYPE(objectPrototype) |
229 | |
230 | void init(ExecutionEngine *engine, Object *ctor); |
231 | |
232 | static double getThisDate(ExecutionEngine *v4, const Value *thisObject); |
233 | |
234 | static ReturnedValue method_parse(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
235 | static ReturnedValue method_UTC(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
236 | static ReturnedValue method_now(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
237 | |
238 | static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
239 | static ReturnedValue method_toDateString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
240 | static ReturnedValue method_toTimeString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
241 | static ReturnedValue method_toLocaleString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
242 | static ReturnedValue method_toLocaleDateString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
243 | static ReturnedValue method_toLocaleTimeString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
244 | static ReturnedValue method_valueOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
245 | static ReturnedValue method_getTime(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
246 | static ReturnedValue method_getYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
247 | static ReturnedValue method_getFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
248 | static ReturnedValue method_getUTCFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
249 | static ReturnedValue method_getMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
250 | static ReturnedValue method_getUTCMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
251 | static ReturnedValue method_getDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
252 | static ReturnedValue method_getUTCDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
253 | static ReturnedValue method_getDay(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
254 | static ReturnedValue method_getUTCDay(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
255 | static ReturnedValue method_getHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
256 | static ReturnedValue method_getUTCHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
257 | static ReturnedValue method_getMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
258 | static ReturnedValue method_getUTCMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
259 | static ReturnedValue method_getSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
260 | static ReturnedValue method_getUTCSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
261 | static ReturnedValue method_getMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
262 | static ReturnedValue method_getUTCMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
263 | static ReturnedValue method_getTimezoneOffset(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
264 | static ReturnedValue method_setTime(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
265 | static ReturnedValue method_setMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
266 | static ReturnedValue method_setUTCMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
267 | static ReturnedValue method_setSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
268 | static ReturnedValue method_setUTCSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
269 | static ReturnedValue method_setMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
270 | static ReturnedValue method_setUTCMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
271 | static ReturnedValue method_setHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
272 | static ReturnedValue method_setUTCHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
273 | static ReturnedValue method_setDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
274 | static ReturnedValue method_setUTCDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
275 | static ReturnedValue method_setMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
276 | static ReturnedValue method_setUTCMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
277 | static ReturnedValue method_setYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
278 | static ReturnedValue method_setFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
279 | static ReturnedValue method_setUTCFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
280 | static ReturnedValue method_toUTCString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
281 | static ReturnedValue method_toISOString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
282 | static ReturnedValue method_toJSON(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); |
283 | static ReturnedValue method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int); |
284 | |
285 | static void timezoneUpdated(ExecutionEngine *e); |
286 | }; |
287 | |
288 | } |
289 | |
290 | QT_END_NAMESPACE |
291 | |
292 | #endif // QV4ECMAOBJECTS_P_H |
293 | |