1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
// Copyright (C) 2018 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "datastreamconverter.h"
#include "debugtextdumper.h"
#include "variantorderedmap.h"
#include <QDataStream>
using namespace Qt::StringLiterals;
static const char dataStreamOptionHelp[] =
"byteorder=host|big|little Byte order to use.\n"
"version=<n> QDataStream version (default: Qt 6.0).\n"
;
static const char signature[] = "qds";
static DataStreamConverter dataStreamConverter;
static DebugTextDumper debugTextDumper;
QDataStream &operator<<(QDataStream &ds, const VariantOrderedMap &map)
{
ds << qint64(map.size());
for (const auto &pair : map)
ds << pair.first << pair.second;
return ds;
}
QDataStream &operator>>(QDataStream &ds, VariantOrderedMap &map)
{
map.clear();
qint64 size;
ds >> size;
map.reserve(size);
while (size-- > 0) {
VariantOrderedMap::value_type pair;
ds >> pair.first >> pair.second;
map.append(pair);
}
return ds;
}
DataStreamConverter::DataStreamConverter()
{
qRegisterMetaType<VariantOrderedMap>();
}
QString DataStreamConverter::name() const
{
return "datastream"_L1;
}
Converter::Directions DataStreamConverter::directions() const
{
return Direction::InOut;
}
Converter::Options DataStreamConverter::outputOptions() const
{
return SupportsArbitraryMapKeys;
}
const char *DataStreamConverter::optionsHelp() const
{
return dataStreamOptionHelp;
}
bool DataStreamConverter::probeFile(QIODevice *f) const
{
return f->isReadable() && f->peek(sizeof(signature) - 1) == signature;
}
QVariant DataStreamConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
{
if (!outputConverter)
outputConverter = &debugTextDumper;
char c;
if (f->read(sizeof(signature) - 1) != signature || !f->getChar(&c) || (c != 'l' && c != 'B'))
qFatal("Could not load QDataStream file: invalid signature.");
QDataStream ds(f);
ds.setByteOrder(c == 'l' ? QDataStream::LittleEndian : QDataStream::BigEndian);
std::underlying_type<QDataStream::Version>::type version;
ds >> version;
ds.setVersion(QDataStream::Version(version));
QVariant result;
ds >> result;
return result;
}
void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents,
const QStringList &options) const
{
QDataStream::Version version = QDataStream::Qt_6_0;
auto order = QDataStream::ByteOrder(QSysInfo::ByteOrder);
for (const QString &option : options) {
const QStringList pair = option.split('=');
if (pair.size() == 2) {
if (pair.first() == "byteorder") {
if (pair.last() == "little") {
order = QDataStream::LittleEndian;
continue;
} else if (pair.last() == "big") {
order = QDataStream::BigEndian;
continue;
} else if (pair.last() == "host") {
order = QDataStream::ByteOrder(QSysInfo::ByteOrder);
continue;
}
}
if (pair.first() == "version") {
bool ok;
int n = pair.last().toInt(&ok);
if (ok) {
version = QDataStream::Version(n);
continue;
}
qFatal("Invalid version number '%s': must be a number from 1 to %d.",
qPrintable(pair.last()), QDataStream::Qt_DefaultCompiledVersion);
}
}
qFatal("Unknown QDataStream formatting option '%s'. Available options are:\n%s",
qPrintable(option), dataStreamOptionHelp);
}
char c = order == QDataStream::LittleEndian ? 'l' : 'B';
f->write(signature);
f->write(&c, 1);
QDataStream ds(f);
ds.setVersion(version);
ds.setByteOrder(order);
ds << std::underlying_type<decltype(version)>::type(version);
ds << contents;
}
|