Metatemplateprogramming is really cool

master
Marc Wäckerlin 16 years ago
parent 933208f849
commit a750bfc1c3
  1. 9
      doc/examples/list_serialization.cxx
  2. 55
      src/xml-cxx/xml.hxx
  3. 183
      src/xml.cxx

@ -14,11 +14,12 @@
class A: public xml::Serialize {
public:
std::list<std::string> list;
xml::List<std::string> list;
protected:
void initXmlMembers() {
LOG("A::initXmlMembers");
className("A");
persist(list, "list", "item");
persist(list, "list");
}
};
@ -35,8 +36,8 @@ int main(int, char**) {
A a;
std::cout<<"Schema:\n"<<a.schema()<<std::endl;
a.loadXml(ss);
if (a.list.front()=="Hello") a.list.front()="Good Bye";
if (a.list.back()=="you") a.list.back()="we";
// 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;
return 0;
}

@ -829,25 +829,8 @@ namespace xml {
virtual ~Serialize();
Serialize& operator=(const Serialize& other) throw();
Serialize& className(const std::string& name) throw();
Serialize& persist(Serialize& member,
const std::string& name) throw();
template<typename TYPE, class ALLOC>
Serialize& persist(std::list<TYPE, ALLOC>& member,
const std::string& name) throw() {
return persist(member, name, name);
}
template<typename TYPE, class ALLOC>
Serialize& persist(std::list<TYPE, ALLOC>& member,
const std::string& list,
const std::string& item) throw() {
_xmlNames[list] = &member;
Serialize ser(list);
TYPE dummy;
ser.persist(dummy, item);
*_xmlFactory<<(xml::Node(list).limits(1,1)
<<(*ser._xmlFactory)[0].limits(0, 0));
return *this;
}
virtual Serialize& persist(Serialize& member,
const std::string& name) throw();
Serialize& persist(bool& member,
const std::string& name) throw();
Serialize& persist(char& member,
@ -885,6 +868,7 @@ namespace xml {
protected:
virtual void initXmlMembers();
private:
public: //! @todo
void clear() throw();
void copy(const Serialize& o) throw();
template<typename TYPE>
@ -896,8 +880,8 @@ namespace xml {
_xmlFactory = schema;
return *this;
}
void fromNode(boost::any member, const xml::Node& node);
void toNode(const boost::any member, xml::Node& node) const;
virtual void fromNode(boost::any member, const xml::Node& node);
virtual void toNode(const boost::any member, xml::Node& node) const;
/*
template<typename TYPE, class ALLOC>
void fromNode(std::list<TYPE, ALLOC>* member, xml::Node& node) {
@ -911,6 +895,35 @@ namespace xml {
static std::set<ToNodeFunc> _toNode;
};
template<class TYPE, class ALLOC=std::allocator<TYPE> > class List:
public std::list<TYPE, ALLOC>, public Serialize {
public:
List() {}
List(const List& o): std::list<TYPE, ALLOC>(o), Serialize(o) {}
List(const std::string& className) throw(): Serialize(className) {}
virtual ~List() {}
protected:
/*virtual void initXmlMembers() {
LOG("initXmlMembers std::list");
//_xmlNames[list] = this;
TYPE dummy;
std::string itemName("item");
if (typeid(TYPE*)==typeid(Serialize*)) {
Serialize* ser((Serialize*)&dummy);
if (!ser->_xmlFactory) ser->initXmlMembers();
itemName = **ser->_xmlFactory;
}
persist(dummy, itemName);
_xmlFactory->limits(0, 0);
}
virtual void fromNode(boost::any member, const xml::Node& node) {
LOG("fromNode std::list");
}
virtual void toNode(const boost::any member, xml::Node& node) const {
LOG("toNode std::list");
}*/
};
//@}
}

@ -1135,130 +1135,75 @@ namespace xml {
}
template<typename TYPE> bool assignFromNode(boost::any member,
const xml::Node& node) {
if (member.type()==typeid(TYPE*)) {
*boost::any_cast<TYPE*>(member) =
(TYPE)dynamic_cast<const xml::String&>(node);
return true;
}
return false;
if (member.type()!=typeid(TYPE*)) 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*)) {
std::stringstream ss;
ss<<*boost::any_cast<TYPE*>(member);
node.text(ss.str());
return true;
}
return false;
if (member.type()!=typeid(TYPE*)) return false;
std::stringstream ss;
ss<<*boost::any_cast<TYPE*>(member);
node.text(ss.str());
return true;
}
template<> bool assignFromNode<bool>(boost::any member,
const xml::Node& node) {
if (member.type()==typeid(bool*)) {
std::string s(*dynamic_cast<const xml::String&>(node));
std::string::size_type
start(s.find_first_not_of(" \t\n\r")),
end(s.find_last_not_of(" \t\n\r"));
if (start==std::string::npos) {
*boost::any_cast<bool*>(member) = false;
} else {
s = s.substr(start, end-start+1);
*boost::any_cast<bool*>(member) =
s!="0" && s!="false" && s!="no" && s!="off";
}
return true;
if (member.type()!=typeid(bool*)) return false;
std::string s(*dynamic_cast<const xml::String&>(node));
std::string::size_type
start(s.find_first_not_of(" \t\n\r")),
end(s.find_last_not_of(" \t\n\r"));
if (start==std::string::npos) {
*boost::any_cast<bool*>(member) = false;
} else {
s = s.substr(start, end-start+1);
*boost::any_cast<bool*>(member) =
s!="0" && s!="false" && s!="no" && s!="off";
}
return false;
return true;
}
template<> bool assignToNode<bool>(const boost::any member,
xml::Node& node) {
if (member.type()==typeid(bool*)) {
node.text(*boost::any_cast<bool*>(member)?"true":"false");
return true;
}
return false;
if (member.type()!=typeid(bool*)) return false;
node.text(*boost::any_cast<bool*>(member)?"true":"false");
return true;
}
template<> bool assignFromNode<Serialize>(boost::any member,
const xml::Node& node) {
if (member.type()==typeid(Serialize*)) {
//! @todo improve this (inefficient)
std::stringstream ss; // simple but inefficient: rewrite and reread
ss<<node;
boost::any_cast<Serialize*>(member)->loadXml(ss, node.name());
return true;
}
return false;
if (member.type()!=typeid(Serialize*)) 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());
return true;
}
template<> bool assignToNode<Serialize>(const boost::any member,
xml::Node& node) {
if (member.type()==typeid(Serialize*)) {
std::stringstream ss;
boost::any_cast<Serialize*>(member)->saveXml(ss, node.name());
xml::Factory factory(node);
node = *factory.read(ss);
return true;
}
return false;
}
template<typename TYPE, class ALLOC>
bool containerFromNode(boost::any member,
const xml::Node& node) {
LOG("ASSIGN List");
}
if (member.type()!=typeid(Serialize*)) 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) {
if (!_fromNode.size()) { // initial initialization
_fromNode.insert(&assignFromNode<Serialize>);
_fromNode.insert(&assignFromNode<std::string>);
_fromNode.insert(&assignFromNode<float>);
_fromNode.insert(&assignFromNode<double>);
_fromNode.insert(&assignFromNode<bool>);
_fromNode.insert(&assignFromNode<char>);
_fromNode.insert(&assignFromNode<signed char>);
_fromNode.insert(&assignFromNode<unsigned char>);
_fromNode.insert(&assignFromNode<short>);
_fromNode.insert(&assignFromNode<signed short>);
_fromNode.insert(&assignFromNode<unsigned short>);
_fromNode.insert(&assignFromNode<int>);
_fromNode.insert(&assignFromNode<signed int>);
_fromNode.insert(&assignFromNode<unsigned int>);
_fromNode.insert(&assignFromNode<long>);
_fromNode.insert(&assignFromNode<signed long>);
_fromNode.insert(&assignFromNode<unsigned long>);
}
_fromNode.insert(fromNodeFunc);
}
//----------------------------------------------------------------------------
//typedef boost::mpl::vector<Serialize, std::string, float, double, bool, char, signed char, unsigned char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long> BasicTypes;
//----------------------------------------------------------------------------
//typedef boost::mpl::vector<Serialize, std::string, float, double, bool, char, signed char, unsigned char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long> BasicTypes;
template<typename TYPE> class RegisterAssignToNode {
RegisterAssignToNode() {
registerToNode(&assignToNode<TYPE>);
}
};
void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) {
if (!_toNode.size()) { // initial initialization
_toNode.insert(&assignToNode<Serialize>);
_toNode.insert(&assignToNode<std::string>);
_toNode.insert(&assignToNode<float>);
_toNode.insert(&assignToNode<double>);
_toNode.insert(&assignToNode<bool>);
_toNode.insert(&assignToNode<char>);
_toNode.insert(&assignToNode<signed char>);
_toNode.insert(&assignToNode<unsigned char>);
_toNode.insert(&assignToNode<short>);
_toNode.insert(&assignToNode<signed short>);
_toNode.insert(&assignToNode<unsigned short>);
_toNode.insert(&assignToNode<int>);
_toNode.insert(&assignToNode<signed int>);
_toNode.insert(&assignToNode<unsigned int>);
_toNode.insert(&assignToNode<long>);
_toNode.insert(&assignToNode<signed long>);
_toNode.insert(&assignToNode<unsigned long>);
}
_toNode.insert(toNodeFunc);
}
void Serialize::initXmlMembers() {}
@ -1287,4 +1232,40 @@ namespace xml {
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;};
template<> struct SimpleTypes<2> {typedef Serialize Type;};
template<> struct SimpleTypes<3> {typedef bool Type;};
template<> struct SimpleTypes<4> {typedef unsigned char Type;};
template<> struct SimpleTypes<5> {typedef signed char Type;};
template<> struct SimpleTypes<6> {typedef char Type;};
template<> struct SimpleTypes<7> {typedef unsigned short Type;};
template<> struct SimpleTypes<8> {typedef signed short Type;};
template<> struct SimpleTypes<9> {typedef short Type;};
template<> struct SimpleTypes<10> {typedef unsigned int Type;};
template<> struct SimpleTypes<11> {typedef signed int Type;};
template<> struct SimpleTypes<12> {typedef int Type;};
template<> struct SimpleTypes<13> {typedef unsigned long Type;};
template<> struct SimpleTypes<14> {typedef signed long Type;};
template<> struct SimpleTypes<15> {typedef long Type;};
template<> struct SimpleTypes<16> {typedef float Type;};
template<> struct SimpleTypes<17> {typedef double Type;};
const int START_NUM(17);
// Init To and From Node ---------------------------------------------------
namespace {
template<int NUM=START_NUM> struct RegisterTemplateForStdTypes {
RegisterTemplateForStdTypes<NUM-1> next; // recurse to next until 0
RegisterTemplateForStdTypes() {
Serialize::registerToNode
(&assignToNode<typename SimpleTypes<NUM>::Type>);
Serialize::registerFromNode
(&assignFromNode<typename SimpleTypes<NUM>::Type>);
}
};
template<> struct RegisterTemplateForStdTypes<0> {}; // stop recursion
static RegisterTemplateForStdTypes<> init; // execute initialisation
}
// ===========================================================================
}

Loading…
Cancel
Save