first approach to list - requires work -> are the items xml::Serialize?
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//@}
|
||||
|
101
src/xml.cxx
101
src/xml.cxx
@@ -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;};
|
||||
|
Reference in New Issue
Block a user