first approach to list - requires work -> are the items xml::Serialize?

master
Marc Wäckerlin 15 years ago
parent a750bfc1c3
commit 0871fd927f
  1. 33
      doc/examples/list_serialization.cxx
  2. 56
      src/xml-cxx/xml.hxx
  3. 101
      src/xml.cxx

@ -17,14 +17,31 @@ class A: public xml::Serialize {
xml::List<std::string> list;
protected:
void initXmlMembers() {
LOG("A::initXmlMembers");
className("A");
persist(list, "list");
}
};
class B: public xml::Serialize {
public:
int b;
A a;
xml::List<A> as;
protected:
void initXmlMembers() {
className("B");
persist(b, "b");
persist(a, "a");
persist(as, "As");
}
};
int main(int, char**) {
std::stringstream ss("<A>\n"
std::stringstream ss("<B>\n"
"<b>1234</b>"
"<a><list><item>guguseli</item></list></a>"
"<As>"
"<item>\n"
"\t<list>\n"
"\t\t<item>Hello</item>\n"
"\t\t<item>World</item>\n"
@ -32,12 +49,14 @@ int main(int, char**) {
"\t\t<item>are</item>\n"
"\t\t<item>you</item>\n"
"\t</list>\n"
"</A>");
A a;
std::cout<<"Schema:\n"<<a.schema()<<std::endl;
a.loadXml(ss);
"</item>"
"</As>"
"</B>");
B b;
std::cout<<"SCHEMA:"<<std::endl<<b.schema()<<std::endl;
b.loadXml(ss);
// if (a.list.front()=="Hello") a.list.front()="Good Bye";
// if (a.list.back()=="you") a.list.back()="we";
a.saveXml(std::cout)<<std::endl;
b.saveXml(std::cout)<<std::endl;
return 0;
}

@ -324,6 +324,14 @@ namespace xml {
Node* _node;
};
//----------------------------------------------------------------------------
class type_not_registered: public exception {
public:
type_not_registered(std::string type, std::string name, const Node& t):
exception("serialized node type is not registered\ntype: "
+type+"\nname: "+name, t) {
}
};
//----------------------------------------------------------------------------
class empty_attribute_list: public exception {
public:
empty_attribute_list(const std::string& name) throw():
@ -701,6 +709,7 @@ namespace xml {
private:
friend class stream_error;
friend class Serialize;
template<class T, class A> friend class List;
Node& operator*() throw(factory_not_valid);
Node*const operator->() throw(factory_not_valid);
bool ws(char c) throw();
@ -867,9 +876,16 @@ namespace xml {
static void registerToNode(ToNodeFunc toNodeFunc);
protected:
virtual void initXmlMembers();
void checkInit(const Serialize* const ser=0) const {
if (ser) {
if (!ser->_xmlFactory) const_cast<Serialize*>(ser)->initXmlMembers();
} else {
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers();
}
}
private:
public: //! @todo
void clear() throw();
void reset() throw();
void copy(const Serialize& o) throw();
template<typename TYPE>
Serialize& persistSimpleType(TYPE& member,
@ -903,25 +919,41 @@ namespace xml {
List(const std::string& className) throw(): Serialize(className) {}
virtual ~List() {}
protected:
/*virtual void initXmlMembers() {
LOG("initXmlMembers std::list");
//_xmlNames[list] = this;
TYPE dummy;
virtual void initXmlMembers() {
std::string itemName("item");
TYPE tmp;
LOG("initXmlMembers List for: "<<typeid(TYPE).name());
if (typeid(TYPE*)==typeid(Serialize*)) {
Serialize* ser((Serialize*)&dummy);
if (!ser->_xmlFactory) ser->initXmlMembers();
LOG("Liste von Serialize");
Serialize* ser((Serialize*)&tmp);
checkInit(ser);
itemName = **ser->_xmlFactory;
}
persist(dummy, itemName);
_xmlFactory->limits(0, 0);
_xmlFactory = xml::Node("dummyroot"); // dummy root, (uninitialized exc)
persist(tmp, itemName); // add _reference as child of dummyroot
(*_xmlFactory)[0].limits(0, 0); // any number of children possible
}
virtual void fromNode(boost::any member, const xml::Node& node) {
LOG("fromNode std::list");
this->clear();
for (xml::Node::size_type i(0); i<node.parent().children(); ++i) {
TYPE tmp;
Serialize::fromNode(&tmp, node.parent()[i]); // reads into tmp
push_back(tmp);
}
}
virtual void toNode(const boost::any member, xml::Node& node) const {
LOG("toNode std::list");
}*/
std::auto_ptr<xml::Node> tpl(node.clone());
xml::Node& parent(node.parent());
parent.clear(); // "node" is now invalid
for (typename List::const_iterator it = this->begin();
it!=this->end(); ++it) {
TYPE tmp;
tmp = *it;
std::auto_ptr<xml::Node> item(tpl->clone());
Serialize::toNode(&tmp, *item);
parent<<*item;
}
}
};
//@}

@ -245,7 +245,7 @@ namespace xml {
it!=o._contents.end(); ++it)
_contents.push_back((*it)->clone(this).release());
}
//! Clones But clears the parent.
//! Clones But resets the parent reference.
/*! You get a new instance of the node, but detached from the
parent. It is then ready to be inserted below a new parent.
@ -1026,7 +1026,7 @@ namespace xml {
copy(other);
}
Serialize::~Serialize() {
clear();
reset();
}
Serialize& Serialize::operator=(const Serialize& other) throw() {
copy(other);
@ -1043,7 +1043,7 @@ namespace xml {
}
Serialize& Serialize::persist(Serialize& ser,
const std::string& name) throw() {
if (!ser._xmlFactory) ser.initXmlMembers();
ser.checkInit();
_xmlNames[name] = &ser;
xml::Node schema(*_xmlFactory);
xml::Node node(xml::Node(name).limits(1,1));
@ -1106,7 +1106,7 @@ namespace xml {
}
std::ostream& Serialize::saveXml(std::ostream& os,
const std::string& name) const throw() {
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers();
checkInit();
xml::Node node(*_xmlFactory);
if (name.size()) node.name(name);
for (std::map<std::string, boost::any>::const_iterator
@ -1117,7 +1117,7 @@ namespace xml {
return os;
}
std::istream& Serialize::loadXml(std::istream& is, const std::string& name) {
if (!_xmlFactory) initXmlMembers();
checkInit();
xml::Factory factory(_xmlFactory);
if (name.size()) factory->name(name);
std::auto_ptr<xml::Node> node(factory.read(is));
@ -1128,21 +1128,54 @@ namespace xml {
return is;
}
std::string Serialize::schema() const throw() {
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers();
checkInit();
std::stringstream ss;
ss<<*_xmlFactory;
return ss.str();
}
void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) {
_fromNode.insert(fromNodeFunc);
}
void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) {
_toNode.insert(toNodeFunc);
}
void Serialize::initXmlMembers() {}
void Serialize::reset() throw() {
_xmlFactory.reset();
_xmlNames.clear();
}
void Serialize::copy(const Serialize& o) throw() {
reset();
initXmlMembers();
}
void Serialize::fromNode(boost::any member, const xml::Node& node) {
for (std::set<FromNodeFunc>::const_iterator it(_fromNode.begin());
it!=_fromNode.end(); ++it)
if ((**it)(member, node)) return; // found match
throw type_not_registered(member.type().name(), node.name(), node);
}
void Serialize::toNode(const boost::any member, xml::Node& node) const {
for (std::set<ToNodeFunc>::const_iterator it(_toNode.begin());
it!=_toNode.end(); ++it)
if ((**it)(member, node)) return; // found match
throw type_not_registered(member.type().name(), node.name(), node);
}
std::set<Serialize::FromNodeFunc> Serialize::_fromNode;
std::set<Serialize::ToNodeFunc> Serialize::_toNode;
//=============================================================== Assign Types
template<typename TYPE> bool assignFromNode(boost::any member,
const xml::Node& node) {
if (member.type()!=typeid(TYPE*)) return false;
if (!boost::any_cast<TYPE*>(&member)) return false;
*boost::any_cast<TYPE*>(member) =
(TYPE)dynamic_cast<const xml::String&>(node);
return true;
}
template<typename TYPE> bool assignToNode(const boost::any member,
xml::Node& node) {
if (member.type()!=typeid(TYPE*)) return false;
if (!boost::any_cast<TYPE*>(&member)) return false;
std::stringstream ss;
ss<<*boost::any_cast<TYPE*>(member);
node.text(ss.str());
@ -1172,66 +1205,26 @@ namespace xml {
}
template<> bool assignFromNode<Serialize>(boost::any member,
const xml::Node& node) {
if (member.type()!=typeid(Serialize*)) return false;
if (!boost::any_cast<Serialize*>(&member)) return false;
//! @todo improve this (inefficient)
std::stringstream ss; // simple but inefficient: rewrite and reread
ss<<node;
boost::any_cast<Serialize*>(member)->loadXml(ss, node.name());
/*
Serialize* ser(boost::any_cast<Serialize*>(member));
for (xml::Node::size_type i(0); i<node.children(); ++i)
ser->fromNode(ser->_xmlNames[*node[i]], node[i]);*/
return true;
}
template<> bool assignToNode<Serialize>(const boost::any member,
xml::Node& node) {
if (member.type()!=typeid(Serialize*)) return false;
if (!boost::any_cast<Serialize*>(&member)) return false;
std::stringstream ss;
boost::any_cast<Serialize*>(member)->saveXml(ss, node.name());
xml::Factory factory(node);
node = *factory.read(ss);
return true;
}
// template<typename TYPE, template<class TYPE> class CONTAINER>
// bool containerFromNode(boost::any member,
// const xml::Node& node) {
// if (member.type()!=typeid(TYPE*)) return false;
// LOG("ASSIGN List");
// return false;
// }
// template<typename TYPE, class ALLOC>
// bool assignToNode(const boost::any member, xml::Node& node) {
// }
void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) {
_fromNode.insert(fromNodeFunc);
}
void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) {
_toNode.insert(toNodeFunc);
}
void Serialize::initXmlMembers() {}
void Serialize::clear() throw() {
_xmlFactory.reset();
_xmlNames.clear();
}
void Serialize::copy(const Serialize& o) throw() {
clear();
initXmlMembers();
}
void Serialize::fromNode(boost::any member, const xml::Node& node) {
if (!_fromNode.size()) registerFromNode(&assignFromNode<std::string>);
for (std::set<FromNodeFunc>::const_iterator it(_fromNode.begin());
it!=_fromNode.end(); ++it)
if ((**it)(member, node)) return; // found match
throw std::runtime_error(node.name());
}
void Serialize::toNode(const boost::any member, xml::Node& node) const {
if (!_toNode.size()) registerToNode(&assignToNode<std::string>);
for (std::set<ToNodeFunc>::const_iterator it(_toNode.begin());
it!=_toNode.end(); ++it)
if ((**it)(member, node)) return; // found match
throw std::runtime_error(node.name());
}
std::set<Serialize::FromNodeFunc> Serialize::_fromNode;
std::set<Serialize::ToNodeFunc> Serialize::_toNode;
// Register for all simple Types =============================================
template<int NUM> struct SimpleTypes {};
template<> struct SimpleTypes<1> {typedef std::string Type;};

Loading…
Cancel
Save