You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
384 lines
9.5 KiB
C++
384 lines
9.5 KiB
C++
#pragma once
|
|
|
|
#include <QHash>
|
|
#include <string>
|
|
#include <QVector>
|
|
|
|
#include "ZxDynamic.h"
|
|
#include "ZxXpf.h"
|
|
|
|
class ZxXpfNode;
|
|
class ZxXpfDoc;
|
|
|
|
// 序列化器
|
|
class I_BASE_EXPORT ZxSerializer
|
|
{
|
|
public:
|
|
enum Flags
|
|
{
|
|
flagTemplate = 0x01, // 模版
|
|
_reserve_1 = 0x02,
|
|
_reserve_2 = 0x04,
|
|
_reserve_3 = 0x08
|
|
};
|
|
|
|
ZxSerializer(ZxXpfDoc* p, bool write);
|
|
|
|
// 把对象加载序列化器中, 并返回对象的id
|
|
unsigned int addObject(IxDynObj* p);
|
|
|
|
// 获取对象的id.
|
|
// 如果对象未被序列化, 则id是不确定的, 此函数将返回0
|
|
unsigned int getObjectId(IxDynObj* p);
|
|
unsigned int getObjectIndex(IxDynObj* p);
|
|
|
|
// 获取对象指针
|
|
IxDynObj* getObjectById(unsigned int id);
|
|
IxDynObj* getObjectByIndex(unsigned int index);
|
|
|
|
// 保存整棵树
|
|
void save(const IxDynObj* root);
|
|
|
|
// 返回整棵树
|
|
IxDynObj* load();
|
|
|
|
// 获取当前Xpf节点指针
|
|
ZxXpfNode* getXpfNode();
|
|
|
|
// 获取当前Xpf节点指针
|
|
ZxXpfNode* node();
|
|
|
|
// 节点指针压栈进入指定子节点
|
|
ZxXpfNode* push(const QString& sName);
|
|
|
|
// 节点指针压栈进入指定节点
|
|
ZxXpfNode* push(ZxXpfNode* pChildNode);
|
|
|
|
// 节点指针压栈进入匿名节点
|
|
ZxXpfNode* push();
|
|
|
|
// 节点指针弹栈退出到父节点
|
|
ZxXpfNode* pop();
|
|
|
|
// 保存Variant的数据
|
|
void setAttribute(const QString& key, const QVariant& v);
|
|
|
|
// 以Variant的方式读取指定数据
|
|
const QVariant& getAttribute(const QString& key);
|
|
|
|
// 保存对象指针
|
|
template <typename T>
|
|
void write(QString key, T* p)
|
|
{
|
|
Q_ASSERT_X(p==0 || dynamic_cast<IxDynObj*>(p) != 0, __FUNCTION__, "Pointer is not IxDynObj type. ");
|
|
Q_ASSERT(m_bWrite);
|
|
unsigned int id = addObject(p);
|
|
setAttribute(key, id);
|
|
}
|
|
|
|
// 读取对象指针
|
|
template <typename T>
|
|
void read(QString key, T*& p)
|
|
{
|
|
Q_ASSERT(!m_bWrite);
|
|
unsigned int id = getAttribute(key).toUInt();
|
|
delete p;
|
|
p = dynamic_cast<T*>(getObjectById(id));
|
|
Q_ASSERT_X(p==0 || dynamic_cast<IxDynObj*>(p) != 0, __FUNCTION__, "Pointer is not IxDynObj type. ");
|
|
}
|
|
|
|
// 保存普通变量
|
|
// @note 枚举变量请用 write<int>()
|
|
template <typename T>
|
|
void write(QString key, const T& v)
|
|
{
|
|
Q_ASSERT(m_bWrite);
|
|
setAttribute(key, QVariant::fromValue(v));
|
|
}
|
|
|
|
// 读取普通变量
|
|
// @note 枚举变量请用 read<int>()
|
|
template <typename T>
|
|
void read(QString key, T& v)
|
|
{
|
|
Q_ASSERT(!m_bWrite);
|
|
const QVariant& v0 = getAttribute(key);
|
|
|
|
if (v0.isValid()) //added 20171129 zx
|
|
v = v0.value<T>();
|
|
}
|
|
|
|
// 把T1类型的变量转换为T0类型保存
|
|
// @code
|
|
// ser->write<int>(m_lineStyle)
|
|
// @endcode
|
|
template <typename T0, typename T1>
|
|
void write(QString key, const T1& v)
|
|
{
|
|
Q_ASSERT(m_bWrite);
|
|
setAttribute(key, QVariant::fromValue((T0)v));
|
|
}
|
|
|
|
// 把变量作为T0类型读取, 再转换为T1返回
|
|
// @code
|
|
// ser->read<int>(m_lineStyle)
|
|
// @endcode
|
|
template <typename T0, typename T1>
|
|
void read(QString key, T1& v)
|
|
{
|
|
Q_ASSERT(!m_bWrite);
|
|
const QVariant& v0 = getAttribute(key);
|
|
v = (T1)v0.value<T0>();
|
|
}
|
|
|
|
// 以二进制块(QByteArray)方式保存数组
|
|
template <typename T>
|
|
void writeBin(QString key, const QVector<T>& vec)
|
|
{
|
|
QByteArray buf((const char*)vec.data(), vec.size()* sizeof(T));
|
|
write(key, buf);
|
|
}
|
|
|
|
// 以二进制块(QByteArray)方式读取数组
|
|
template <typename T>
|
|
void readBin(QString key, QVector<T>& vec)
|
|
{
|
|
QByteArray buf;
|
|
read(key, buf);
|
|
Q_ASSERT(buf.size() % sizeof(T) == 0);
|
|
vec.resize(buf.size() / sizeof(T));
|
|
memcpy(vec.data(), buf.data(), buf.size());
|
|
}
|
|
|
|
// 以二进制块(QByteArray)方式保存列表
|
|
template <typename T>
|
|
void writeBin(QString key, const QList<T>& list)
|
|
{
|
|
const int count = list.size();
|
|
const int bytes = count* sizeof(T);
|
|
QByteArray buf;
|
|
buf.resize(bytes);
|
|
T* p = (T*) buf.data();
|
|
|
|
for (auto it = list.begin(); it != list.end(); ++it, ++p)
|
|
{
|
|
*p = *it;
|
|
}
|
|
write(key, buf);
|
|
}
|
|
|
|
// 以二进制块(QByteArray)方式读取列表
|
|
template <typename T>
|
|
void readBin(QString key, QList<T>& list)
|
|
{
|
|
QByteArray buf;
|
|
read(key, buf);
|
|
Q_ASSERT(buf.size() % sizeof(T) == 0);
|
|
list.clear();
|
|
const T* p0 = (const T*) buf.data();
|
|
auto p1 = p0 + buf.size() / sizeof(T);
|
|
for (auto p = p0; p < p1; p++)
|
|
{
|
|
list.append(*p);
|
|
}
|
|
}
|
|
|
|
// 保存对象指针数组
|
|
template <typename T>
|
|
void write(QString key, const QVector<T*>& vec)
|
|
{
|
|
Q_ASSERT(m_bWrite);
|
|
if (!vec.isEmpty())
|
|
{
|
|
push(key);
|
|
int n = vec.count();
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
unsigned int id = addObject(vec[i]);
|
|
m_pNode->addUnnamedChild(id);
|
|
}
|
|
pop();
|
|
}
|
|
}
|
|
|
|
// 读取对象指针数组
|
|
template <typename T>
|
|
void read(QString key, QVector<T*>& vec)
|
|
{
|
|
Q_ASSERT(!m_bWrite);
|
|
vec.clear();
|
|
ZxXpfNode* node = m_pNode->findChild(key, false);
|
|
if (node)
|
|
{
|
|
const QVector<ZxXpfNode *>& nodes = node->getChildren();
|
|
int n = nodes.count();
|
|
vec.reserve(n);
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
ZxXpfNode* node1 = nodes[i];
|
|
int id = node1->getData().toUInt();
|
|
T* p = dynamic_cast<T*>(getObjectById(id));
|
|
vec.push_back(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 保存对象指针列表
|
|
template <typename T>
|
|
void write(QString key, const QList<T*>& vec)
|
|
{
|
|
Q_ASSERT(m_bWrite);
|
|
if (!vec.isEmpty())
|
|
{
|
|
push(key);
|
|
int n = vec.count();
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
unsigned int id = addObject(vec[i]);
|
|
m_pNode->addUnnamedChild(id);
|
|
}
|
|
pop();
|
|
}
|
|
}
|
|
|
|
// 读取对象指针列表
|
|
template <typename T>
|
|
void read(QString key, QList<T*>& vec)
|
|
{
|
|
Q_ASSERT(!m_bWrite);
|
|
vec.clear();
|
|
ZxXpfNode* node = m_pNode->findChild(key, false);
|
|
if (node)
|
|
{
|
|
const QVector<ZxXpfNode *>& nodes = node->getChildren();
|
|
int n = nodes.count();
|
|
vec.reserve(n);
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
ZxXpfNode* node1 = nodes[i];
|
|
unsigned int id = node1->getData().toUInt();
|
|
T* p = dynamic_cast<T*>(getObjectById(id));
|
|
vec.push_back(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 保存普通非动态对象数组(例如QVector<QString>)
|
|
template <typename T>
|
|
void write(QString key, const QVector<T>& vec)
|
|
{
|
|
Q_ASSERT(m_bWrite);
|
|
if (!vec.isEmpty())
|
|
{
|
|
push(key);
|
|
int n = vec.count();
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
ZxXpfNode* p = new ZxXpfNode();
|
|
p->setData(vec[i]);
|
|
m_pNode->addChild(p);
|
|
}
|
|
pop();
|
|
}
|
|
}
|
|
|
|
// 读取普通非动态对象数组(例如QVector<QString>)
|
|
template <typename T>
|
|
void read(QString key, QVector<T>& vec)
|
|
{
|
|
Q_ASSERT(!m_bWrite);
|
|
vec.clear();
|
|
ZxXpfNode* node = m_pNode->findChild(key, false);
|
|
if (node)
|
|
{
|
|
const QVector<ZxXpfNode *>& nodes = node->getChildren();
|
|
int n = nodes.count();
|
|
vec.reserve(n);
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
ZxXpfNode* node1 = nodes[i];
|
|
vec.push_back( node1->getData().value<T>() );
|
|
}
|
|
}
|
|
}
|
|
|
|
// 保存普通非动态对象列表(例如QList<QString>)
|
|
template <typename T>
|
|
void write(QString key, const QList<T>& vec)
|
|
{
|
|
Q_ASSERT(m_bWrite);
|
|
if (!vec.isEmpty())
|
|
{
|
|
push(key);
|
|
int n = vec.count();
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
ZxXpfNode* p = new ZxXpfNode();
|
|
p->setData(vec[i]);
|
|
m_pNode->addChild(p);
|
|
}
|
|
pop();
|
|
}
|
|
}
|
|
|
|
// 读取普通非动态对象列表(例如QList<QString>)
|
|
template <typename T>
|
|
void read(QString key, QList<T>& vec)
|
|
{
|
|
Q_ASSERT(!m_bWrite);
|
|
vec.clear();
|
|
ZxXpfNode* node = m_pNode->findChild(key, false);
|
|
if (node)
|
|
{
|
|
const QVector<ZxXpfNode *>& nodes = node->getChildren();
|
|
int n = nodes.count();
|
|
for (int i=0; i<n; i++)
|
|
{
|
|
ZxXpfNode* node1 = nodes[i];
|
|
vec.push_back( node1->getData().value<T>() );
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------
|
|
|
|
// 是否模版模式
|
|
bool isTemplate() const;
|
|
|
|
// 设置模版模式
|
|
void setTemplate(bool b);
|
|
|
|
// Xpf格式版本号
|
|
quint32 getXpfVer() const;
|
|
|
|
// 文档类型
|
|
QString getDocType() const;
|
|
void setDocType(const QString& sDocType);
|
|
|
|
// 文档标识
|
|
quint32 getDocFlags() const;
|
|
void setDocFlags(quint32 flags, bool bSet);
|
|
|
|
// 应用层的文件版本号
|
|
quint32 getDocVer() const;
|
|
void setDocVer(quint32 nVersion);
|
|
|
|
// 8位数日期
|
|
quint32 getDocDate() const;
|
|
void setDocDate(quint32 nDate);
|
|
|
|
unsigned int objectIndexToId(unsigned int index) const;
|
|
unsigned int objectIdToIndex(unsigned int id) const;
|
|
bool isObjectId(unsigned int n) const; // NULL的id也返回true
|
|
bool isObjectIndex(unsigned int n) const; // 0 也返回true
|
|
|
|
private:
|
|
|
|
QHash<IxDynObj*, unsigned int> m_hashObjIds;
|
|
QVector<IxDynObj*> m_vecObjs;
|
|
|
|
ZxXpfDoc* m_pDoc;
|
|
ZxXpfNode* m_pNode;
|
|
bool m_bWrite;
|
|
};
|