-
Mikhail Svechnikov authoredMikhail Svechnikov authored
Streamer.h 3.45 KiB
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/Support/XML/Streamer.h
//! @brief Defines class Streamer
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2021
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#ifndef BORNAGAIN_GUI_SUPPORT_XML_STREAMER_H
#define BORNAGAIN_GUI_SUPPORT_XML_STREAMER_H
#include "Base/Util/Assert.h"
#include <QXmlStreamWriter> // used in every including file
#include <functional>
#include <heinz/Vectors3D.h>
namespace StreamerXML {
namespace Tags {
constexpr auto Id("id");
constexpr auto Value("value");
constexpr auto Decimals("decimals");
constexpr auto Version("version");
} // namespace Tags
} // namespace XML
//! Supports serialization to or deserialization from QXmlStream.
//!
//! Can be either a writer or a reader, depending on the constructor.
class Streamer {
public:
Streamer(QXmlStreamWriter* w)
: m_w(w)
{
}
Streamer(QXmlStreamReader* r)
: m_r(r)
{
}
QXmlStreamWriter* xmlWriter() { return m_w; } //!< Returns stream writer or nullptr.
QXmlStreamReader* xmlReader() { return m_r; } //!< Returns stream reader or nullptr.
//! As writer, serializes the given version number. As reader, does nothing.
void writeVersion(unsigned version) const;
//! As reader, throws DeserializationException unless the expected version is read.
//! As writer, does nothing.
void assertVersion(unsigned expectedVersion) const;
template <typename Catalog>
void write(const QString& tag, typename Catalog::CatalogedType* p);
template <typename Catalog, typename... Args>
void read(const QString& tag, typename Catalog::CatalogedType*& p, Args... argsForConstructor);
void gotoStartElementOfTag(const QString& tag);
void gotoEndElementOfTag(const QString& tag);
void assertCurrentTag(const QString& expectedTag) const;
void start(const QString& tag);
void finish(const QString& tag);
private:
void assertCurrentToken(QXmlStreamReader::TokenType token) const;
QXmlStreamWriter* m_w = nullptr;
QXmlStreamReader* m_r = nullptr;
};
// ************************************************************************************************
// Templates implementation
// ************************************************************************************************
template <typename Catalog>
void Streamer::write(const QString& tag, typename Catalog::CatalogedType* p)
{
ASSERT(m_w);
m_w->writeStartElement(tag);
m_w->writeAttribute("type", QString::number(static_cast<uint8_t>(Catalog::type(p))));
if (p != nullptr)
p->serialize(*this);
m_w->writeEndElement();
}
template <typename Catalog, typename... Args>
void Streamer::read(const QString& tag, typename Catalog::CatalogedType*& p,
Args... argsForConstructor)
{
ASSERT(m_r);
gotoStartElementOfTag(tag);
const auto type = static_cast<typename Catalog::Type>(m_r->attributes().value("type").toUInt());
p = Catalog::create(type, argsForConstructor...);
if (p != nullptr)
p->serialize(*this);
gotoEndElementOfTag(tag);
}
#endif // BORNAGAIN_GUI_SUPPORT_XML_STREAMER_H