32 #define START_OBJECT { m_objectOffsets.append(Dest.size()); } 48 static inline void WriteReference(quint64 Reference, quint8 Size, quint8* Pointer, quint64 &Counter)
54 Pointer[Counter++] = (quint8)(Reference & 0xff);
59 quint16 buffer = qToBigEndian((quint16)(Reference & 0xffff));
60 for (
int i = 0; i < 2; ++i)
61 Pointer[Counter++] = *((quint8*)&buffer + i);
66 quint32 buffer = qToBigEndian((quint32)(Reference & 0xffffffff));
67 for (
int i = 0; i < 4; ++i)
68 Pointer[Counter++] = *((quint8*)&buffer + i);
73 quint64 buffer = qToBigEndian(Reference);
74 for (
int i = 0; i < 8; ++i)
75 Pointer[Counter++] = *((quint8*)&buffer + i);
93 m_objectOffsets.clear();
94 Dest.append(
"bplist00");
101 CountObjects(count, Value);
103 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Max object count %1").arg(count));
105 m_referenceSize = count < 0x000000ff ? 1 :
106 count < 0x0000ffff ? 2 :
107 count < 0xffffffff ? 4 : 8;
111 quint64 offset = Dest.size();
112 QByteArray references(2 * m_referenceSize, 0);
113 Dest.append(references);
115 WriteReference(BinaryFromQString(Dest, Name), m_referenceSize, (quint8*)Dest.data(), offset);
116 WriteReference(BinaryFromVariant(Dest, Name, Value), m_referenceSize, (quint8*)Dest.data(), offset);
121 quint64 table = Dest.size();
123 quint8 offsetsize = table < 0x000000ff ? 1 :
124 table < 0x0000ffff ? 2 :
125 table < 0xffffffff ? 4 : 8;
127 QList<quint64>::const_iterator it = m_objectOffsets.constBegin();
132 for ( ; it != m_objectOffsets.constEnd(); ++it)
133 Dest.append((quint8)((*it) & 0xff));
138 for ( ; it != m_objectOffsets.constEnd(); ++it)
140 quint16 buffer = qToBigEndian((quint16)((*it) & 0xffff));
141 Dest.append(*((quint8*)&buffer));
142 Dest.append(*((quint8*)&buffer + 1));
148 for ( ; it != m_objectOffsets.constEnd(); ++it)
150 quint32 buffer= qToBigEndian((quint32)((*it) & 0xffffffff));
151 Dest.append(*((quint8*)&buffer));
152 Dest.append(*((quint8*)&buffer + 1));
153 Dest.append(*((quint8*)&buffer + 2));
154 Dest.append(*((quint8*)&buffer + 3));
160 for ( ; it != m_objectOffsets.constEnd(); ++it)
162 quint64 buffer = qToBigEndian((*it));
163 Dest.append(*((quint8*)&buffer));
164 Dest.append(*((quint8*)&buffer + 1));
165 Dest.append(*((quint8*)&buffer + 2));
166 Dest.append(*((quint8*)&buffer + 3));
167 Dest.append(*((quint8*)&buffer + 4));
168 Dest.append(*((quint8*)&buffer + 5));
169 Dest.append(*((quint8*)&buffer + 6));
170 Dest.append(*((quint8*)&buffer + 7));
178 table = qToBigEndian(table);
179 quint64 count = qToBigEndian((quint64)m_objectOffsets.count());
181 QByteArray trailer(32, 0);
182 trailer[6] = offsetsize;
183 trailer[7] = m_referenceSize;
184 trailer[8] = *((quint8*)&count);
185 trailer[9] = *((quint8*)&count + 1);
186 trailer[10] = *((quint8*)&count + 2);
187 trailer[11] = *((quint8*)&count + 3);
188 trailer[12] = *((quint8*)&count + 4);
189 trailer[13] = *((quint8*)&count + 5);
190 trailer[14] = *((quint8*)&count + 6);
191 trailer[15] = *((quint8*)&count + 7);
192 trailer[24] = *((quint8*)&table);
193 trailer[25] = *((quint8*)&table + 1);
194 trailer[26] = *((quint8*)&table + 2);
195 trailer[27] = *((quint8*)&table + 3);
196 trailer[28] = *((quint8*)&table + 4);
197 trailer[29] = *((quint8*)&table + 5);
198 trailer[30] = *((quint8*)&table + 6);
199 trailer[31] = *((quint8*)&table + 7);
201 Dest.append(trailer);
203 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Actual object count %1").arg(m_objectOffsets.count()));
206 QByteArray testdata(Dest.data(), Dest.size());
208 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"\n%1").arg(test.ToString()));
212 quint64 TorcBinaryPListSerialiser::BinaryFromVariant(QByteArray &Dest,
const QString &Name,
const QVariant &Value)
215 quint64 result = m_objectOffsets.size();
223 switch ((
int)Value.type())
225 case QMetaType::QVariantList:
return BinaryFromArray(Dest, Name, Value.toList());
226 case QMetaType::QStringList:
return BinaryFromStringList(Dest, Name, Value.toStringList());
227 case QMetaType::QVariantMap:
return BinaryFromMap(Dest, Name, Value.toMap());
228 case QMetaType::QUuid: BinaryFromUuid(Dest, Value);
return result;
229 case QMetaType::QByteArray: BinaryFromData(Dest, Value);
return result;
230 case QMetaType::Bool:
233 bool value = Value.toBool();
237 case QMetaType::Char:
244 case QMetaType::Short:
245 case QMetaType::Long:
246 case QMetaType::LongLong:
247 case QMetaType::Float:
248 case QMetaType::Double:
251 double value = Value.toDouble();
253 #if Q_BYTE_ORDER == Q_BIG_ENDIAN && !defined (__VFP_FP__) 254 Dest.append(*((
char*)&value));
255 Dest.append(*((
char*)&value + 1));
256 Dest.append(*((
char*)&value + 2));
257 Dest.append(*((
char*)&value + 3));
258 Dest.append(*((
char*)&value + 4));
259 Dest.append(*((
char*)&value + 5));
260 Dest.append(*((
char*)&value + 6));
261 Dest.append(*((
char*)&value + 7));
263 Dest.append(*((
char*)&value + 7));
264 Dest.append(*((
char*)&value + 6));
265 Dest.append(*((
char*)&value + 5));
266 Dest.append(*((
char*)&value + 4));
267 Dest.append(*((
char*)&value + 3));
268 Dest.append(*((
char*)&value + 2));
269 Dest.append(*((
char*)&value + 1));
270 Dest.append(*((
char*)&value));
274 case QMetaType::UInt:
275 case QMetaType::UShort:
276 case QMetaType::ULong:
277 case QMetaType::ULongLong:
280 BinaryFromUInt(Dest, Value.toULongLong());
283 case QMetaType::QDateTime:
287 double value = (double)Value.toDateTime().toTime_t();
288 #if Q_BYTE_ORDER == Q_BIG_ENDIAN && !defined (__VFP_FP__) 289 Dest.append(*((
char*)&value));
290 Dest.append(*((
char*)&value + 1));
291 Dest.append(*((
char*)&value + 2));
292 Dest.append(*((
char*)&value + 3));
293 Dest.append(*((
char*)&value + 4));
294 Dest.append(*((
char*)&value + 5));
295 Dest.append(*((
char*)&value + 6));
296 Dest.append(*((
char*)&value + 7));
298 Dest.append(*((
char*)&value + 7));
299 Dest.append(*((
char*)&value + 6));
300 Dest.append(*((
char*)&value + 5));
301 Dest.append(*((
char*)&value + 4));
302 Dest.append(*((
char*)&value + 3));
303 Dest.append(*((
char*)&value + 2));
304 Dest.append(*((
char*)&value + 1));
305 Dest.append(*((
char*)&value));
309 case QMetaType::QString:
311 return BinaryFromQString(Dest, Value.toString());
315 quint64 TorcBinaryPListSerialiser::BinaryFromStringList(QByteArray &Dest,
const QString &Name,
const QStringList &Value)
319 quint64 result = m_objectOffsets.size();
322 int size = Value.size();
324 if (size >= BPLIST_LOW_MAX)
325 BinaryFromUInt(Dest, size);
327 quint64 offset = Dest.size();
328 QByteArray references(size * m_referenceSize, 0);
329 Dest.append(references);
331 QStringList::const_iterator it = Value.constBegin();
332 for ( ; it != Value.constEnd(); ++it)
333 WriteReference(BinaryFromQString(Dest, (*it)), m_referenceSize, (quint8*)Dest.data(), offset);
338 quint64 TorcBinaryPListSerialiser::BinaryFromArray(QByteArray &Dest,
const QString &Name,
const QVariantList &Value)
340 if (!Value.isEmpty())
342 int type = Value[0].type();
344 QVariantList::const_iterator it = Value.constBegin();
345 for ( ; it != Value.constEnd(); ++it)
346 if ((
int)(*it).type() != type)
347 return BinaryFromQString(Dest, QStringLiteral(
"Error: QVariantList is not valid service return type"));
350 quint64 result = m_objectOffsets.size();
353 int size = Value.size();
355 if (size >= BPLIST_LOW_MAX)
356 BinaryFromUInt(Dest, size);
358 quint64 offset = Dest.size();
359 QByteArray references(size * m_referenceSize, 0);
360 Dest.append(references);
362 QVariantList::const_iterator it = Value.constBegin();
363 for ( ; it != Value.constEnd(); ++it)
364 WriteReference(BinaryFromVariant(Dest, Name, (*it)), m_referenceSize, (quint8*)Dest.data(), offset);
369 quint64 TorcBinaryPListSerialiser::BinaryFromMap(QByteArray &Dest,
const QString &Name,
const QVariantMap &Value)
373 quint64 result = m_objectOffsets.size();
376 int size = Value.size();
378 if (size >= BPLIST_LOW_MAX)
379 BinaryFromUInt(Dest, size);
381 quint64 offset = Dest.size();
382 QByteArray references(size * 2 * m_referenceSize, 0);
383 Dest.append(references);
385 QVariantMap::const_iterator it = Value.constBegin();
386 for ( ; it != Value.constEnd(); ++it)
387 WriteReference(BinaryFromQString(Dest, it.key()), m_referenceSize, (quint8*)Dest.data(), offset);
390 for ( ; it != Value.end(); ++it)
391 WriteReference(BinaryFromVariant(Dest, it.key(), it.value()), m_referenceSize, (quint8*)Dest.data(), offset);
396 quint64 TorcBinaryPListSerialiser::BinaryFromQString(QByteArray &Dest,
const QString &Value)
398 static QTextCodec* textCodec = QTextCodec::codecForName(
"UTF-16BE");
400 QHash<QString,quint64>::const_iterator it = m_strings.constFind(Value);
401 if (it != m_strings.constEnd())
404 quint64 result = (quint64)m_objectOffsets.size();
405 m_strings.insert(Value, result);
409 QByteArray output = textCodec->fromUnicode(Value);
411 quint64 size = (output.size() >> 1) - 1;
414 if (size >= BPLIST_LOW_MAX)
415 BinaryFromUInt(Dest, size);
417 Dest.append(output.data() + 2, output.size() - 2);
425 Dest.append(*((quint8*)&Value));
426 Dest.append(*((quint8*)&Value + 1));
427 Dest.append(*((quint8*)&Value + 2));
428 Dest.append(*((quint8*)&Value + 3));
429 Dest.append(*((quint8*)&Value + 4));
430 Dest.append(*((quint8*)&Value + 5));
431 Dest.append(*((quint8*)&Value + 6));
432 Dest.append(*((quint8*)&Value + 7));
436 quint32 value32= qToBigEndian((quint32)(Value & 0xffffffff));
437 Dest.append(*((quint8*)&value32));
438 Dest.append(*((quint8*)&value32 + 1));
439 Dest.append(*((quint8*)&value32 + 2));
440 Dest.append(*((quint8*)&value32 + 3));
444 quint16 value16 = qToBigEndian((quint16)(Value & 0xffff));
445 Dest.append(*((quint8*)&value16));
446 Dest.append(*((quint8*)&value16 + 1));
450 Dest.append((quint8)(Value & 0xff));
454 void TorcBinaryPListSerialiser::BinaryFromData(QByteArray &Dest,
const QVariant &Value)
457 QByteArray data = Value.toByteArray();
460 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to retrieve binary data"));
465 int size = data.size();
467 if (size >= BPLIST_LOW_MAX)
468 BinaryFromUInt(Dest, size);
472 void TorcBinaryPListSerialiser::BinaryFromUuid(QByteArray &Dest,
const QVariant &Value)
475 QByteArray value = Value.toUuid().toRfc4122();
476 if (value.size() == 16)
479 quint64 buffer = (quint64)(qToBigEndian(*((quint64*)value.constData() + 8)));
480 uint8_t size = buffer <= UINT8_MAX ? 1 : buffer <= UINT16_MAX ? 2 : buffer <= UINT32_MAX ? 4 : 8;
486 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Unknown UUID binary with size %1 bytes").arg(value.size()));
491 void TorcBinaryPListSerialiser::BinaryFromUInt(QByteArray &Dest, quint64 Value)
493 uint8_t size = Value <= UINT8_MAX ? 0 : Value <= UINT16_MAX ? 1 : Value <= UINT32_MAX ? 2 : 3;
498 void TorcBinaryPListSerialiser::CountObjects(quint64 &Count,
const QVariant &Value)
500 switch (static_cast<QMetaType::Type>(Value.type()))
502 case QMetaType::QVariantMap:
504 QVariantMap map = Value.toMap();
505 QVariantMap::const_iterator it = map.constBegin();
506 for ( ; it != map.constEnd(); ++it)
507 CountObjects(Count, it.value());
511 case QMetaType::QVariantList:
515 QVariantList list = Value.toList();
516 QVariantList::const_iterator it = list.constBegin();
517 uint type = list.isEmpty() ? QMetaType::UnknownType :
static_cast<QMetaType::Type
>(list[0].type());
518 for ( ; it != list.constEnd(); ++it)
520 if ((*it).type() != type)
522 CountObjects(Count, (*it));
525 Count += list.size();
528 case (QVariant::Type)QMetaType::QStringList:
531 QStringList list = Value.toStringList();
532 Count += list.size();
TorcSerialiser * Create(void)
TorcBinaryPListSerialiserFactory()
void Begin(QByteArray &Dest) override
TorcSerialiser * Create(void)
static void WriteReference(quint64 Reference, quint8 Size, quint8 *Pointer, quint64 &Counter)
void binaryFromUint(QByteArray &Dest, quint64 Value, uint8_t size)
TorcBinaryPListSerialiser()
TorcBinaryPListSerialiserFactory TorcBinaryPListSerialiserFactory
void Prepare(QByteArray &) override
void AddProperty(QByteArray &Dest, const QString &Name, const QVariant &Value) override
A parser for binary property lists.
void End(QByteArray &Dest) override
#define LOG(_MASK_, _LEVEL_, _STRING_)
HTTPResponseType ResponseType(void) override
TorcAppleBinaryPListSerialiserFactory()
TorcAppleBinaryPListSerialiserFactory TorcAppleBinaryPListSerialiserFactory