mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 22:02:58 -06:00
262 lines
6 KiB
C++
262 lines
6 KiB
C++
#ifndef _PolyXML_h_
|
|
#define _PolyXML_h_
|
|
|
|
#include <ClassFactory/ClassFactory.h>
|
|
|
|
NAMESPACE_UPP;
|
|
|
|
template<class T> class WithPolyXML : public WithFactory<T>
|
|
{
|
|
public:
|
|
// Xmlizer
|
|
virtual void Xmlize(XmlIO &xml) {};
|
|
|
|
// Check if object is marked as erased so the array don't store it on xml
|
|
// useful if you don't remove objects from array but just mark them as erased
|
|
// to be redefined if you need this feature !
|
|
virtual bool IsErased(void) { return false; }
|
|
};
|
|
|
|
template<class T> class PolyXMLUnknown : public T
|
|
{
|
|
private:
|
|
String tag;
|
|
String rawXML;
|
|
public:
|
|
PolyXMLUnknown(String const &_tag, String const &xml)
|
|
{
|
|
tag = _tag;
|
|
rawXML = xml;
|
|
}
|
|
|
|
virtual String const &IsA(void) { return CLASSFACTORY_UNKNOWN; }
|
|
String const &GetUnknownClassName(void) { return tag; }
|
|
|
|
virtual void Xmlize(XmlIO &xml)
|
|
{
|
|
if(xml.IsStoring())
|
|
{
|
|
XmlNode node = ParseXML(rawXML);
|
|
xml.Add();
|
|
xml.Node() = pick(node);
|
|
}
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// PolyXMLArray class -- add support for streaming polymorphic arrays of objects
|
|
template<class T> class PolyXMLArray : public Array<T>
|
|
{
|
|
public:
|
|
// Xmlizer
|
|
void Xmlize(XmlIO &xml);
|
|
|
|
T& Add(const T &data) { return Array<T>::Add(data); }
|
|
T& Add(T *data) { return Array<T>::Add(data); }
|
|
|
|
// progress callback
|
|
Callback2<int, int>Progress;
|
|
};
|
|
|
|
template<class T> void PolyXMLArray<T>::Xmlize(XmlIO &xml)
|
|
{
|
|
if(xml.IsStoring())
|
|
{
|
|
int count = PolyXMLArray::GetCount();
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
Progress(i, count);
|
|
T &data = PolyXMLArray::operator[](i);
|
|
if(!data.IsErased())
|
|
{
|
|
String tag = data.IsA();
|
|
XmlIO io = xml.Add(tag);
|
|
data.Xmlize(io);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PolyXMLArray::Clear();
|
|
int count = xml->GetCount();
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
Progress(i, count);
|
|
if(xml->Node(i).IsTag())
|
|
{
|
|
String tag = xml->Node(i).GetTag();
|
|
T *data = T::CreatePtr(tag);
|
|
if(data)
|
|
{
|
|
XmlIO io = xml.At(i);
|
|
data->Xmlize(io);
|
|
Add(data);
|
|
}
|
|
else
|
|
{
|
|
// unknown class -- gather raw xml node
|
|
String rawXml = AsXML(xml.At(i).Node());
|
|
|
|
// strips xml header, we don't need it
|
|
// rawXml = rawXml.Mid(rawXml.Find(xml->Node(i).GetTag()));
|
|
|
|
// creates an unknown class and stores raw xml on it
|
|
Add((T *)new PolyXMLUnknown<T>(tag, rawXml));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// PolyXMLArrayMap class -- add support for streaming polymorphic maps of objects
|
|
template<class K, class T> class PolyXMLArrayMap : public ArrayMap<K, T>
|
|
{
|
|
public:
|
|
// Xmlizer
|
|
void Xmlize(XmlIO &xml);
|
|
|
|
T& Add(const K &key, const T &data) { return ArrayMap<K, T>::Add(key, data); }
|
|
T& Add(const K &key, T *data) { return ArrayMap<K, T>::Add(key, data); }
|
|
|
|
// progress callback
|
|
Callback2<int, int>Progress;
|
|
};
|
|
|
|
template<class K, class T> void PolyXMLArrayMap<K, T>::Xmlize(XmlIO &xml)
|
|
{
|
|
if(xml.IsStoring())
|
|
{
|
|
int count = PolyXMLArrayMap::GetCount();
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
Progress(i, count);
|
|
|
|
// skip unlinked elements
|
|
if(ArrayMap<K, T>::IsUnlinked(i))
|
|
continue;
|
|
T &data = PolyXMLArrayMap::operator[](i);
|
|
K const &key = PolyXMLArrayMap::GetKey(i);
|
|
|
|
// skip data marked as erase too
|
|
if(data.IsErased())
|
|
continue;
|
|
String tag = data.IsA();
|
|
XmlIO ioKey = xml.Add("key");
|
|
XmlizeStore(ioKey, key);
|
|
XmlIO ioTag = xml.Add(tag);
|
|
XmlizeStore(ioTag, data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PolyXMLArrayMap<K, T>::Clear();
|
|
int count = xml->GetCount() - 1;
|
|
for(int i = 0; i < count && xml->Node(i).IsTag("key");)
|
|
{
|
|
Progress(i, count);
|
|
|
|
if(xml->Node(i).IsTag())
|
|
{
|
|
K key;
|
|
|
|
XmlIO io = xml.At(i++);
|
|
Upp::Xmlize(io, key);
|
|
String tag = xml->Node(i).GetTag();
|
|
T *data = T::CreatePtr(tag);
|
|
if(data)
|
|
{
|
|
XmlIO io = xml.At(i++);
|
|
data->Xmlize(io);
|
|
Add(key, data);
|
|
}
|
|
else
|
|
{
|
|
// unknown class -- gather raw xml node
|
|
String rawXml = AsXML(xml.At(i).Node());
|
|
|
|
// creates an unknown class and stores raw xml on it
|
|
Add(key, (T *)new PolyXMLUnknown<T>(tag, rawXml));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// PolyXMLArrayMapOne class -- add support for streaming polymorphic maps of One<> objects
|
|
template<class K, class T> class PolyXMLArrayMapOne : public ArrayMap<K, One<T> >
|
|
{
|
|
public:
|
|
// Xmlizer
|
|
void Xmlize(XmlIO &xml);
|
|
|
|
One<T>& Add(const K &key, pick_ One<T> &data) { return ArrayMap<K, One<T> >::AddPick(key, pick(data)); }
|
|
|
|
// progress callback
|
|
Callback2<int, int>Progress;
|
|
};
|
|
|
|
template<class K, class T> void PolyXMLArrayMapOne<K, T>::Xmlize(XmlIO &xml)
|
|
{
|
|
if(xml.IsStoring())
|
|
{
|
|
int count = PolyXMLArrayMapOne::GetCount();
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
Progress(i, count);
|
|
|
|
// skip unlinked elements
|
|
if(ArrayMap<K, One<T> >::IsUnlinked(i))
|
|
continue;
|
|
One<T> &data = PolyXMLArrayMapOne::operator[](i);
|
|
K const &key = PolyXMLArrayMapOne::GetKey(i);
|
|
|
|
// skip data marked as erase too
|
|
if(data->IsErased())
|
|
continue;
|
|
String tag = data->IsA();
|
|
XmlIO ioKey = xml.Add("key");
|
|
XmlizeStore(ioKey, key);
|
|
XmlIO ioTag = xml.Add(tag);
|
|
XmlizeStore(ioTag, *data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PolyXMLArrayMapOne<K, T>::Clear();
|
|
int count = xml->GetCount() - 1;
|
|
for(int i = 0; i < count && xml->Node(i).IsTag("key");)
|
|
{
|
|
Progress(i, count);
|
|
|
|
if(xml->Node(i).IsTag())
|
|
{
|
|
K key;
|
|
XmlIO io = xml.At(i++);
|
|
Upp::Xmlize(io, key);
|
|
String tag = xml->Node(i).GetTag();
|
|
One<T> data = T::CreatePtr(tag);
|
|
if(data)
|
|
{
|
|
XmlIO io = xml.At(i++);
|
|
data->Xmlize(io);
|
|
Add(key, data);
|
|
}
|
|
else
|
|
{
|
|
// unknown class -- gather raw xml node
|
|
String rawXml = AsXML(xml.At(i).Node());
|
|
|
|
// creates an unknown class and stores raw xml on it
|
|
One<T> raw = (T *)new PolyXMLUnknown<T>(tag, rawXml);
|
|
Add(key, raw);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
END_UPP_NAMESPACE;
|
|
|
|
#endif
|