Metatemplateprogramming is really cool
This commit is contained in:
		| @@ -14,11 +14,12 @@ | |||||||
|  |  | ||||||
| class A: public xml::Serialize { | class A: public xml::Serialize { | ||||||
|   public: |   public: | ||||||
|     std::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", "item"); |       persist(list, "list"); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -35,8 +36,8 @@ int main(int, char**) { | |||||||
|   A a; |   A a; | ||||||
|   std::cout<<"Schema:\n"<<a.schema()<<std::endl; |   std::cout<<"Schema:\n"<<a.schema()<<std::endl; | ||||||
|   a.loadXml(ss); |   a.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; |   a.saveXml(std::cout)<<std::endl; | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -829,25 +829,8 @@ namespace xml { | |||||||
|       virtual ~Serialize(); |       virtual ~Serialize(); | ||||||
|       Serialize& operator=(const Serialize& other) throw(); |       Serialize& operator=(const Serialize& other) throw(); | ||||||
|       Serialize& className(const std::string& name) throw(); |       Serialize& className(const std::string& name) throw(); | ||||||
|       Serialize& persist(Serialize& member, |       virtual Serialize& persist(Serialize& member, | ||||||
|                          const std::string& name) throw(); |                                  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; |  | ||||||
|       } |  | ||||||
|       Serialize& persist(bool& member, |       Serialize& persist(bool& member, | ||||||
|                          const std::string& name) throw(); |                          const std::string& name) throw(); | ||||||
|       Serialize& persist(char& member, |       Serialize& persist(char& member, | ||||||
| @@ -885,6 +868,7 @@ namespace xml { | |||||||
|     protected: |     protected: | ||||||
|       virtual void initXmlMembers(); |       virtual void initXmlMembers(); | ||||||
|     private: |     private: | ||||||
|  |     public: //! @todo | ||||||
|       void clear() throw(); |       void clear() throw(); | ||||||
|       void copy(const Serialize& o) throw(); |       void copy(const Serialize& o) throw(); | ||||||
|       template<typename TYPE> |       template<typename TYPE> | ||||||
| @@ -896,8 +880,8 @@ namespace xml { | |||||||
|         _xmlFactory = schema; |         _xmlFactory = schema; | ||||||
|         return *this; |         return *this; | ||||||
|       } |       } | ||||||
|       void fromNode(boost::any member, const xml::Node& node); |       virtual void fromNode(boost::any member, const xml::Node& node); | ||||||
|       void toNode(const boost::any member, xml::Node& node) const; |       virtual void toNode(const boost::any member, xml::Node& node) const; | ||||||
|       /* |       /* | ||||||
|       template<typename TYPE, class ALLOC> |       template<typename TYPE, class ALLOC> | ||||||
|           void fromNode(std::list<TYPE, ALLOC>* member, xml::Node& node) { |           void fromNode(std::list<TYPE, ALLOC>* member, xml::Node& node) { | ||||||
| @@ -911,6 +895,35 @@ namespace xml { | |||||||
|       static std::set<ToNodeFunc> _toNode; |       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, |   template<typename TYPE> bool assignFromNode(boost::any member, | ||||||
|                                               const xml::Node& node) { |                                               const xml::Node& node) { | ||||||
|     if (member.type()==typeid(TYPE*)) { |     if (member.type()!=typeid(TYPE*)) 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; | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
|   } |   } | ||||||
|   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*)) { |     if (member.type()!=typeid(TYPE*)) 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()); | ||||||
|       return true; |     return true; | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
|   } |   } | ||||||
|   template<> bool assignFromNode<bool>(boost::any member, |   template<> bool assignFromNode<bool>(boost::any member, | ||||||
|                                        const xml::Node& node) { |                                        const xml::Node& node) { | ||||||
|     if (member.type()==typeid(bool*)) { |     if (member.type()!=typeid(bool*)) return false; | ||||||
|       std::string s(*dynamic_cast<const xml::String&>(node)); |     std::string s(*dynamic_cast<const xml::String&>(node)); | ||||||
|       std::string::size_type |     std::string::size_type | ||||||
|         start(s.find_first_not_of(" \t\n\r")), |       start(s.find_first_not_of(" \t\n\r")), | ||||||
|         end(s.find_last_not_of(" \t\n\r")); |       end(s.find_last_not_of(" \t\n\r")); | ||||||
|       if (start==std::string::npos) { |     if (start==std::string::npos) { | ||||||
|         *boost::any_cast<bool*>(member) = false; |       *boost::any_cast<bool*>(member) = false; | ||||||
|       } else { |     } else { | ||||||
|         s = s.substr(start, end-start+1); |       s = s.substr(start, end-start+1); | ||||||
|         *boost::any_cast<bool*>(member) =  |       *boost::any_cast<bool*>(member) =  | ||||||
|           s!="0" && s!="false" && s!="no" && s!="off"; |         s!="0" && s!="false" && s!="no" && s!="off"; | ||||||
|       } |  | ||||||
|       return true; |  | ||||||
|     } |     } | ||||||
|     return false; |     return true; | ||||||
|   } |   } | ||||||
|   template<> bool assignToNode<bool>(const boost::any member, |   template<> bool assignToNode<bool>(const boost::any member, | ||||||
|                                      xml::Node& node) { |                                      xml::Node& node) { | ||||||
|     if (member.type()==typeid(bool*)) { |     if (member.type()!=typeid(bool*)) return false; | ||||||
|       node.text(*boost::any_cast<bool*>(member)?"true":"false"); |     node.text(*boost::any_cast<bool*>(member)?"true":"false"); | ||||||
|       return true; |     return true; | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
|   } |   } | ||||||
|   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*)) { |     if (member.type()!=typeid(Serialize*)) 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()); | ||||||
|       return true; |     return true; | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
|   } |   } | ||||||
|   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*)) { |     if (member.type()!=typeid(Serialize*)) 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; | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
|   } |  | ||||||
|   template<typename TYPE, class ALLOC> |  | ||||||
|       bool containerFromNode(boost::any member, |  | ||||||
|                              const xml::Node& node) { |  | ||||||
|     LOG("ASSIGN List"); |  | ||||||
|   } |   } | ||||||
|  | //   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> | //   template<typename TYPE, class ALLOC> | ||||||
| //       bool assignToNode(const boost::any member, xml::Node& node) { | //       bool assignToNode(const boost::any member, xml::Node& node) { | ||||||
| //   } | //   } | ||||||
|  |  | ||||||
|   void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) { |   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); |     _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) { |   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); |     _toNode.insert(toNodeFunc); | ||||||
|   } |   } | ||||||
|   void Serialize::initXmlMembers() {} |   void Serialize::initXmlMembers() {} | ||||||
| @@ -1287,4 +1232,40 @@ namespace xml { | |||||||
|   std::set<Serialize::FromNodeFunc> Serialize::_fromNode; |   std::set<Serialize::FromNodeFunc> Serialize::_fromNode; | ||||||
|   std::set<Serialize::ToNodeFunc> Serialize::_toNode; |   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