43#if QT_VERSION < QT_VERSION_CHECK(6,11,0)
44#include <QSequentialIterable>
46#include <QMetaSequence>
56#define LOC QString("PList: ")
58static const QByteArray
MAGIC {
"bplist" };
60#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
102#if (Q_BYTE_ORDER == Q_BIG_ENDIAN) && !defined (__VFP_FP__)
103 return *(
reinterpret_cast<const T *
>(
p));
105 static std::array<uint8_t,
sizeof(T)> temp;
106 for (
size_t i = 0; i < (
sizeof(T) / 2); i++)
108 size_t j =
sizeof(T) - 1 - i;
112 return *(
reinterpret_cast<const T *
>(temp.data()));
123#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
124 auto type =
static_cast<QMetaType::Type
>(
m_result.type());
129 if (
type != QMetaType::QVariantMap)
133 for (
auto it = map.cbegin(); it != map.cend(); ++it)
143 buf.open(QBuffer::WriteOnly);
151 QXmlStreamWriter xml(
Device);
152 xml.setAutoFormatting(
true);
153 xml.setAutoFormattingIndent(4);
154 xml.writeStartDocument();
155 xml.writeDTD(R
"(<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">)");
156 xml.writeStartElement("plist");
157 xml.writeAttribute(
"version",
"1.0");
159 xml.writeEndElement();
160 xml.writeEndDocument();
162 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Invalid result.");
168#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
169 auto type =
static_cast<QMetaType::Type
>(Data.type());
171 auto type = Data.typeId();
175 case QMetaType::QVariantMap:
178 case QMetaType::QVariantList:
181 case QMetaType::Double:
182 Xml.writeTextElement(
"real", QString(
"%1").arg(Data.toDouble(), 0,
'f', 6));
184 case QMetaType::QByteArray:
185 Xml.writeTextElement(
"data", Data.toByteArray().toBase64().data());
187 case QMetaType::ULongLong:
188 Xml.writeTextElement(
"integer", QString(
"%1").arg(Data.toULongLong()));
190 case QMetaType::QString:
191 Xml.writeTextElement(
"string", Data.toString());
193 case QMetaType::QDateTime:
194 Xml.writeTextElement(
"date", Data.toDateTime().toString(
Qt::ISODate));
196 case QMetaType::Bool:
198 bool val = Data.toBool();
199 Xml.writeEmptyElement(val ?
"true" :
"false");
203 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unknown type.");
211 Xml.writeStartElement(
"dict");
212 QVariantMap map = Data.toMap();
213 for (
auto it = map.cbegin(); it != map.cend(); ++it)
215 Xml.writeStartElement(
"key");
216 Xml.writeCharacters(it.key());
217 Xml.writeEndElement();
218 ToXML(it.value(), Xml);
220 Xml.writeEndElement();
225 Xml.writeStartElement(
"array");
226#if QT_VERSION < QT_VERSION_CHECK(6,11,0)
227 auto list = Data.value<QSequentialIterable>();
229 auto list = Data.value<QMetaSequence::Iterable>();
231 for (
const auto & item : std::as_const(list))
233 Xml.writeEndElement();
242 auto size = Data.size();
246 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Binary: size %1, startswith '%2'")
247 .arg(size).arg(Data.left(8).data()));
252 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unrecognised start sequence. Corrupt?");
256 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Parsing binary plist (%1 bytes)").arg(size));
258 m_data =
reinterpret_cast<uint8_t*
>(
const_cast<char*
>(Data.data()));
267 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
268 QString(
"numObjs: %1 parmSize: %2 offsetSize: %3 rootObj: %4"
275 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error parsing binary plist. Corrupt?");
281 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Parse complete.");
290 quint16
type = (*data) & 0xf0;
291 uint64_t size = (*data) & 0x0f;
323 if (Size == 1)
return static_cast<uint64_t
>(*Data);
324 if (Size == 2)
return qFromBigEndian<quint16>(Data);
325 if (Size == 4)
return qFromBigEndian<quint32>(Data);
326 if (Size == 8)
return qFromBigEndian<quint64>(Data);
329#if (Q_BYTE_ORDER == Q_BIG_ENDIAN)
330 return static_cast<uint64_t
>(((*Data) << 16) + (*(Data + 1) << 8) + (*(Data + 2)));
332 return static_cast<uint64_t
>((*Data) + (*(Data + 1) << 8) + ((*(Data + 2)) << 16));
346 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"GetBinaryObject num %1, offsize %2 offset %3")
358 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Dict: Size %1").arg(count));
363 for (uint64_t i = 0; i < count; i++, Data +=
m_parmSize)
369 if (!key.canConvert<QString>())
371 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid dictionary key type.");
374 result.insert(key.toString(), val);
381 QList<QVariant> result;
386 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Array: Size %1").arg(count));
390 result.reserve(count);
391 for (uint64_t i = 0; i < count; i++, Data +=
m_parmSize)
395 result.push_back(val);
404 return {
static_cast<quint64
>(result)};
406 uint64_t size = 1 << ((**Data) & 0x0f);
411 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"UInt: %1").arg(result));
412 return {
static_cast<quint64
>(result)};
425 result = QString::fromLatin1(
reinterpret_cast<const char*
>(Data),
static_cast<int>(count));
426 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"ASCII String: %1").arg(result));
440 count = 1ULL << count;
441 if (count ==
sizeof(
float))
443 result = convert_float<float>(Data);
445 else if (count ==
sizeof(
double))
447 result = convert_float<double>(Data);
450 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Real: %1").arg(result, 0,
'f', 6));
464 auto sec =
static_cast<uint64_t
>(convert_float<double>(Data));
465#if QT_VERSION < QT_VERSION_CHECK(6,5,0)
469 QTimeZone(QTimeZone::UTC));
472 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Date: %1").arg(result.toString(
Qt::ISODate)));
486 result = QByteArray(
reinterpret_cast<const char*
>(Data),
static_cast<int>(count));
487 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Data: Size %1 (count %2)")
488 .arg(result.size()).arg(count));
504 for (uint64_t i = 0; i < count; i++, Data += 2)
506 auto twobyte = qFromBigEndian<quint16>(Data);
507 tmp.append(
static_cast<char>(twobyte & 0xff));
508 tmp.append(
static_cast<char>((twobyte >> 8) & 0xff));
510 result = QString::fromUtf16(
reinterpret_cast<const char16_t*
>(tmp.data()),
static_cast<int>(count));
511 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Unicode: %1").arg(result));
517 uint64_t count = (**Data) & 0x0f;
522 if (!newcount.canConvert<uint64_t>())
524 count = newcount.toULongLong();
A device containing images (ie. USB stick, CD, storage group etc)
QVariant GetValue(const QString &Key)
QVariantMap ParseBinaryDict(uint8_t *Data)
QList< QVariant > ParseBinaryArray(uint8_t *Data)
static QVariant ParseBinaryUnicode(uint8_t *Data)
QVariant ParseBinaryNode(uint64_t Num)
void ParseBinaryPList(const QByteArray &Data)
static QVariant ParseBinaryDate(uint8_t *Data)
static uint64_t GetBinaryUInt(uint8_t *Data, uint64_t Size)
static QVariant ParseBinaryData(uint8_t *Data)
static QVariant ParseBinaryString(uint8_t *Data)
uint8_t * GetBinaryObject(uint64_t Num)
static uint64_t GetBinaryCount(uint8_t **Data)
void ArrayToXML(const QVariant &Data, QXmlStreamWriter &Xml)
void DictToXML(const QVariant &Data, QXmlStreamWriter &Xml)
bool ToXML(QIODevice *Device)
MythBinaryPList(const QByteArray &Data)
static QVariant ParseBinaryReal(uint8_t *Data)
static QVariant ParseBinaryUInt(uint8_t **Data)
static constexpr ssize_t MIN_SIZE
static constexpr uint8_t TRAILER_ROOTOBJ_INDEX
static T convert_float(const uint8_t *p)
static constexpr ssize_t MAGIC_SIZE
static constexpr uint8_t TRAILER_PARMSIZE_INDEX
static const QByteArray MAGIC
static constexpr ssize_t VERSION_SIZE
static constexpr uint8_t TRAILER_OFFSIZE_INDEX
static constexpr uint8_t TRAILER_OFFTAB_INDEX
static constexpr ssize_t TRAILER_SIZE
static const QByteArray VERSION
static constexpr uint64_t CORE_DATA_EPOCH
static constexpr uint8_t TRAILER_NUMOBJ_INDEX
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...