Browse Source

implemented xml parser

pull/2/head
Skycoder42 7 years ago
parent
commit
8963d0abc2
No known key found for this signature in database GPG Key ID: 8E01AD9EF0578D2B
  1. 51
      tools/settingsgenerator/main.cpp
  2. 4
      tools/settingsgenerator/qsettingsgenerator.xsd
  3. 214
      tools/settingsgenerator/settingsgenerator.cpp
  4. 102
      tools/settingsgenerator/settingsgenerator.h
  5. 6
      tools/settingsgenerator/settingsgenerator.pro

51
tools/settingsgenerator/main.cpp

@ -1,8 +1,57 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QCommandLineParser>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>
#include "settingsgenerator.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
QCoreApplication::setApplicationName(QStringLiteral(TARGET));
QCoreApplication::setApplicationVersion(QStringLiteral(VERSION));
QCoreApplication::setOrganizationName(QStringLiteral(COMPANY));
QCoreApplication::setOrganizationDomain(QStringLiteral(BUNDLE_PREFIX));
QCommandLineParser parser;
parser.setApplicationDescription(QStringLiteral("A tool to...")); //TODO description
parser.addVersionOption();
parser.addHelpOption();
parser.addOption({
{QStringLiteral("t"), QStringLiteral("translate")},
QStringLiteral("Translate the given settings file. The output will be"
"a dummy cpp file, writte to --impl.")
});
parser.addOption({
QStringLiteral("in"),
QStringLiteral("The input XML <file> containing the settings definition"),
QStringLiteral("file")
});
parser.addOption({
QStringLiteral("header"),
QStringLiteral("The <name> of the header file to generate"),
QStringLiteral("name")
});
parser.addOption({
QStringLiteral("impl"),
QStringLiteral("The <name> of the implementation file to generate"),
QStringLiteral("name")
});
parser.process(a);
return a.exec(); try {
SettingsGenerator generator {
parser.value(QStringLiteral("in")),
parser.value(QStringLiteral("header")),
parser.value(QStringLiteral("impl"))
};
generator.process();
return EXIT_SUCCESS;
} catch (const QString &str) {
qCritical() << qUtf8Printable(str);
return EXIT_FAILURE;
}
} }

4
tools/settingsgenerator/qsettingsgenerator.xsd

@ -14,7 +14,7 @@
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="xs:string"> <xs:extension base="xs:string">
<xs:attribute default="true" name="required" type="xs:boolean" use="optional"/> <xs:attribute default="true" name="required" type="xs:boolean" use="optional"/>
<xs:attribute name="rootnode" type="xs:string" use="optional"/> <xs:attribute name="rootNode" type="xs:string" use="optional"/>
</xs:extension> </xs:extension>
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
@ -62,7 +62,7 @@
<xs:attribute name="qmlGroupKey" type="xs:string" use="optional"/> <xs:attribute name="qmlGroupKey" type="xs:string" use="optional"/>
<xs:attribute name="default" type="xs:string" use="optional"/> <xs:attribute name="default" type="xs:string" use="optional"/>
<xs:attribute default="false" name="tr" type="xs:boolean" use="optional"/> <xs:attribute default="false" name="tr" type="xs:boolean" use="optional"/>
<xs:attribute name="trcontext" type="xs:string" use="optional"/> <xs:attribute name="trContext" type="xs:string" use="optional"/>
</xs:extension> </xs:extension>
</xs:complexContent> </xs:complexContent>
</xs:complexType> </xs:complexType>

214
tools/settingsgenerator/settingsgenerator.cpp

