ultimatepp/bazaar/PolyXML/PolyXML.h
cxl 2a208a73e1 bazaar: Fixing for C++11
git-svn-id: svn://ultimatepp.org/upp/trunk@9130 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-11-01 19:19:17 +00:00

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