containment can be serialized
This commit is contained in:
@@ -37,6 +37,10 @@ class B: public xml::Serialize {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& fn(std::ostream& os) {
|
||||||
|
os<<std::endl<<"HALLO"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int, char**) {
|
int main(int, char**) {
|
||||||
{ // Serialization as a member
|
{ // Serialization as a member
|
||||||
std::stringstream ss("<b>\n"
|
std::stringstream ss("<b>\n"
|
||||||
@@ -54,6 +58,7 @@ int main(int, char**) {
|
|||||||
std::cout<<"Text B: "<<b.txt<<std::endl;
|
std::cout<<"Text B: "<<b.txt<<std::endl;
|
||||||
std::cout<<"Text A: "<<b.a.txt<<std::endl;
|
std::cout<<"Text A: "<<b.a.txt<<std::endl;
|
||||||
b.saveXml(std::cout)<<std::endl;
|
b.saveXml(std::cout)<<std::endl;
|
||||||
|
std::cout<<fn;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -739,52 +739,69 @@ namespace xml {
|
|||||||
|
|
||||||
@section serActual Actual Status
|
@section serActual Actual Status
|
||||||
|
|
||||||
Instead of:
|
The following member types are supported
|
||||||
|
- All built-in C++ types are supported
|
||||||
|
- std::string is supported
|
||||||
|
- Contained classes are supported
|
||||||
|
|
||||||
|
The following will be supported soon (ideas):
|
||||||
|
- lists, maps
|
||||||
|
- inheritance
|
||||||
|
- choices (one of)
|
||||||
|
- optional members (pointer)
|
||||||
|
|
||||||
|
Pointers cannot be stored.
|
||||||
|
|
||||||
|
There are many ways of implemenation. best practice is to
|
||||||
|
inherit xml::Serialize and to overwrite
|
||||||
|
xml::Serialize::initXmlMembers:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
class A {
|
class A: public xml::Serialize {
|
||||||
protected:
|
protected:
|
||||||
int _anInteger;
|
// all persitent members must be registered
|
||||||
bool _aBool;
|
virtual void initXmlMembers() {
|
||||||
double _aDouble;
|
className("A"); // giving a class name is very important
|
||||||
std::string _aString;
|
persist(_anInteger, "anInteger");
|
||||||
std::string _anotherString;
|
persist(_aBool, "aBool");
|
||||||
unsigned long _aLong;
|
persist(_aDouble, "aDouble");
|
||||||
|
persist(_aString, "aString");
|
||||||
|
persist(_anotherString, "anotherString");
|
||||||
|
persist(_aLong, "aLong");
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int _anInteger;
|
||||||
|
bool _aBool;
|
||||||
|
double _aDouble;
|
||||||
|
std::string _aString;
|
||||||
|
std::string _anotherString;
|
||||||
|
unsigned long _aLong;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class B: public xml::Serialize {
|
||||||
|
protected:
|
||||||
|
virtual void initXmlMembers() {
|
||||||
|
className("B");
|
||||||
|
persist(_a); // name must not be given, it's already known
|
||||||
|
persist(_anInteger, "anInteger");
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
A _a; // contains an A
|
||||||
|
int _anInteger;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
A a;
|
||||||
|
B b;
|
||||||
|
// ... do something with a and b, then write it to stdout:
|
||||||
|
a.saveXml(std::out)<<std::endl;
|
||||||
|
b.saveXml(std::out)<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
You have to write:
|
@example serialization.cxx
|
||||||
|
@example contain_serialization.cxx */
|
||||||
@code
|
|
||||||
class A {
|
|
||||||
protected:
|
|
||||||
XML_DECLARE_MEMBER(int, anInteger);
|
|
||||||
XML_DECLARE_MEMBER(bool, aBool);
|
|
||||||
XML_DECLARE_MEMBER(double, aDouble);
|
|
||||||
XML_DECLARE_MEMBER(std::string, aString);
|
|
||||||
XML_DECLARE_MEMBER(std::string, anotherString);
|
|
||||||
XML_DECLARE_MEMBER(unsigned long, aLong);
|
|
||||||
private:
|
|
||||||
XML_INIT_BEGIN(A);
|
|
||||||
XML_INIT_MEMBER(A, anInteger);
|
|
||||||
XML_INIT_MEMBER(A, aBool);
|
|
||||||
XML_INIT_MEMBER(A, aDouble);
|
|
||||||
XML_INIT_MEMBER(A, aString);
|
|
||||||
XML_INIT_MEMBER(A, anotherString);
|
|
||||||
XML_INIT_MEMBER(A, aLong);
|
|
||||||
XML_INIT_END;
|
|
||||||
};
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
You get:
|
|
||||||
- All the members (with @c _ as member prefix)
|
|
||||||
- method <code>void saveXml(std::ostream&) const</code>
|
|
||||||
- method <code>void loadXml(std::istream&)</code>
|
|
||||||
|
|
||||||
@todo Up to now: Only base types plus std::string are supported,
|
|
||||||
no list, no inheritance is possible and no optional members.
|
|
||||||
|
|
||||||
@example serialization.cxx */
|
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
class Serialize {
|
class Serialize {
|
||||||
@@ -797,10 +814,10 @@ namespace xml {
|
|||||||
Serialize& persist(Serialize& ser) throw();
|
Serialize& persist(Serialize& ser) throw();
|
||||||
template<typename TYPE>
|
template<typename TYPE>
|
||||||
Serialize& persist(TYPE& member, const std::string& name) throw() {
|
Serialize& persist(TYPE& member, const std::string& name) throw() {
|
||||||
assert(mapName<TYPE>().find(name)==mapName<TYPE>().end());
|
assert(mapName<TYPE>().find(std::make_pair(this, name))==mapName<TYPE>().end());
|
||||||
assert(mapMember<TYPE>().find(&member)==mapMember<TYPE>().end());
|
assert(mapMember<TYPE>().find(&member)==mapMember<TYPE>().end());
|
||||||
assert(_xmlNames.find(name)==_xmlNames.end());
|
assert(_xmlNames.find(name)==_xmlNames.end());
|
||||||
mapName<TYPE>()[name] = &member;
|
mapName<TYPE>()[std::make_pair(this, name)] = &member;
|
||||||
mapMember<TYPE>()[&member] = name;
|
mapMember<TYPE>()[&member] = name;
|
||||||
_xmlNames[name] = &typeid(TYPE);
|
_xmlNames[name] = &typeid(TYPE);
|
||||||
xml::Node schema(*_xmlFactory);
|
xml::Node schema(*_xmlFactory);
|
||||||
@@ -813,8 +830,10 @@ namespace xml {
|
|||||||
protected:
|
protected:
|
||||||
virtual void initXmlMembers();
|
virtual void initXmlMembers();
|
||||||
private:
|
private:
|
||||||
template<typename TYPE> std::map<std::string, TYPE*>& mapName() const {
|
template<typename TYPE>
|
||||||
static std::map<std::string, TYPE*> MAP;
|
std::map<std::pair<const Serialize*, std::string>, TYPE*>&
|
||||||
|
mapName() const {
|
||||||
|
static std::map<std::pair<const Serialize*, std::string>, TYPE*> MAP;
|
||||||
return MAP;
|
return MAP;
|
||||||
}
|
}
|
||||||
template<typename TYPE> std::map<TYPE*, std::string>& mapMember() const {
|
template<typename TYPE> std::map<TYPE*, std::string>& mapMember() const {
|
||||||
|
57
src/xml.cxx
57
src/xml.cxx
@@ -993,18 +993,55 @@ namespace xml {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
template<> void Serialize::fromNode<Serialize>(Serialize* member,
|
template<> void Serialize::fromNode<Serialize>(Serialize* member,
|
||||||
xml::Node& node) {
|
xml::Node& node) {
|
||||||
member->_xmlFactory = node[member->_xmlFactory->name()];
|
//! @todo improve this (inefficient)
|
||||||
|
std::stringstream ss; // simple but inefficient: rewrite and reread
|
||||||
|
ss<<node[member->_xmlFactory->name()];
|
||||||
|
member->loadXml(ss);
|
||||||
}
|
}
|
||||||
template<> void Serialize::toNode<Serialize>(Serialize* member,
|
template<> void Serialize::toNode<Serialize>(Serialize* member,
|
||||||
xml::Node& node) const {
|
xml::Node& node) const {
|
||||||
node[member->_xmlFactory->name()] = *member->_xmlFactory;
|
//! @todo improve this (inefficient)
|
||||||
|
std::stringstream ss; // simple but inefficient: write and reread
|
||||||
|
member->saveXml(ss);
|
||||||
|
node[member->_xmlFactory->name()] = *member->_xmlFactory.read(ss);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Serialize::Serialize() throw() {}
|
Serialize::Serialize() throw() {}
|
||||||
Serialize::Serialize(const std::string& className) throw():
|
Serialize::Serialize(const std::string& className) throw():
|
||||||
_xmlFactory(xml::Node(xml::String(className).limits(1,1))) {
|
_xmlFactory(xml::Node(xml::String(className).limits(1,1))) {
|
||||||
}
|
}
|
||||||
Serialize::~Serialize() {};
|
Serialize::~Serialize() {
|
||||||
|
// Remove my entries from the maps
|
||||||
|
for (std::map<std::string, const std::type_info*>::const_iterator
|
||||||
|
it(_xmlNames.begin());
|
||||||
|
it!=_xmlNames.end(); ++it) {
|
||||||
|
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \
|
||||||
|
if (*it->second==typeid(TYPE)) { \
|
||||||
|
mapMember<TYPE>() \
|
||||||
|
.erase(mapName<TYPE>()[std::make_pair(this, it->first)]); \
|
||||||
|
mapName<TYPE>().erase(std::make_pair(this, it->first)); \
|
||||||
|
} else
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(float)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(double)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(bool)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(char)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(signed char)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(unsigned char)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(short)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(signed short)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(unsigned short)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(int)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(signed int)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(unsigned int)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(long)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(signed long)
|
||||||
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(unsigned long)
|
||||||
|
{} // ignore coding error here, but memory leaks - better abort?
|
||||||
|
#undef QWERTZ_CHECK_TYPE_ZTREWQ___XXX
|
||||||
|
}
|
||||||
|
}
|
||||||
Serialize& Serialize::className(const std::string& name) throw() {
|
Serialize& Serialize::className(const std::string& name) throw() {
|
||||||
_xmlFactory=xml::Node(xml::String(name).limits(1,1));
|
_xmlFactory=xml::Node(xml::String(name).limits(1,1));
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1012,7 +1049,7 @@ namespace xml {
|
|||||||
Serialize& Serialize::persist(Serialize& ser) throw() {
|
Serialize& Serialize::persist(Serialize& ser) throw() {
|
||||||
ser.initXmlMembers();
|
ser.initXmlMembers();
|
||||||
std::string name(ser._xmlFactory->name());
|
std::string name(ser._xmlFactory->name());
|
||||||
mapName<Serialize>()[name] = &ser;
|
mapName<Serialize>()[std::make_pair(this, name)] = &ser;
|
||||||
mapMember<Serialize>()[&ser] = name;
|
mapMember<Serialize>()[&ser] = name;
|
||||||
_xmlNames[name] = &typeid(Serialize);
|
_xmlNames[name] = &typeid(Serialize);
|
||||||
xml::Node schema(*_xmlFactory);
|
xml::Node schema(*_xmlFactory);
|
||||||
@@ -1026,9 +1063,9 @@ namespace xml {
|
|||||||
for (std::map<std::string, const std::type_info*>::const_iterator
|
for (std::map<std::string, const std::type_info*>::const_iterator
|
||||||
it(_xmlNames.begin());
|
it(_xmlNames.begin());
|
||||||
it!=_xmlNames.end(); ++it) {
|
it!=_xmlNames.end(); ++it) {
|
||||||
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \
|
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \
|
||||||
if (*it->second==typeid(TYPE)) \
|
if (*it->second==typeid(TYPE)) \
|
||||||
toNode(mapName<TYPE>()[it->first], node); \
|
toNode(mapName<TYPE>()[std::make_pair(this, it->first)], node); \
|
||||||
else
|
else
|
||||||
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize)
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize)
|
||||||
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string)
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string)
|
||||||
@@ -1059,9 +1096,9 @@ namespace xml {
|
|||||||
for (std::map<std::string, const std::type_info*>::const_iterator
|
for (std::map<std::string, const std::type_info*>::const_iterator
|
||||||
it(_xmlNames.begin());
|
it(_xmlNames.begin());
|
||||||
it!=_xmlNames.end(); ++it) {
|
it!=_xmlNames.end(); ++it) {
|
||||||
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \
|
#define QWERTZ_CHECK_TYPE_ZTREWQ___XXX(TYPE) \
|
||||||
if (*it->second==typeid(TYPE)) \
|
if (*it->second==typeid(TYPE)) \
|
||||||
fromNode(mapName<TYPE>()[it->first], *node); \
|
fromNode(mapName<TYPE>()[std::make_pair(this, it->first)], *node); \
|
||||||
else
|
else
|
||||||
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize)
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(Serialize)
|
||||||
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string)
|
QWERTZ_CHECK_TYPE_ZTREWQ___XXX(std::string)
|
||||||
|
Reference in New Issue
Block a user