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

master
Marc Wäckerlin 16 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; xml::List<std::string> list;
protected: protected:
void initXmlMembers() { void initXmlMembers() {
LOG("A::initXmlMembers");
className("A"); className("A");
persist(list, "list"); 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**) { 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<list>\n"
"\t\t<item>Hello</item>\n" "\t\t<item>Hello</item>\n"
"\t\t<item>World</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>are</item>\n"
"\t\t<item>you</item>\n" "\t\t<item>you</item>\n"
"\t</list>\n" "\t</list>\n"
"</A>"); "</item>"
A a; "</As>"
std::cout<<"Schema:\n"<<a.schema()<<std::endl; "</B>");
a.loadXml(ss); 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.front()=="Hello") a.list.front()="Good Bye";
// if (a.list.back()=="you") a.list.back()="we"; // if (a.list.back()=="you") a.list.back()="we";
a.saveXml(std::cout)<<std::endl; b.saveXml(std::cout)<<std::endl;
return 0; return 0;
} }

@ -324,6 +324,14 @@ namespace xml {
Node* _node; 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 { class empty_attribute_list: public exception {
public: public:
empty_attribute_list(const std::string& name) throw(): empty_attribute_list(const std::string& name) throw():
@ -701,6 +709,7 @@ namespace xml {
private: private:
friend class stream_error; friend class stream_error;
friend class Serialize; friend class Serialize;
template<class T, class A> friend class List;
Node& operator*() throw(factory_not_valid); Node& operator*() throw(factory_not_valid);
Node*const operator->() throw(factory_not_valid); Node*const operator->() throw(factory_not_valid);
bool ws(char c) throw(); bool ws(char c) throw();
@ -867,9 +876,16 @@ namespace xml {
static void registerToNode(ToNodeFunc toNodeFunc); static void registerToNode(ToNodeFunc toNodeFunc);
protected: protected:
virtual void initXmlMembers(); 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: private:
public: //! @todo public: //! @todo
void clear() throw(); void reset() throw();
void copy(const Serialize& o) throw(); void copy(const Serialize& o) throw();
template<typename TYPE> template<typename TYPE>
Serialize& persistSimpleType(TYPE& member, Serialize& persistSimpleType(TYPE& member,
@ -903,25 +919,41 @@ namespace xml {
List(const std::string& className) throw(): Serialize(className) {} List(const std::string& className) throw(): Serialize(className) {}
virtual ~List() {} virtual ~List() {}
protected: protected:
/*virtual void initXmlMembers() { virtual void initXmlMembers() {
LOG("initXmlMembers std::list");
//_xmlNames[list] = this;
TYPE dummy;
std::string itemName("item"); std::string itemName("item");
TYPE tmp;
LOG("initXmlMembers List for: "<<typeid(TYPE).name());
if (typeid(TYPE*)==typeid(Serialize*)) { if (typeid(TYPE*)==typeid(Serialize*)) {
Serialize* ser((Serialize*)&dummy); LOG("Liste von Serialize");
if (!ser->_xmlFactory) ser->initXmlMembers(); Serialize* ser((Serialize*)&tmp);
checkInit(ser);
itemName = **ser->_xmlFactory; itemName = **ser->_xmlFactory;
} }
persist(dummy, itemName); _xmlFactory = xml::Node("dummyroot"); // dummy root, (uninitialized exc)
_xmlFactory->limits(0, 0); 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) { 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 { 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) it!=o._contents.end(); ++it)
_contents.push_back((*it)->clone(this).release()); _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 /*! You get a new instance of the node, but detached from the
parent. It is then ready to be inserted below a new parent. parent. It is then ready to be inserted below a new parent.
@ -1026,7 +1026,7 @@ namespace xml {
copy(other); copy(other);
} }
Serialize::~Serialize() { Serialize::~Serialize() {
clear(); reset();
} }
Serialize& Serialize::operator=(const Serialize& other) throw() { Serialize& Serialize::operator=(const Serialize& other) throw() {
copy(other); copy(other);
@ -1043,7 +1043,7 @@ namespace xml {
} }
Serialize& Serialize::persist(Serialize& ser, Serialize& Serialize::persist(Serialize& ser,
const std::string& name) throw() { const std::string& name) throw() {
if (!ser._xmlFactory) ser.initXmlMembers(); ser.checkInit();
_xmlNames[name] = &ser; _xmlNames[name] = &ser;
xml::Node schema(*_xmlFactory); xml::Node schema(*_xmlFactory);
xml::Node node(xml::Node(name).limits(1,1)); xml::Node node(xml::Node(name).limits(1,1));
@ -1106,7 +1106,7 @@ namespace xml {
} }
std::ostream& Serialize::saveXml(std::ostream& os, std::ostream& Serialize::saveXml(std::ostream& os,
const std::string& name) const throw() { const std::string& name) const throw() {
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers(); checkInit();
xml::Node node(*_xmlFactory); xml::Node node(*_xmlFactory);
if (name.size()) node.name(name); if (name.size()) node.name(name);
for (std::map<std::string, boost::any>::const_iterator for (std::map<std::string, boost::any>::const_iterator
@ -1117,7 +1117,7 @@ namespace xml {
return os; return os;
} }
std::istream& Serialize::loadXml(std::istream& is, const std::string& name) { std::istream& Serialize::loadXml(std::istream& is, const std::string& name) {
if (!_xmlFactory) initXmlMembers(); checkInit();
xml::Factory factory(_xmlFactory); xml::Factory factory(_xmlFactory);
if (name.size()) factory->name(name); if (name.size()) factory->name(name);
std::auto_ptr<xml::Node> node(factory.read(is)); std::auto_ptr<xml::Node> node(factory.read(is));
@ -1128,21 +1128,54 @@ namespace xml {
return is; return is;
} }
std::string Serialize::schema() const throw() { std::string Serialize::schema() const throw() {
if (!_xmlFactory) const_cast<Serialize*>(this)->initXmlMembers(); checkInit();
std::stringstream ss; std::stringstream ss;
ss<<*_xmlFactory; ss<<*_xmlFactory;
return ss.str(); 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, template<typename TYPE> bool assignFromNode(boost::any member,
const xml::Node& node) { const xml::Node& node) {
if (member.type()!=typeid(TYPE*)) return false; if (!boost::any_cast<TYPE*>(&member)) return false;
*boost::any_cast<TYPE*>(member) = *boost::any_cast<TYPE*>(member) =
(TYPE)dynamic_cast<const xml::String&>(node); (TYPE)dynamic_cast<const xml::String&>(node);
return true; return true;
} }
template<typename TYPE> bool assignToNode(const boost::any member, template<typename TYPE> bool assignToNode(const boost::any member,
xml::Node& node) { xml::Node& node) {
if (member.type()!=typeid(TYPE*)) return false; if (!boost::any_cast<TYPE*>(&member)) return false;
std::stringstream ss; std::stringstream ss;
ss<<*boost::any_cast<TYPE*>(member); ss<<*boost::any_cast<TYPE*>(member);
node.text(ss.str()); node.text(ss.str());
@ -1172,66 +1205,26 @@ namespace xml {
} }
template<> bool assignFromNode<Serialize>(boost::any member, template<> bool assignFromNode<Serialize>(boost::any member,
const xml::Node& node) { const xml::Node& node) {
if (member.type()!=typeid(Serialize*)) return false; if (!boost::any_cast<Serialize*>(&member)) return false;
//! @todo improve this (inefficient) //! @todo improve this (inefficient)
std::stringstream ss; // simple but inefficient: rewrite and reread std::stringstream ss; // simple but inefficient: rewrite and reread
ss<<node; ss<<node;
boost::any_cast<Serialize*>(member)->loadXml(ss, node.name()); 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; return true;
} }
template<> bool assignToNode<Serialize>(const boost::any member, template<> bool assignToNode<Serialize>(const boost::any member,
xml::Node& node) { xml::Node& node) {
if (member.type()!=typeid(Serialize*)) return false; if (!boost::any_cast<Serialize*>(&member)) return false;
std::stringstream ss; std::stringstream ss;
boost::any_cast<Serialize*>(member)->saveXml(ss, node.name()); boost::any_cast<Serialize*>(member)->saveXml(ss, node.name());
xml::Factory factory(node); xml::Factory factory(node);
node = *factory.read(ss); node = *factory.read(ss);
return true; 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 ============================================= // Register for all simple Types =============================================
template<int NUM> struct SimpleTypes {}; template<int NUM> struct SimpleTypes {};
template<> struct SimpleTypes<1> {typedef std::string Type;}; template<> struct SimpleTypes<1> {typedef std::string Type;};

Loading…
Cancel
Save