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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
101
src/xml.cxx
101
src/xml.cxx
@@ -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;};
|
||||||
|
Reference in New Issue
Block a user