Commit 0d309fc8 authored by Jochen Becher's avatar Jochen Becher

ModelEditor: Introduce newest version of qtserialization framework

This change unfortunately contains many single changes because it is an
update of the 3rd party component:

* Introduce new Parameter class for better serialization of containers
and other future enhancements
* Delete dead code
* Introduce user data in base archive class
* Fix minor source code issues and typos in comments
* Remove unused and conceptionally broken support of forward refernces
* Fix a memory leak in QXmlInArchive
* prefer load()/save() methods over stream operators
* throw exception on unsuported forward references in QXmlOutArchive
* refactor serialization of pointer types into own header
* remove unneeded specialisation for serialization of free functions
* check for default value of serialization using a getter

Change-Id: Ic197a92b00b22b85dab4a1b88c431cf4da8b3c3b
Reviewed-by: default avatarTobias Hunger <tobias.hunger@theqtcompany.com>
parent f4628dcc
......@@ -55,12 +55,24 @@ void save(Archive &archive, const T &t)
Access<Archive, T>::save(archive, t);
}
template<class Archive, class T>
void save(Archive &archive, const T &t, const Parameters &)
{
save(archive, t);
}
template<class Archive, class T>
void load(Archive &archive, T &t)
{
Access<Archive, T>::load(archive, t);
}
template<class Archive, class T>
void load(Archive &archive, T &t, const Parameters &)
{
load(archive, t);
}
template<class Archive, class T>
void serialize(Archive &archive, T &t)
{
......@@ -92,30 +104,9 @@ void serialize_helper(Archive &archive, T &t)
static inline void serialize(Archive &archive, TYPE &); \
};
#if 0
#define QARK_ACCESS_SPECIALIZE_LOAD_SAVE(INARCHIVE, OUTARCHIVE, TYPE) \
template<> class Access<INARCHIVE, TYPE> { public: static inline void load(INARCHIVE &archive, TYPE &); void serialize(INARCHIVE &, TYPE &); }; \
template<> class Access<OUTARCHIVE, TYPE> { public: static inline void save(OUTARCHIVE &archive, const TYPE &); void serialize(OUTARCHIVE &, TYPE &); }; \
void Access<INARCHIVE, TYPE>::serialize(INARCHIVE &, TYPE &) { } \
void Access<OUTARCHIVE, TYPE>::serialize(OUTARCHIVE &, TYPE &) { } \
template class Access<INARCHIVE, TYPE>; \
template class Access<OUTARCHIVE, TYPE>;
#endif
#define QARK_ACCESS_SPECIALIZE(INARCHIVE, OUTARCHIVE, TYPE) \
template class Access<INARCHIVE, TYPE>; \
template class Access<OUTARCHIVE, TYPE>;
#if 0
#define QARK_SPECIALIZE_SERIALIZE(INARCHIVE, OUTARCHIVE, TYPE) \
QARK_ACCESS_SPECIALIZE(INARCHIVE, OUTARCHIVE, TYPE); \
template void serialize<INARCHIVE, TYPE>(INARCHIVE &, TYPE &); \
template void serialize<OUTARCHIVE, TYPE>(OUTARCHIVE &, TYPE &);
#define QARK_SPECIALIZE_LOAD_SAVE(INARCHIVE, OUTARCHIVE, TYPE) \
template void load<INARCHIVE, TYPE>(INARCHIVE &, TYPE &); \
template void save<OUTARCHIVE, TYPE>(OUTARCHIVE &, const TYPE &);
#endif
#endif // QARK_ACCESS_H
......@@ -33,6 +33,10 @@
#include "flag.h"
#include <QVariant>
#include <QString>
#include <QHash>
namespace qark {
class ArchiveBasics
......@@ -48,8 +52,40 @@ public:
bool takeFlag(const Flag &flag) { bool f = (_flags & flag.getMask()) != 0; _flags &= ~flag.getMask(); return f; }
bool hasUserData(const QString &key)
{
return _user_data.contains(key);
}
template<typename T>
T getUserData(const QString &key)
{
return _user_data.value(key).value<T>();
}
template<typename T>
T getUserData(const QString &key, const T &default_value)
{
// gcc 4.8.2 fails to compile if the following 2 statements are written in one expression
//return _user_data.value(key, data).value<T>();
QVariant v = _user_data.value(key, default_value);
return v.value<T>();
}
template<class T>
void setUserData(const QString &key, const T &data)
{
_user_data.insert(key, data);
}
void removeUserData(const QString &key)
{
_user_data.remove(key);
}
private:
Flag::mask_type _flags;
QHash<QString, QVariant> _user_data;
};
}
......
......@@ -32,6 +32,7 @@
#define QARK_BASECLASS_H
#include "typeregistry.h"
#include "parameters.h"
#include <QString>
......@@ -41,21 +42,31 @@ namespace qark {
template<class BASE, class DERIVED>
class Base {
public:
explicit Base(const QString &qualified_name, DERIVED &obj)
Base(const QString &qualified_name, DERIVED &obj)
: _qualified_name(qualified_name),
_base(obj)
{
}
Base(const QString &qualified_name, DERIVED &obj, const Parameters &parameters)
: _qualified_name(qualified_name),
_base(obj),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; }
const BASE &getBase() const { return _base; }
BASE &getBase() { return _base; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
BASE &_base;
Parameters _parameters;
};
template<class BASE, class DERIVED>
......@@ -64,18 +75,36 @@ Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED &obj)
return Base<BASE, DERIVED>(qualified_name, obj);
}
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED &obj, const Parameters &parameters)
{
return Base<BASE, DERIVED>(qualified_name, obj, parameters);
}
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED *&obj)
{
return Base<BASE, DERIVED>(qualified_name, *obj);
}
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED *&obj, const Parameters &parameters)
{
return Base<BASE, DERIVED>(qualified_name, *obj, parameters);
}
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(DERIVED &obj)
{
return Base<BASE, DERIVED>(QString(QStringLiteral("base-%1")).arg(get_type_uid<BASE>()), obj);
}
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(DERIVED &obj, const Parameters &parameters)
{
return Base<BASE, DERIVED>(QString(QStringLiteral("base-%1")).arg(get_type_uid<BASE>()), obj, parameters);
}
}
#endif // QARK_BASECLASS_H
......@@ -28,8 +28,8 @@
**
****************************************************************************/
#ifndef QMT_FRIEND_ACCESS_H
#define QMT_FRIEND_ACCESS_H
#ifndef QARK_FRIEND_ACCESS_H
#define QARK_FRIEND_ACCESS_H
#define QARK_FRIEND_ACCESS \
template<class Archive, class T> \
......
/***************************************************************************
**
** Copyright (C) 2015 Jochen Becher
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** 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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef QARK_PARAMETER_H
#define QARK_PARAMETER_H
#include "flag.h"
namespace qark {
class Parameters
{
public:
Parameters()
: _flags(0)
{
}
Parameters(const Flag &flag)
: _flags(flag.getMask())
{
}
public:
void setFlag(const Flag &flag) { _flags |= flag.getMask(); }
void clearFlag(const Flag &flag) { _flags &= ~flag.getMask(); }
bool hasFlag(const Flag &flag) const { return (_flags & flag.getMask()) != 0; }
bool takeFlag(const Flag &flag) { bool f = (_flags & flag.getMask()) != 0; _flags &= ~flag.getMask(); return f; }
private:
Flag::mask_type _flags;
};
}
#endif // QARK_PARAMETER_H
......@@ -49,8 +49,13 @@ class QXmlOutArchive :
{
public:
class UnsupportedForwardReference :
public std::exception
{
};
class DanglingReferences :
public std::exception
public std::exception
{
};
......@@ -58,6 +63,7 @@ public:
static const bool out_archive = true;
public:
QXmlOutArchive(QXmlStreamWriter &stream)
: _stream(stream),
_next_pointer_is_reference(false)
......@@ -76,6 +82,9 @@ public:
template<typename T>
void write(T *p)
{
if (!_saving_ref_map.hasDefinedRef(p)) {
throw UnsupportedForwardReference();
}
write(_saving_ref_map.getRef(p).get());
}
......
......@@ -38,6 +38,7 @@
#include "access.h"
#include "typeregistry.h"
#include "serialize_pointer.h"
#include "serialize_basic.h"
#include "serialize_container.h"
#include "serialize_enum.h"
......@@ -51,102 +52,27 @@ namespace qark {
template<class Archive, class T>
inline Archive &operator<<(Archive &archive, const T &t)
{
save(archive, t);
save(archive, t, Parameters());
return archive;
}
template<class Archive, class T>
inline Archive &operator>>(Archive &archive, T &t)
{
load(archive, t);
load(archive, t, Parameters());
return archive;
}
template<class Archive, class T>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, T &t)
{
save(archive, (const T &) t);
return archive;
return archive << t;
}
template<class Archive, class T>
typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, T &t)
{
load(archive, t);
return archive;
}
template<class Archive, class T>
inline Archive &operator<<(Archive &archive, T *p)
{
if (p) {
if (archive.isReference(p)) {
archive.beginPointer();
archive.write(p);
archive.endPointer();
} else {
if (typeid(*p) == typeid(T)) {
archive.beginInstance();
registry::save_pointer<Archive, T, T>(archive, p);
archive.endInstance();
} else {
archive.beginInstance(get_type_uid(*p));
//typename registry::TypeRegistry<Archive, typename qark::non_const<T>::type>::type_info type_data
// = get_type_info<Archive, typename qark::non_const<T>::type>(*p);
typename registry::TypeRegistry<Archive, T>::type_info type_data = get_type_info<Archive, T>(*p);
if (type_data.save_func == 0) {
throw unregistered_type();
} else {
type_data.save_func(archive, p);
}
archive.endInstance();
}
}
} else {
archive.beginNullPointer();
archive.endNullPointer();
}
return archive;
}
template<class Archive, class T>
inline Archive &operator>>(Archive &archive, T *&p)
{
typename Archive::ReferenceTag ref_tag = archive.readReferenceTag();
switch (ref_tag.kind) {
case Archive::NULLPOINTER:
p = 0;
break;
case Archive::POINTER:
archive.read(p);
break;
case Archive::INSTANCE:
if (ref_tag.type_name.isEmpty()) {
registry::load_non_virtual_pointer<Archive,T>(archive, p);
} else {
typename registry::TypeRegistry<Archive, T>::type_info type_data = get_type_info<Archive, T>(ref_tag.type_name);
if (type_data.load_func == 0) {
throw unregistered_type();
} else {
type_data.load_func(archive, p);
}
}
break;
}
archive.readReferenceEndTag(ref_tag.kind);
return archive;
}
template<class Archive, class T>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, T *&p)
{
return archive << p;
}
template<class Archive, class T>
typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, T *&p)
{
return archive >> p;
return archive >> t;
}
template<class Archive, class T>
......@@ -175,32 +101,6 @@ typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive
return archive >> f;
}
template<class Archive>
inline Archive &operator<<(Archive &archive, void (*f)(Archive &))
{
f(archive);
return archive;
}
template<class Archive>
inline Archive &operator>>(Archive &archive, void (*f)(Archive &))
{
f(archive);
return archive;
}
template<class Archive>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, void (*f)(Archive &))
{
return archive << f;
}
template<class Archive>
typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, void (*f)(Archive &))
{
return archive >> f;
}
template<class Archive>
inline Archive &operator<<(Archive &archive, const Tag &tag)
{
......@@ -311,7 +211,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Attr<T> &attr)
{
archive.beginAttribute(attr);
archive << *attr.getValue();
save(archive, *attr.getValue(), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
......@@ -336,10 +236,23 @@ typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive
}
template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetterAttr<U, T> &attr)
typename std::enable_if<!std::is_abstract<U>::value, Archive &>::type
operator<<(Archive &archive, const GetterAttr<U, T> &attr)
{
if (!((attr.getObject().*(attr.getGetter()))() == (U().*(attr.getGetter()))())) {
archive.beginAttribute(attr);
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
}
return archive;
}
template<class Archive, class U, typename T>
typename std::enable_if<std::is_abstract<U>::value, Archive &>::type
operator<<(Archive &archive, const GetterAttr<U, T> &attr)
{
archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))();
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
......@@ -358,7 +271,7 @@ operator<<(Archive &archive, const GetterSetterAttr<U, T, V> &attr)
{
if (!((attr.getObject().*(attr.getGetter()))() == (U().*(attr.getGetter()))())) {
archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))();
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
}
return archive;
......@@ -370,7 +283,7 @@ typename std::enable_if<std::is_abstract<U>::value, Archive &>::type
operator<<(Archive &archive, const GetterSetterAttr<U, T, V> &attr)
{
archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))();
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
......@@ -398,7 +311,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetFuncAttr<U, T> &attr)
{
archive.beginAttribute(attr);
archive << ((*attr.getGetFunc())(attr.getObject()));
save(archive, ((*attr.getGetFunc())(attr.getObject())), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
......@@ -414,7 +327,7 @@ template<class Archive, class U, typename T, typename V>
Archive &operator<<(Archive &archive, const GetSetFuncAttr<U, T, V> &attr)
{
archive.beginAttribute(attr);
archive << ((*attr.getGetFunc())(attr.getObject()));
save(archive, ((*attr.getGetFunc())(attr.getObject())), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
......@@ -442,7 +355,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Ref<T *> &ref)
{
archive.beginReference(ref);
archive << *ref.getValue();
save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref);
return archive;
}
......@@ -451,7 +364,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Ref<T * const> &ref)
{
archive.beginReference(ref);
archive << *ref.getValue();
save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref);
return archive;
}
......@@ -467,7 +380,7 @@ template<class Archive, typename T>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, const Ref<T *> &ref)
{
archive.beginReference(ref);
archive << *ref.getValue();
save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref);
return archive;
}
......@@ -482,7 +395,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetterRef<U, T> &ref)
{
archive.beginReference(ref);
archive << (ref.getObject().*(ref.getGetter()))();
save(archive, (ref.getObject().*(ref.getGetter()))(), ref.getParameters());
archive.endReference(ref);
return archive;
}
......@@ -498,7 +411,7 @@ template<class Archive, class U, typename T, typename V>
Archive &operator<<(Archive &archive, const GetterSetterRef<U, T, V> &ref)
{
archive.beginReference(ref);
archive << (ref.getObject().*(ref.getGetter()))();
save(archive, (ref.getObject().*(ref.getGetter()))(), ref.getParameters());
archive.endReference(ref);
return archive;
}
......@@ -526,7 +439,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetFuncRef<U, T> &ref)
{
archive.beginReference(ref);
archive << ref.getGetFunc()(ref.getObject());
save(archive, ref.getGetFunc()(ref.getObject()), ref.getParameters());
archive.endReference(ref);
return archive;
}
......@@ -542,7 +455,7 @@ template<class Archive, class U, typename T, typename V>
Archive &operator<<(Archive &archive, const GetSetFuncRef<U, T, V> &ref)
{
archive.beginReference(ref);
archive << ref.getGetFunc()(ref.getObject());
save(archive, ref.getGetFunc()(ref.getObject()), ref.getParameters());
archive.endReference(ref);
return archive;
}
......
......@@ -31,6 +31,7 @@
#ifndef QARK_SERIALIZE_BASIC_H
#define QARK_SERIALIZE_BASIC_H
#include "parameters.h"
#include "qstringparser/qstringparser.h"
#include <QString>
......@@ -42,12 +43,12 @@
#define QARK_BASIC_SAVELOAD(TYPE) \
template<class Archive> \
inline void save(Archive &archive, TYPE v) \
inline void save(Archive &archive, TYPE v, const Parameters &) \
{ \
archive.write(v); \
} \
template<class Archive> \
inline void load(Archive &archive, TYPE &v) \
inline void load(Archive &archive, TYPE &v, const Parameters &) \
{ \