7#include <private/qv4dateobject_p.h>
8#include <private/qv4objectproto_p.h>
9#include <private/qv4qobjectwrapper_p.h>
10#include <private/qv4regexp_p.h>
11#include <private/qv4regexpobject_p.h>
12#include <private/qv4sequenceobject_p.h>
13#include <private/qv4value_p.h>
54 return quint8(type) << 24 | (size & 0xFFFFFF);
59 return (
Type)(header >> 24);
64 return header & 0xFFFFFF;
67static inline void push(QByteArray &data, quint32 value)
69 data.append((
const char *)&value,
sizeof(quint32));
72static inline void push(QByteArray &data,
double value)
74 data.append((
const char *)&value,
sizeof(
double));
77static inline void push(QByteArray &data,
void *ptr)
79 data.append((
const char *)&ptr,
sizeof(
void *));
82static inline void reserve(QByteArray &data,
int extra)
84 data.reserve(data.size() + extra);
89 quint32 rv = *((
const quint32 *)data);
90 data +=
sizeof(quint32);
96 double rv = *((
const double *)data);
97 data +=
sizeof(
double);
101static inline void *
popPtr(
const char *&data)
103 void *rv = *((
void *
const *)data);
104 data +=
sizeof(
void *);
108#define ALIGN(size) (((size) + 3
) & ~3
)
111 int length = str.size();
112 if (length > 0xFFFFFF) {
113 push(data, valueheader(WorkerUndefined));
116 int utf16size =
ALIGN(length *
sizeof(quint16));
118 reserve(data, utf16size +
sizeof(quint32));
119 push(data, valueheader(type, length));
121 int offset = data.size();
122 data.resize(data.size() + utf16size);
123 char *buffer = data.data() + offset;
125 memcpy(buffer, str.constData(), length*
sizeof(QChar));
131void Serialize::serialize(QByteArray &data,
const QV4::Value &v, ExecutionEngine *engine)
133 QV4::Scope scope(engine);
136 Q_ASSERT(!
"Serialize: got empty value");
137 }
else if (v.isUndefined()) {
138 push(data, valueheader(WorkerUndefined));
139 }
else if (v.isNull()) {
140 push(data, valueheader(WorkerNull));
141 }
else if (v.isBoolean()) {
142 push(data, valueheader(v.booleanValue() ==
true ? WorkerTrue : WorkerFalse));
143 }
else if (v.isString()) {
144 serializeString(data, v.toQString(), WorkerString);
145 }
else if (v.as<FunctionObject>()) {
148 push(data, valueheader(WorkerUndefined));
149 }
else if (
const QV4::ArrayObject *array = v.as<ArrayObject>()) {
150 uint length = array->getLength();
151 if (length > 0xFFFFFF) {
152 push(data, valueheader(WorkerUndefined));
155 reserve(data,
sizeof(quint32) + length *
sizeof(quint32));
156 push(data, valueheader(WorkerArray, length));
157 ScopedValue val(scope);
158 for (uint ii = 0; ii < length; ++ii)
159 serialize(data, (val = array->get(ii)), engine);
160 }
else if (v.isInteger()) {
161 reserve(data, 2 *
sizeof(quint32));
162 push(data, valueheader(WorkerInt32));
163 push(data, (quint32)v.integerValue());
168 }
else if (v.isNumber()) {
169 reserve(data,
sizeof(quint32) +
sizeof(
double));
170 push(data, valueheader(WorkerNumber));
171 push(data, v.asDouble());
172 }
else if (
const QV4::DateObject *d = v.as<DateObject>()) {
173 reserve(data,
sizeof(quint32) +
sizeof(
double));
174 push(data, valueheader(WorkerDate));
175 push(data, d->date());
176 }
else if (
const RegExpObject *re = v.as<RegExpObject>()) {
177 quint32 flags = re->flags();
178 QString pattern = re->source();
179 int length = pattern.size() + 1;
180 if (length > 0xFFFFFF) {
181 push(data, valueheader(WorkerUndefined));
184 int utf16size =
ALIGN(length *
sizeof(quint16));
186 reserve(data,
sizeof(quint32) + utf16size);
187 push(data, valueheader(WorkerRegexp, flags));
188 push(data, (quint32)length);
190 int offset = data.size();
191 data.resize(data.size() + utf16size);
192 char *buffer = data.data() + offset;
194 memcpy(buffer, pattern.constData(), length*
sizeof(QChar));
195 }
else if (
const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
198 if (QObject *lm = qobjectWrapper->object()) {
199 if (QObject *agent = qvariant_cast<QObject *>(lm->property(
"agent"))) {
200 if (QMetaObject::invokeMethod(agent,
"addref")) {
201 push(data, valueheader(WorkerListModel));
202 push(data, (
void *)agent);
208 push(data, valueheader(WorkerUndefined));
209 }
else if (
const Sequence *s = v.as<Sequence>()) {
211 uint seqLength = ScopedValue(scope, s->get(engine->id_length()))->toUInt32();
212 uint length = seqLength + 1;
213 if (length > 0xFFFFFF) {
214 push(data, valueheader(WorkerUndefined));
217 reserve(data,
sizeof(quint32) + length *
sizeof(quint32));
218 push(data, valueheader(WorkerSequence, length));
221 serialize(data, QV4::Value::fromInt32(
222 QV4::SequencePrototype::metaTypeForSequence(s).id()), engine);
224 ScopedValue val(scope);
225 for (uint ii = 0; ii < seqLength; ++ii)
226 serialize(data, (val = s->get(ii)), engine);
229 }
else if (
const Object *o = v.as<Object>()) {
230 const QVariant variant = QV4::ExecutionEngine::toVariant(
231 v, QMetaType::fromType<QUrl>(),
false);
232 if (variant.userType() == QMetaType::QUrl) {
233 serializeString(data, variant.value<QUrl>().toString(), WorkerUrl);
238 QV4::ScopedValue val(scope, v);
239 QV4::ScopedArrayObject properties(scope, QV4::ObjectPrototype::getOwnPropertyNames(engine, val));
240 quint32 length = properties->getLength();
241 if (length > 0xFFFFFF) {
242 push(data, valueheader(WorkerUndefined));
245 push(data, valueheader(WorkerObject, length));
247 QV4::ScopedValue s(scope);
248 for (quint32 ii = 0; ii < length; ++ii) {
249 s = properties->get(ii);
250 serialize(data, s, engine);
252 QV4::String *str = s->as<String>();
254 if (scope.hasException())
255 scope.engine->catchException();
257 serialize(data, val, engine);
261 push(data, valueheader(WorkerUndefined));
282 QMetaObject::invokeMethod(obj,
"addref");
288 QMetaObject::invokeMethod(obj,
"release");
296Q_DECLARE_METATYPE(VariantRef)
297Q_DECLARE_METATYPE(QV4::ExecutionEngine *)
300ReturnedValue Serialize::deserialize(
const char *&data, ExecutionEngine *engine)
302 quint32 header = popUint32(data);
303 Type type = headertype(header);
308 case WorkerUndefined:
309 return QV4::Encode::undefined();
311 return QV4::Encode::null();
313 return QV4::Encode(
true);
315 return QV4::Encode(
false);
319 quint32 size = headersize(header);
320 QString qstr((
const QChar *)data, size);
321 data +=
ALIGN(size *
sizeof(quint16));
322 return (type == WorkerUrl)
323 ? engine->fromVariant(QVariant::fromValue(QUrl(qstr)))
324 : Encode(engine->newString(qstr));
327 Q_ASSERT(!
"Unreachable");
331 quint32 size = headersize(header);
332 ScopedArrayObject a(scope, engine->newArrayObject());
333 ScopedValue v(scope);
334 for (quint32 ii = 0; ii < size; ++ii) {
335 v = deserialize(data, engine);
338 return a.asReturnedValue();
342 quint32 size = headersize(header);
343 ScopedObject o(scope, engine->newObject());
344 ScopedValue name(scope);
345 ScopedString n(scope);
346 ScopedValue value(scope);
347 for (quint32 ii = 0; ii < size; ++ii) {
348 name = deserialize(data, engine);
349 value = deserialize(data, engine);
350 n = name->asReturnedValue();
353 return o.asReturnedValue();
356 return QV4::Encode((qint32)popUint32(data));
358 return QV4::Encode(popUint32(data));
360 return QV4::Encode(popDouble(data));
362 return QV4::Encode(engine->newDateObject(popDouble(data)));
365 quint32 flags = headersize(header);
366 quint32 length = popUint32(data);
367 QString pattern = QString((
const QChar *)data, length - 1);
368 data +=
ALIGN(length *
sizeof(quint16));
369 return Encode(engine->newRegExpObject(pattern, flags));
371 case WorkerListModel:
373 QObject *agent =
reinterpret_cast<QObject *>(popPtr(data));
374 QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(engine, agent));
376 VariantRef ref(agent);
377 QVariant var = QVariant::fromValue(ref);
378 QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
379 QV4::ScopedString s(scope, engine->newString(QStringLiteral(
"__qml:hidden:ref")));
380 rv->as<Object>()->defineReadonlyProperty(s, v);
382 QMetaObject::invokeMethod(agent,
"release");
383 agent->setProperty(
"engine", QVariant::fromValue(engine));
384 return rv->asReturnedValue();
388 ScopedValue value(scope);
389 quint32 length = headersize(header);
390 quint32 seqLength = length - 1;
391 value = deserialize(data, engine);
392 int sequenceType = value->integerValue();
393 ScopedArrayObject array(scope, engine->newArrayObject());
394 array->arrayReserve(seqLength);
395 for (quint32 ii = 0; ii < seqLength; ++ii) {
396 value = deserialize(data, engine);
397 array->arrayPut(ii, value);
399 array->setArrayLengthUnchecked(seqLength);
400 QVariant seqVariant = QV4::SequencePrototype::toVariant(array, QMetaType(sequenceType));
401 return QV4::SequencePrototype::fromVariant(engine, seqVariant);
404 Q_ASSERT(!
"Unreachable");
405 return QV4::Encode::undefined();
408QByteArray Serialize::serialize(
const QV4::Value &value, ExecutionEngine *engine)
411 serialize(rv, value, engine);
415ReturnedValue Serialize::deserialize(
const QByteArray &data, ExecutionEngine *engine)
417 const char *stream = data.constData();
418 return deserialize(stream, engine);
Type
\value X11 \value Windows \value MacPrinter \value CoreGraphics \macos's Quartz2D (CoreGraphics) \val...
static quint32 valueheader(Type type, quint32 size=0)
static quint32 popUint32(const char *&data)
static void reserve(QByteArray &data, int extra)
static void * popPtr(const char *&data)
static Type headertype(quint32 header)
static double popDouble(const char *&data)
static void push(QByteArray &data, quint32 value)
static quint32 headersize(quint32 header)
static void push(QByteArray &data, void *ptr)
static void serializeString(QByteArray &data, const QString &str, Type type)
static void push(QByteArray &data, double value)
VariantRef(const VariantRef &r)
VariantRef & operator=(const VariantRef &o)