Metatemplateprogramming is really cool
This commit is contained in:
		| @@ -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"); | ||||
|           }*/ | ||||
|   }; | ||||
|    | ||||
|   //@} | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										181
									
								
								src/xml.cxx
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								src/xml.cxx
									
									
									
									
									
								
							| @@ -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 | ||||
|   } | ||||
|   // =========================================================================== | ||||
|    | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user