@ -0,0 +1,214 @@
#include "settingsgenerator.h"
#include <QDebug>
SettingsGenerator::SettingsGenerator(const QString &inPath, const QString &hdrPath, const QString &srcPath) :
_inFile{inPath},
_hdrFile{hdrPath},
_srcFile{srcPath},
_xml{&_inFile},
_hdr{&_hdrFile},
_src{&_srcFile}
{}
void SettingsGenerator::process()
{
if(!_inFile.open(QIODevice::ReadOnly | QIODevice::Text))
throwFile(_inFile);
if(!_hdrFile.open(QIODevice::WriteOnly | QIODevice::Text))
throwFile(_hdrFile);
if(!_srcFile.open(QIODevice::WriteOnly | QIODevice::Text))
throwFile(_srcFile);
readData();
}
void SettingsGenerator::readData()
{
if(!_xml.readNextStartElement())
throwReader();
if(_xml.name() != QStringLiteral("Settings"))
throwChild();
_data = readSettings();
checkError();
qDebug() << "Completed parsing xml - it is valid";
}
SettingsGenerator::Include SettingsGenerator::readInclude()
{
Include include;
include.local = readAttrib<bool>(QStringLiteral("local"), false);
include.include = _xml.readElementText();
checkError();
return include;
}
SettingsGenerator::Param SettingsGenerator::readParam()
{
Param param;
param.key = readAttrib(QStringLiteral("key"), {}, true);
param.type = readAttrib(QStringLiteral("type"), {}, true);
param.asStr = readAttrib<bool>(QStringLiteral("asStr"), false);
param.value = _xml.readElementText();
checkError();
return param;
}
QSharedPointer<SettingsGenerator::Backend> SettingsGenerator::readBackend()
{
auto backend = QSharedPointer<Backend>::create();
backend->className = readAttrib(QStringLiteral("class"), {}, true);
while(_xml.readNextStartElement()) {
if(_xml.name() == QStringLiteral("Param"))
backend->params.append(readParam());
else
throwChild();
}
checkError();
return backend;
}
QPair<QString, QString> SettingsGenerator::readTypeMapping()
{
QPair<QString, QString> mapping;
mapping.first = readAttrib(QStringLiteral("key"), {}, true);
mapping.second = readAttrib(QStringLiteral("type"), {}, true);
checkError();
return mapping;
}
SettingsGenerator::Node SettingsGenerator::readNode()
{
Node node;
node.key = readAttrib(QStringLiteral("key"), {}, true);
while(_xml.readNextStartElement()) {
if(_xml.name() == QStringLiteral("Node"))
node.subNodes.append(readNode());
else if(_xml.name() == QStringLiteral("Entry"))
node.subEntries.append(readEntry());
else if(_xml.name() == QStringLiteral("Import"))
node.subImports.append(readImport());
else
throwChild();
}
checkError();
return node;
}
SettingsGenerator::Entry SettingsGenerator::readEntry()
{
Entry entry;
entry.key = readAttrib(QStringLiteral("key"), {}, true);
entry.type = readAttrib(QStringLiteral("type"), {}, true);
entry.qmlGroupKey = readAttrib(QStringLiteral("qmlGroupKey"));
entry.defaultValue = readAttrib(QStringLiteral("default"));
entry.tr = readAttrib<bool>(QStringLiteral("tr"), false);
entry.trContext = readAttrib(QStringLiteral("trContext"));
while(_xml.readNextStartElement()) {
if(_xml.name() == QStringLiteral("Code")) {
if(!entry.defaultValue.isNull())
throwChild();
entry.defaultValue = _xml.readElementText();
entry.defaultIsCode = true;
checkError();
} else if(_xml.name() == QStringLiteral("Node"))
entry.subNodes.append(readNode());
else if(_xml.name() == QStringLiteral("Entry"))
entry.subEntries.append(readEntry());
else if(_xml.name() == QStringLiteral("Import"))
entry.subImports.append(readImport());
else
throwChild();
}
checkError();
return entry;
}
SettingsGenerator::Import SettingsGenerator::readImport()
{
Import import;
import.required = readAttrib<bool>(QStringLiteral("required"), true);
import.rootNode = readAttrib(QStringLiteral("rootNode"));
import.import = _xml.readElementText();
checkError();
return import;
}
SettingsGenerator::Settings SettingsGenerator::readSettings()
{
Settings settings;
settings.name = readAttrib(QStringLiteral("name"), {}, true);
settings.prefix = readAttrib(QStringLiteral("prefix"));
while(_xml.readNextStartElement()) {
if(_xml.name() == QStringLiteral("Include"))
settings.includes.append(readInclude());
else if(_xml.name() == QStringLiteral("Backend"))
settings.backend = readBackend();
else if(_xml.name() == QStringLiteral("TypeMapping")) {
auto mapping = readTypeMapping();
settings.typeMapping.insert(mapping.first, mapping.second);
} else if(_xml.name() == QStringLiteral("Node"))
settings.subNodes.append(readNode());
else if(_xml.name() == QStringLiteral("Entry"))
settings.subEntries.append(readEntry());
else if(_xml.name() == QStringLiteral("Import"))
settings.subImports.append(readImport());
else
throwChild();
}
checkError();
return settings;
}
void SettingsGenerator::checkError() const
{
if(_xml.hasError())
throwReader();
}
template<typename T>
T SettingsGenerator::readAttrib(const QString &key, const T &defaultValue, bool required) const
{
if(_xml.attributes().hasAttribute(key))
return QVariant(_xml.attributes().value(key).toString()).template value<T>();
else if(required)
throwReader(QStringLiteral("Required attribute \"%1\" but was not set").arg(key));
else
return defaultValue;
}
template<>
bool SettingsGenerator::readAttrib<bool>(const QString &key, const bool &defaultValue, bool required) const
{
if(_xml.attributes().hasAttribute(key)) {
if(_xml.attributes().value(key) == QStringLiteral("true"))
return true;
else if(_xml.attributes().value(key) == QStringLiteral("false"))
return false;
else
throwReader(QStringLiteral("Value of attribute \"%1\" is not a xs:boolean!").arg(key));
} else if(required)
throwReader(QStringLiteral("Required attribute \"%1\" but was not set").arg(key));
else
return defaultValue;
}
void SettingsGenerator::throwFile(const QFileDevice &file) const
{
throw QStringLiteral("%1: %2").arg(file.fileName(), file.errorString());
}
void SettingsGenerator::throwReader(const QString &overwriteError) const
{
throw QStringLiteral("%1:%2:%3: %4")
.arg(dynamic_cast<QFileDevice*>(_xml.device())->fileName())
.arg(_xml.lineNumber())
.arg(_xml.columnNumber())
.arg(overwriteError.isNull() ? _xml.errorString() : overwriteError);
}
void SettingsGenerator::throwChild()
{
throwReader(QStringLiteral("Unexpected child element: %1").arg(_xml.name()));
}

