2021-04-19 16:06:08 +02:00
|
|
|
/*
|
|
|
|
* SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
* MuseScore-CLA-applies
|
|
|
|
*
|
|
|
|
* MuseScore
|
|
|
|
* Music Composition & Notation
|
|
|
|
*
|
|
|
|
* Copyright (C) 2021 MuseScore BVBA and others
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2020-12-09 12:44:55 +01:00
|
|
|
|
2020-12-09 10:51:17 +01:00
|
|
|
#include "xmlreader.h"
|
|
|
|
|
|
|
|
#include <QXmlStreamReader>
|
|
|
|
#include <QFile>
|
|
|
|
|
|
|
|
using namespace mu::framework;
|
2021-06-16 18:35:39 +02:00
|
|
|
using namespace mu::io;
|
2020-12-09 10:51:17 +01:00
|
|
|
|
2020-12-23 10:26:43 +01:00
|
|
|
static XmlReader::TokenType convertTokenType(QXmlStreamReader::TokenType type)
|
|
|
|
{
|
2020-12-09 12:34:47 +01:00
|
|
|
switch (type) {
|
|
|
|
case QXmlStreamReader::TokenType::NoToken:
|
|
|
|
case QXmlStreamReader::TokenType::Invalid:
|
|
|
|
case QXmlStreamReader::TokenType::DTD:
|
|
|
|
case QXmlStreamReader::TokenType::EntityReference:
|
|
|
|
case QXmlStreamReader::TokenType::ProcessingInstruction:
|
|
|
|
return XmlReader::TokenType::Unknown;
|
|
|
|
case QXmlStreamReader::TokenType::StartDocument:
|
|
|
|
return XmlReader::TokenType::StartDocument;
|
|
|
|
case QXmlStreamReader::TokenType::EndDocument:
|
|
|
|
return XmlReader::TokenType::EndDocument;
|
|
|
|
case QXmlStreamReader::TokenType::StartElement:
|
|
|
|
return XmlReader::TokenType::StartElement;
|
|
|
|
case QXmlStreamReader::TokenType::EndElement:
|
|
|
|
return XmlReader::TokenType::EndElement;
|
|
|
|
case QXmlStreamReader::TokenType::Comment:
|
|
|
|
return XmlReader::TokenType::Comment;
|
|
|
|
case QXmlStreamReader::TokenType::Characters:
|
|
|
|
return XmlReader::TokenType::Characters;
|
|
|
|
}
|
|
|
|
|
|
|
|
return XmlReader::TokenType::Unknown;
|
|
|
|
}
|
|
|
|
|
2020-12-09 10:51:17 +01:00
|
|
|
XmlReader::XmlReader(const io::path& path)
|
|
|
|
{
|
|
|
|
m_device = std::make_unique<QFile>(path.toQString());
|
2021-06-16 18:35:39 +02:00
|
|
|
m_device->open(Device::ReadOnly);
|
2020-12-09 10:51:17 +01:00
|
|
|
|
|
|
|
m_reader = std::make_unique<QXmlStreamReader>(m_device.get());
|
|
|
|
}
|
|
|
|
|
2021-06-16 18:35:39 +02:00
|
|
|
XmlReader::XmlReader(Device* device)
|
2020-12-09 10:51:17 +01:00
|
|
|
{
|
|
|
|
m_reader = std::make_unique<QXmlStreamReader>(device);
|
|
|
|
}
|
|
|
|
|
|
|
|
XmlReader::XmlReader(const QByteArray& bytes)
|
|
|
|
{
|
|
|
|
m_reader = std::make_unique<QXmlStreamReader>(bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
XmlReader::~XmlReader()
|
|
|
|
{
|
2020-12-09 12:44:55 +01:00
|
|
|
if (m_device) {
|
|
|
|
m_device->close();
|
|
|
|
}
|
2020-12-09 10:51:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool XmlReader::readNextStartElement()
|
|
|
|
{
|
|
|
|
return m_reader->readNextStartElement();
|
|
|
|
}
|
|
|
|
|
2020-12-09 12:34:47 +01:00
|
|
|
XmlReader::TokenType XmlReader::readNext()
|
|
|
|
{
|
|
|
|
return convertTokenType(m_reader->readNext());
|
|
|
|
}
|
|
|
|
|
|
|
|
XmlReader::TokenType XmlReader::tokenType() const
|
|
|
|
{
|
|
|
|
return convertTokenType(m_reader->tokenType());
|
|
|
|
}
|
|
|
|
|
2020-12-10 15:14:19 +01:00
|
|
|
bool XmlReader::canRead() const
|
2020-12-09 12:34:47 +01:00
|
|
|
{
|
2020-12-10 15:14:19 +01:00
|
|
|
return !m_reader->atEnd();
|
2020-12-09 12:34:47 +01:00
|
|
|
}
|
|
|
|
|
2020-12-09 10:51:17 +01:00
|
|
|
void XmlReader::skipCurrentElement()
|
|
|
|
{
|
|
|
|
m_reader->skipCurrentElement();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string XmlReader::tagName() const
|
|
|
|
{
|
|
|
|
return m_reader->name().toString().toStdString();
|
|
|
|
}
|
|
|
|
|
|
|
|
int XmlReader::intAttribute(std::string_view name, int defaultValue) const
|
|
|
|
{
|
|
|
|
if (hasAttribute(name)) {
|
|
|
|
return attributeValue(name).toInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
return defaultValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
double XmlReader::doubleAttribute(std::string_view name, double defaultValue) const
|
|
|
|
{
|
|
|
|
if (hasAttribute(name)) {
|
|
|
|
return attributeValue(name).toDouble();
|
|
|
|
}
|
|
|
|
|
|
|
|
return defaultValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string XmlReader::attribute(std::string_view name) const
|
|
|
|
{
|
|
|
|
return attributeValue(name).toString().toStdString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringRef XmlReader::attributeValue(std::string_view name) const
|
|
|
|
{
|
|
|
|
return m_reader->attributes().value(name.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool XmlReader::hasAttribute(std::string_view name) const
|
|
|
|
{
|
|
|
|
return m_reader->attributes().hasAttribute(name.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
int XmlReader::readInt()
|
|
|
|
{
|
|
|
|
return readElementText().toInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
double XmlReader::readDouble()
|
|
|
|
{
|
|
|
|
return readElementText().toDouble();
|
|
|
|
}
|
|
|
|
|
2020-12-10 15:14:19 +01:00
|
|
|
std::string XmlReader::readString(ReadStringBehavior behavior)
|
2020-12-09 10:51:17 +01:00
|
|
|
{
|
2020-12-10 15:14:19 +01:00
|
|
|
return readElementText(behavior).toStdString();
|
2020-12-09 10:51:17 +01:00
|
|
|
}
|
|
|
|
|
2020-12-10 15:14:19 +01:00
|
|
|
QString XmlReader::readElementText(ReadStringBehavior behavior)
|
2020-12-09 10:51:17 +01:00
|
|
|
{
|
2020-12-12 12:49:00 +01:00
|
|
|
auto _behavior = QXmlStreamReader::ReadElementTextBehaviour::ErrorOnUnexpectedElement;
|
2020-12-10 10:37:47 +01:00
|
|
|
|
2020-12-10 15:14:19 +01:00
|
|
|
switch (behavior) {
|
2020-12-10 10:37:47 +01:00
|
|
|
case ErrorOnUnexpectedElement:
|
2020-12-12 12:49:00 +01:00
|
|
|
_behavior = QXmlStreamReader::ErrorOnUnexpectedElement;
|
2020-12-10 10:37:47 +01:00
|
|
|
break;
|
|
|
|
case IncludeChildElements:
|
2020-12-12 12:49:00 +01:00
|
|
|
_behavior = QXmlStreamReader::IncludeChildElements;
|
2020-12-10 10:37:47 +01:00
|
|
|
break;
|
|
|
|
case SkipChildElements:
|
2020-12-12 12:49:00 +01:00
|
|
|
_behavior = QXmlStreamReader::SkipChildElements;
|
2020-12-10 10:37:47 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-12-12 12:49:00 +01:00
|
|
|
return m_reader->readElementText(_behavior);
|
2020-12-09 10:51:17 +01:00
|
|
|
}
|
2020-12-10 13:11:01 +01:00
|
|
|
|
2020-12-22 09:43:37 +01:00
|
|
|
bool XmlReader::success() const
|
2020-12-10 13:11:01 +01:00
|
|
|
{
|
2020-12-22 09:43:37 +01:00
|
|
|
return !m_reader->hasError();
|
2020-12-10 13:11:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string XmlReader::error() const
|
|
|
|
{
|
|
|
|
return m_reader->errorString().toStdString();
|
|
|
|
}
|