diff options
Diffstat (limited to 'examples/corelib/serialization/convert/datastreamconverter.cpp')
-rw-r--r-- | examples/corelib/serialization/convert/datastreamconverter.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/examples/corelib/serialization/convert/datastreamconverter.cpp b/examples/corelib/serialization/convert/datastreamconverter.cpp new file mode 100644 index 0000000000..7cdb844141 --- /dev/null +++ b/examples/corelib/serialization/convert/datastreamconverter.cpp @@ -0,0 +1,273 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "datastreamconverter.h" + +#include <QDataStream> +#include <QDebug> +#include <QTextStream> + +static const char optionHelp[] = + "byteorder=host|big|little Byte order to use.\n" + "version=<n> QDataStream version (default: Qt 5.0).\n" + ; + +static const char signature[] = "qds"; + +static DataStreamDumper dataStreamDumper; +static DataStreamConverter DataStreamConverter; + +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; +} + + +static QString dumpVariant(const QVariant &v, const QString &indent = QLatin1String("\n")) +{ + QString result; + QString indented = indent + QLatin1String(" "); + + int type = v.userType(); + if (type == qMetaTypeId<VariantOrderedMap>() || type == QVariant::Map) { + const auto map = (type == QVariant::Map) ? + VariantOrderedMap(v.toMap()) : v.value<VariantOrderedMap>(); + + result = QLatin1String("Map {"); + for (const auto &pair : map) { + result += indented + dumpVariant(pair.first, indented); + result.chop(1); // remove comma + result += QLatin1String(" => ") + dumpVariant(pair.second, indented); + + } + result.chop(1); // remove comma + result += indent + QLatin1String("},"); + } else if (type == QVariant::List) { + const QVariantList list = v.toList(); + + result = QLatin1String("List ["); + for (const auto &item : list) + result += indented + dumpVariant(item, indented); + result.chop(1); // remove comma + result += indent + QLatin1String("],"); + } else { + QDebug debug(&result); + debug.nospace() << v << ','; + } + return result; +} + +QString DataStreamDumper::name() +{ + return QStringLiteral("datastream-dump"); +} + +Converter::Direction DataStreamDumper::directions() +{ + return Out; +} + +Converter::Options DataStreamDumper::outputOptions() +{ + return SupportsArbitraryMapKeys; +} + +const char *DataStreamDumper::optionsHelp() +{ + return nullptr; +} + +bool DataStreamDumper::probeFile(QIODevice *f) +{ + Q_UNUSED(f); + return false; +} + +QVariant DataStreamDumper::loadFile(QIODevice *f, Converter *&outputConverter) +{ + Q_UNREACHABLE(); + Q_UNUSED(f); + Q_UNUSED(outputConverter); + return QVariant(); +} + +void DataStreamDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) +{ + Q_UNUSED(options); + QString s = dumpVariant(contents); + s[s.size() - 1] = QLatin1Char('\n'); // replace the comma with newline + + QTextStream out(f); + out << s; +} + +DataStreamConverter::DataStreamConverter() +{ + qRegisterMetaType<VariantOrderedMap>(); + qRegisterMetaTypeStreamOperators<VariantOrderedMap>(); +} + +QString DataStreamConverter::name() +{ + return QStringLiteral("datastream"); +} + +Converter::Direction DataStreamConverter::directions() +{ + return InOut; +} + +Converter::Options DataStreamConverter::outputOptions() +{ + return SupportsArbitraryMapKeys; +} + +const char *DataStreamConverter::optionsHelp() +{ + return optionHelp; +} + +bool DataStreamConverter::probeFile(QIODevice *f) +{ + return f->isReadable() && f->peek(sizeof(signature) - 1) == signature; +} + +QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter) +{ + if (!outputConverter) + outputConverter = &dataStreamDumper; + + char c; + if (f->read(sizeof(signature) -1) != signature || + !f->getChar(&c) || (c != 'l' && c != 'B')) { + fprintf(stderr, "Could not load QDataStream file: invalid signature.\n"); + exit(EXIT_FAILURE); + } + + 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) +{ + QDataStream::Version version = QDataStream::Qt_5_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; + } + + fprintf(stderr, "Invalid version number '%s': must be a number from 1 to %d.\n", + qPrintable(pair.last()), QDataStream::Qt_DefaultCompiledVersion); + exit(EXIT_FAILURE); + } + } + + fprintf(stderr, "Unknown QDataStream formatting option '%s'. Available options are:\n%s", + qPrintable(option), optionHelp); + exit(EXIT_FAILURE); + } + + 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; +} |