102
tools/settingsgenerator/settingsgenerator.h

@ -0,0 +1,102 @@
#ifndef SETTINGSGENERATOR_H
#define SETTINGSGENERATOR_H
#include <QFile>
#include <QXmlStreamReader>
#include <QTextStream>
#include <QSharedPointer>
class SettingsGenerator
{
public:
SettingsGenerator(const QString &inPath,
const QString &hdrPath,
const QString &srcPath);
void process();
private:
QFile _inFile;
QFile _hdrFile;
QFile _srcFile;
QXmlStreamReader _xml;
QTextStream _hdr;
QTextStream _src;
struct Include{
bool local;
QString include;
};
struct Param {
QString key;
QString type;
bool asStr;
QString value;
};
struct Backend {
QString className;
QList<Param> params;
};
struct Entry;
struct Import;
struct Node {
QString key;
QList<Node> subNodes;
QList<Entry> subEntries;
QList<Import> subImports;
};
struct Entry : public Node {
QString type;
QString qmlGroupKey;
QString defaultValue;
bool defaultIsCode = false;
bool tr;
QString trContext;
};
struct Import {
bool required;
QString rootNode;
QString import;
};
struct Settings : public Node {
QString name;
QString prefix;
QList<Include> includes;
QSharedPointer<Backend> backend;
QHash<QString, QString> typeMapping;
} _data;
void readData();
Include readInclude();
Param readParam();
QSharedPointer<Backend> readBackend();
QPair<QString, QString> readTypeMapping();
Node readNode();
Entry readEntry();
Import readImport();
Settings readSettings();
template <typename T = QString>
T readAttrib(const QString &key, const T &defaultValue = {}, bool required = false) const;
void checkError() const;
Q_NORETURN void throwFile(const QFileDevice &file) const;
Q_NORETURN void throwReader(const QString &overwriteError = {}) const;
Q_NORETURN void throwChild();
};
template<>
bool SettingsGenerator::readAttrib<bool>(const QString &key, const bool &defaultValue, bool required) const;
#endif // SETTINGSGENERATOR_H

6
tools/settingsgenerator/settingsgenerator.pro

@ -13,10 +13,12 @@ DEFINES += "VERSION=\\\"$$VERSION\\\""
DEFINES += "COMPANY=\\\"$$COMPANY\\\"" DEFINES += "COMPANY=\\\"$$COMPANY\\\""
DEFINES += "BUNDLE_PREFIX=\\\"$$BUNDLE_PREFIX\\\"" DEFINES += "BUNDLE_PREFIX=\\\"$$BUNDLE_PREFIX\\\""
HEADERS += HEADERS += \
settingsgenerator.h
SOURCES += \ SOURCES += \
main.cpp main.cpp \
settingsgenerator.cpp
load(qt_tool) load(qt_tool)

Loading…
Cancel
Save