mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-06 17:25:24 +08:00
6.5.3 clean
This commit is contained in:
@ -4,6 +4,10 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(convert LANGUAGES CXX)
|
||||
|
||||
if (ANDROID)
|
||||
message(FATAL_ERROR "This project cannot be built on Android.")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
@ -18,6 +22,7 @@ qt_add_executable(convert
|
||||
cborconverter.cpp cborconverter.h
|
||||
converter.h
|
||||
datastreamconverter.cpp datastreamconverter.h
|
||||
debugtextdumper.cpp debugtextdumper.h
|
||||
jsonconverter.cpp jsonconverter.h
|
||||
main.cpp
|
||||
nullconverter.cpp nullconverter.h
|
||||
|
@ -3,19 +3,21 @@
|
||||
|
||||
#include "cborconverter.h"
|
||||
|
||||
#include <QCborArray>
|
||||
#include <QCborMap>
|
||||
#include <QCborStreamReader>
|
||||
#include <QCborStreamWriter>
|
||||
#include <QCborMap>
|
||||
#include <QCborArray>
|
||||
#include <QCborValue>
|
||||
#include <QDataStream>
|
||||
#include <QFloat16>
|
||||
#include <QFile>
|
||||
#include <QFloat16>
|
||||
#include <QMetaType>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static CborConverter cborConverter;
|
||||
static CborDiagnosticDumper cborDiagnosticDumper;
|
||||
|
||||
@ -118,33 +120,33 @@ static QCborValue convertFromVariant(const QVariant &v, TrimFloatingPoint fpTrim
|
||||
}
|
||||
//! [1]
|
||||
|
||||
QString CborDiagnosticDumper::name()
|
||||
QString CborDiagnosticDumper::name() const
|
||||
{
|
||||
return QStringLiteral("cbor-dump");
|
||||
return "cbor-dump"_L1;
|
||||
}
|
||||
|
||||
Converter::Direction CborDiagnosticDumper::directions()
|
||||
Converter::Directions CborDiagnosticDumper::directions() const
|
||||
{
|
||||
return Out;
|
||||
return Direction::Out;
|
||||
}
|
||||
|
||||
Converter::Options CborDiagnosticDumper::outputOptions()
|
||||
Converter::Options CborDiagnosticDumper::outputOptions() const
|
||||
{
|
||||
return SupportsArbitraryMapKeys;
|
||||
}
|
||||
|
||||
const char *CborDiagnosticDumper::optionsHelp()
|
||||
const char *CborDiagnosticDumper::optionsHelp() const
|
||||
{
|
||||
return diagnosticHelp;
|
||||
}
|
||||
|
||||
bool CborDiagnosticDumper::probeFile(QIODevice *f)
|
||||
bool CborDiagnosticDumper::probeFile(QIODevice *f) const
|
||||
{
|
||||
Q_UNUSED(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant CborDiagnosticDumper::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
QVariant CborDiagnosticDumper::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
Q_UNREACHABLE();
|
||||
Q_UNUSED(f);
|
||||
@ -152,7 +154,8 @@ QVariant CborDiagnosticDumper::loadFile(QIODevice *f, Converter *&outputConverte
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
||||
void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const
|
||||
{
|
||||
QCborValue::DiagnosticNotationOptions opts = QCborValue::LineWrapped;
|
||||
for (const QString &s : options) {
|
||||
@ -181,8 +184,7 @@ void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, cons
|
||||
}
|
||||
|
||||
QTextStream out(f);
|
||||
out << convertFromVariant(contents, Double).toDiagnosticNotation(opts)
|
||||
<< Qt::endl;
|
||||
out << convertFromVariant(contents, Double).toDiagnosticNotation(opts) << Qt::endl;
|
||||
}
|
||||
|
||||
CborConverter::CborConverter()
|
||||
@ -190,37 +192,37 @@ CborConverter::CborConverter()
|
||||
qRegisterMetaType<QCborTag>();
|
||||
}
|
||||
|
||||
QString CborConverter::name()
|
||||
QString CborConverter::name() const
|
||||
{
|
||||
return "cbor";
|
||||
}
|
||||
|
||||
Converter::Direction CborConverter::directions()
|
||||
Converter::Directions CborConverter::directions() const
|
||||
{
|
||||
return InOut;
|
||||
return Direction::InOut;
|
||||
}
|
||||
|
||||
Converter::Options CborConverter::outputOptions()
|
||||
Converter::Options CborConverter::outputOptions() const
|
||||
{
|
||||
return SupportsArbitraryMapKeys;
|
||||
}
|
||||
|
||||
const char *CborConverter::optionsHelp()
|
||||
const char *CborConverter::optionsHelp() const
|
||||
{
|
||||
return cborOptionHelp;
|
||||
}
|
||||
|
||||
bool CborConverter::probeFile(QIODevice *f)
|
||||
bool CborConverter::probeFile(QIODevice *f) const
|
||||
{
|
||||
if (QFile *file = qobject_cast<QFile *>(f)) {
|
||||
if (file->fileName().endsWith(QLatin1String(".cbor")))
|
||||
if (file->fileName().endsWith(".cbor"_L1))
|
||||
return true;
|
||||
}
|
||||
return f->isReadable() && f->peek(3) == QByteArray("\xd9\xd9\xf7", 3);
|
||||
}
|
||||
|
||||
//! [2]
|
||||
QVariant CborConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
QVariant CborConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
const char *ptr = nullptr;
|
||||
if (auto file = qobject_cast<QFile *>(f))
|
||||
@ -256,7 +258,7 @@ QVariant CborConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
}
|
||||
//! [2]
|
||||
//! [3]
|
||||
void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
||||
void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) const
|
||||
{
|
||||
//! [3]
|
||||
bool useSignature = true;
|
||||
@ -318,8 +320,9 @@ void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStri
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
//! [4]
|
||||
QCborValue v = convertFromVariant(contents,
|
||||
useFloat16 == Always ? Float16 : useFloat == Always ? Float : Double);
|
||||
QCborValue v =
|
||||
convertFromVariant(contents,
|
||||
useFloat16 == Always ? Float16 : useFloat == Always ? Float : Double);
|
||||
QCborStreamWriter writer(f);
|
||||
if (useSignature)
|
||||
writer.append(QCborKnownTags::Signature);
|
||||
|
@ -10,13 +10,14 @@ class CborDiagnosticDumper : public Converter
|
||||
{
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
class CborConverter : public Converter
|
||||
@ -26,13 +27,14 @@ public:
|
||||
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
#endif // CBORCONVERTER_H
|
||||
|
@ -12,17 +12,19 @@ INSTALLS += target
|
||||
|
||||
SOURCES += main.cpp \
|
||||
cborconverter.cpp \
|
||||
jsonconverter.cpp \
|
||||
datastreamconverter.cpp \
|
||||
debugtextdumper.cpp \
|
||||
jsonconverter.cpp \
|
||||
nullconverter.cpp \
|
||||
textconverter.cpp \
|
||||
xmlconverter.cpp \
|
||||
nullconverter.cpp
|
||||
xmlconverter.cpp
|
||||
|
||||
HEADERS += \
|
||||
converter.h \
|
||||
cborconverter.h \
|
||||
jsonconverter.h \
|
||||
datastreamconverter.h \
|
||||
debugtextdumper.h \
|
||||
jsonconverter.h \
|
||||
nullconverter.h \
|
||||
textconverter.h \
|
||||
xmlconverter.h \
|
||||
nullconverter.h
|
||||
xmlconverter.h
|
||||
|
@ -5,10 +5,10 @@
|
||||
#define CONVERTER_H
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <QVariant>
|
||||
#include <QVariantMap>
|
||||
#include <QList>
|
||||
|
||||
class VariantOrderedMap : public QList<QPair<QVariant, QVariant>>
|
||||
{
|
||||
@ -32,26 +32,25 @@ protected:
|
||||
public:
|
||||
static Converter *null;
|
||||
|
||||
enum Direction {
|
||||
In = 1, Out = 2, InOut = 3
|
||||
};
|
||||
enum class Direction { In = 1, Out = 2, InOut = In | Out };
|
||||
Q_DECLARE_FLAGS(Directions, Direction)
|
||||
|
||||
enum Option {
|
||||
SupportsArbitraryMapKeys = 0x01
|
||||
};
|
||||
enum Option { SupportsArbitraryMapKeys = 0x01 };
|
||||
Q_DECLARE_FLAGS(Options, Option)
|
||||
|
||||
virtual ~Converter() = 0;
|
||||
|
||||
virtual QString name() = 0;
|
||||
virtual Direction directions() = 0;
|
||||
virtual Options outputOptions() = 0;
|
||||
virtual const char *optionsHelp() = 0;
|
||||
virtual bool probeFile(QIODevice *f) = 0;
|
||||
virtual QVariant loadFile(QIODevice *f, Converter *&outputConverter) = 0;
|
||||
virtual void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) = 0;
|
||||
virtual QString name() const = 0;
|
||||
virtual Directions directions() const = 0;
|
||||
virtual Options outputOptions() const = 0;
|
||||
virtual const char *optionsHelp() const = 0;
|
||||
virtual bool probeFile(QIODevice *f) const = 0;
|
||||
virtual QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const = 0;
|
||||
virtual void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const = 0;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Directions)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Options)
|
||||
|
||||
#endif // CONVERTER_H
|
||||
|
@ -2,20 +2,21 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "datastreamconverter.h"
|
||||
#include "debugtextdumper.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QTextStream>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static const char dataStreamOptionHelp[] =
|
||||
"byteorder=host|big|little Byte order to use.\n"
|
||||
"version=<n> QDataStream version (default: Qt 5.0).\n"
|
||||
"version=<n> QDataStream version (default: Qt 6.0).\n"
|
||||
;
|
||||
|
||||
static const char signature[] = "qds";
|
||||
|
||||
static DataStreamDumper dataStreamDumper;
|
||||
static DataStreamConverter DataStreamConverter;
|
||||
static DataStreamConverter dataStreamConverter;
|
||||
static DebugTextDumper debugTextDumper;
|
||||
|
||||
QDataStream &operator<<(QDataStream &ds, const VariantOrderedMap &map)
|
||||
{
|
||||
@ -42,123 +43,43 @@ QDataStream &operator>>(QDataStream &ds, VariantOrderedMap &map)
|
||||
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 == QMetaType::QVariantMap) {
|
||||
const auto map = (type == QMetaType::QVariantMap) ?
|
||||
VariantOrderedMap(v.toMap()) : qvariant_cast<VariantOrderedMap>(v);
|
||||
|
||||
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 == QMetaType::QVariantList) {
|
||||
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>();
|
||||
}
|
||||
|
||||
QString DataStreamConverter::name()
|
||||
QString DataStreamConverter::name() const
|
||||
{
|
||||
return QStringLiteral("datastream");
|
||||
return "datastream"_L1;
|
||||
}
|
||||
|
||||
Converter::Direction DataStreamConverter::directions()
|
||||
Converter::Directions DataStreamConverter::directions() const
|
||||
{
|
||||
return InOut;
|
||||
return Direction::InOut;
|
||||
}
|
||||
|
||||
Converter::Options DataStreamConverter::outputOptions()
|
||||
Converter::Options DataStreamConverter::outputOptions() const
|
||||
{
|
||||
return SupportsArbitraryMapKeys;
|
||||
}
|
||||
|
||||
const char *DataStreamConverter::optionsHelp()
|
||||
const char *DataStreamConverter::optionsHelp() const
|
||||
{
|
||||
return dataStreamOptionHelp;
|
||||
}
|
||||
|
||||
bool DataStreamConverter::probeFile(QIODevice *f)
|
||||
bool DataStreamConverter::probeFile(QIODevice *f) const
|
||||
{
|
||||
return f->isReadable() && f->peek(sizeof(signature) - 1) == signature;
|
||||
}
|
||||
|
||||
QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
QVariant DataStreamConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
if (!outputConverter)
|
||||
outputConverter = &dataStreamDumper;
|
||||
outputConverter = &debugTextDumper;
|
||||
|
||||
char c;
|
||||
if (f->read(sizeof(signature) -1) != signature ||
|
||||
!f->getChar(&c) || (c != 'l' && c != 'B')) {
|
||||
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);
|
||||
}
|
||||
@ -175,9 +96,10 @@ QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter
|
||||
return result;
|
||||
}
|
||||
|
||||
void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
||||
void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const
|
||||
{
|
||||
QDataStream::Version version = QDataStream::Qt_5_0;
|
||||
QDataStream::Version version = QDataStream::Qt_6_0;
|
||||
auto order = QDataStream::ByteOrder(QSysInfo::ByteOrder);
|
||||
for (const QString &option : options) {
|
||||
const QStringList pair = option.split('=');
|
||||
@ -213,7 +135,7 @@ void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, const
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char c = order == QDataStream::LittleEndian ? 'l' : 'B';
|
||||
char c = order == QDataStream::LittleEndian ? 'l' : 'B';
|
||||
f->write(signature);
|
||||
f->write(&c, 1);
|
||||
|
||||
|
@ -6,19 +6,6 @@
|
||||
|
||||
#include "converter.h"
|
||||
|
||||
class DataStreamDumper : public Converter
|
||||
{
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
};
|
||||
|
||||
class DataStreamConverter : public Converter
|
||||
{
|
||||
public:
|
||||
@ -26,13 +13,14 @@ public:
|
||||
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
#endif // DATASTREAMCONVERTER_H
|
||||
|
89
examples/corelib/serialization/convert/debugtextdumper.cpp
Normal file
89
examples/corelib/serialization/convert/debugtextdumper.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright (C) 2018 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "debugtextdumper.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTextStream>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
// Static instance is declared in datastreamconverter.cpp, since it uses it.
|
||||
|
||||
static QString dumpVariant(const QVariant &v, const QString &indent = "\n"_L1)
|
||||
{
|
||||
QString result;
|
||||
QString indented = indent + " "_L1;
|
||||
|
||||
int type = v.userType();
|
||||
if (type == qMetaTypeId<VariantOrderedMap>() || type == QMetaType::QVariantMap) {
|
||||
const auto map = (type == QMetaType::QVariantMap) ? VariantOrderedMap(v.toMap())
|
||||
: qvariant_cast<VariantOrderedMap>(v);
|
||||
|
||||
result = "Map {"_L1;
|
||||
for (const auto &pair : map) {
|
||||
result += indented + dumpVariant(pair.first, indented);
|
||||
result.chop(1); // remove comma
|
||||
result += " => "_L1 + dumpVariant(pair.second, indented);
|
||||
}
|
||||
result.chop(1); // remove comma
|
||||
result += indent + "},"_L1;
|
||||
} else if (type == QMetaType::QVariantList) {
|
||||
const QVariantList list = v.toList();
|
||||
|
||||
result = "List ["_L1;
|
||||
for (const auto &item : list)
|
||||
result += indented + dumpVariant(item, indented);
|
||||
result.chop(1); // remove comma
|
||||
result += indent + "],"_L1;
|
||||
} else {
|
||||
QDebug debug(&result);
|
||||
debug.nospace() << v << ',';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QString DebugTextDumper::name() const
|
||||
{
|
||||
return "debugtext-dump"_L1;
|
||||
}
|
||||
|
||||
Converter::Directions DebugTextDumper::directions() const
|
||||
{
|
||||
return Direction::Out;
|
||||
}
|
||||
|
||||
Converter::Options DebugTextDumper::outputOptions() const
|
||||
{
|
||||
return SupportsArbitraryMapKeys;
|
||||
}
|
||||
|
||||
const char *DebugTextDumper::optionsHelp() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DebugTextDumper::probeFile(QIODevice *f) const
|
||||
{
|
||||
Q_UNUSED(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant DebugTextDumper::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
Q_UNREACHABLE();
|
||||
Q_UNUSED(f);
|
||||
Q_UNUSED(outputConverter);
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void DebugTextDumper::saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const
|
||||
{
|
||||
Q_UNUSED(options);
|
||||
QString s = dumpVariant(contents);
|
||||
s[s.size() - 1] = u'\n'; // replace the comma with newline
|
||||
|
||||
QTextStream out(f);
|
||||
out << s;
|
||||
}
|
23
examples/corelib/serialization/convert/debugtextdumper.h
Normal file
23
examples/corelib/serialization/convert/debugtextdumper.h
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2018 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef DEBUGTEXTDUMPER_H
|
||||
#define DEBUGTEXTDUMPER_H
|
||||
|
||||
#include "converter.h"
|
||||
|
||||
class DebugTextDumper : public Converter
|
||||
{
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
#endif // DEBUGTEXTDUMPER_H
|
@ -3,7 +3,8 @@
|
||||
|
||||
/*!
|
||||
\example serialization/convert
|
||||
\examplecategory {Input/Output}
|
||||
\examplecategory {Data Processing & I/O}
|
||||
\meta tag {network}
|
||||
\title Convert Example
|
||||
|
||||
\brief The Convert example demonstrates how to convert between different
|
||||
@ -59,7 +60,7 @@
|
||||
\section1 The DataStreamConverter Class
|
||||
|
||||
The DataStreamConverter class is used to serialize to and from the
|
||||
QDataStream format. There is also the DataStreamDumper class for outputting
|
||||
QDataStream format. There is also the DebugTextDumper class for outputting
|
||||
the data lossless in a non-standardized human readable format.
|
||||
|
||||
\section1 The JsonConverter Class
|
||||
|
@ -9,10 +9,11 @@
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static JsonConverter jsonConverter;
|
||||
|
||||
static const char jsonOptionHelp[] =
|
||||
"compact=no|yes Use compact JSON form.\n";
|
||||
static const char jsonOptionHelp[] = "compact=no|yes Use compact JSON form.\n";
|
||||
|
||||
static QJsonDocument convertFromVariant(const QVariant &v)
|
||||
{
|
||||
@ -24,34 +25,30 @@ static QJsonDocument convertFromVariant(const QVariant &v)
|
||||
return doc;
|
||||
}
|
||||
|
||||
JsonConverter::JsonConverter()
|
||||
QString JsonConverter::name() const
|
||||
{
|
||||
return "json"_L1;
|
||||
}
|
||||
|
||||
QString JsonConverter::name()
|
||||
Converter::Directions JsonConverter::directions() const
|
||||
{
|
||||
return "json";
|
||||
return Direction::InOut;
|
||||
}
|
||||
|
||||
Converter::Direction JsonConverter::directions()
|
||||
{
|
||||
return InOut;
|
||||
}
|
||||
|
||||
Converter::Options JsonConverter::outputOptions()
|
||||
Converter::Options JsonConverter::outputOptions() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const char *JsonConverter::optionsHelp()
|
||||
const char *JsonConverter::optionsHelp() const
|
||||
{
|
||||
return jsonOptionHelp;
|
||||
}
|
||||
|
||||
bool JsonConverter::probeFile(QIODevice *f)
|
||||
bool JsonConverter::probeFile(QIODevice *f) const
|
||||
{
|
||||
if (QFile *file = qobject_cast<QFile *>(f)) {
|
||||
if (file->fileName().endsWith(QLatin1String(".json")))
|
||||
if (file->fileName().endsWith(".json"_L1))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -62,7 +59,7 @@ bool JsonConverter::probeFile(QIODevice *f)
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant JsonConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
QVariant JsonConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
if (!outputConverter)
|
||||
outputConverter = this;
|
||||
@ -87,13 +84,14 @@ QVariant JsonConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
return doc.toVariant();
|
||||
}
|
||||
|
||||
void JsonConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
||||
void JsonConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const
|
||||
{
|
||||
QJsonDocument::JsonFormat format = QJsonDocument::Indented;
|
||||
for (const QString &s : options) {
|
||||
if (s == QLatin1String("compact=no")) {
|
||||
if (s == "compact=no"_L1) {
|
||||
format = QJsonDocument::Indented;
|
||||
} else if (s == QLatin1String("compact=yes")) {
|
||||
} else if (s == "compact=yes"_L1) {
|
||||
format = QJsonDocument::Compact;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown option '%s' to JSON output. Valid options are:\n%s",
|
||||
|
@ -8,18 +8,16 @@
|
||||
|
||||
class JsonConverter : public Converter
|
||||
{
|
||||
public:
|
||||
JsonConverter();
|
||||
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
#endif // JSONCONVERTER_H
|
||||
|
@ -11,12 +11,14 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static QList<Converter *> *availableConverters;
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static QList<const Converter *> *availableConverters;
|
||||
|
||||
Converter::Converter()
|
||||
{
|
||||
if (!availableConverters)
|
||||
availableConverters = new QList<Converter *>;
|
||||
availableConverters = new QList<const Converter *>;
|
||||
availableConverters->append(this);
|
||||
}
|
||||
|
||||
@ -31,64 +33,68 @@ int main(int argc, char *argv[])
|
||||
|
||||
QStringList inputFormats;
|
||||
QStringList outputFormats;
|
||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
||||
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||
auto direction = conv->directions();
|
||||
QString name = conv->name();
|
||||
if (direction & Converter::In)
|
||||
if (direction.testFlag(Converter::Direction::In))
|
||||
inputFormats << name;
|
||||
if (direction & Converter::Out)
|
||||
if (direction.testFlag(Converter::Direction::Out))
|
||||
outputFormats << name;
|
||||
}
|
||||
inputFormats.sort();
|
||||
outputFormats.sort();
|
||||
inputFormats.prepend("auto");
|
||||
outputFormats.prepend("auto");
|
||||
inputFormats.prepend("auto"_L1);
|
||||
outputFormats.prepend("auto"_L1);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QStringLiteral("Qt file format conversion tool"));
|
||||
parser.setApplicationDescription("Qt file format conversion tool"_L1);
|
||||
parser.addHelpOption();
|
||||
|
||||
QCommandLineOption inputFormatOption(QStringList{"I", "input-format"});
|
||||
inputFormatOption.setDescription(QLatin1String("Select the input format for the input file. Available formats: ") +
|
||||
inputFormats.join(", "));
|
||||
inputFormatOption.setValueName("format");
|
||||
QCommandLineOption inputFormatOption(QStringList{ "I"_L1, "input-format"_L1 });
|
||||
inputFormatOption.setDescription(
|
||||
"Select the input format for the input file. Available formats: "_L1
|
||||
+ inputFormats.join(", "_L1));
|
||||
inputFormatOption.setValueName("format"_L1);
|
||||
inputFormatOption.setDefaultValue(inputFormats.constFirst());
|
||||
parser.addOption(inputFormatOption);
|
||||
|
||||
QCommandLineOption outputFormatOption(QStringList{"O", "output-format"});
|
||||
outputFormatOption.setDescription(QLatin1String("Select the output format for the output file. Available formats: ") +
|
||||
outputFormats.join(", "));
|
||||
outputFormatOption.setValueName("format");
|
||||
QCommandLineOption outputFormatOption(QStringList{ "O"_L1, "output-format"_L1 });
|
||||
outputFormatOption.setDescription(
|
||||
"Select the output format for the output file. Available formats: "_L1
|
||||
+ outputFormats.join(", "_L1));
|
||||
outputFormatOption.setValueName("format"_L1);
|
||||
outputFormatOption.setDefaultValue(outputFormats.constFirst());
|
||||
parser.addOption(outputFormatOption);
|
||||
|
||||
QCommandLineOption optionOption(QStringList{"o", "option"});
|
||||
optionOption.setDescription(QStringLiteral("Format-specific options. Use --format-options to find out what options are available."));
|
||||
optionOption.setValueName("options...");
|
||||
QCommandLineOption optionOption(QStringList{ "o"_L1, "option"_L1 });
|
||||
optionOption.setDescription(
|
||||
"Format-specific options. Use --format-options to find out what options are available."_L1);
|
||||
optionOption.setValueName("options..."_L1);
|
||||
optionOption.setDefaultValues({});
|
||||
parser.addOption(optionOption);
|
||||
|
||||
QCommandLineOption formatOptionsOption("format-options");
|
||||
formatOptionsOption.setDescription(QStringLiteral("Prints the list of valid options for --option for the converter format <format>."));
|
||||
formatOptionsOption.setValueName("format");
|
||||
QCommandLineOption formatOptionsOption("format-options"_L1);
|
||||
formatOptionsOption.setDescription(
|
||||
"Prints the list of valid options for --option for the converter format <format>."_L1);
|
||||
formatOptionsOption.setValueName("format"_L1);
|
||||
parser.addOption(formatOptionsOption);
|
||||
|
||||
parser.addPositionalArgument(QStringLiteral("[source]"),
|
||||
QStringLiteral("File to read from (stdin if none)"));
|
||||
parser.addPositionalArgument(QStringLiteral("[destination]"),
|
||||
QStringLiteral("File to write to (stdout if none)"));
|
||||
parser.addPositionalArgument("[source]"_L1, "File to read from (stdin if none)"_L1);
|
||||
parser.addPositionalArgument("[destination]"_L1, "File to write to (stdout if none)"_L1);
|
||||
|
||||
parser.process(app);
|
||||
|
||||
if (parser.isSet(formatOptionsOption)) {
|
||||
QString format = parser.value(formatOptionsOption);
|
||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
||||
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (conv->name() == format) {
|
||||
const char *help = conv->optionsHelp();
|
||||
if (help)
|
||||
printf("The following options are available for format '%s':\n\n%s", qPrintable(format), help);
|
||||
else
|
||||
if (help) {
|
||||
printf("The following options are available for format '%s':\n\n%s",
|
||||
qPrintable(format), help);
|
||||
} else {
|
||||
printf("Format '%s' supports no options.\n", qPrintable(format));
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
@ -97,10 +103,10 @@ int main(int argc, char *argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Converter *inconv = nullptr;
|
||||
const Converter *inconv = nullptr;
|
||||
QString format = parser.value(inputFormatOption);
|
||||
if (format != "auto") {
|
||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (format != "auto"_L1) {
|
||||
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (conv->name() == format) {
|
||||
inconv = conv;
|
||||
break;
|
||||
@ -113,10 +119,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
Converter *outconv = nullptr;
|
||||
const Converter *outconv = nullptr;
|
||||
format = parser.value(outputFormatOption);
|
||||
if (format != "auto") {
|
||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (format != "auto"_L1) {
|
||||
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (conv->name() == format) {
|
||||
outconv = conv;
|
||||
break;
|
||||
@ -155,8 +161,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (!inconv) {
|
||||
// probe the input to find a file format
|
||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (conv->directions() & Converter::In && conv->probeFile(&input)) {
|
||||
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (conv->directions().testFlag(Converter::Direction::In)
|
||||
&& conv->probeFile(&input)) {
|
||||
inconv = conv;
|
||||
break;
|
||||
}
|
||||
@ -170,8 +177,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (!outconv) {
|
||||
// probe the output to find a file format
|
||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (conv->directions() & Converter::Out && conv->probeFile(&output)) {
|
||||
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||
if (conv->directions().testFlag(Converter::Direction::Out)
|
||||
&& conv->probeFile(&output)) {
|
||||
outconv = conv;
|
||||
break;
|
||||
}
|
||||
|
@ -3,36 +3,38 @@
|
||||
|
||||
#include "nullconverter.h"
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static NullConverter nullConverter;
|
||||
Converter* Converter::null = &nullConverter;
|
||||
Converter *Converter::null = &nullConverter;
|
||||
|
||||
QString NullConverter::name()
|
||||
QString NullConverter::name() const
|
||||
{
|
||||
return QLatin1String("null");
|
||||
return "null"_L1;
|
||||
}
|
||||
|
||||
Converter::Direction NullConverter::directions()
|
||||
Converter::Directions NullConverter::directions() const
|
||||
{
|
||||
return Out;
|
||||
return Direction::Out;
|
||||
}
|
||||
|
||||
Converter::Options NullConverter::outputOptions()
|
||||
Converter::Options NullConverter::outputOptions() const
|
||||
{
|
||||
return SupportsArbitraryMapKeys;
|
||||
}
|
||||
|
||||
const char *NullConverter::optionsHelp()
|
||||
const char *NullConverter::optionsHelp() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool NullConverter::probeFile(QIODevice *f)
|
||||
bool NullConverter::probeFile(QIODevice *f) const
|
||||
{
|
||||
Q_UNUSED(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant NullConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
QVariant NullConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
Q_UNUSED(f);
|
||||
Q_UNUSED(outputConverter);
|
||||
@ -40,10 +42,12 @@ QVariant NullConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void NullConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
||||
void NullConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const
|
||||
{
|
||||
if (!options.isEmpty()) {
|
||||
fprintf(stderr, "Unknown option '%s' to null output. This format has no options.\n", qPrintable(options.first()));
|
||||
fprintf(stderr, "Unknown option '%s' to null output. This format has no options.\n",
|
||||
qPrintable(options.first()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,14 @@ class NullConverter : public Converter
|
||||
{
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
#endif // NULLCONVERTER_H
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static void dumpVariant(QTextStream &out, const QVariant &v)
|
||||
{
|
||||
switch (v.userType()) {
|
||||
@ -42,67 +44,62 @@ static void dumpVariant(QTextStream &out, const QVariant &v)
|
||||
}
|
||||
}
|
||||
|
||||
QString TextConverter::name()
|
||||
QString TextConverter::name() const
|
||||
{
|
||||
return QStringLiteral("text");
|
||||
return "text"_L1;
|
||||
}
|
||||
|
||||
Converter::Direction TextConverter::directions()
|
||||
Converter::Directions TextConverter::directions() const
|
||||
{
|
||||
return InOut;
|
||||
return Direction::InOut;
|
||||
}
|
||||
|
||||
Converter::Options TextConverter::outputOptions()
|
||||
Converter::Options TextConverter::outputOptions() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const char *TextConverter::optionsHelp()
|
||||
const char *TextConverter::optionsHelp() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool TextConverter::probeFile(QIODevice *f)
|
||||
bool TextConverter::probeFile(QIODevice *f) const
|
||||
{
|
||||
if (QFile *file = qobject_cast<QFile *>(f))
|
||||
return file->fileName().endsWith(QLatin1String(".txt"));
|
||||
return file->fileName().endsWith(".txt"_L1);
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant TextConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
QVariant TextConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
if (!outputConverter)
|
||||
outputConverter = this;
|
||||
|
||||
QVariantList list;
|
||||
QTextStream in(f);
|
||||
QString line ;
|
||||
QString line;
|
||||
while (!in.atEnd()) {
|
||||
in.readLineInto(&line);
|
||||
|
||||
bool ok;
|
||||
qint64 v = line.toLongLong(&ok);
|
||||
if (ok) {
|
||||
|
||||
if (qint64 v = line.toLongLong(&ok); ok)
|
||||
list.append(v);
|
||||
continue;
|
||||
}
|
||||
|
||||
double d = line.toDouble(&ok);
|
||||
if (ok) {
|
||||
else if (double d = line.toDouble(&ok); ok)
|
||||
list.append(d);
|
||||
continue;
|
||||
}
|
||||
|
||||
list.append(line);
|
||||
else
|
||||
list.append(line);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void TextConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
||||
void TextConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const
|
||||
{
|
||||
if (!options.isEmpty()) {
|
||||
fprintf(stderr, "Unknown option '%s' to text output. This format has no options.\n", qPrintable(options.first()));
|
||||
fprintf(stderr, "Unknown option '%s' to text output. This format has no options.\n",
|
||||
qPrintable(options.first()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -8,16 +8,16 @@
|
||||
|
||||
class TextConverter : public Converter
|
||||
{
|
||||
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
#endif // TEXTCONVERTER_H
|
||||
|
@ -13,8 +13,9 @@
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
static const char xmlOptionHelp[] =
|
||||
"compact=no|yes Use compact XML form.\n";
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static const char xmlOptionHelp[] = "compact=no|yes Use compact XML form.\n";
|
||||
|
||||
static XmlConverter xmlConverter;
|
||||
|
||||
@ -23,7 +24,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
||||
static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||
{
|
||||
QVariantList list;
|
||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("list"))) {
|
||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "list"_L1)) {
|
||||
xml.readNext();
|
||||
switch (xml.tokenType()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
@ -47,8 +48,7 @@ static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options option
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
||||
xml.lineNumber(), xml.columnNumber(),
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -57,10 +57,11 @@ static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options option
|
||||
return list;
|
||||
}
|
||||
|
||||
static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||
static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml,
|
||||
Converter::Options options)
|
||||
{
|
||||
QVariant key, value;
|
||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("entry"))) {
|
||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "entry"_L1)) {
|
||||
xml.readNext();
|
||||
switch (xml.tokenType()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
@ -89,8 +90,7 @@ static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Conv
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
||||
xml.lineNumber(), xml.columnNumber(),
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -103,11 +103,11 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||
QVariantMap map1;
|
||||
VariantOrderedMap map2;
|
||||
|
||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("map"))) {
|
||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "map"_L1)) {
|
||||
xml.readNext();
|
||||
switch (xml.tokenType()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (xml.name() == QLatin1String("entry")) {
|
||||
if (xml.name() == "entry"_L1) {
|
||||
auto pair = mapEntryFromXml(xml, options);
|
||||
if (options & Converter::SupportsArbitraryMapKeys)
|
||||
map2.append(pair);
|
||||
@ -134,8 +134,7 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
||||
xml.lineNumber(), xml.columnNumber(),
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -149,18 +148,18 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||
static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||
{
|
||||
QStringView name = xml.name();
|
||||
if (name == QLatin1String("list"))
|
||||
if (name == "list"_L1)
|
||||
return listFromXml(xml, options);
|
||||
if (name == QLatin1String("map"))
|
||||
if (name == "map"_L1)
|
||||
return mapFromXml(xml, options);
|
||||
if (name != QLatin1String("value")) {
|
||||
if (name != "value"_L1) {
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML key '%s'.\n",
|
||||
xml.lineNumber(), xml.columnNumber(), qPrintable(name.toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
QXmlStreamAttributes attrs = xml.attributes();
|
||||
QStringView type = attrs.value(QLatin1String("type"));
|
||||
QStringView type = attrs.value("type"_L1);
|
||||
|
||||
forever {
|
||||
xml.readNext();
|
||||
@ -169,8 +168,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
||||
if (xml.isCDATA() || xml.isCharacters() || xml.isEndElement())
|
||||
break;
|
||||
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
||||
xml.lineNumber(), xml.columnNumber(),
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||
qPrintable(xml.tokenString()), qPrintable(name.toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -180,45 +178,45 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
||||
text = text.trimmed();
|
||||
|
||||
QVariant result;
|
||||
bool ok;
|
||||
if (type.isEmpty()) {
|
||||
// ok
|
||||
} else if (type == QLatin1String("number")) {
|
||||
} else if (type == "number"_L1) {
|
||||
// try integer first
|
||||
bool ok;
|
||||
qint64 v = text.toLongLong(&ok);
|
||||
if (ok) {
|
||||
result = v;
|
||||
} else {
|
||||
// let's see floating point
|
||||
double d = text.toDouble(&ok);
|
||||
result = d;
|
||||
if (!ok) {
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML: could not interpret '%s' as a number.\n",
|
||||
xml.lineNumber(), xml.columnNumber(), qPrintable(text.toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
result = d;
|
||||
}
|
||||
} else if (type == QLatin1String("bytes")) {
|
||||
} else if (type == "bytes"_L1) {
|
||||
QByteArray data = text.toLatin1();
|
||||
QStringView encoding = attrs.value("encoding");
|
||||
if (encoding == QLatin1String("base64url")) {
|
||||
if (encoding == "base64url"_L1) {
|
||||
result = QByteArray::fromBase64(data, QByteArray::Base64UrlEncoding);
|
||||
} else if (encoding == QLatin1String("hex")) {
|
||||
} else if (encoding == "hex"_L1) {
|
||||
result = QByteArray::fromHex(data);
|
||||
} else if (encoding.isEmpty() || encoding == QLatin1String("base64")) {
|
||||
} else if (encoding.isEmpty() || encoding == "base64"_L1) {
|
||||
result = QByteArray::fromBase64(data);
|
||||
} else {
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML: unknown encoding '%s' for bytes.\n",
|
||||
xml.lineNumber(), xml.columnNumber(), qPrintable(encoding.toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (type == QLatin1String("string")) {
|
||||
} else if (type == "string"_L1) {
|
||||
result = text.toString();
|
||||
} else if (type == QLatin1String("null")) {
|
||||
} else if (type == "null"_L1) {
|
||||
result = QVariant::fromValue(nullptr);
|
||||
} else if (type == QLatin1String("CBOR simple type")) {
|
||||
} else if (type == "CBOR simple type"_L1) {
|
||||
result = QVariant::fromValue(QCborSimpleType(text.toShort()));
|
||||
} else if (type == QLatin1String("bits")) {
|
||||
} else if (type == "bits"_L1) {
|
||||
QBitArray ba;
|
||||
ba.resize(text.size());
|
||||
qsizetype n = 0;
|
||||
@ -238,13 +236,13 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
||||
result = ba;
|
||||
} else {
|
||||
int id = QMetaType::UnknownType;
|
||||
if (type == QLatin1String("datetime"))
|
||||
if (type == "datetime"_L1)
|
||||
id = QMetaType::QDateTime;
|
||||
else if (type == QLatin1String("url"))
|
||||
else if (type == "url"_L1)
|
||||
id = QMetaType::QUrl;
|
||||
else if (type == QLatin1String("uuid"))
|
||||
else if (type == "uuid"_L1)
|
||||
id = QMetaType::QUuid;
|
||||
else if (type == QLatin1String("regex"))
|
||||
else if (type == "regex"_L1)
|
||||
id = QMetaType::QRegularExpression;
|
||||
else
|
||||
id = QMetaType::fromName(type.toLatin1()).id();
|
||||
@ -267,8 +265,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
||||
} while (xml.isComment() || xml.isWhitespace());
|
||||
|
||||
if (!xml.isEndElement()) {
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
||||
xml.lineNumber(), xml.columnNumber(),
|
||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||
qPrintable(xml.tokenString()), qPrintable(name.toString()));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -287,9 +284,9 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
||||
variantToXml(xml, v);
|
||||
xml.writeEndElement();
|
||||
} else if (type == QMetaType::QVariantMap || type == qMetaTypeId<VariantOrderedMap>()) {
|
||||
const VariantOrderedMap map = (type == QMetaType::QVariantMap) ?
|
||||
VariantOrderedMap(v.toMap()) :
|
||||
qvariant_cast<VariantOrderedMap>(v);
|
||||
const VariantOrderedMap map = (type == QMetaType::QVariantMap)
|
||||
? VariantOrderedMap(v.toMap())
|
||||
: qvariant_cast<VariantOrderedMap>(v);
|
||||
|
||||
xml.writeStartElement("map");
|
||||
for (const auto &pair : map) {
|
||||
@ -301,7 +298,7 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
||||
xml.writeEndElement();
|
||||
} else {
|
||||
xml.writeStartElement("value");
|
||||
QString typeString = QStringLiteral("type");
|
||||
QString typeString = "type"_L1;
|
||||
switch (type) {
|
||||
case QMetaType::Short:
|
||||
case QMetaType::UShort:
|
||||
@ -399,37 +396,37 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
||||
}
|
||||
}
|
||||
|
||||
QString XmlConverter::name()
|
||||
QString XmlConverter::name() const
|
||||
{
|
||||
return QStringLiteral("xml");
|
||||
return "xml"_L1;
|
||||
}
|
||||
|
||||
Converter::Direction XmlConverter::directions()
|
||||
Converter::Directions XmlConverter::directions() const
|
||||
{
|
||||
return InOut;
|
||||
return Direction::InOut;
|
||||
}
|
||||
|
||||
Converter::Options XmlConverter::outputOptions()
|
||||
Converter::Options XmlConverter::outputOptions() const
|
||||
{
|
||||
return SupportsArbitraryMapKeys;
|
||||
}
|
||||
|
||||
const char *XmlConverter::optionsHelp()
|
||||
const char *XmlConverter::optionsHelp() const
|
||||
{
|
||||
return xmlOptionHelp;
|
||||
}
|
||||
|
||||
bool XmlConverter::probeFile(QIODevice *f)
|
||||
bool XmlConverter::probeFile(QIODevice *f) const
|
||||
{
|
||||
if (QFile *file = qobject_cast<QFile *>(f)) {
|
||||
if (file->fileName().endsWith(QLatin1String(".xml")))
|
||||
if (file->fileName().endsWith(".xml"_L1))
|
||||
return true;
|
||||
}
|
||||
|
||||
return f->isReadable() && f->peek(5) == "<?xml";
|
||||
}
|
||||
|
||||
QVariant XmlConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
QVariant XmlConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||
{
|
||||
if (!outputConverter)
|
||||
outputConverter = this;
|
||||
@ -445,13 +442,14 @@ QVariant XmlConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
||||
return v;
|
||||
}
|
||||
|
||||
void XmlConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
||||
void XmlConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const
|
||||
{
|
||||
bool compact = false;
|
||||
for (const QString &s : options) {
|
||||
if (s == QLatin1String("compact=no")) {
|
||||
if (s == "compact=no"_L1) {
|
||||
compact = false;
|
||||
} else if (s == QLatin1String("compact=yes")) {
|
||||
} else if (s == "compact=yes"_L1) {
|
||||
compact = true;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown option '%s' to XML output. Valid options are:\n%s",
|
||||
|
@ -10,13 +10,14 @@ class XmlConverter : public Converter
|
||||
{
|
||||
// Converter interface
|
||||
public:
|
||||
QString name() override;
|
||||
Direction directions() override;
|
||||
Options outputOptions() override;
|
||||
const char *optionsHelp() override;
|
||||
bool probeFile(QIODevice *f) override;
|
||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
||||
QString name() const override;
|
||||
Directions directions() const override;
|
||||
Options outputOptions() const override;
|
||||
const char *optionsHelp() const override;
|
||||
bool probeFile(QIODevice *f) const override;
|
||||
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||
void saveFile(QIODevice *f, const QVariant &contents,
|
||||
const QStringList &options) const override;
|
||||
};
|
||||
|
||||
#endif // XMLCONVERTER_H
|
||||
|
Reference in New Issue
Block a user