From a750bfc1c39bd29cfdf1de0c4083a99a5a6b90b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Wed, 29 Apr 2009 11:58:57 +0000 Subject: [PATCH] Metatemplateprogramming is really cool --- doc/examples/list_serialization.cxx | 9 +- src/xml-cxx/xml.hxx | 55 +++++---- src/xml.cxx | 183 +++++++++++++--------------- 3 files changed, 121 insertions(+), 126 deletions(-) diff --git a/doc/examples/list_serialization.cxx b/doc/examples/list_serialization.cxx index ecde5f6..53b17bc 100644 --- a/doc/examples/list_serialization.cxx +++ b/doc/examples/list_serialization.cxx @@ -14,11 +14,12 @@ class A: public xml::Serialize { public: - std::list list; + xml::List 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"< - Serialize& persist(std::list& member, - const std::string& name) throw() { - return persist(member, name, name); - } - template - Serialize& persist(std::list& 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 @@ -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 void fromNode(std::list* member, xml::Node& node) { @@ -911,6 +895,35 @@ namespace xml { static std::set _toNode; }; + template > class List: + public std::list, public Serialize { + public: + List() {} + List(const List& o): std::list(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"); + }*/ + }; + //@} } diff --git a/src/xml.cxx b/src/xml.cxx index fb1d691..c5bae4f 100644 --- a/src/xml.cxx +++ b/src/xml.cxx @@ -1135,130 +1135,75 @@ namespace xml { } template bool assignFromNode(boost::any member, const xml::Node& node) { - if (member.type()==typeid(TYPE*)) { - *boost::any_cast(member) = - (TYPE)dynamic_cast(node); - return true; - } - return false; + if (member.type()!=typeid(TYPE*)) return false; + *boost::any_cast(member) = + (TYPE)dynamic_cast(node); + return true; } template bool assignToNode(const boost::any member, xml::Node& node) { - if (member.type()==typeid(TYPE*)) { - std::stringstream ss; - ss<<*boost::any_cast(member); - node.text(ss.str()); - return true; - } - return false; + if (member.type()!=typeid(TYPE*)) return false; + std::stringstream ss; + ss<<*boost::any_cast(member); + node.text(ss.str()); + return true; } template<> bool assignFromNode(boost::any member, const xml::Node& node) { - if (member.type()==typeid(bool*)) { - std::string s(*dynamic_cast(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(member) = false; - } else { - s = s.substr(start, end-start+1); - *boost::any_cast(member) = - s!="0" && s!="false" && s!="no" && s!="off"; - } - return true; + if (member.type()!=typeid(bool*)) return false; + std::string s(*dynamic_cast(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(member) = false; + } else { + s = s.substr(start, end-start+1); + *boost::any_cast(member) = + s!="0" && s!="false" && s!="no" && s!="off"; } - return false; + return true; } template<> bool assignToNode(const boost::any member, xml::Node& node) { - if (member.type()==typeid(bool*)) { - node.text(*boost::any_cast(member)?"true":"false"); - return true; - } - return false; + if (member.type()!=typeid(bool*)) return false; + node.text(*boost::any_cast(member)?"true":"false"); + return true; } template<> bool assignFromNode(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<(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<(member)->loadXml(ss, node.name()); + return true; } template<> bool assignToNode(const boost::any member, xml::Node& node) { - if (member.type()==typeid(Serialize*)) { - std::stringstream ss; - boost::any_cast(member)->saveXml(ss, node.name()); - xml::Factory factory(node); - node = *factory.read(ss); - return true; - } - return false; - } - template - 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(member)->saveXml(ss, node.name()); + xml::Factory factory(node); + node = *factory.read(ss); + return true; + } +// template class CONTAINER> +// bool containerFromNode(boost::any member, +// const xml::Node& node) { +// if (member.type()!=typeid(TYPE*)) return false; +// LOG("ASSIGN List"); +// return false; +// } // template // bool assignToNode(const boost::any member, xml::Node& node) { // } + void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) { - if (!_fromNode.size()) { // initial initialization - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - _fromNode.insert(&assignFromNode); - } _fromNode.insert(fromNodeFunc); } - //---------------------------------------------------------------------------- - //typedef boost::mpl::vector BasicTypes; - //---------------------------------------------------------------------------- - //typedef boost::mpl::vector BasicTypes; - template class RegisterAssignToNode { - RegisterAssignToNode() { - registerToNode(&assignToNode); - } - }; + void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) { - if (!_toNode.size()) { // initial initialization - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - _toNode.insert(&assignToNode); - } _toNode.insert(toNodeFunc); } void Serialize::initXmlMembers() {} @@ -1287,4 +1232,40 @@ namespace xml { std::set Serialize::_fromNode; std::set Serialize::_toNode; + // Register for all simple Types ============================================= + template 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 struct RegisterTemplateForStdTypes { + RegisterTemplateForStdTypes next; // recurse to next until 0 + RegisterTemplateForStdTypes() { + Serialize::registerToNode + (&assignToNode::Type>); + Serialize::registerFromNode + (&assignFromNode::Type>); + } + }; + template<> struct RegisterTemplateForStdTypes<0> {}; // stop recursion + static RegisterTemplateForStdTypes<> init; // execute initialisation + } + // =========================================================================== + }