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.
nmWTAI-Platform/Include/iBase/iBase/ZxSerializer.h

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;
};