Prechádzať zdrojové kódy

ReAntTweakBar now uses only inline methods to avoid duplicate symbols
EmbreeIntersector now properly deallocates memory if init is called multiple times
XmlSerializer is now incapsulated in a unnamed namespace


Former-commit-id: b25cb8951b8aa496bc5918c0c2d7c3c61fa6da15

Daniele Panozzo 11 rokov pred
rodič
commit
693e1032cf

+ 21 - 21
include/igl/ReAntTweakBar.cpp

@@ -9,12 +9,12 @@
 #include <map>
 #include <map>
 
 
 // GLOBAL WRAPPERS
 // GLOBAL WRAPPERS
-namespace igl
+namespace 
 {
 {
   std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > > ReTw_custom_types;
   std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > > ReTw_custom_types;
 }
 }
 
 
-TwType igl::ReTwDefineEnum(
+IGL_INLINE TwType igl::ReTwDefineEnum(
   const char *name, 
   const char *name, 
   const TwEnumVal *enumValues, 
   const TwEnumVal *enumValues, 
   unsigned int nbValues)
   unsigned int nbValues)
@@ -33,7 +33,7 @@ TwType igl::ReTwDefineEnum(
   return type;
   return type;
 }
 }
 
 
-namespace igl
+namespace
 {
 {
   struct ReTwTypeString
   struct ReTwTypeString
   {
   {
@@ -70,19 +70,19 @@ namespace igl
   };
   };
 }
 }
 
 
-igl::ReTwBar::ReTwBar():
+IGL_INLINE igl::ReTwBar::ReTwBar():
  bar(NULL),rw_items(),cb_items()
  bar(NULL),rw_items(),cb_items()
 {
 {
 }
 }
 
 
-igl::ReTwBar::ReTwBar(const igl::ReTwBar & that):
+IGL_INLINE igl::ReTwBar::ReTwBar(const igl::ReTwBar & that):
   bar(that.bar),
   bar(that.bar),
   rw_items(that.rw_items),
   rw_items(that.rw_items),
   cb_items(that.cb_items)
   cb_items(that.cb_items)
 {
 {
 }
 }
 
 
-igl::ReTwBar & igl::ReTwBar::operator=(const igl::ReTwBar & that)
+IGL_INLINE igl::ReTwBar & igl::ReTwBar::operator=(const igl::ReTwBar & that)
 {
 {
   // check for self assignment
   // check for self assignment
   if(this != &that)
   if(this != &that)
@@ -96,7 +96,7 @@ igl::ReTwBar & igl::ReTwBar::operator=(const igl::ReTwBar & that)
 
 
 
 
 // BAR WRAPPERS
 // BAR WRAPPERS
-void igl::ReTwBar::TwNewBar(const char *name)
+IGL_INLINE void igl::ReTwBar::TwNewBar(const char *name)
 {
 {
   // double colon without anything in front of it means look for this in the
   // double colon without anything in front of it means look for this in the
   // global namespace... I hope...
   // global namespace... I hope...
@@ -104,7 +104,7 @@ void igl::ReTwBar::TwNewBar(const char *name)
   this->bar = ::TwNewBar(name);
   this->bar = ::TwNewBar(name);
 }
 }
 
 
-int igl::ReTwBar::TwAddVarRW(
+IGL_INLINE int igl::ReTwBar::TwAddVarRW(
   const char *name, 
   const char *name, 
   TwType type, 
   TwType type, 
   void *var, 
   void *var, 
@@ -119,7 +119,7 @@ int igl::ReTwBar::TwAddVarRW(
   return ret;
   return ret;
 }
 }
 
 
-int igl::ReTwBar::TwAddVarCB(
+IGL_INLINE int igl::ReTwBar::TwAddVarCB(
   const char *name, 
   const char *name, 
   TwType type, 
   TwType type, 
   TwSetVarCallback setCallback, 
   TwSetVarCallback setCallback, 
@@ -137,7 +137,7 @@ int igl::ReTwBar::TwAddVarCB(
   return ret;
   return ret;
 }
 }
 
 
-int igl::ReTwBar::TwAddVarRO(
+IGL_INLINE int igl::ReTwBar::TwAddVarRO(
   const char *name, 
   const char *name, 
   TwType type, 
   TwType type, 
   void *var, 
   void *var, 
@@ -152,7 +152,7 @@ int igl::ReTwBar::TwAddVarRO(
   return ret;
   return ret;
 }
 }
 
 
-int igl::ReTwBar::TwAddButton(
+IGL_INLINE int igl::ReTwBar::TwAddButton(
   const char *name, 
   const char *name, 
   TwButtonCallback buttonCallback, 
   TwButtonCallback buttonCallback, 
   void *clientData, 
   void *clientData, 
@@ -168,7 +168,7 @@ int igl::ReTwBar::TwAddButton(
   return ret;
   return ret;
 }
 }
 
 
-int igl::ReTwBar::TwSetParam(
+IGL_INLINE int igl::ReTwBar::TwSetParam(
   const char *varName, 
   const char *varName, 
   const char *paramName, 
   const char *paramName, 
   TwParamValueType paramValueType, 
   TwParamValueType paramValueType, 
@@ -186,7 +186,7 @@ int igl::ReTwBar::TwSetParam(
       inValues);
       inValues);
 }
 }
 
 
-int igl::ReTwBar::TwGetParam(
+IGL_INLINE int igl::ReTwBar::TwGetParam(
   const char *varName, 
   const char *varName, 
   const char *paramName, 
   const char *paramName, 
   TwParamValueType paramValueType, 
   TwParamValueType paramValueType, 
@@ -203,12 +203,12 @@ int igl::ReTwBar::TwGetParam(
       outValues);
       outValues);
 }
 }
 
 
-int igl::ReTwBar::TwRefreshBar()
+IGL_INLINE int igl::ReTwBar::TwRefreshBar()
 {
 {
   return ::TwRefreshBar(this->bar);
   return ::TwRefreshBar(this->bar);
 }
 }
 
 
-int igl::ReTwBar::TwTerminate()
+IGL_INLINE int igl::ReTwBar::TwTerminate()
 {
 {
   //std::cout<<"TwTerminate"<<std::endl;
   //std::cout<<"TwTerminate"<<std::endl;
   int r = ::TwTerminate();
   int r = ::TwTerminate();
@@ -216,7 +216,7 @@ int igl::ReTwBar::TwTerminate()
   return r;
   return r;
 }
 }
 
 
-bool igl::ReTwBar::save(const char *file_name)
+IGL_INLINE bool igl::ReTwBar::save(const char *file_name)
 {
 {
   FILE * fp;
   FILE * fp;
   if(file_name == NULL)
   if(file_name == NULL)
@@ -279,7 +279,7 @@ bool igl::ReTwBar::save(const char *file_name)
   return true;
   return true;
 }
 }
 
 
-std::string igl::ReTwBar::get_value_as_string(
+IGL_INLINE std::string igl::ReTwBar::get_value_as_string(
   void * var, 
   void * var, 
   TwType type)
   TwType type)
 {
 {
@@ -410,7 +410,7 @@ std::string igl::ReTwBar::get_value_as_string(
   return sstr.str();
   return sstr.str();
 }
 }
 
 
-bool igl::ReTwBar::load(const char *file_name)
+IGL_INLINE bool igl::ReTwBar::load(const char *file_name)
 {
 {
   FILE * fp;
   FILE * fp;
   fp = fopen(file_name,"r");
   fp = fopen(file_name,"r");
@@ -471,7 +471,7 @@ bool igl::ReTwBar::load(const char *file_name)
   return true;
   return true;
 }
 }
 
 
-bool igl::ReTwBar::type_from_string(const char *type_str, TwType & type)
+IGL_INLINE bool igl::ReTwBar::type_from_string(const char *type_str, TwType & type)
 {
 {
   // first check default types
   // first check default types
   for(int j = 0; j < RETW_NUM_DEFAULT_TYPE_STRINGS; j++)
   for(int j = 0; j < RETW_NUM_DEFAULT_TYPE_STRINGS; j++)
@@ -826,12 +826,12 @@ bool igl::ReTwBar::set_value_from_string(
   return true;
   return true;
 }
 }
 
 
-const std::vector<igl::ReTwRWItem> & igl::ReTwBar::get_rw_items()
+IGL_INLINE const std::vector<igl::ReTwRWItem> & igl::ReTwBar::get_rw_items()
 {
 {
   return rw_items;
   return rw_items;
 }
 }
 
 
-const std::vector<igl::ReTwCBItem> & igl::ReTwBar::get_cb_items()
+IGL_INLINE const std::vector<igl::ReTwCBItem> & igl::ReTwBar::get_cb_items()
 {
 {
   return cb_items;
   return cb_items;
 }
 }

+ 21 - 21
include/igl/ReAntTweakBar.h

@@ -66,7 +66,7 @@ namespace igl
     TwType type;
     TwType type;
     void * var;
     void * var;
     // Default constructor
     // Default constructor
-    ReTwRWItem(
+    IGL_INLINE ReTwRWItem(
       const std::string _name,
       const std::string _name,
       TwType _type, 
       TwType _type, 
       void *_var):
       void *_var):
@@ -77,7 +77,7 @@ namespace igl
     }
     }
     // Shallow copy constructor
     // Shallow copy constructor
     // I solemnly swear it's OK to copy var this way
     // I solemnly swear it's OK to copy var this way
-    ReTwRWItem(const ReTwRWItem & that):
+    IGL_INLINE ReTwRWItem(const ReTwRWItem & that):
       name(that.name),
       name(that.name),
       type(that.type),
       type(that.type),
       var(that.var)
       var(that.var)
@@ -85,7 +85,7 @@ namespace igl
     }
     }
     // Shallow assignment 
     // Shallow assignment 
     // I solemnly swear it's OK to copy var this way
     // I solemnly swear it's OK to copy var this way
-    ReTwRWItem & operator=(const ReTwRWItem & that)
+    IGL_INLINE ReTwRWItem & operator=(const ReTwRWItem & that)
     {
     {
       if(this != &that)
       if(this != &that)
       {
       {
@@ -106,7 +106,7 @@ namespace igl
     TwGetVarCallback getCallback;
     TwGetVarCallback getCallback;
     void * clientData;
     void * clientData;
     // Default constructor
     // Default constructor
-    ReTwCBItem(
+    IGL_INLINE ReTwCBItem(
       const std::string _name,
       const std::string _name,
       TwType _type, 
       TwType _type, 
       TwSetVarCallback _setCallback,
       TwSetVarCallback _setCallback,
@@ -121,7 +121,7 @@ namespace igl
     }
     }
     // Shallow copy
     // Shallow copy
     // I solemnly swear it's OK to copy clientData this way
     // I solemnly swear it's OK to copy clientData this way
-    ReTwCBItem(const ReTwCBItem & that):
+    IGL_INLINE ReTwCBItem(const ReTwCBItem & that):
       name(that.name),
       name(that.name),
       type(that.type),
       type(that.type),
       setCallback(that.setCallback),
       setCallback(that.setCallback),
@@ -131,7 +131,7 @@ namespace igl
     }
     }
     // Shallow assignment
     // Shallow assignment
     // I solemnly swear it's OK to copy clientData this way
     // I solemnly swear it's OK to copy clientData this way
-    ReTwCBItem & operator=(const ReTwCBItem & that)
+    IGL_INLINE ReTwCBItem & operator=(const ReTwCBItem & that)
     {
     {
       if(this != &that)
       if(this != &that)
       {
       {
@@ -161,23 +161,23 @@ namespace igl
       std::vector<ReTwCBItem> cb_items;
       std::vector<ReTwCBItem> cb_items;
     public:
     public:
       // Default constructor with explicit initialization
       // Default constructor with explicit initialization
-      ReTwBar();
+      IGL_INLINE ReTwBar();
     private:
     private:
       // Copy constructor does shallow copy
       // Copy constructor does shallow copy
-      ReTwBar(const ReTwBar & that);
+      IGL_INLINE ReTwBar(const ReTwBar & that);
       // Assignment operator does shallow assignment
       // Assignment operator does shallow assignment
-      ReTwBar &operator=(const ReTwBar & that);
+      IGL_INLINE ReTwBar &operator=(const ReTwBar & that);
   
   
     // WRAPPERS FOR ANTTWEAKBAR FUNCTIONS 
     // WRAPPERS FOR ANTTWEAKBAR FUNCTIONS 
     public:
     public:
       void TwNewBar(const char *barName);
       void TwNewBar(const char *barName);
-      int TwAddVarRW(
+      IGL_INLINE int TwAddVarRW(
         const char *name, 
         const char *name, 
         TwType type, 
         TwType type, 
         void *var, 
         void *var, 
         const char *def,
         const char *def,
         const bool record=true);
         const bool record=true);
-      int TwAddVarCB(
+      IGL_INLINE int TwAddVarCB(
         const char *name, 
         const char *name, 
         TwType type, 
         TwType type, 
         TwSetVarCallback setCallback, 
         TwSetVarCallback setCallback, 
@@ -186,26 +186,26 @@ namespace igl
         const char *def,
         const char *def,
         const bool record=true);
         const bool record=true);
       // Wrappers for convenience (not recorded, just passed on)
       // Wrappers for convenience (not recorded, just passed on)
-      int TwAddVarRO(const char *name, TwType type, void *var, const char *def);
-      int TwAddButton(
+      IGL_INLINE int TwAddVarRO(const char *name, TwType type, void *var, const char *def);
+      IGL_INLINE int TwAddButton(
         const char *name, 
         const char *name, 
         TwButtonCallback buttonCallback, 
         TwButtonCallback buttonCallback, 
         void *clientData, 
         void *clientData, 
         const char *def);
         const char *def);
-      int TwSetParam(
+      IGL_INLINE int TwSetParam(
         const char *varName, 
         const char *varName, 
         const char *paramName, 
         const char *paramName, 
         TwParamValueType paramValueType, 
         TwParamValueType paramValueType, 
         unsigned int inValueCount, 
         unsigned int inValueCount, 
         const void *inValues);
         const void *inValues);
-      int TwGetParam(
+      IGL_INLINE int TwGetParam(
         const char *varName, 
         const char *varName, 
         const char *paramName, 
         const char *paramName, 
         TwParamValueType paramValueType, 
         TwParamValueType paramValueType, 
         unsigned int outValueMaxCount, 
         unsigned int outValueMaxCount, 
         void *outValues);
         void *outValues);
-      int TwRefreshBar();
-      int TwTerminate();
+      IGL_INLINE int TwRefreshBar();
+      IGL_INLINE int TwTerminate();
   
   
   
   
     // IO FUNCTIONS
     // IO FUNCTIONS
@@ -216,7 +216,7 @@ namespace igl
       //   to stdout
       //   to stdout
       // Return:
       // Return:
       //   true only if there were no (fatal) errors
       //   true only if there were no (fatal) errors
-      bool save(const char *file_name);
+      IGL_INLINE bool save(const char *file_name);
       std::string get_value_as_string(
       std::string get_value_as_string(
         void * var, 
         void * var, 
         TwType type);
         TwType type);
@@ -225,7 +225,7 @@ namespace igl
       //   file_name  name of input file to load
       //   file_name  name of input file to load
       // Return:
       // Return:
       //   true only if there were no (fatal) errors
       //   true only if there were no (fatal) errors
-      bool load(const char *file_name);
+      IGL_INLINE bool load(const char *file_name);
       // Get TwType from string
       // Get TwType from string
       // Input
       // Input
       //   type_str  string of type 
       //   type_str  string of type 
@@ -233,10 +233,10 @@ namespace igl
       //   type  TwType converted from string
       //   type  TwType converted from string
       // Returns
       // Returns
       //   true only if string matched a valid type
       //   true only if string matched a valid type
-      bool type_from_string(const char *type_str, TwType & type);
+      IGL_INLINE bool type_from_string(const char *type_str, TwType & type);
       // I realize that I mix std::string and const char * all over the place.
       // I realize that I mix std::string and const char * all over the place.
       // What can you do...
       // What can you do...
-      bool set_value_from_string(
+      IGL_INLINE bool set_value_from_string(
         const char * name, 
         const char * name, 
         TwType type, 
         TwType type, 
         const char * value_str);
         const char * value_str);

+ 11 - 2
include/igl/embree/EmbreeIntersector.h

@@ -103,6 +103,7 @@ namespace igl
     embree::RTCTriangle* triangles;
     embree::RTCTriangle* triangles;
     embree::RTCVertex *vertices;
     embree::RTCVertex *vertices;
     embree::Intersector1 *intersector;
     embree::Intersector1 *intersector;
+    bool initialized;
   };
   };
 }
 }
 
 
@@ -148,7 +149,8 @@ inline igl::EmbreeIntersector::EmbreeIntersector()
   mesh(NULL),
   mesh(NULL),
   triangles(NULL),
   triangles(NULL),
   vertices(NULL),
   vertices(NULL),
-  intersector(NULL)
+  intersector(NULL),
+  initialized(false)
 {
 {
 }
 }
 
 
@@ -173,6 +175,10 @@ inline void igl::EmbreeIntersector::init(
   const char* builder,
   const char* builder,
   const char* traverser)
   const char* traverser)
 {
 {
+  
+  if (initialized)
+    deinit();
+  
   using namespace std;
   using namespace std;
   global_init();
   global_init();
 
 
@@ -203,12 +209,15 @@ inline void igl::EmbreeIntersector::init(
   embree::rtcCleanupGeometry(mesh);
   embree::rtcCleanupGeometry(mesh);
   
   
   intersector = embree::rtcQueryIntersector1(mesh,traverser);
   intersector = embree::rtcQueryIntersector1(mesh,traverser);
+  
+  initialized = true;
 }
 }
 
 
 igl::EmbreeIntersector
 igl::EmbreeIntersector
 ::~EmbreeIntersector()
 ::~EmbreeIntersector()
 {
 {
-  deinit();
+//  if (initialized)
+//    deinit();
 }
 }
 
 
 void igl::EmbreeIntersector::deinit()
 void igl::EmbreeIntersector::deinit()

+ 0 - 210
include/igl/xml/ReAntTweakBarXMLSerialization.cpp

@@ -1,210 +0,0 @@
-#include "ReAntTweakBarXMLSerialization.h"
-#include "XMLSerializer.h"
-
-#include <igl/ReAntTweakBar.h>
-
-IGL_INLINE bool igl::save_ReAntTweakBar(igl::ReTwBar* bar, const char* file_name)
-{
-  const char * name_chars = TwGetBarName(bar->bar);
-  std::string name = std::string(name_chars) + "_AntTweakBar";
-	
-  const std::vector<igl::ReTwRWItem>& rw_items = bar->get_rw_items();
-	for(std::vector<ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
-	{	
-		std::string val = bar->get_value_as_string(it->var,it->type);
-		igl::XMLSerializer::SaveObject(val,it->name,name,file_name,false);
-	}
-
-	char var[REANTTWEAKBAR_MAX_CB_VAR_SIZE];
-	// Print all CB variables
-  const std::vector<igl::ReTwCBItem>& cb_items = bar->get_cb_items();
-  for(std::vector<ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
-	{
-		TwType type = it->type;
-		//TwSetVarCallback setCallback = it->setCallback;
-		TwGetVarCallback getCallback = it->getCallback;
-		void * clientData = it->clientData;
-		// I'm not sure how to do what I want to do. getCallback needs to be sure
-		// that it can write to var. So var needs to point to a valid and big
-		// enough chunk of memory
-		getCallback(var,clientData);
-		
-		std::string val = bar->get_value_as_string(var,type);
-		igl::XMLSerializer::SaveObject(val,it->name,name,file_name,false);
-	}
-
-	return true;
-}
-
-IGL_INLINE bool igl::save_ReAntTweakBar(igl::ReTwBar* bar, tinyxml2::XMLDocument* doc)
-{
-  std::vector<char**> buffer;
-	
-  const char * name_chars = TwGetBarName(bar->bar);
-  std::string name = std::string(name_chars) + "_AntTweakBar";
-	igl::XMLSerializer* s = new igl::XMLSerializer(name);
-	
-  const std::vector<igl::ReTwRWItem>& rw_items = bar->get_rw_items();
-	for(std::vector<ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
-	{	
-		std::string val = bar->get_value_as_string(it->var,it->type);
-		char** cval = new char*; // create char* on heap
-		*cval = new char[val.size()+1];
-		buffer.push_back(cval);
-		strcpy(*cval,val.c_str());
-		s->Add(*cval,it->name);
-	}
-
-	char var[REANTTWEAKBAR_MAX_CB_VAR_SIZE];
-	// Print all CB variables
-  const std::vector<igl::ReTwCBItem>& cb_items = bar->get_cb_items();
-	for(std::vector<ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
-	{
-		TwType type = it->type;
-		//TwSetVarCallback setCallback = it->setCallback;
-		TwGetVarCallback getCallback = it->getCallback;
-		void * clientData = it->clientData;
-		// I'm not sure how to do what I want to do. getCallback needs to be sure
-		// that it can write to var. So var needs to point to a valid and big
-		// enough chunk of memory
-		getCallback(var,clientData);
-		
-		std::string val = bar->get_value_as_string(var,type);
-		char** cval = new char*; // create char* on heap
-		*cval = new char[val.size()+1];
-		buffer.push_back(cval);
-		strcpy(*cval,val.c_str());
-		s->Add(*cval,it->name);
-	}
-
-	s->SaveToXMLDoc(name,doc);
-
-	// delete pointer buffers
-	for(unsigned int i=0;i<buffer.size();i++)
-	{
-		delete[] *buffer[i];
-		delete buffer[i];
-	}
-
-	delete s;
-
-	return true;
-}
-
-IGL_INLINE bool igl::load_ReAntTweakBar(igl::ReTwBar* bar, const char *file_name)
-{
-	char type_str[REANTTWEAKBAR_MAX_WORD];
-	char value_str[REANTTWEAKBAR_MAX_WORD];
-	TwType type;
-	
-  const char * name_chars = TwGetBarName(bar->bar);
-  std::string name = std::string(name_chars) + "_AntTweakBar";
-
-  const std::vector<igl::ReTwRWItem>& rw_items = bar->get_rw_items();
-	for(std::vector<ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
-	{	
-		char* val;
-		igl::XMLSerializer::LoadObject(val,it->name,name,file_name);
-		sscanf(val,"%s %[^\n]",type_str,value_str);
-		
-		if(!bar->type_from_string(type_str,type))
-		{
-		  printf("ERROR: %s type not found... Skipping...\n",type_str);
-		  continue;
-		}
-		
-		bar->set_value_from_string(it->name.c_str(),type,value_str);
-		delete[] val;
-	}
-
-  const std::vector<igl::ReTwCBItem>& cb_items = bar->get_cb_items();
-	for(std::vector<ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
-	{
-		char* val;
-		igl::XMLSerializer::LoadObject(val,it->name,name,file_name);
-		sscanf(val,"%s %[^\n]",type_str,value_str);
-		
-		if(!bar->type_from_string(type_str,type))
-		{
-		  printf("ERROR: %s type not found... Skipping...\n",type_str);
-		  continue;
-		}
-		
-		bar->set_value_from_string(it->name.c_str(),type,value_str);
-		delete[] val;
-	}
-
-	return true;
-}
-
-IGL_INLINE bool igl::load_ReAntTweakBar(igl::ReTwBar* bar, tinyxml2::XMLDocument* doc)
-{
-	std::map<std::string,char*> variables;
-	std::map<std::string,char*> cbVariables;
-
-  const char * name_chars = TwGetBarName(bar->bar);
-  std::string name = std::string(name_chars) + "_AntTweakBar";
-	igl::XMLSerializer* s = new igl::XMLSerializer(name);
-	
-	std::map<std::string,char*>::iterator iter;
-  const std::vector<igl::ReTwRWItem>& rw_items = bar->get_rw_items();
-	for(std::vector<ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
-	{	
-		variables[it->name] = NULL;
-		iter = variables.find(it->name);
-		s->Add(iter->second,iter->first);
-	}
-
-	// Add all CB variables
-  const std::vector<igl::ReTwCBItem>& cb_items = bar->get_cb_items();
-	for(std::vector<ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
-	{
-		cbVariables[it->name] = NULL;
-		iter = cbVariables.find(it->name);
-		s->Add(iter->second,iter->first);
-	}
-	
-	s->LoadFromXMLDoc(doc);
-
-	// Set loaded values
-	char type_str[REANTTWEAKBAR_MAX_WORD];
-	char value_str[REANTTWEAKBAR_MAX_WORD];
-	TwType type;
-
-	for(iter = variables.begin(); iter != variables.end(); iter++)
-	{
-		sscanf(iter->second,"%s %[^\n]",type_str,value_str);
-		
-		if(!bar->type_from_string(type_str,type))
-		{
-		  printf("ERROR: %s type not found... Skipping...\n",type_str);
-		  continue;
-		}
-		
-		bar->set_value_from_string(iter->first.c_str(),type,value_str);
-	}
-
-	for(iter = cbVariables.begin(); iter != cbVariables.end(); iter++)
-	{
-		sscanf(iter->second,"%s %[^\n]",type_str,value_str);
-		
-		if(!bar->type_from_string(type_str,type))
-		{
-		  printf("ERROR: %s type not found... Skipping...\n",type_str);
-		  continue;
-		}
-		
-		bar->set_value_from_string(iter->first.c_str(),type,value_str);
-	}
-
-	// delete buffers
-	for(iter = variables.begin(); iter != variables.end(); iter++)
-		delete[] iter->second;
-
-	for(iter = cbVariables.begin(); iter != cbVariables.end(); iter++)
-		delete[] iter->second;	
-
-	delete s;
-
-	return true;
-}

+ 222 - 9
include/igl/xml/ReAntTweakBarXMLSerialization.h

@@ -1,6 +1,10 @@
 #ifndef IGL_REANTTWEAKBAR_XML_SERIALIZATION_H
 #ifndef IGL_REANTTWEAKBAR_XML_SERIALIZATION_H
 #define IGL_REANTTWEAKBAR_XML_SERIALIZATION_H
 #define IGL_REANTTWEAKBAR_XML_SERIALIZATION_H
 #include "../igl_inline.h"
 #include "../igl_inline.h"
+#include "XMLSerializer.h"
+
+#undef IGL_HEADER_ONLY
+#include <igl/ReAntTweakBar.h>
 
 
 // Forward declarations
 // Forward declarations
 namespace igl
 namespace igl
@@ -13,15 +17,224 @@ namespace tinyxml2
 };
 };
 
 
 namespace igl
 namespace igl
-{  
-  IGL_INLINE bool save_ReAntTweakBar(igl::ReTwBar* bar, const char* file_name);
-  IGL_INLINE bool save_ReAntTweakBar(igl::ReTwBar* bar, tinyxml2::XMLDocument* doc);
-  IGL_INLINE bool load_ReAntTweakBar(igl::ReTwBar* bar, const char *file_name);
-  IGL_INLINE bool load_ReAntTweakBar(igl::ReTwBar* bar, tinyxml2::XMLDocument* doc);
+{
+  
+//  namespace
+//  {
+  
+//    IGL_INLINE bool save_ReAntTweakBar(::igl::ReTwBar* bar, const char* file_name);
+//    IGL_INLINE bool save_ReAntTweakBar(::igl::ReTwBar* bar, tinyxml2::XMLDocument* doc);
+//    IGL_INLINE bool load_ReAntTweakBar(::igl::ReTwBar* bar, const char *file_name);
+//    IGL_INLINE bool load_ReAntTweakBar(::igl::ReTwBar* bar, tinyxml2::XMLDocument* doc);
+    
+    
+    IGL_INLINE bool save_ReAntTweakBar(::igl::ReTwBar* bar, const char* file_name)
+    {
+      const char * name_chars = TwGetBarName(bar->bar);
+      std::string name = std::string(name_chars) + "_AntTweakBar";
+      
+      const std::vector< ::igl::ReTwRWItem>& rw_items = bar->get_rw_items();
+      for(std::vector< ::igl::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
+      {
+        std::string val = bar->get_value_as_string(it->var,it->type);
+        ::igl::XMLSerializer::SaveObject(val,it->name,name,file_name,false);
+      }
+      
+      char var[REANTTWEAKBAR_MAX_CB_VAR_SIZE];
+      // Print all CB variables
+      const std::vector< ::igl::ReTwCBItem>& cb_items = bar->get_cb_items();
+      for(std::vector< ::igl::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
+      {
+        TwType type = it->type;
+        //TwSetVarCallback setCallback = it->setCallback;
+        TwGetVarCallback getCallback = it->getCallback;
+        void * clientData = it->clientData;
+        // I'm not sure how to do what I want to do. getCallback needs to be sure
+        // that it can write to var. So var needs to point to a valid and big
+        // enough chunk of memory
+        getCallback(var,clientData);
+        
+        std::string val = bar->get_value_as_string(var,type);
+        ::igl::XMLSerializer::SaveObject(val,it->name,name,file_name,false);
+      }
+      
+      return true;
+    }
+    
+    IGL_INLINE bool save_ReAntTweakBar(::igl::ReTwBar* bar, tinyxml2::XMLDocument* doc)
+    {
+      std::vector<char**> buffer;
+      
+      const char * name_chars = TwGetBarName(bar->bar);
+      std::string name = std::string(name_chars) + "_AntTweakBar";
+      ::igl::XMLSerializer* s = new ::igl::XMLSerializer(name);
+      
+      const std::vector< ::igl::ReTwRWItem>& rw_items = bar->get_rw_items();
+      for(std::vector< ::igl::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
+      {
+        std::string val = bar->get_value_as_string(it->var,it->type);
+        char** cval = new char*; // create char* on heap
+        *cval = new char[val.size()+1];
+        buffer.push_back(cval);
+        strcpy(*cval,val.c_str());
+        s->Add(*cval,it->name);
+      }
+      
+      char var[REANTTWEAKBAR_MAX_CB_VAR_SIZE];
+      // Print all CB variables
+      const std::vector< ::igl::ReTwCBItem>& cb_items = bar->get_cb_items();
+      for(std::vector< ::igl::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
+      {
+        TwType type = it->type;
+        //TwSetVarCallback setCallback = it->setCallback;
+        TwGetVarCallback getCallback = it->getCallback;
+        void * clientData = it->clientData;
+        // I'm not sure how to do what I want to do. getCallback needs to be sure
+        // that it can write to var. So var needs to point to a valid and big
+        // enough chunk of memory
+        getCallback(var,clientData);
+        
+        std::string val = bar->get_value_as_string(var,type);
+        char** cval = new char*; // create char* on heap
+        *cval = new char[val.size()+1];
+        buffer.push_back(cval);
+        strcpy(*cval,val.c_str());
+        s->Add(*cval,it->name);
+      }
+      
+      s->SaveToXMLDoc(name,doc);
+      
+      // delete pointer buffers
+      for(unsigned int i=0;i<buffer.size();i++)
+      {
+        delete[] *buffer[i];
+        delete buffer[i];
+      }
+      
+      delete s;
+      
+      return true;
+    }
+    
+    IGL_INLINE bool load_ReAntTweakBar(::igl::ReTwBar* bar, const char *file_name)
+    {
+      char type_str[REANTTWEAKBAR_MAX_WORD];
+      char value_str[REANTTWEAKBAR_MAX_WORD];
+      TwType type;
+      
+      const char * name_chars = TwGetBarName(bar->bar);
+      std::string name = std::string(name_chars) + "_AntTweakBar";
+      
+      const std::vector< ::igl::ReTwRWItem>& rw_items = bar->get_rw_items();
+      for(std::vector< ::igl::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
+      {
+        char* val;
+        ::igl::XMLSerializer::LoadObject(val,it->name,name,file_name);
+        sscanf(val,"%s %[^\n]",type_str,value_str);
+        
+        if(!bar->type_from_string(type_str,type))
+        {
+          printf("ERROR: %s type not found... Skipping...\n",type_str);
+          continue;
+        }
+        
+        bar->set_value_from_string(it->name.c_str(),type,value_str);
+        delete[] val;
+      }
+      
+      const std::vector< ::igl::ReTwCBItem>& cb_items = bar->get_cb_items();
+      for(std::vector< ::igl::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
+      {
+        char* val;
+        ::igl::XMLSerializer::LoadObject(val,it->name,name,file_name);
+        sscanf(val,"%s %[^\n]",type_str,value_str);
+        
+        if(!bar->type_from_string(type_str,type))
+        {
+          printf("ERROR: %s type not found... Skipping...\n",type_str);
+          continue;
+        }
+        
+        bar->set_value_from_string(it->name.c_str(),type,value_str);
+        delete[] val;
+      }
+      
+      return true;
+    }
+    
+    IGL_INLINE bool load_ReAntTweakBar(::igl::ReTwBar* bar, tinyxml2::XMLDocument* doc)
+    {
+      std::map<std::string,char*> variables;
+      std::map<std::string,char*> cbVariables;
+      
+      const char * name_chars = TwGetBarName(bar->bar);
+      std::string name = std::string(name_chars) + "_AntTweakBar";
+      ::igl::XMLSerializer* s = new ::igl::XMLSerializer(name);
+      
+      std::map<std::string,char*>::iterator iter;
+      const std::vector< ::igl::ReTwRWItem>& rw_items = bar->get_rw_items();
+      for(std::vector< ::igl::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
+      {
+        variables[it->name] = NULL;
+        iter = variables.find(it->name);
+        s->Add(iter->second,iter->first);
+      }
+      
+      // Add all CB variables
+      const std::vector< ::igl::ReTwCBItem>& cb_items = bar->get_cb_items();
+      for(std::vector< ::igl::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
+      {
+        cbVariables[it->name] = NULL;
+        iter = cbVariables.find(it->name);
+        s->Add(iter->second,iter->first);
+      }
+      
+      s->LoadFromXMLDoc(doc);
+      
+      // Set loaded values
+      char type_str[REANTTWEAKBAR_MAX_WORD];
+      char value_str[REANTTWEAKBAR_MAX_WORD];
+      TwType type;
+      
+      for(iter = variables.begin(); iter != variables.end(); iter++)
+      {
+        sscanf(iter->second,"%s %[^\n]",type_str,value_str);
+        
+        if(!bar->type_from_string(type_str,type))
+        {
+          printf("ERROR: %s type not found... Skipping...\n",type_str);
+          continue;
+        }
+        
+        bar->set_value_from_string(iter->first.c_str(),type,value_str);
+      }
+      
+      for(iter = cbVariables.begin(); iter != cbVariables.end(); iter++)
+      {
+        sscanf(iter->second,"%s %[^\n]",type_str,value_str);
+        
+        if(!bar->type_from_string(type_str,type))
+        {
+          printf("ERROR: %s type not found... Skipping...\n",type_str);
+          continue;
+        }
+        
+        bar->set_value_from_string(iter->first.c_str(),type,value_str);
+      }
+      
+      // delete buffers
+      for(iter = variables.begin(); iter != variables.end(); iter++)
+        delete[] iter->second;
+      
+      for(iter = cbVariables.begin(); iter != cbVariables.end(); iter++)
+        delete[] iter->second;
+      
+      delete s;
+      
+      return true;
+    }
+    
+//  }
 }
 }
 
 
-#ifdef IGL_HEADER_ONLY
-#  include "ReAntTweakBarXMLSerialization.cpp"
-#endif
-
 #endif
 #endif

+ 0 - 1599
include/igl/xml/XMLSerializer.cpp

@@ -1,1599 +0,0 @@
-#include "XMLSerializer.h"
-
-//TODO: these should probably be static. Do they need to be in the igl
-//namespace?
-namespace igl
-{
-  int numForbiddenChars = 8;
-  char forbiddenChars[] = {' ','/','~','#','&','>','<','='};
-}
-
-void igl::ReplaceSubString(std::string& str, const std::string& search, const std::string& replace)
-{
-  size_t pos = 0;
-  while ((pos = str.find(search, pos)) != std::string::npos)
-  {
-    str.replace(pos, search.length(), replace);
-    pos += replace.length();
-  }
-}
-
-void igl::EncodeXMLElementName(std::string& name)
-{    
-  // must not start with a digit
-  if(isdigit(*name.begin()))
-  {
-    name = ":::" + name;
-  }
-    
-  std::stringstream stream;
-  for(int i=0;i<numForbiddenChars;i++)
-  {
-    std::string search;
-    search = forbiddenChars[i];
-    std::stringstream replaces;
-    replaces << ":" << (int)forbiddenChars[i];
-    std::string replace = replaces.str(); 
-      
-    ReplaceSubString(name,search,replace);
-  }
-}
-
-/*void igl::DecodeXMLElementName(std::string& name)
-{
-  if(name.find("::", 0) == 0)
-    name.replace(0,3,"");
-
-  std::stringstream stream;
-  for(unsigned int i=0;i<numForbiddenChars;i++)
-  {
-    std::stringstream searchs;
-    searchs << ":" << (int)forbiddenChars[i];
-    std::string search = searchs.str();
-    std::string replace;
-    replace = forbiddenChars[i];
-      
-    ReplaceSubString(name,search,replace);
-  }
-}*/
-
-void igl::XMLSerialization::Init()
-{
-}
-
-bool igl::XMLSerialization::Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element)
-{
-  bool serialized = false;
-  
-  if(BeforeSerialization())
-  {
-    serialized = xmlSerializer->SaveGroupToXMLElement(doc,element,Name);
-    AfterSerialization();
-  }
-
-  return serialized;
-}
-
-bool igl::XMLSerialization::Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element)
-{
-  bool serialized = false;
-  
-  if(BeforeDeserialization())
-  {
-    serialized = xmlSerializer->LoadGroupFromXMLElement(Name,doc,element);
-    AfterDeserialization();
-  }
-  
-  return serialized;
-}
-
-igl::XMLSerialization::XMLSerialization(const std::string& name)
-{
-  Name = name;
-  xmlSerializer = new igl::XMLSerializer(name);
-}
-
-igl::XMLSerialization::~XMLSerialization()
-{
-  delete xmlSerializer;
-}
-
-bool igl::XMLSerialization::BeforeSerialization()
-{
-  return true;
-}
-
-void igl::XMLSerialization::AfterSerialization()
-{
-}
-
-bool igl::XMLSerialization::BeforeDeserialization()
-{
-  return true;
-}
-
-void igl::XMLSerialization::AfterDeserialization()
-{
-}
-
-igl::XMLSerializableObject::XMLSerializableObject(const std::string& name, const std::string& group)
-{
-  std::string groupName = group;
-  std::string objectName = name;
-    
-  igl::EncodeXMLElementName(groupName);
-  igl::EncodeXMLElementName(objectName);
-    
-  Name = objectName;
-}
-
-igl::XMLSerializableObject::~XMLSerializableObject()
-{
-}
-
-// set attribute conversion functions
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, char& dest)
-{ 
-  element->SetAttribute(name,dest);
-}
-  
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, char*& dest)
-{ 
-  element->SetAttribute(name,const_cast<const char*>(dest));
-}
-
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, std::string& dest)
-{
-  element->SetAttribute(name,dest.c_str());
-}
-
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, bool& dest)
-{
-  element->SetAttribute(name,dest);
-}
-  
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, unsigned int& dest)
-{
-  element->SetAttribute(name,dest);
-}
-
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, int& dest)
-{
-  element->SetAttribute(name,dest);
-}
-
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, float& dest)
-{
-  element->SetAttribute(name,dest);
-}
-
-void igl::XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, double& dest)
-{
-  element->SetAttribute(name,dest);
-}
-
-// get attribute conversion functions
-void igl::XMLSerializableObject::GetAttribute(const char* src, char& dest)
-{ 
-  dest = (char)atoi(src);
-}
-  
-void igl::XMLSerializableObject::GetAttribute(const char* src, char*& dest)
-{ 
-  unsigned int length = strlen(src)+1;
-  dest = new char[length];
-  strcpy(dest, src);
-}
-
-void igl::XMLSerializableObject::GetAttribute(const char* src, std::string& dest)
-{
-  dest = src;
-}
-  
-void igl::XMLSerializableObject::GetAttribute(const char* src, bool& dest)
-{
-  tinyxml2::XMLUtil::ToBool(src,&dest);
-}
-  
-void igl::XMLSerializableObject::GetAttribute(const char* src, unsigned int& dest)
-{
-  tinyxml2::XMLUtil::ToUnsigned(src,&dest);
-}
-
-void igl::XMLSerializableObject::GetAttribute(const char* src, int& dest)
-{
-  tinyxml2::XMLUtil::ToInt(src,&dest);
-}
-
-void igl::XMLSerializableObject::GetAttribute(const char* src, float& dest)
-{
-  tinyxml2::XMLUtil::ToFloat(src,&dest);
-}
-
-void igl::XMLSerializableObject::GetAttribute(const char* src, double& dest)
-{
-  tinyxml2::XMLUtil::ToDouble(src,&dest);
-}
-
-// specify default value of types
-void igl::XMLSerializableObject::Init(char& val)
-{
-  val = '0';
-}
-
-void igl::XMLSerializableObject::Init(char*& val)
-{
-  val = NULL;
-}
-
-void igl::XMLSerializableObject::Init(std::string& val)
-{
-  val = "";
-}
-
-void igl::XMLSerializableObject::Init(bool& val)
-{
-  val = false;
-}
-
-void igl::XMLSerializableObject::Init(unsigned int& val)
-{
-  val = 0;
-}
-
-void igl::XMLSerializableObject::Init(int& val)
-{
-  val = 0;
-}
-
-void igl::XMLSerializableObject::Init(float& val)
-{
-  val = 0.0f;
-}
-
-void igl::XMLSerializableObject::Init(double& val)
-{
-  val = 0.000000000000000;
-}
-
-template<typename T>
-void igl::XMLSerializableObject::Init(T*& obj)
-{
-  igl::XMLSerializable* object = static_cast<igl::XMLSerializable*>(obj);
-  object->Init();  
-}
-
-/*template<typename T, int S>
-void igl::XMLSerializableObject::Init(std::array<T,S>& obj)
-{
-  for(unsigned int i=0;i<obj.size();i++)
-    Init(obj[i]);  
-}*/
-
-template<typename T0, typename T1>
-void igl::XMLSerializableObject::Init(std::pair<T0,T1>& obj)
-{
-  Init(obj.first);
-  Init(obj.second);
-}
-
-template<typename T>
-void igl::XMLSerializableObject::Init(std::vector<T>& obj)
-{
-  obj.clear();
-}
-
-template<typename T, int R, int C>
-void igl::XMLSerializableObject::Init(Eigen::Matrix<T,R,C>& obj)
-{
-  obj.setZero(obj.rows(),obj.cols());
-}
-
-template<typename T>
-void  igl::XMLSerializableObject::Init(Eigen::SparseMatrix<T>& obj)
-{
-  obj.setZero();
-}
-
-bool igl::XMLSerializableObject::Serialize(char& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-// overload function for char*, it interpreted as char array and can be used to handle strings
-bool igl::XMLSerializableObject::Serialize(char*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(std::string& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(std::string*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(bool& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(bool*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(unsigned int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(float& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(float*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(double& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return setElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Serialize(double*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Serialize(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{ 
-  return false;
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Serialize(T*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  // Serialize object implementing XMLSerializable interface
-  igl::XMLSerializable* object = static_cast<igl::XMLSerializable*>(obj);
-  
-  tinyxml2::XMLElement* child = doc->NewElement(name.c_str());
-  element->InsertEndChild(child);
-  
-  return object->Serialize(doc,child);
-}
-
-bool igl::XMLSerializableObject::Deserialize(char& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);      
-}
-
-// template specialisation for char*, it interpreted as char array and can be used to handle strings
-bool igl::XMLSerializableObject::Deserialize(char*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);    
-}
-
-bool igl::XMLSerializableObject::Deserialize(std::string& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(std::string*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Deserialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(bool& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(bool*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Deserialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(unsigned int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Deserialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Deserialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(float& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(float*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Deserialize(*obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(double& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return getElementAttribute(obj,doc,element,name);
-}
-
-bool igl::XMLSerializableObject::Deserialize(double*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Deserialize(*obj,doc,element,name);
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Deserialize(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  return false;  
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Deserialize(T*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  obj = new T();
-  igl::XMLSerializable* object = static_cast<igl::XMLSerializable*>(obj);
-  
-  const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
-
-  object->Name = child->FirstChild()->Value();
-
-  if(child != NULL)
-  {  
-    obj->Deserialize(doc,child);
-  }
-  else
-  {
-    obj->Init();
-    return false;
-  }
-
-  return true;
-}
-
-/*template<typename T, size_t S>
-bool igl::XMLSerializableObject::Serialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  tinyxml2::XMLElement* ar = doc->NewElement(name.c_str());
-  element->InsertEndChild(ar);
-  
-  ar->SetAttribute("size",(unsigned int)obj.size());
-    
-  std::stringstream num;
-  for(unsigned int i=0;i<obj.size();i++)
-  {
-    num.str("");
-    num << "value" << i;
-    Serialize(obj[i],doc,ar,num.str());
-  }
-
-  return true;
-}
-
-template<typename T, size_t S>
-bool igl::XMLSerializableObject::Serialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-template<typename T, size_t S>
-bool igl::XMLSerializableObject::Deserialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  bool res = true;
-     
-  const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
-  if(child != NULL)
-  {  
-    int size = child->UnsignedAttribute("size");
-    size = S < size ? S : size;
-
-    std::stringstream num;
-    const tinyxml2::XMLAttribute* attribute = NULL;
-    for(unsigned int i=0;i<size;i++)
-    {
-      num.str("");
-      num << "value" << i;
-      
-      res &= Deserialize(obj[i],doc,child,num.str());
-    }
-  }
-  else
-    return false;
-  
-  return res;
-}
-
-template<typename T, size_t S>
-bool igl::XMLSerializableObject::Deserialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  obj = new std::array<T,S>();
-  return Deserialize(*obj,doc,element,name);
-}*/
-
-template<typename T0, typename T1>
-bool igl::XMLSerializableObject::Serialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  bool res = true;
-
-  tinyxml2::XMLElement* pair = doc->NewElement(name.c_str());
-  element->InsertEndChild(pair);
-
-  res &= Serialize(obj.first,doc,pair,"first");
-  res &= Serialize(obj.second,doc,pair,"second");
-
-  return res;
-}
-
-template<typename T0, typename T1>
-bool igl::XMLSerializableObject::Serialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-template<typename T0, typename T1>
-bool igl::XMLSerializableObject::Deserialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  bool res = true;
-  
-  const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
-  if(child != NULL)
-  {  
-    res &= Deserialize(obj.first,doc,child,"first");
-    res &= Deserialize(obj.second,doc,child,"second");
-  }
-  else
-  {
-    Init(obj.first);
-    Init(obj.second);
-    return false;
-  }
-
-  return res;
-}
-
-template<typename T0, typename T1>
-bool igl::XMLSerializableObject::Deserialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  obj = new std::pair<T0,T1>();
-  return Deserialize(*obj,doc,element,name);
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Serialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  tinyxml2::XMLElement* vector = doc->NewElement(name.c_str());
-  element->InsertEndChild(vector);
-  
-  vector->SetAttribute("size",(unsigned int)obj.size());
-    
-  std::stringstream num;
-  for(unsigned int i=0;i<obj.size();i++)
-  {
-    num.str("");
-    num << "value" << i;
-    Serialize(obj[i],doc,vector,num.str());
-  }
-
-  return true;
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Deserialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  bool res = true;
-  obj.clear();
-    
-  const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
-  if(child != NULL)
-  {  
-    unsigned int size = child->UnsignedAttribute("size");
-    obj.resize(size);
-
-    std::stringstream num;
-    for(unsigned int i=0;i<size;i++)
-    {
-      num.str("");
-      num << "value" << i;
-      
-      res &= Deserialize(obj[i],doc,child,num.str());
-    }
-  }
-  else
-    return false;
-  
-  return res;
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Serialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Deserialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  obj = new std::vector<T>();
-  return Deserialize(*obj,doc,element,name);
-}
-
-template<typename T, int R, int C>
-bool igl::XMLSerializableObject::Serialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  tinyxml2::XMLElement* matrix = doc->NewElement(name.c_str());
-  element->InsertEndChild(matrix);
-  
-  const unsigned int rows = obj.rows();
-  const unsigned int cols = obj.cols();
-
-  matrix->SetAttribute("rows",rows);
-  matrix->SetAttribute("cols",cols);
-
-  std::stringstream ms;
-  ms << "\n";
-  for(unsigned int r=0;r<rows;r++)
-  {
-    for(unsigned int c=0;c<cols;c++)
-    {
-      ms << obj(r,c) << ",";
-    }
-    ms << "\n";
-  }
-
-  std::string mString = ms.str();
-  if(mString.size() > 1)
-    mString[mString.size()-2] = '\0';
-
-  matrix->SetAttribute("matrix",mString.c_str());
-    
-  return true;
-}
-
-template<typename T, int R, int C>
-bool igl::XMLSerializableObject::Serialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-template<typename T, int R, int C>
-bool igl::XMLSerializableObject::Deserialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
-  if(child != NULL)
-  {
-    const unsigned int rows = child->UnsignedAttribute("rows");
-    const unsigned int cols = child->UnsignedAttribute("cols");
-    
-    obj.resize(rows,cols);
-    
-    const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
-    if(attribute == NULL)
-    {
-      Init(obj);
-      return false;
-    }
-    
-    char* matTemp; 
-    GetAttribute(attribute->Value(),matTemp);
-    
-    std::string line, srows, scols;
-    std::stringstream mats;
-    mats.str(matTemp);
-    
-    int r=0;
-    std::string val;
-    // for each line
-    getline(mats,line);
-    while(getline(mats,line))
-    {
-      // get current line
-      std::stringstream liness(line);
-
-      for(unsigned int c=0;c<cols-1;c++)
-      {
-        // split line
-        getline(liness, val, ',');
-
-        // push pack the data if any
-        if(!val.empty())
-          GetAttribute(val.c_str(),obj.coeffRef(r,c));
-      }
-
-      getline(liness, val);
-      GetAttribute(val.c_str(),obj.coeffRef(r,cols-1));
-
-      r++;
-    }
-  }
-  else
-  {
-    Init(obj);
-    return false;
-  }
-    
-  return true;
-}
-
-template<typename T, int R, int C>
-bool igl::XMLSerializableObject::Deserialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  obj = new Eigen::PlainObjectBase<T>();
-  return Deserialize(*obj,doc,element,name);
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Serialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  tinyxml2::XMLElement* matrix = doc->NewElement(name.c_str());
-  element->InsertEndChild(matrix);
-
-  const unsigned int rows = obj.rows();
-  const unsigned int cols = obj.cols();
-
-  matrix->SetAttribute("rows",rows);
-  matrix->SetAttribute("cols",cols);
-    
-  std::stringstream ms;
-  ms << "\n";
-  for (int k=0;k<obj.outerSize();++k)
-  {
-    for (typename Eigen::SparseMatrix<T>::InnerIterator it(obj,k);it;++it)
-    {
-      ms << it.row() << "," << it.col() << "," << it.value() << "\n";
-    }
-  }
-
-  std::string mString = ms.str();
-  if(mString.size() > 0)
-    mString[mString.size()-1] = '\0';
-
-  matrix->SetAttribute("matrix",mString.c_str());
-
-  return true;
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Serialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return Serialize(*obj,doc,element,name);
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Deserialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
-  if(child != NULL)
-  {
-    const unsigned int rows = child->UnsignedAttribute("rows");
-    const unsigned int cols = child->UnsignedAttribute("cols");
-    
-    obj.resize(rows,cols);
-    obj.setZero();
-    
-    const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
-    if(attribute == NULL)
-    {
-      Init(obj);
-      return false;
-    }
-    
-    char* matTemp; 
-    GetAttribute(attribute->Value(),matTemp);
-
-    std::string line, srows, scols;
-    std::stringstream mats;
-    mats.str(matTemp);
-
-    std::vector<Eigen::Triplet<T> > triplets;
-    int r=0;
-    std::string val;
-
-    // for each line
-    getline(mats,line);
-    while(getline(mats,line))
-    {
-      // get current line
-      std::stringstream liness(line);
-
-      // row
-      getline(liness, val, ',');
-      int row = atoi(val.c_str());
-      // col
-      getline(liness, val, ',');
-      int col = atoi(val.c_str());
-      // val
-      getline(liness, val);
-      T value;
-      GetAttribute(val.c_str(),value);
-
-      triplets.push_back(Eigen::Triplet<T>(row,col,value));
-
-      r++;
-    }
-
-    obj.setFromTriplets(triplets.begin(),triplets.end());
-  }
-  else
-  {
-    Init(obj);
-    return false;
-  }
-    
-  return true;
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::Deserialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-  obj = new Eigen::SparseMatrix<T>();
-  return Deserialize(*obj,doc,element,name);
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::setElementAttribute(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  tinyxml2::XMLElement* child = doc->NewElement(name.c_str());
-  element->InsertEndChild(child);
-  SetAttribute(child,"val",obj);
-  return true;
-}
-
-template<typename T>
-bool igl::XMLSerializableObject::getElementAttribute(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
-{
-// basic data type
-  const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
-  if(child != NULL)
-  {  
-    igl::XMLSerializableObject::GetAttribute(child->Attribute("val"),obj);
-    return true;
-  }
-  else
-  {
-    Init(obj);
-    return false;
-  }
-}
-
-template<typename T>
-igl::XMLSerializableInstance<T>::XMLSerializableInstance(T& obj, const std::string& name, const std::string group)
-  : XMLSerializableObject(name, group), Object(obj)
-{
-  igl::XMLSerializableObject::Init(DefaultValue);
-}
-
-template<typename T>
-igl::XMLSerializableInstance<T>::XMLSerializableInstance(T& obj, const std::string& name, const std::string group, T defaultValue)
-  : XMLSerializableObject(name, group), Object(obj), DefaultValue(defaultValue)
-{
-}
-
-template<typename T>
-igl::XMLSerializableInstance<T>::~XMLSerializableInstance()
-{
-}
-
-template<typename T>
-void igl::XMLSerializableInstance<T>::Init()
-{
-  igl::XMLSerializableObject::Init(DefaultValue);
-}
-
-template<typename T>
-bool igl::XMLSerializableInstance<T>::Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element)
-{
-  return igl::XMLSerializableObject::Serialize(Object,doc,element,Name);
-}
-
-template<typename T>
-bool igl::XMLSerializableInstance<T>::Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element)
-{
-  return igl::XMLSerializableObject::Deserialize(Object,doc,element,Name);
-}
-
-template<typename T>
-bool igl::XMLSerializer::SaveObject(T& object, const char* filename)
-{
-  return SaveObject(object,"Object","Serialization",filename,true);
-}
-
-template<typename T>
-bool igl::XMLSerializer::SaveObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite)
-{
-  bool result = true;
-  XMLSerializer* serializer = new XMLSerializer(groupName);
-  result &= serializer->Add(object,objectName);
-  result &= serializer->Save(objectName,groupName,filename,overwrite);
-  delete serializer;
-  return result;
-}
-
-template<typename T>
-bool igl::XMLSerializer::LoadObject(T& object, const char* filename)
-{
-  return LoadObject(object,"Object","Serialization",filename);
-}
-
-template<typename T>
-bool igl::XMLSerializer::LoadObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename)
-{
-  bool result = true;
-  XMLSerializer* serializer = new XMLSerializer(groupName);
-  result &= serializer->Add(object,objectName);
-  result &= serializer->Load(objectName,groupName,filename);
-  delete serializer;
-  return result;
-}
-    
-igl::XMLSerializer::XMLSerializer(const std::string& defaultGroup) 
-{
-  SetCurrentGroup(defaultGroup);
-}
-
-igl::XMLSerializer::~XMLSerializer()
-{
-  std::map<std::string,XMLSerializerGroup*>::iterator it;
-  for (it=groups.begin();it!=groups.end();it++)
-  {
-    delete it->second->Objects;
-    delete it->second;
-  }
-}
-
-bool igl::XMLSerializer::Save(const char* filename, bool overwrite)
-{
-  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
-
-  if(overwrite == false)
-  {
-    // Check if file exists
-    tinyxml2::XMLError error = doc->LoadFile(filename);
-    if(error != tinyxml2::XML_NO_ERROR)
-      doc->Clear();
-  }
-
-  if(SaveToXMLDoc(doc) == false)
-    return false;
-    
-  // Save
-  tinyxml2::XMLError error = doc->SaveFile(filename);
-  if(error != tinyxml2::XML_NO_ERROR)
-  {
-    doc->PrintError();
-    return false;
-  }
-
-  delete doc;
-
-  return true;
-}
-
-bool igl::XMLSerializer::SaveToXMLDoc(tinyxml2::XMLDocument* doc)
-{
-  std::map<std::string,XMLSerializerGroup*>::iterator it;
-  for (it=groups.begin();it!=groups.end();it++)
-  {
-    // Update group
-    tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
-    if(element != NULL)
-    {
-      element->DeleteChildren();
-    }
-    else
-    {
-      element = doc->NewElement(it->first.c_str());
-      doc->InsertEndChild(element);
-    }
-
-    std::vector<XMLSerializable*>* group = it->second->Objects;
-    for(unsigned  int i=0;i<group->size();i++)
-    {
-      if((*group)[i]->Serialize(doc,element) == false)
-        return false;
-    }
-  }
-
-  return true;
-}
-
-bool igl::XMLSerializer::Save(const std::string& groupName, const char* filename, bool overwrite)
-{
-  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
-    
-  if(overwrite == false)
-  {
-    // Check if file exists
-    tinyxml2::XMLError error = doc->LoadFile(filename);
-    if(error != tinyxml2::XML_NO_ERROR)
-      doc->Clear();
-  }
-
-  if(SaveToXMLDoc(groupName, doc) == false)
-    return false;
-
-  // Save
-  tinyxml2::XMLError error = doc->SaveFile(filename);
-  if(error != tinyxml2::XML_NO_ERROR)
-  {
-    doc->PrintError();
-    return false;
-  }
-
-  delete doc;
-    
-  return true;
-}
-
-bool igl::XMLSerializer::SaveToXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc)
-{
-  std::string gn = groupName;
-  EncodeXMLElementName(gn);
-    
-  std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
-  if(it == groups.end())
-    return false;
-
-  // Update group
-  tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
-  if(element != NULL)
-  {
-    element->DeleteChildren();
-  }
-  else
-  {
-    element = doc->NewElement(it->first.c_str());
-    doc->InsertEndChild(element);
-  }
-    
-  std::vector<XMLSerializable*>* groups = it->second->Objects;
-  for(unsigned int i=0;i<groups->size();i++)
-  {
-    if((*groups)[i]->Serialize(doc,element) == false)
-      return false;
-  }
-    
-  return true;
-}
-
-bool igl::XMLSerializer::Save(const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite)
-{
-  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
-    
-  if(overwrite == false)
-  {
-    // Check if file exists
-    tinyxml2::XMLError error = doc->LoadFile(filename);
-    if(error != tinyxml2::XML_NO_ERROR)
-      doc->Clear();
-  }
-    
-  if(SaveToXMLDoc(objectName, groupName, doc) == false)
-    return false;
-
-  // Save
-  tinyxml2::XMLError error = doc->SaveFile(filename);
-  if(error != tinyxml2::XML_NO_ERROR)
-  {
-    doc->PrintError();
-    return false;
-  }
-
-  delete doc;
-    
-  return true;
-}
-
-bool igl::XMLSerializer::SaveToXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc)
-{
-  std::string gn = groupName;
-  EncodeXMLElementName(gn);
-
-  std::string on = objectName;
-  EncodeXMLElementName(on);
-    
-  std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
-  if(it == groups.end())
-    return false;
-
-  // Get/Add group
-  tinyxml2::XMLElement* element = findAddGroup(doc, it->first.c_str());
-    
-  // Serialize
-  std::vector<XMLSerializable*>* groups = it->second->Objects;
-  bool found = false;
-  for(unsigned int i=0;i<groups->size();i++)
-  {
-    if((*groups)[i]->Name == on)
-    {
-      found = true;
-        
-      tinyxml2::XMLElement* child = element->FirstChildElement(on.c_str());
-      if(child != NULL)
-      {
-        element->DeleteChild(child);
-      }
-
-      if((*groups)[i]->Serialize(doc,element) == false)
-        return false;
-    }
-  }
-
-  return found;
-}
-
-bool igl::XMLSerializer::SaveGroupToXMLElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{
-  return SaveGroupToXMLElement(currentGroup->first,doc,element,name);
-}
-
-bool igl::XMLSerializer::SaveGroupToXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
-{ 
-  std::string gn = groupName;
-  EncodeXMLElementName(gn);
-    
-  std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
-  if(it == groups.end())
-    return false;
-
-  // Add new group
-  tinyxml2::XMLElement* group = doc->NewElement(name.c_str());
-  element->InsertEndChild(group);
-    
-  std::vector<XMLSerializable*>* groups = it->second->Objects;
-  for(unsigned int i=0;i<groups->size();i++)
-  {
-    if((*groups)[i]->Serialize(doc,group) == false)
-      return false;
-  } 
-
-  return true;
-}
-
-bool igl::XMLSerializer::Load(const char* filename)
-{
-  tinyxml2::XMLDocument* doc = openDoc(filename);
-  if(doc == NULL)
-    return false;
-
-  if(LoadFromXMLDoc(doc) == false)
-    return false;
-
-  delete doc;
-
-  return true;
-}
-
-bool igl::XMLSerializer::LoadFromXMLDoc(tinyxml2::XMLDocument* doc)
-{
-  std::map<std::string,XMLSerializerGroup*>::iterator it;
-  for (it=groups.begin();it!=groups.end();it++)
-  {
-    tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
-    if(element == NULL)
-    return false;
-      
-    // Deserialize
-    std::vector<XMLSerializable*>* group = it->second->Objects;
-    for(unsigned int i=0;i<group->size();i++)
-    {
-      if(element == NULL || (*group)[i]->Deserialize(doc,element) == false)
-        (*group)[i]->Init(); // Load default value;
-    }
-  }
-
-  return true;
-}
-
-bool igl::XMLSerializer::Load(const std::string& groupName, const char* filename)
-{
-  tinyxml2::XMLDocument* doc = openDoc(filename);
-  if(doc == NULL)
-    return false;
-
-  if(LoadFromXMLDoc(groupName, doc) == false)
-    return false;
-
-  delete doc;
-    
-  return true;
-}
-
-bool igl::XMLSerializer::LoadFromXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc)
-{
-  std::string gn = groupName;
-  EncodeXMLElementName(gn);
-
-  std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
-  if(it == groups.end())
-    return false;
-
-  tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
-  if(element == NULL)
-    return false;
-
-  // Deserialize
-  std::vector<XMLSerializable*>* groups = it->second->Objects;
-  for(unsigned int i=0;i<groups->size();i++)
-  {
-    if(element == NULL || (*groups)[i]->Deserialize(doc,element) == false)
-      (*groups)[i]->Init(); // Load default value;
-  }
-    
-  return true;
-}
-
-bool igl::XMLSerializer::Load(const std::string& objectName, const std::string& groupName, const char* filename)
-{
-  tinyxml2::XMLDocument* doc = openDoc(filename);
-  if(doc == NULL)
-    return false;
-
-  if(LoadFromXMLDoc(objectName,groupName,doc) == false)
-    return false;
-
-  delete doc;
-    
-  return true;
-}
-
-bool igl::XMLSerializer::LoadFromXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc)
-{
-  std::string gn = groupName;
-  EncodeXMLElementName(gn);
-    
-  std::string on = objectName;
-  EncodeXMLElementName(on);
-    
-  std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
-  if(it == groups.end())
-    return false;
-
-  tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
-  if(element == NULL)
-    return false;
-
-  // Deserialize
-  std::vector<XMLSerializable*>* groups = it->second->Objects;
-  bool found = false;
-  for(unsigned int i=0;i<groups->size();i++)
-  {
-    if((*groups)[i]->Name == on)
-    {
-      found = true;
-      if(element == NULL || (*groups)[i]->Deserialize(doc,element) == false)
-        (*groups)[i]->Init(); // Load default value;
-    }
-  }
-    
-  return found;
-}
-
-bool igl::XMLSerializer::LoadGroupFromXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element)
-{
-  std::string gn = groupName;
-  EncodeXMLElementName(gn);
-
-  std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
-  if(it == groups.end())
-    return false;
-
-  const tinyxml2::XMLElement* group = element->FirstChildElement(groupName.c_str());
-  if(group == NULL)
-    return false;
-
-  // Deserialize
-  std::vector<XMLSerializable*>* groups = it->second->Objects;
-  for(unsigned int i=0;i<groups->size();i++)
-  {
-    if(element == NULL || (*groups)[i]->Deserialize(doc,group) == false)
-      (*groups)[i]->Init(); // Load default value;
-  }
-    
-  return true;
-}
-
-void igl::XMLSerializer::SetCurrentGroup(const std::string& group)
-{
-  currentGroup = setGetGroup(group);
-}
-
-std::string igl::XMLSerializer::GetCurrentGroup()
-{
-  return currentGroup->first;
-}
-  
-template<typename T>
-bool igl::XMLSerializer::Add(T& obj, const std::string& name)
-{
-  igl::XMLSerializable* object = static_cast<igl::XMLSerializable*>(obj);
-  
-  object->Name = name;
-  return addObjectToGroup(object,currentGroup);  
-}
-
-bool igl::XMLSerializer::Add(char& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-bool igl::XMLSerializer::Add(char*& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-bool igl::XMLSerializer::Add(std::string& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-bool igl::XMLSerializer::Add(bool& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-bool igl::XMLSerializer::Add(unsigned int& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-bool igl::XMLSerializer::Add(int& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-bool igl::XMLSerializer::Add(float& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-bool igl::XMLSerializer::Add(double& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-/*template<typename T, size_t S>
-bool igl::XMLSerializer::Add(std::array<T,S>& obj, const std::string& name)
-{
-  return add(obj,name);
-}*/
-
-template<typename T0, typename T1>
-bool igl::XMLSerializer::Add(std::pair<T0,T1>& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-template<typename T>
-bool igl::XMLSerializer::Add(std::vector<T>& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-template<typename T, int R, int C>
-bool igl::XMLSerializer::Add(Eigen::Matrix<T,R,C>& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-template<typename T>
-bool igl::XMLSerializer::Add(Eigen::SparseMatrix<T>& obj, const std::string& name)
-{
-  return add(obj,name);
-}
-
-template<typename T>
-bool igl::XMLSerializer::Add(T& object, const std::string& name, T defaultValue)
-{
-  return false;    
-}
-
-bool igl::XMLSerializer::Add(char& obj, const std::string& name, char defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-bool igl::XMLSerializer::Add(char*& obj, const std::string& name, char* defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-bool igl::XMLSerializer::Add(std::string& obj, const std::string& name, std::string defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-bool igl::XMLSerializer::Add(bool& obj, const std::string& name, bool defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-bool igl::XMLSerializer::Add(unsigned int& obj, const std::string& name, unsigned int defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-bool igl::XMLSerializer::Add(int& obj, const std::string& name, int defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-bool igl::XMLSerializer::Add(float& obj, const std::string& name, float defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-bool igl::XMLSerializer::Add(double& obj, const std::string& name, double defaultValue)
-{
-  return add(obj,name,defaultValue);
-}
-
-template<typename T>
-bool igl::XMLSerializer::add(T& obj, const std::string& name)
-{
-  XMLSerializable* object = new igl::XMLSerializableInstance<T>(obj,name,currentGroup->first);
-  return addObjectToGroup(object,currentGroup);
-}
-
-template<typename T>
-bool igl::XMLSerializer::add(T& obj, const std::string& name, T defaultValue)
-{
-  igl::XMLSerializable* object = new igl::XMLSerializableInstance<T>(obj,name,currentGroup->first,defaultValue);
-  return addObjectToGroup(object,currentGroup);
-}
-  
-bool igl::XMLSerializer::addObjectToGroup(XMLSerializable* obj, const std::string& group)
-{
-  std::map<std::string,XMLSerializerGroup*>::iterator it = setGetGroup(group);
-  return addObjectToGroup(obj, it);
-}
-  
-bool igl::XMLSerializer::addObjectToGroup(XMLSerializable* object, std::map<std::string,XMLSerializerGroup*>::iterator it)
-{
-  std::vector<XMLSerializable*>* objects = it->second->Objects;
-  for(unsigned int i=0;i<objects->size();i++)
-  {
-    if((*objects)[i]->Name == object->Name)
-      return false;
-  }
-
-  objects->push_back(object);
-    
-  return true;
-}
-
-std::map<std::string,igl::XMLSerializerGroup*>::iterator igl::XMLSerializer::setGetGroup(const std::string& group)
-{
-  std::string groupName = group;
-  EncodeXMLElementName(groupName);
-    
-  std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(groupName);
-  if(it == groups.end())
-  {
-    XMLSerializerGroup* newGroup = new XMLSerializerGroup();
-    newGroup->Objects = new std::vector<XMLSerializable*>();
-    groups[groupName] = newGroup;
-    it = groups.find(groupName);
-  }
-    
-  return it;
-}
-
-tinyxml2::XMLDocument* igl::XMLSerializer::openDoc(const char* filename)
-{
-  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
-
-  tinyxml2::XMLError error = doc->LoadFile(filename);
-  if(error != tinyxml2::XML_NO_ERROR)
-  {
-    doc->PrintError();
-    doc = NULL;
-  }
-
-  return doc;
-}
-
-tinyxml2::XMLElement* igl::XMLSerializer::findAddGroup(tinyxml2::XMLDocument* doc, const char* groupName)
-{
-  tinyxml2::XMLElement* group = doc->FirstChildElement(groupName);
-  if(group == NULL)
-  {
-    group = doc->NewElement(groupName);
-    doc->InsertEndChild(group);
-  }
-  return group;
-}
-
-igl::XMLSerializerTest::XMLSerializerTest()
-  : XMLSerialization("testObject")
-{
-  xmlSerializer->Add(testInt,"testInt");
-  xmlSerializer->Add(testVector,"testVector");
-
-  testInt = 10;
-  
-  testVector.push_back(1.0001f);
-  testVector.push_back(2.0001f);
-  testVector.push_back(3.0001f);
-}
-
-#ifndef IGL_HEADER_ONLY
-// Explicit template specialization
-//igl::XMLSerializerTest test;
-template bool igl::XMLSerializer::LoadObject<Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, -1, 0, -1, -1>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<igl::XMLSerializerTest*>(igl::XMLSerializerTest*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<char*>(char*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<std::pair<int, bool> >(std::pair<int, bool>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> > >(std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> > >(std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<std::vector<int, std::allocator<int> > >(std::vector<int, std::allocator<int> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<bool>(bool&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<char>(char&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<double>(double&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<float>(float&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<int>(int&, char const*);
-template bool igl::XMLSerializer::LoadObject<int>(int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::LoadObject<unsigned int>(unsigned int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
-template bool igl::XMLSerializer::SaveObject<Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, -1, 0, -1, -1>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<igl::XMLSerializerTest*>(igl::XMLSerializerTest*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<char*>(char*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<std::pair<int, bool> >(std::pair<int, bool>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> > >(std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> > >(std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<std::vector<int, std::allocator<int> > >(std::vector<int, std::allocator<int> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<bool>(bool&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<char>(char&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<double>(double&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<float>(float&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<int>(int&, char const*);
-template bool igl::XMLSerializer::SaveObject<int>(int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::SaveObject<unsigned int>(unsigned int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
-template bool igl::XMLSerializer::Add<igl::XMLSerializerTest*>(std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
-template bool igl::XMLSerializer::Add<igl::XMLSerializerTest*>(igl::XMLSerializerTest*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
-template bool igl::XMLSerializer::Add<std::pair<int, bool>*>(std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
-template bool igl::XMLSerializer::Add<double>(Eigen::SparseMatrix<double, 0, int>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
-template bool igl::XMLSerializer::Add<int>(std::vector<int, std::allocator<int> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
-template bool igl::XMLSerializer::Add<int, bool>(std::pair<int, bool>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
-template bool igl::XMLSerializer::Add<int, -1, -1>
-(Eigen::Matrix<int, -1, -1>&, std::basic_string<char,
-    std::char_traits<char>, std::allocator<char> > const&);
-template bool igl::XMLSerializer::Add<int, 3, 3>
-(Eigen::Matrix<int, 3, 3>&, std::basic_string<char,
-    std::char_traits<char>, std::allocator<char> > const&);
-#endif

+ 1999 - 386
include/igl/xml/XMLSerializer.h

@@ -1,23 +1,25 @@
 /* ---------------------------------------------------------------------------
 /* ---------------------------------------------------------------------------
-// XMLSerializer.h
-// Author: Christian Schüller on 08/05/13.
-------------------------------------------------------------------------------
-
-This class allows to save and load a serialization of basic c++ data types like
-char, char*, std::string, bool, uint, int, float, double to and from a xml file.
-Containers like std::vector, std::std::pair, Eigen dense and sparse matrices are supported
-as well as combination of them (like vector<pair<string,bool>> or vector<vector<int>>).
-To serialize an arbitary object use the XMLSerializable interface.
+ // XMLSerializer.h
+ // Author: Christian Schüller on 08/05/13.
+ ------------------------------------------------------------------------------
  
  
-The serialized objects are organised in groups in the xml file and have
-their own names which must be unique within one group.
-
-You can find examples how to use it in the test case class XMLSerializerTest.
-
-----------------------------------------------------------------------------*/
+ This class allows to save and load a serialization of basic c++ data types like
+ char, char*, std::string, bool, uint, int, float, double to and from a xml file.
+ Containers like std::vector, std::std::pair, Eigen dense and sparse matrices are supported
+ as well as combination of them (like vector<pair<string,bool>> or vector<vector<int>>).
+ To serialize an arbitary object use the XMLSerializable interface.
+ 
+ The serialized objects are organised in groups in the xml file and have
+ their own names which must be unique within one group.
+ 
+ You can find examples how to use it in the test case class XMLSerializerTest.
+ 
+ ----------------------------------------------------------------------------*/
 #ifndef XML_SERIALIZER_H
 #ifndef XML_SERIALIZER_H
 #define XML_SERIALIZER_H
 #define XML_SERIALIZER_H
 
 
+#include <igl/igl_inline.h>
+
 #include <iostream>
 #include <iostream>
 //#include <array>
 //#include <array>
 #include <vector>
 #include <vector>
@@ -28,439 +30,2050 @@ You can find examples how to use it in the test case class XMLSerializerTest.
 
 
 #include <tinyxml2.h>
 #include <tinyxml2.h>
 
 
+
 namespace igl
 namespace igl
 {
 {
-
-  void EncodeXMLElementName(std::string& name);
-  //void DecodeXMLElementName(std::string& name);
-  void ReplaceSubString(std::string& str, const std::string& search, const std::string& replace);
-
-  // Forward declaration
-  class XMLSerializer;
-
-  /**
-     * interface XMLSerializable
-     * Inherit from this interface to have full control over the serialization of you user defined class.
-     */ 
-  class XMLSerializable
+  
+  namespace
   {
   {
-  public:
-    std::string Name;
-
-    /**
-     * This function gets called if the objects were not found during deserialization.
-     * Initialize your objects as you like. 
-     */ 
-    virtual void Init() = 0;
+  
+    void EncodeXMLElementName(std::string& name);
+    void DecodeXMLElementName(std::string& name);
+    void ReplaceSubString(std::string& str, const std::string& search, const std::string& replace);
+    
+    // Forward declaration
+    class XMLSerializer;
+    
     /**
     /**
-     * Serialize your stuff within this function.
-     * It contains the current serialization xml file. You can use SaveToXMLDoc or SaveGroupToXMLElement to add your objects.
-     */ 
-    virtual bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element) = 0;
-
+     * interface XMLSerializable
+     * Inherit from this interface to have full control over the serialization of you user defined class.
+     */
+    class XMLSerializable
+    {
+    public:
+      std::string Name;
+      
+      /**
+       * This function gets called if the objects were not found during deserialization.
+       * Initialize your objects as you like.
+       */
+      virtual void Init() = 0;
+      /**
+       * Serialize your stuff within this function.
+       * It contains the current serialization xml file. You can use SaveToXMLDoc or SaveGroupToXMLElement to add your objects.
+       */
+      virtual bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element) = 0;
+      
+      /**
+       * Deserialize your stuff within this function.
+       * It contains the current serialization xml file. You can use LoadFromXMLDoc or LoadGroupFromXMLElement to read out your objects.
+       */
+      virtual bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element) = 0;
+    };
+    
     /**
     /**
-     * Deserialize your stuff within this function.
-     * It contains the current serialization xml file. You can use LoadFromXMLDoc or LoadGroupFromXMLElement to read out your objects.
-     */ 
-    virtual bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element) = 0;
-  };
-
-  /**
      * class XMLSerialization
      * class XMLSerialization
      * Inherit from this class to have the easiest way to serialize your user defined class.
      * Inherit from this class to have the easiest way to serialize your user defined class.
      */
      */
-  class XMLSerialization : public XMLSerializable
-  {
-  public:
-    igl::XMLSerializer* xmlSerializer;
-
+    class XMLSerialization : public XMLSerializable
+    {
+    public:
+      XMLSerializer* xmlSerializer;
+      
+      /**
+       * Default implementation of XMLSerializable interface
+       */
+      virtual void Init();
+      virtual bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element);
+      virtual bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
+      
+      XMLSerialization(const std::string& name);
+      ~XMLSerialization();
+      
+      /**
+       * Following functions can be overwritten to handle the specific events.
+       * Return false to prevent serialization of object.
+       */
+      virtual bool BeforeSerialization();
+      virtual void AfterSerialization();
+      virtual bool BeforeDeserialization();
+      virtual void AfterDeserialization();
+    };
+    
+    
     /**
     /**
-     * Default implementation of XMLSerializable interface
+     * class XMLSerializableObject
+     * internal usage
      */
      */
-    virtual void Init();
-    virtual bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element);
-    virtual bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
+    class XMLSerializableObject : public XMLSerializable
+    {
+    public:
+      
+      XMLSerializableObject(const std::string& name, const std::string& group);
+      virtual ~XMLSerializableObject();
+      
+      // set attribute conversion functions
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, char& dest);
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, char*& dest);
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, std::string& dest);
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, bool& dest);
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, unsigned int& dest);
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, int& dest);
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, float& dest);
+      void SetAttribute(tinyxml2::XMLElement* element, const char* name, double& dest);
+      
+      // get attribute conversion functions
+      void GetAttribute(const char* src, char& dest);
+      void GetAttribute(const char* src, char*& dest);
+      void GetAttribute(const char* src, std::string& dest);
+      void GetAttribute(const char* src, bool& dest);
+      void GetAttribute(const char* src, unsigned int& dest);
+      void GetAttribute(const char* src, int& dest);
+      void GetAttribute(const char* src, float& dest);
+      void GetAttribute(const char* src, double& dest);
+      
+      // Initialization
+      
+      // Basic data types
+      using XMLSerializable::Init;
+      void Init(char& val);
+      void Init(char*& val);
+      void Init(std::string& val);
+      void Init(bool& val);
+      void Init(unsigned int& val);
+      void Init(int& val);
+      void Init(float& val);
+      void Init(double& val);
+      
+      // XMLSerializable*
+      template<typename T>
+      void Init(T& obj);
+      template<typename T>
+      void Init(T*& obj);
+      
+      // STL containers
+      /*template<typename T, int S>
+       void Init(std::array<T,S>& obj);*/
+      template<typename T0, typename T1>
+      void Init(std::pair<T0,T1>& obj);
+      template<typename T>
+      void Init(std::vector<T>& obj);
+      
+      // Eigen types
+      template<typename T, int R, int C>
+      void Init(Eigen::Matrix<T,R,C>& obj);
+      template<typename T>
+      void Init(Eigen::SparseMatrix<T>& obj);
+      
+      // Serialization
+      
+      // Basic data types
+      using XMLSerializable::Serialize;
+      bool Serialize(char& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(char*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(std::string& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(std::string*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(bool obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(bool*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(unsigned int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(float& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(float*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(double& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(double*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      
+      // XMLSerializable*
+      template<typename T>
+      bool Serialize(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T>
+      bool Serialize(T*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      
+      // STL containers
+      /*template<typename T, size_t S>
+       bool Serialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+       template<typename T, size_t S>
+       bool Serialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);*/
+      
+      template<typename T0, typename T1>
+      bool Serialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T0, typename T1>
+      bool Serialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      
+      template<typename T>
+      bool Serialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T>
+      bool Serialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
 
 
-    XMLSerialization(const std::string& name);
-    ~XMLSerialization();
+      bool Serialize(std::vector<bool>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool Serialize(std::vector<bool>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      
+      // Eigen types
+      template<typename T, int R, int C>
+      bool Serialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T, int R, int C>
+      bool Serialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      
+      template<typename T>
+      bool Serialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T>
+      bool Serialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      
+      // Serialization
+      
+      // Basic data types
+      using XMLSerializable::Deserialize;
+      bool Deserialize(char& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(char*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(std::string& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(std::string*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(bool& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(bool*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(unsigned int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(float& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(float*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(double& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(double*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      
+      // XMLSerializable*
+      template<typename T>
+      bool Deserialize(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T>
+      bool Deserialize(T*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      
+      // STL containers
+      /*template<typename T, size_t S>
+       bool Deserialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+       template<typename T, size_t S>
+       bool Deserialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);*/
+      
+      template<typename T0, typename T1>
+      bool Deserialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T0, typename T1>
+      bool Deserialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      
+      template<typename T>
+      bool Deserialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T>
+      bool Deserialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
 
 
+      bool Deserialize(std::vector<bool>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      bool Deserialize(std::vector<bool>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      
+      // Eigen types
+      template<typename T, int R, int C>
+      bool Deserialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T, int R, int C>
+      bool Deserialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      
+      template<typename T>
+      bool Deserialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T>
+      bool Deserialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+      
+    private:
+      
+      template<typename T>
+      bool setElementAttribute(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      template<typename T>
+      bool getElementAttribute(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+    };
+    
     /**
     /**
-     * Following functions can be overwritten to handle the specific events.
-     * Return false to prevent serialization of object.
+     * class XMLSerializableInstance
+     * internal usage
      */
      */
-    virtual bool BeforeSerialization();
-    virtual void AfterSerialization();
-    virtual bool BeforeDeserialization();
-    virtual void AfterDeserialization();
-  };
-
-
-  /**
-     * class XMLSerializableObject
+    template<typename T>
+    class XMLSerializableInstance : public XMLSerializableObject
+    {
+    public:
+      
+      T& Object;
+      T DefaultValue;
+      
+      XMLSerializableInstance(T& obj, const std::string& name, const std::string group);
+      XMLSerializableInstance(T& obj, const std::string& name, const std::string group, T defaultValue);
+      ~XMLSerializableInstance();
+      
+      // XMLSerializable interface implementation
+      void Init();
+      bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element);
+      bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
+    };
+    
+    /**
+     * struct XMLSerializerGroup
      * internal usage
      * internal usage
      */
      */
-  class XMLSerializableObject : public XMLSerializable
-  {
-  public:
-  
-    XMLSerializableObject(const std::string& name, const std::string& group);
-    virtual ~XMLSerializableObject();
-
+    struct XMLSerializerGroup
+    {
+      std::string Name;
+      std::vector<XMLSerializable*>* Objects;
+    };
+    
+    /**
+     * class XMLSerializer
+     * This is the core class which takes care of saving and loading of serialization of object structures.
+     */
+    class XMLSerializer
+    {
+    public:
+      
+      /**
+       * Serializes an object to a file
+       */
+      template<typename T>
+      static bool SaveObject(T& object, const char* filename);
+      template<typename T>
+      static bool SaveObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite);
+      
+      /**
+       * Loads the serialization of an object from a file.
+       */
+      template<typename T>
+      static bool LoadObject(T& object, const char* filename);
+      template<typename T>
+      static bool LoadObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename);
+      
+      /**
+       * Constructor which sets the default group
+       */
+      XMLSerializer(const std::string& defaultGroup);
+      ~XMLSerializer();
+      
+      /**
+       * Save the serialization of all groups to file.
+       * Parameter overwrite specifies if file gets overwritten or updated
+       */
+      bool Save(const char* filename, bool overwrite);
+      bool Save(const std::string& groupName, const char* filename, bool overwrite);
+      bool Save(const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite);
+      
+      /**
+       * Save the serialization of all groups to a XMLDocument instance.
+       */
+      bool SaveToXMLDoc(tinyxml2::XMLDocument* doc);
+      bool SaveToXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc);
+      bool SaveToXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc);
+      
+      /**
+       * Save the serialization of a group with a new provided name to given XMLElement instance.
+       */
+      bool SaveGroupToXMLElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      bool SaveGroupToXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+      
+      /**
+       * Load the serialization from a file.
+       */
+      bool Load(const char* filename);
+      bool Load(const std::string& groupName, const char* filename);
+      bool Load(const std::string& objectName, const std::string& groupName, const char* filename);
+      
+      /**
+       * Load the serialization from an XMLDocument instance.
+       */
+      bool LoadFromXMLDoc(tinyxml2::XMLDocument* doc);
+      bool LoadFromXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc);
+      bool LoadFromXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc);
+      
+      /**
+       * Load the serialization from a XMLElement instance to given group.
+       */
+      bool LoadGroupFromXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
+      
+      /**
+       * Set/Get current group. Every object which is added afterwards will be in this group, except it specifies another group.
+       */
+      void SetCurrentGroup(const std::string& group);
+      std::string GetCurrentGroup();
+      
+      /**
+       * Add an object to the serializer. Can be simple types like char, char*, string, unsigned int, int, float, double or containers like std::array, std::pair, std::vector.
+       * Also Eigen dense or sparse matrices are supported and all objects of type Serializable* and combinations of thoses types like vector<vector>, vector<pair> or even vector<pair<vector,Serializable*>>>.
+       * Also pointers to those objects can be used (for instance like vector<vector<pair<int,float>*>*>).
+       * char* is also possible as base type and represents a array of chars, but be carefull that the pointer is not just a copy but a valid instance in the current programm scope.
+       */
+      
+      // Basic types
+      bool Add(char& obj, const std::string& name);
+      bool Add(char*& obj, const std::string& name);
+      bool Add(std::string& obj, const std::string& name);
+      bool Add(bool& obj, const std::string& name);
+      bool Add(unsigned int& obj, const std::string& name);
+      bool Add(int& obj, const std::string& name);
+      bool Add(float& obj, const std::string& name);
+      bool Add(double& obj, const std::string& name);
+      
+      bool Add(char& obj, const std::string& name, char defaultValue);
+      bool Add(char*& obj, const std::string& name, char* defaultValue);
+      bool Add(std::string& obj, const std::string& name, std::string defaultValue);
+      bool Add(bool& obj, const std::string& name, bool defaultValue);
+      bool Add(unsigned int& obj, const std::string& name, unsigned int defaultValue);
+      bool Add(int& obj, const std::string& name, int defaultValue);
+      bool Add(float& obj, const std::string& name, float defaultValue);
+      bool Add(double& obj, const std::string& name, double defaultValue);
+      
+      // XMLSerializable*
+      template<typename T>
+      bool Add(T& object, const std::string& name);
+      template<typename T>
+      bool Add(T& object, const std::string& name, T defaultValue);
+      
+      // STL containers
+      /*template<typename T, size_t S>
+       bool Add(std::array<T,S>& obj, const std::string& name);*/
+      template<typename T0, typename T1>
+      bool Add(std::pair<T0,T1>& obj, const std::string& name);
+      template<typename T>
+      bool Add(std::vector<T>& obj, const std::string& name);
+      
+      // Eigen types
+      template<typename T, int R, int C>
+      bool Add(Eigen::Matrix<T,R,C>& obj, const std::string& name);
+      template<typename T>
+      bool Add(Eigen::SparseMatrix<T>& obj, const std::string& name);
+      
+    private:
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator currentGroup;
+      std::map<std::string,XMLSerializerGroup*> groups;
+      
+      template<typename T>
+      bool add(T& object, const std::string& name);
+      template<typename T>
+      bool add(T& object, const std::string& name, T defaultValue);
+      bool addObjectToGroup(XMLSerializable* object, const std::string& group);
+      bool addObjectToGroup(XMLSerializable* object, std::map<std::string,XMLSerializerGroup*>::iterator it);
+      std::map<std::string,XMLSerializerGroup*>::iterator setGetGroup(const std::string& group);
+      tinyxml2::XMLDocument* openDoc(const char* filename);
+      tinyxml2::XMLElement* findAddGroup(tinyxml2::XMLDocument* doc, const char* groupName);
+    };
+    
+    /**
+     * class XMLSerializerTest
+     * Used to test the functionality of the library and also shows howto use it.
+     */
+    class XMLSerializerTest : public XMLSerialization
+    {
+    public:
+      
+      int testInt;
+      std::vector<float> testVector;
+      
+      XMLSerializerTest();
+      
+      bool Test();
+    };
+    
+    
+    
+    int numForbiddenChars = 8;
+    char forbiddenChars[] = {' ','/','~','#','&','>','<','='};
+    
+    void ReplaceSubString(std::string& str, const std::string& search, const std::string& replace)
+    {
+      size_t pos = 0;
+      while ((pos = str.find(search, pos)) != std::string::npos)
+      {
+        str.replace(pos, search.length(), replace);
+        pos += replace.length();
+      }
+    }
+    
+    void EncodeXMLElementName(std::string& name)
+    {
+      // must not start with a digit
+      if(isdigit(*name.begin()))
+      {
+        name = ":::" + name;
+      }
+      
+      std::stringstream stream;
+      for(int i=0;i<numForbiddenChars;i++)
+      {
+        std::string search;
+        search = forbiddenChars[i];
+        std::stringstream replaces;
+        replaces << ":" << (int)forbiddenChars[i];
+        std::string replace = replaces.str();
+        
+        ReplaceSubString(name,search,replace);
+      }
+    }
+    
+    void DecodeXMLElementName(std::string& name)
+    {
+      if(name.find("::", 0) == 0)
+        name.replace(0,3,"");
+      
+      std::stringstream stream;
+      for(unsigned int i=0;i<numForbiddenChars;i++)
+      {
+        std::stringstream searchs;
+        searchs << ":" << (int)forbiddenChars[i];
+        std::string search = searchs.str();
+        std::string replace;
+        replace = forbiddenChars[i];
+        
+        ReplaceSubString(name,search,replace);
+      }
+    }
+    
+    void XMLSerialization::Init()
+    {
+    }
+    
+    bool XMLSerialization::Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element)
+    {
+      bool serialized = false;
+      
+      if(BeforeSerialization())
+      {
+        serialized = xmlSerializer->SaveGroupToXMLElement(doc,element,Name);
+        AfterSerialization();
+      }
+      
+      return serialized;
+    }
+    
+    bool XMLSerialization::Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element)
+    {
+      bool serialized = false;
+      
+      if(BeforeDeserialization())
+      {
+        serialized = xmlSerializer->LoadGroupFromXMLElement(Name,doc,element);
+        AfterDeserialization();
+      }
+      
+      return serialized;
+    }
+    
+    XMLSerialization::XMLSerialization(const std::string& name)
+    {
+      Name = name;
+      xmlSerializer = new XMLSerializer(name);
+    }
+    
+    XMLSerialization::~XMLSerialization()
+    {
+      delete xmlSerializer;
+    }
+    
+    bool XMLSerialization::BeforeSerialization()
+    {
+      return true;
+    }
+    
+    void XMLSerialization::AfterSerialization()
+    {
+    }
+    
+    bool XMLSerialization::BeforeDeserialization()
+    {
+      return true;
+    }
+    
+    void XMLSerialization::AfterDeserialization()
+    {
+    }
+    
+    XMLSerializableObject::XMLSerializableObject(const std::string& name, const std::string& group)
+    {
+      std::string groupName = group;
+      std::string objectName = name;
+      
+      EncodeXMLElementName(groupName);
+      EncodeXMLElementName(objectName);
+      
+      Name = objectName;
+    }
+    
+    XMLSerializableObject::~XMLSerializableObject()
+    {
+    }
+    
     // set attribute conversion functions
     // set attribute conversion functions
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, char& dest);  
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, char*& dest);
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, std::string& dest);
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, bool& dest);
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, unsigned int& dest);
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, int& dest);
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, float& dest);
-    void SetAttribute(tinyxml2::XMLElement* element, const char* name, double& dest);
-
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, char& dest)
+    {
+      element->SetAttribute(name,dest);
+    }
+    
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, char*& dest)
+    {
+      element->SetAttribute(name,const_cast<const char*>(dest));
+    }
+    
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, std::string& dest)
+    {
+      element->SetAttribute(name,dest.c_str());
+    }
+    
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, bool& dest)
+    {
+      element->SetAttribute(name,dest);
+    }
+    
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, unsigned int& dest)
+    {
+      element->SetAttribute(name,dest);
+    }
+    
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, int& dest)
+    {
+      element->SetAttribute(name,dest);
+    }
+    
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, float& dest)
+    {
+      element->SetAttribute(name,dest);
+    }
+    
+    void XMLSerializableObject::SetAttribute(tinyxml2::XMLElement* element, const char* name, double& dest)
+    {
+      element->SetAttribute(name,dest);
+    }
+    
     // get attribute conversion functions
     // get attribute conversion functions
-    void GetAttribute(const char* src, char& dest);
-    void GetAttribute(const char* src, char*& dest);
-    void GetAttribute(const char* src, std::string& dest);
-    void GetAttribute(const char* src, bool& dest);
-    void GetAttribute(const char* src, unsigned int& dest);
-    void GetAttribute(const char* src, int& dest);
-    void GetAttribute(const char* src, float& dest);
-    void GetAttribute(const char* src, double& dest);
-
-    // Initialization
-
-    // Basic data types
-    using XMLSerializable::Init;
-    void Init(char& val);
-    void Init(char*& val);
-    void Init(std::string& val);
-    void Init(bool& val);
-    void Init(unsigned int& val);
-    void Init(int& val);
-    void Init(float& val);
-    void Init(double& val);
-
-    // XMLSerializable*
-    template<typename T>
-    void Init(T& obj);
+    void XMLSerializableObject::GetAttribute(const char* src, char& dest)
+    {
+      dest = (char)atoi(src);
+    }
+    
+    void XMLSerializableObject::GetAttribute(const char* src, char*& dest)
+    {
+      unsigned int length = strlen(src)+1;
+      dest = new char[length];
+      strcpy(dest, src);
+    }
+    
+    void XMLSerializableObject::GetAttribute(const char* src, std::string& dest)
+    {
+      dest = src;
+    }
+    
+    void XMLSerializableObject::GetAttribute(const char* src, bool& dest)
+    {
+      tinyxml2::XMLUtil::ToBool(src,&dest);
+    }
+    
+    void XMLSerializableObject::GetAttribute(const char* src, unsigned int& dest)
+    {
+      tinyxml2::XMLUtil::ToUnsigned(src,&dest);
+    }
+    
+    void XMLSerializableObject::GetAttribute(const char* src, int& dest)
+    {
+      tinyxml2::XMLUtil::ToInt(src,&dest);
+    }
+    
+    void XMLSerializableObject::GetAttribute(const char* src, float& dest)
+    {
+      tinyxml2::XMLUtil::ToFloat(src,&dest);
+    }
+    
+    void XMLSerializableObject::GetAttribute(const char* src, double& dest)
+    {
+      tinyxml2::XMLUtil::ToDouble(src,&dest);
+    }
+    
+    // specify default value of types
+    void XMLSerializableObject::Init(char& val)
+    {
+      val = '0';
+    }
+    
+    void XMLSerializableObject::Init(char*& val)
+    {
+      val = NULL;
+    }
+    
+    void XMLSerializableObject::Init(std::string& val)
+    {
+      val = "";
+    }
+    
+    void XMLSerializableObject::Init(bool& val)
+    {
+      val = false;
+    }
+    
+    void XMLSerializableObject::Init(unsigned int& val)
+    {
+      val = 0;
+    }
+    
+    void XMLSerializableObject::Init(int& val)
+    {
+      val = 0;
+    }
+    
+    void XMLSerializableObject::Init(float& val)
+    {
+      val = 0.0f;
+    }
+    
+    void XMLSerializableObject::Init(double& val)
+    {
+      val = 0.000000000000000;
+    }
+    
     template<typename T>
     template<typename T>
-    void Init(T*& obj);
-
-    // STL containers
+    void XMLSerializableObject::Init(T*& obj)
+    {
+      XMLSerializable* object = static_cast<XMLSerializable*>(obj);
+      object->Init();
+    }
+    
     /*template<typename T, int S>
     /*template<typename T, int S>
-    void Init(std::array<T,S>& obj);*/
+     void XMLSerializableObject::Init(std::array<T,S>& obj)
+     {
+     for(unsigned int i=0;i<obj.size();i++)
+     Init(obj[i]);
+     }*/
+    
     template<typename T0, typename T1>
     template<typename T0, typename T1>
-    void Init(std::pair<T0,T1>& obj);
+    void XMLSerializableObject::Init(std::pair<T0,T1>& obj)
+    {
+      Init(obj.first);
+      Init(obj.second);
+    }
+    
     template<typename T>
     template<typename T>
-    void Init(std::vector<T>& obj);
+    void XMLSerializableObject::Init(std::vector<T>& obj)
+    {
+      obj.clear();
+    }
     
     
-    // Eigen types
     template<typename T, int R, int C>
     template<typename T, int R, int C>
-    void Init(Eigen::Matrix<T,R,C>& obj);
+    void XMLSerializableObject::Init(Eigen::Matrix<T,R,C>& obj)
+    {
+      obj.setZero(obj.rows(),obj.cols());
+    }
+    
     template<typename T>
     template<typename T>
-    void Init(Eigen::SparseMatrix<T>& obj);
-
-    // Serialization
-
-    // Basic data types
-    using XMLSerializable::Serialize;
-    bool Serialize(char& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(char*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(std::string& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(std::string*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(bool& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(bool*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(unsigned int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(float& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(float*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(double& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool Serialize(double*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    
-    // XMLSerializable*
-    template<typename T>
-    bool Serialize(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    template<typename T>
-    bool Serialize(T*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-
-    // STL containers
-    /*template<typename T, size_t S>
-    bool Serialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    template<typename T, size_t S>
-    bool Serialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);*/
-   
+    void  XMLSerializableObject::Init(Eigen::SparseMatrix<T>& obj)
+    {
+      obj.setZero();
+    }
+    
+    bool XMLSerializableObject::Serialize(char& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    // overload function for char*, it interpreted as char array and can be used to handle strings
+    bool XMLSerializableObject::Serialize(char*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(std::string& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(std::string*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(bool obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(bool*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(unsigned int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(float& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(float*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(double& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return setElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Serialize(double*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    template<typename T>
+    bool XMLSerializableObject::Serialize(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return false;
+    }
+    
+    template<typename T>
+    bool XMLSerializableObject::Serialize(T*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      // Serialize object implementing XMLSerializable interface
+      XMLSerializable* object = static_cast<XMLSerializable*>(obj);
+      
+      tinyxml2::XMLElement* child = doc->NewElement(name.c_str());
+      element->InsertEndChild(child);
+      
+      return object->Serialize(doc,child);
+    }
+    
+    bool XMLSerializableObject::Deserialize(char& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    // template specialisation for char*, it interpreted as char array and can be used to handle strings
+    bool XMLSerializableObject::Deserialize(char*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(std::string& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(std::string*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Deserialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(bool& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(bool*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Deserialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(unsigned int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Deserialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Deserialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(float& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(float*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Deserialize(*obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(double& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return getElementAttribute(obj,doc,element,name);
+    }
+    
+    bool XMLSerializableObject::Deserialize(double*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Deserialize(*obj,doc,element,name);
+    }
+    
+    template<typename T>
+    bool XMLSerializableObject::Deserialize(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return false;
+    }
+    
+    template<typename T>
+    bool XMLSerializableObject::Deserialize(T*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      obj = new T();
+      XMLSerializable* object = static_cast<XMLSerializable*>(obj);
+      
+      const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+      
+      object->Name = child->FirstChild()->Value();
+      
+      if(child != NULL)
+      {
+        obj->Deserialize(doc,child);
+      }
+      else
+      {
+        obj->Init();
+        return false;
+      }
+      
+      return true;
+    }
+    
+    /*
+     template<typename T, size_t S>
+     bool XMLSerializableObject::Serialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+     {
+     tinyxml2::XMLElement* ar = doc->NewElement(name.c_str());
+     element->InsertEndChild(ar);
+     
+     ar->SetAttribute("size",(unsigned int)obj.size());
+     
+     std::stringstream num;
+     for(unsigned int i=0;i<obj.size();i++)
+     {
+     num.str("");
+     num << "value" << i;
+     Serialize(obj[i],doc,ar,num.str());
+     }
+     
+     return true;
+     }
+     
+     template<typename T, size_t S>
+     bool XMLSerializableObject::Serialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+     {
+     return Serialize(*obj,doc,element,name);
+     }
+     
+     template<typename T, size_t S>
+     bool XMLSerializableObject::Deserialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+     {
+     bool res = true;
+     
+     const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+     if(child != NULL)
+     {
+     int size = child->UnsignedAttribute("size");
+     size = S < size ? S : size;
+     
+     std::stringstream num;
+     const tinyxml2::XMLAttribute* attribute = NULL;
+     for(unsigned int i=0;i<size;i++)
+     {
+     num.str("");
+     num << "value" << i;
+     
+     res &= Deserialize(obj[i],doc,child,num.str());
+     }
+     }
+     else
+     return false;
+     
+     return res;
+     }
+     
+     template<typename T, size_t S>
+     bool XMLSerializableObject::Deserialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+     {
+     obj = new std::array<T,S>();
+     return Deserialize(*obj,doc,element,name);
+     }
+     */
     template<typename T0, typename T1>
     template<typename T0, typename T1>
-    bool Serialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Serialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      bool res = true;
+      
+      tinyxml2::XMLElement* pair = doc->NewElement(name.c_str());
+      element->InsertEndChild(pair);
+      
+      res &= Serialize(obj.first,doc,pair,"first");
+      res &= Serialize(obj.second,doc,pair,"second");
+      
+      return res;
+    }
+    
+    template<typename T0, typename T1>
+    bool XMLSerializableObject::Serialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    template<typename T0, typename T1>
+    bool XMLSerializableObject::Deserialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      bool res = true;
+      
+      const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+      if(child != NULL)
+      {
+        res &= Deserialize(obj.first,doc,child,"first");
+        res &= Deserialize(obj.second,doc,child,"second");
+      }
+      else
+      {
+        Init(obj.first);
+        Init(obj.second);
+        return false;
+      }
+      
+      return res;
+    }
+    
     template<typename T0, typename T1>
     template<typename T0, typename T1>
-    bool Serialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Deserialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      obj = new std::pair<T0,T1>();
+      return Deserialize(*obj,doc,element,name);
+    }
     
     
     template<typename T>
     template<typename T>
-    bool Serialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Serialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      tinyxml2::XMLElement* vector = doc->NewElement(name.c_str());
+      element->InsertEndChild(vector);
+      
+      vector->SetAttribute("size",(unsigned int)obj.size());
+      
+      std::stringstream num;
+      for(unsigned int i=0;i<obj.size();i++)
+      {
+        num.str("");
+        num << "value" << i;
+        Serialize(obj[i],doc,vector,num.str());
+      }
+      
+      return true;
+    }
+    
     template<typename T>
     template<typename T>
-    bool Serialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Deserialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      bool res = true;
+      obj.clear();
+      
+      const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+      if(child != NULL)
+      {
+        unsigned int size = child->UnsignedAttribute("size");
+        obj.resize(size);
+        
+        std::stringstream num;
+        for(unsigned int i=0;i<size;i++)
+        {
+          num.str("");
+          num << "value" << i;
+          
+          res &= Deserialize(obj[i],doc,child,num.str());
+        }
+      }
+      else
+        return false;
+      
+      return res;
+    }
+
+    bool XMLSerializableObject::Serialize(std::vector<bool>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      tinyxml2::XMLElement* vector = doc->NewElement(name.c_str());
+      element->InsertEndChild(vector);
+      
+      vector->SetAttribute("size",(unsigned int)obj.size());
+      
+      std::stringstream num;
+      for(unsigned int i=0;i<obj.size();i++)
+      {
+        num.str("");
+        num << "value" << i;
+        Serialize(obj[i],doc,vector,num.str());
+      }
+      
+      return true;
+    }
     
     
-    // Eigen types
-    template<typename T, int R, int C>
-    bool Serialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    template<typename T, int R, int C>
-    bool Serialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Deserialize(std::vector<bool>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      bool res = true;
+      obj.clear();
+      
+      const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+      if(child != NULL)
+      {
+        unsigned int size = child->UnsignedAttribute("size");
+        obj.resize(size);
+        
+        std::stringstream num;
+        for(unsigned int i=0;i<size;i++)
+        {
+          num.str("");
+          num << "value" << i;
+          bool b;
+          res &= Deserialize(b,doc,child,num.str());
+          obj[i] = b;
+        }
+      }
+      else
+        return false;
+      
+      return res;
+    }
     
     
     template<typename T>
     template<typename T>
-    bool Serialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    template<typename T>
-    bool Serialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Serialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
 
 
-    // Serialization
+    bool XMLSerializableObject::Serialize(std::vector<bool>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    template<typename T>
+    bool XMLSerializableObject::Deserialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      obj = new std::vector<T>();
+      return Deserialize(*obj,doc,element,name);
+    }
 
 
-    // Basic data types
-    using XMLSerializable::Deserialize;
-    bool Deserialize(char& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(char*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(std::string& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(std::string*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(bool& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(bool*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(unsigned int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(float& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(float*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(double& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    bool Deserialize(double*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Deserialize(std::vector<bool>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      obj = new std::vector<bool>();
+      return Deserialize(*obj,doc,element,name);
+    }
 
 
-    // XMLSerializable*
+    template<typename T, int R, int C>
+    bool XMLSerializableObject::Serialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      tinyxml2::XMLElement* matrix = doc->NewElement(name.c_str());
+      element->InsertEndChild(matrix);
+      
+      const unsigned int rows = obj.rows();
+      const unsigned int cols = obj.cols();
+      
+      matrix->SetAttribute("rows",rows);
+      matrix->SetAttribute("cols",cols);
+      
+      std::stringstream ms;
+      ms << "\n";
+      for(unsigned int r=0;r<rows;r++)
+      {
+        for(unsigned int c=0;c<cols;c++)
+        {
+          ms << obj(r,c) << ",";
+        }
+        ms << "\n";
+      }
+      
+      std::string mString = ms.str();
+      if(mString.size() > 1)
+        mString[mString.size()-2] = '\0';
+      
+      matrix->SetAttribute("matrix",mString.c_str());
+      
+      return true;
+    }
+    
+    template<typename T, int R, int C>
+    bool XMLSerializableObject::Serialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
+    
+    template<typename T, int R, int C>
+    bool XMLSerializableObject::Deserialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+      if(child != NULL)
+      {
+        const unsigned int rows = child->UnsignedAttribute("rows");
+        const unsigned int cols = child->UnsignedAttribute("cols");
+        
+        obj.resize(rows,cols);
+        
+        const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
+        if(attribute == NULL)
+        {
+          Init(obj);
+          return false;
+        }
+        
+        char* matTemp;
+        GetAttribute(attribute->Value(),matTemp);
+        
+        std::string line, srows, scols;
+        std::stringstream mats;
+        mats.str(matTemp);
+        
+        int r=0;
+        std::string val;
+        // for each line
+        getline(mats,line);
+        while(getline(mats,line))
+        {
+          // get current line
+          std::stringstream liness(line);
+          
+          for(unsigned int c=0;c<cols-1;c++)
+          {
+            // split line
+            getline(liness, val, ',');
+            
+            // push pack the data if any
+            if(!val.empty())
+              GetAttribute(val.c_str(),obj.coeffRef(r,c));
+          }
+          
+          getline(liness, val);
+          GetAttribute(val.c_str(),obj.coeffRef(r,cols-1));
+          
+          r++;
+        }
+      }
+      else
+      {
+        Init(obj);
+        return false;
+      }
+      
+      return true;
+    }
+    
+    template<typename T, int R, int C>
+    bool XMLSerializableObject::Deserialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      obj = new Eigen::PlainObjectBase<T>();
+      return Deserialize(*obj,doc,element,name);
+    }
+    
     template<typename T>
     template<typename T>
-    bool Deserialize(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Serialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      tinyxml2::XMLElement* matrix = doc->NewElement(name.c_str());
+      element->InsertEndChild(matrix);
+      
+      const unsigned int rows = obj.rows();
+      const unsigned int cols = obj.cols();
+      
+      matrix->SetAttribute("rows",rows);
+      matrix->SetAttribute("cols",cols);
+      
+      std::stringstream ms;
+      ms << "\n";
+      for (int k=0;k<obj.outerSize();++k)
+      {
+        for (typename Eigen::SparseMatrix<T>::InnerIterator it(obj,k);it;++it)
+        {
+          ms << it.row() << "," << it.col() << "," << it.value() << "\n";
+        }
+      }
+      
+      std::string mString = ms.str();
+      if(mString.size() > 0)
+        mString[mString.size()-1] = '\0';
+      
+      matrix->SetAttribute("matrix",mString.c_str());
+      
+      return true;
+    }
+    
     template<typename T>
     template<typename T>
-    bool Deserialize(T*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-
-    // STL containers
-    /*template<typename T, size_t S>
-    bool Deserialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    template<typename T, size_t S>
-    bool Deserialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);*/
+    bool XMLSerializableObject::Serialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return Serialize(*obj,doc,element,name);
+    }
     
     
-    template<typename T0, typename T1>
-    bool Deserialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    template<typename T0, typename T1>
-    bool Deserialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-
     template<typename T>
     template<typename T>
-    bool Deserialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Deserialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+      if(child != NULL)
+      {
+        const unsigned int rows = child->UnsignedAttribute("rows");
+        const unsigned int cols = child->UnsignedAttribute("cols");
+        
+        obj.resize(rows,cols);
+        obj.setZero();
+        
+        const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
+        if(attribute == NULL)
+        {
+          Init(obj);
+          return false;
+        }
+        
+        char* matTemp;
+        GetAttribute(attribute->Value(),matTemp);
+        
+        std::string line, srows, scols;
+        std::stringstream mats;
+        mats.str(matTemp);
+        
+        std::vector<Eigen::Triplet<T> > triplets;
+        int r=0;
+        std::string val;
+        
+        // for each line
+        getline(mats,line);
+        while(getline(mats,line))
+        {
+          // get current line
+          std::stringstream liness(line);
+          
+          // row
+          getline(liness, val, ',');
+          int row = atoi(val.c_str());
+          // col
+          getline(liness, val, ',');
+          int col = atoi(val.c_str());
+          // val
+          getline(liness, val);
+          T value;
+          GetAttribute(val.c_str(),value);
+          
+          triplets.push_back(Eigen::Triplet<T>(row,col,value));
+          
+          r++;
+        }
+        
+        obj.setFromTriplets(triplets.begin(),triplets.end());
+      }
+      else
+      {
+        Init(obj);
+        return false;
+      }
+      
+      return true;
+    }
+    
     template<typename T>
     template<typename T>
-    bool Deserialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::Deserialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      obj = new Eigen::SparseMatrix<T>();
+      return Deserialize(*obj,doc,element,name);
+    }
     
     
-    // Eigen types
-    template<typename T, int R, int C>
-    bool Deserialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-    template<typename T, int R, int C>
-    bool Deserialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+    template<typename T>
+    bool XMLSerializableObject::setElementAttribute(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      tinyxml2::XMLElement* child = doc->NewElement(name.c_str());
+      element->InsertEndChild(child);
+      SetAttribute(child,"val",obj);
+      return true;
+    }
     
     
     template<typename T>
     template<typename T>
-    bool Deserialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
+    bool XMLSerializableObject::getElementAttribute(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name)
+    {
+      // basic data type
+      const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+      if(child != NULL)
+      {
+        XMLSerializableObject::GetAttribute(child->Attribute("val"),obj);
+        return true;
+      }
+      else
+      {
+        Init(obj);
+        return false;
+      }
+    }
+    
     template<typename T>
     template<typename T>
-    bool Deserialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-
-  private:
-
+    XMLSerializableInstance<T>::XMLSerializableInstance(T& obj, const std::string& name, const std::string group)
+    : XMLSerializableObject(name, group), Object(obj)
+    {
+      XMLSerializableObject::Init(DefaultValue);
+    }
+    
     template<typename T>
     template<typename T>
-    bool setElementAttribute(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
+    XMLSerializableInstance<T>::XMLSerializableInstance(T& obj, const std::string& name, const std::string group, T defaultValue)
+    : XMLSerializableObject(name, group), Object(obj), DefaultValue(defaultValue)
+    {
+    }
+    
     template<typename T>
     template<typename T>
-    bool getElementAttribute(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
-  };
-
-  /**
-     * class XMLSerializableInstance
-     * internal usage
-     */
-  template<typename T>
-  class XMLSerializableInstance : public XMLSerializableObject
-  {
-  public:
-
-    T& Object;
-    T DefaultValue;
-
-    XMLSerializableInstance(T& obj, const std::string& name, const std::string group);
-    XMLSerializableInstance(T& obj, const std::string& name, const std::string group, T defaultValue);
-    ~XMLSerializableInstance();
-
-    // XMLSerializable interface implementation
-    void Init();
-    bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element);
-    bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
-  };
-
-  /**
-     * struct XMLSerializerGroup
-     * internal usage
-     */
-  struct XMLSerializerGroup
-  {
-    std::string Name;
-    std::vector<XMLSerializable*>* Objects;
-  };
-
-  /**
-     * class XMLSerializer
-     * This is the core class which takes care of saving and loading of serialization of object structures.
-     */
-  class XMLSerializer
-  {
-  public:
-
-    /**
-     * Serializes an object to a file
-     */ 
+    XMLSerializableInstance<T>::~XMLSerializableInstance()
+    {
+    }
+    
     template<typename T>
     template<typename T>
-    static bool SaveObject(T& object, const char* filename);
+    void XMLSerializableInstance<T>::Init()
+    {
+      XMLSerializableObject::Init(DefaultValue);
+    }
+    
     template<typename T>
     template<typename T>
-    static bool SaveObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite);
-
-    /**
-     * Loads the serialization of an object from a file.
-     */
+    bool XMLSerializableInstance<T>::Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element)
+    {
+      return XMLSerializableObject::Serialize(Object,doc,element,Name);
+    }
+    
     template<typename T>
     template<typename T>
-    static bool LoadObject(T& object, const char* filename);
+    bool XMLSerializableInstance<T>::Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element)
+    {
+      return XMLSerializableObject::Deserialize(Object,doc,element,Name);
+    }
+    
     template<typename T>
     template<typename T>
-    static bool LoadObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename);
+    bool XMLSerializer::SaveObject(T& object, const char* filename)
+    {
+      return SaveObject(object,"Object","Serialization",filename,true);
+    }
     
     
-    /**
-     * Constructor which sets the default group
-     */
-    XMLSerializer(const std::string& defaultGroup);
-    ~XMLSerializer();
-
-    /**
-     * Save the serialization of all groups to file.
-     * Parameter overwrite specifies if file gets overwritten or updated
-     */ 
-    bool Save(const char* filename, bool overwrite);
-    bool Save(const std::string& groupName, const char* filename, bool overwrite);
-    bool Save(const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite);
-
-    /**
-     * Save the serialization of all groups to a XMLDocument instance.
-     */ 
-    bool SaveToXMLDoc(tinyxml2::XMLDocument* doc);
-    bool SaveToXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc);
-    bool SaveToXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc);
-
-    /**
-     * Save the serialization of a group with a new provided name to given XMLElement instance.
-     */
-    bool SaveGroupToXMLElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-    bool SaveGroupToXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
-
-    /**
-     * Load the serialization from a file.
-     */
-    bool Load(const char* filename);
-    bool Load(const std::string& groupName, const char* filename);
-    bool Load(const std::string& objectName, const std::string& groupName, const char* filename);
-
-    /**
-     * Load the serialization from an XMLDocument instance.
-     */
-    bool LoadFromXMLDoc(tinyxml2::XMLDocument* doc);
-    bool LoadFromXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc);
-    bool LoadFromXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc);    
-
-    /**
-     * Load the serialization from a XMLElement instance to given group.
-     */
-    bool LoadGroupFromXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
+    template<typename T>
+    bool XMLSerializer::SaveObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite)
+    {
+      bool result = true;
+      XMLSerializer* serializer = new XMLSerializer(groupName);
+      result &= serializer->Add(object,objectName);
+      result &= serializer->Save(objectName,groupName,filename,overwrite);
+      delete serializer;
+      return result;
+    }
     
     
-    /**
-     * Set/Get current group. Every object which is added afterwards will be in this group, except it specifies another group.
-     */
-    void SetCurrentGroup(const std::string& group);
-    std::string GetCurrentGroup();
-
-    /**
-     * Add an object to the serializer. Can be simple types like char, char*, string, unsigned int, int, float, double or containers like std::array, std::pair, std::vector.
-     * Also Eigen dense or sparse matrices are supported and all objects of type Serializable* and combinations of thoses types like vector<vector>, vector<pair> or even vector<pair<vector,Serializable*>>>.
-     * Also pointers to those objects can be used (for instance like vector<vector<pair<int,float>*>*>).
-     * char* is also possible as base type and represents a array of chars, but be carefull that the pointer is not just a copy but a valid instance in the current programm scope.
-     */
-
-    // Basic types
-    bool Add(char& obj, const std::string& name);
-    bool Add(char*& obj, const std::string& name);
-    bool Add(std::string& obj, const std::string& name);
-    bool Add(bool& obj, const std::string& name);
-    bool Add(unsigned int& obj, const std::string& name);
-    bool Add(int& obj, const std::string& name);
-    bool Add(float& obj, const std::string& name);
-    bool Add(double& obj, const std::string& name);
-
-    bool Add(char& obj, const std::string& name, char defaultValue);
-    bool Add(char*& obj, const std::string& name, char* defaultValue);
-    bool Add(std::string& obj, const std::string& name, std::string defaultValue);
-    bool Add(bool& obj, const std::string& name, bool defaultValue);
-    bool Add(unsigned int& obj, const std::string& name, unsigned int defaultValue);
-    bool Add(int& obj, const std::string& name, int defaultValue);
-    bool Add(float& obj, const std::string& name, float defaultValue);
-    bool Add(double& obj, const std::string& name, double defaultValue);
-
-    // XMLSerializable*
     template<typename T>
     template<typename T>
-    bool Add(T& object, const std::string& name);
+    bool XMLSerializer::LoadObject(T& object, const char* filename)
+    {
+      return LoadObject(object,"Object","Serialization",filename);
+    }
+    
     template<typename T>
     template<typename T>
-    bool Add(T& object, const std::string& name, T defaultValue);
-
-    // STL containers
+    bool XMLSerializer::LoadObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename)
+    {
+      bool result = true;
+      XMLSerializer* serializer = new XMLSerializer(groupName);
+      result &= serializer->Add(object,objectName);
+      result &= serializer->Load(objectName,groupName,filename);
+      delete serializer;
+      return result;
+    }
+    
+    XMLSerializer::XMLSerializer(const std::string& defaultGroup)
+    {
+      SetCurrentGroup(defaultGroup);
+    }
+    
+    XMLSerializer::~XMLSerializer()
+    {
+      std::map<std::string,XMLSerializerGroup*>::iterator it;
+      for (it=groups.begin();it!=groups.end();it++)
+      {
+        delete it->second->Objects;
+        delete it->second;
+      }
+    }
+    
+    bool XMLSerializer::Save(const char* filename, bool overwrite)
+    {
+      tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
+      
+      if(overwrite == false)
+      {
+        // Check if file exists
+        tinyxml2::XMLError error = doc->LoadFile(filename);
+        if(error != tinyxml2::XML_NO_ERROR)
+          doc->Clear();
+      }
+      
+      if(SaveToXMLDoc(doc) == false)
+        return false;
+      
+      // Save
+      tinyxml2::XMLError error = doc->SaveFile(filename);
+      if(error != tinyxml2::XML_NO_ERROR)
+      {
+        doc->PrintError();
+        return false;
+      }
+      
+      delete doc;
+      
+      return true;
+    }
+    
+    bool XMLSerializer::SaveToXMLDoc(tinyxml2::XMLDocument* doc)
+    {
+      std::map<std::string,XMLSerializerGroup*>::iterator it;
+      for (it=groups.begin();it!=groups.end();it++)
+      {
+        // Update group
+        tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
+        if(element != NULL)
+        {
+          element->DeleteChildren();
+        }
+        else
+        {
+          element = doc->NewElement(it->first.c_str());
+          doc->InsertEndChild(element);
+        }
+        
+        std::vector<XMLSerializable*>* group = it->second->Objects;
+        for(unsigned  int i=0;i<group->size();i++)
+        {
+          if((*group)[i]->Serialize(doc,element) == false)
+            return false;
+        }
+      }
+      
+      return true;
+    }
+    
+    bool XMLSerializer::Save(const std::string& groupName, const char* filename, bool overwrite)
+    {
+      tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
+      
+      if(overwrite == false)
+      {
+        // Check if file exists
+        tinyxml2::XMLError error = doc->LoadFile(filename);
+        if(error != tinyxml2::XML_NO_ERROR)
+          doc->Clear();
+      }
+      
+      if(SaveToXMLDoc(groupName, doc) == false)
+        return false;
+      
+      // Save
+      tinyxml2::XMLError error = doc->SaveFile(filename);
+      if(error != tinyxml2::XML_NO_ERROR)
+      {
+        doc->PrintError();
+        return false;
+      }
+      
+      delete doc;
+      
+      return true;
+    }
+    
+    bool XMLSerializer::SaveToXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc)
+    {
+      std::string gn = groupName;
+      EncodeXMLElementName(gn);
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
+      if(it == groups.end())
+        return false;
+      
+      // Update group
+      tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
+      if(element != NULL)
+      {
+        element->DeleteChildren();
+      }
+      else
+      {
+        element = doc->NewElement(it->first.c_str());
+        doc->InsertEndChild(element);
+      }
+      
+      std::vector<XMLSerializable*>* groups = it->second->Objects;
+      for(unsigned int i=0;i<groups->size();i++)
+      {
+        if((*groups)[i]->Serialize(doc,element) == false)
+          return false;
+      }
+      
+      return true;
+    }
+    
+    bool XMLSerializer::Save(const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite)
+    {
+      tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
+      
+      if(overwrite == false)
+      {
+        // Check if file exists
+        tinyxml2::XMLError error = doc->LoadFile(filename);
+        if(error != tinyxml2::XML_NO_ERROR)
+          doc->Clear();
+      }
+      
+      if(SaveToXMLDoc(objectName, groupName, doc) == false)
+        return false;
+      
+      // Save
+      tinyxml2::XMLError error = doc->SaveFile(filename);
+      if(error != tinyxml2::XML_NO_ERROR)
+      {
+        doc->PrintError();
+        return false;
+      }
+      
+      delete doc;
+      
+      return true;
+    }
+    
+    bool XMLSerializer::SaveToXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc)
+    {
+      std::string gn = groupName;
+      EncodeXMLElementName(gn);
+      
+      std::string on = objectName;
+      EncodeXMLElementName(on);
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
+      if(it == groups.end())
+        return false;
+      
+      // Get/Add group
+      tinyxml2::XMLElement* element = findAddGroup(doc, it->first.c_str());
+      
+      // Serialize
+      std::vector<XMLSerializable*>* groups = it->second->Objects;
+      bool found = false;
+      for(unsigned int i=0;i<groups->size();i++)
+      {
+        if((*groups)[i]->Name == on)
+        {
+          found = true;
+          
+          tinyxml2::XMLElement* child = element->FirstChildElement(on.c_str());
+          if(child != NULL)
+          {
+            element->DeleteChild(child);
+          }
+          
+          if((*groups)[i]->Serialize(doc,element) == false)
+            return false;
+        }
+      }
+      
+      return found;
+    }
+    
+    bool XMLSerializer::SaveGroupToXMLElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      return SaveGroupToXMLElement(currentGroup->first,doc,element,name);
+    }
+    
+    bool XMLSerializer::SaveGroupToXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name)
+    {
+      std::string gn = groupName;
+      EncodeXMLElementName(gn);
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
+      if(it == groups.end())
+        return false;
+      
+      // Add new group
+      tinyxml2::XMLElement* group = doc->NewElement(name.c_str());
+      element->InsertEndChild(group);
+      
+      std::vector<XMLSerializable*>* groups = it->second->Objects;
+      for(unsigned int i=0;i<groups->size();i++)
+      {
+        if((*groups)[i]->Serialize(doc,group) == false)
+          return false;
+      }
+      
+      return true;
+    }
+    
+    bool XMLSerializer::Load(const char* filename)
+    {
+      tinyxml2::XMLDocument* doc = openDoc(filename);
+      if(doc == NULL)
+        return false;
+      
+      if(LoadFromXMLDoc(doc) == false)
+        return false;
+      
+      delete doc;
+      
+      return true;
+    }
+    
+    bool XMLSerializer::LoadFromXMLDoc(tinyxml2::XMLDocument* doc)
+    {
+      std::map<std::string,XMLSerializerGroup*>::iterator it;
+      for (it=groups.begin();it!=groups.end();it++)
+      {
+        tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
+        if(element == NULL)
+          return false;
+        
+        // Deserialize
+        std::vector<XMLSerializable*>* group = it->second->Objects;
+        for(unsigned int i=0;i<group->size();i++)
+        {
+          if(element == NULL || (*group)[i]->Deserialize(doc,element) == false)
+            (*group)[i]->Init(); // Load default value;
+        }
+      }
+      
+      return true;
+    }
+    
+    bool XMLSerializer::Load(const std::string& groupName, const char* filename)
+    {
+      tinyxml2::XMLDocument* doc = openDoc(filename);
+      if(doc == NULL)
+        return false;
+      
+      if(LoadFromXMLDoc(groupName, doc) == false)
+        return false;
+      
+      delete doc;
+      
+      return true;
+    }
+    
+    bool XMLSerializer::LoadFromXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc)
+    {
+      std::string gn = groupName;
+      EncodeXMLElementName(gn);
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
+      if(it == groups.end())
+        return false;
+      
+      tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
+      if(element == NULL)
+        return false;
+      
+      // Deserialize
+      std::vector<XMLSerializable*>* groups = it->second->Objects;
+      for(unsigned int i=0;i<groups->size();i++)
+      {
+        if(element == NULL || (*groups)[i]->Deserialize(doc,element) == false)
+          (*groups)[i]->Init(); // Load default value;
+      }
+      
+      return true;
+    }
+    
+    bool XMLSerializer::Load(const std::string& objectName, const std::string& groupName, const char* filename)
+    {
+      tinyxml2::XMLDocument* doc = openDoc(filename);
+      if(doc == NULL)
+        return false;
+      
+      if(LoadFromXMLDoc(objectName,groupName,doc) == false)
+        return false;
+      
+      delete doc;
+      
+      return true;
+    }
+    
+    bool XMLSerializer::LoadFromXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc)
+    {
+      std::string gn = groupName;
+      EncodeXMLElementName(gn);
+      
+      std::string on = objectName;
+      EncodeXMLElementName(on);
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
+      if(it == groups.end())
+        return false;
+      
+      tinyxml2::XMLElement* element = doc->FirstChildElement(it->first.c_str());
+      if(element == NULL)
+        return false;
+      
+      // Deserialize
+      std::vector<XMLSerializable*>* groups = it->second->Objects;
+      bool found = false;
+      for(unsigned int i=0;i<groups->size();i++)
+      {
+        if((*groups)[i]->Name == on)
+        {
+          found = true;
+          if(element == NULL || (*groups)[i]->Deserialize(doc,element) == false)
+            (*groups)[i]->Init(); // Load default value;
+        }
+      }
+      
+      return found;
+    }
+    
+    bool XMLSerializer::LoadGroupFromXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element)
+    {
+      std::string gn = groupName;
+      EncodeXMLElementName(gn);
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(gn);
+      std::cerr << it-> first << std::endl;
+      
+      if(it == groups.end())
+        return false;
+      
+      const tinyxml2::XMLElement* group = element->FirstChildElement(groupName.c_str());
+      if(group == NULL)
+        return false;
+      
+      // Deserialize
+      std::vector<XMLSerializable*>* groups = it->second->Objects;
+      for(unsigned int i=0;i<groups->size();i++)
+      {
+        if(element == NULL || (*groups)[i]->Deserialize(doc,group) == false)
+          (*groups)[i]->Init(); // Load default value;
+      }
+      
+      return true;
+    }
+    
+    void XMLSerializer::SetCurrentGroup(const std::string& group)
+    {
+      currentGroup = setGetGroup(group);
+    }
+    
+    std::string XMLSerializer::GetCurrentGroup()
+    {
+      return currentGroup->first;
+    }
+    
+    template<typename T>
+    bool XMLSerializer::Add(T& obj, const std::string& name)
+    {
+      XMLSerializable* object = static_cast<XMLSerializable*>(&obj);
+      
+      object->Name = name;
+      return addObjectToGroup(object,currentGroup);
+    }
+    
+    bool XMLSerializer::Add(char& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
+    bool XMLSerializer::Add(char*& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
+    bool XMLSerializer::Add(std::string& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
+    bool XMLSerializer::Add(bool& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
+    bool XMLSerializer::Add(unsigned int& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
+    bool XMLSerializer::Add(int& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
+    bool XMLSerializer::Add(float& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
+    bool XMLSerializer::Add(double& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
     /*template<typename T, size_t S>
     /*template<typename T, size_t S>
-    bool Add(std::array<T,S>& obj, const std::string& name);*/
+     bool XMLSerializer::Add(std::array<T,S>& obj, const std::string& name)
+     {
+     return add(obj,name);
+     }*/
+    
     template<typename T0, typename T1>
     template<typename T0, typename T1>
-    bool Add(std::pair<T0,T1>& obj, const std::string& name);
+    bool XMLSerializer::Add(std::pair<T0,T1>& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
     template<typename T>
     template<typename T>
-    bool Add(std::vector<T>& obj, const std::string& name);
+    bool XMLSerializer::Add(std::vector<T>& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
     
     
-    // Eigen types
     template<typename T, int R, int C>
     template<typename T, int R, int C>
-    bool Add(Eigen::Matrix<T,R,C>& obj, const std::string& name);
+    bool XMLSerializer::Add(Eigen::Matrix<T,R,C>& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
     template<typename T>
     template<typename T>
-    bool Add(Eigen::SparseMatrix<T>& obj, const std::string& name);
-
-  private:
-
-    std::map<std::string,XMLSerializerGroup*>::iterator currentGroup;
-    std::map<std::string,XMLSerializerGroup*> groups;
-  
+    bool XMLSerializer::Add(Eigen::SparseMatrix<T>& obj, const std::string& name)
+    {
+      return add(obj,name);
+    }
+    
     template<typename T>
     template<typename T>
-    bool add(T& object, const std::string& name);
+    bool XMLSerializer::Add(T& object, const std::string& name, T defaultValue)
+    {
+      return false;
+    }
+    
+    bool XMLSerializer::Add(char& obj, const std::string& name, char defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
+    bool XMLSerializer::Add(char*& obj, const std::string& name, char* defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
+    bool XMLSerializer::Add(std::string& obj, const std::string& name, std::string defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
+    bool XMLSerializer::Add(bool& obj, const std::string& name, bool defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
+    bool XMLSerializer::Add(unsigned int& obj, const std::string& name, unsigned int defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
+    bool XMLSerializer::Add(int& obj, const std::string& name, int defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
+    bool XMLSerializer::Add(float& obj, const std::string& name, float defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
+    bool XMLSerializer::Add(double& obj, const std::string& name, double defaultValue)
+    {
+      return add(obj,name,defaultValue);
+    }
+    
     template<typename T>
     template<typename T>
-    bool add(T& object, const std::string& name, T defaultValue);
-    bool addObjectToGroup(XMLSerializable* object, const std::string& group);  
-    bool addObjectToGroup(XMLSerializable* object, std::map<std::string,XMLSerializerGroup*>::iterator it);
-    std::map<std::string,XMLSerializerGroup*>::iterator setGetGroup(const std::string& group);
-    tinyxml2::XMLDocument* openDoc(const char* filename);
-    tinyxml2::XMLElement* findAddGroup(tinyxml2::XMLDocument* doc, const char* groupName);
-  };
-  
-  /**
-     * class XMLSerializerTest
-     * Used to test the functionality of the library and also shows howto use it.
-     */
-  class XMLSerializerTest : public igl::XMLSerialization
-  {
-  public:
-
-    int testInt;
-    std::vector<float> testVector;
-
-    XMLSerializerTest();
-
-    bool Test();
-  };
+    bool XMLSerializer::add(T& obj, const std::string& name)
+    {
+      XMLSerializable* object = new XMLSerializableInstance<T>(obj,name,currentGroup->first);
+      return addObjectToGroup(object,currentGroup);
+    }
+    
+    template<typename T>
+    bool XMLSerializer::add(T& obj, const std::string& name, T defaultValue)
+    {
+      XMLSerializable* object = new XMLSerializableInstance<T>(obj,name,currentGroup->first,defaultValue);
+      return addObjectToGroup(object,currentGroup);
+    }
+    
+    bool XMLSerializer::addObjectToGroup(XMLSerializable* obj, const std::string& group)
+    {
+      std::map<std::string,XMLSerializerGroup*>::iterator it = setGetGroup(group);
+      return addObjectToGroup(obj, it);
+    }
+    
+    bool XMLSerializer::addObjectToGroup(XMLSerializable* object, std::map<std::string,XMLSerializerGroup*>::iterator it)
+    {
+      std::vector<XMLSerializable*>* objects = it->second->Objects;
+      for(unsigned int i=0;i<objects->size();i++)
+      {
+        if((*objects)[i]->Name == object->Name)
+          return false;
+      }
+      
+      objects->push_back(object);
+      
+      return true;
+    }
+    
+    std::map<std::string,XMLSerializerGroup*>::iterator XMLSerializer::setGetGroup(const std::string& group)
+    {
+      std::string groupName = group;
+      EncodeXMLElementName(groupName);
+      
+      std::map<std::string,XMLSerializerGroup*>::iterator it = groups.find(groupName);
+      if(it == groups.end())
+      {
+        XMLSerializerGroup* newGroup = new XMLSerializerGroup();
+        newGroup->Objects = new std::vector<XMLSerializable*>();
+        groups[groupName] = newGroup;
+        it = groups.find(groupName);
+      }
+      
+      return it;
+    }
+    
+    tinyxml2::XMLDocument* XMLSerializer::openDoc(const char* filename)
+    {
+      tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
+      
+      tinyxml2::XMLError error = doc->LoadFile(filename);
+      if(error != tinyxml2::XML_NO_ERROR)
+      {
+        doc->PrintError();
+        doc = NULL;
+      }
+      
+      return doc;
+    }
+    
+    tinyxml2::XMLElement* XMLSerializer::findAddGroup(tinyxml2::XMLDocument* doc, const char* groupName)
+    {
+      tinyxml2::XMLElement* group = doc->FirstChildElement(groupName);
+      if(group == NULL)
+      {
+        group = doc->NewElement(groupName);
+        doc->InsertEndChild(group);
+      }
+      return group;
+    }
+    
+    XMLSerializerTest::XMLSerializerTest()
+    : XMLSerialization("testObject")
+    {
+      xmlSerializer->Add(testInt,"testInt");
+      xmlSerializer->Add(testVector,"testVector");
+      
+      testInt = 10;
+      
+      testVector.push_back(1.0001f);
+      testVector.push_back(2.0001f);
+      testVector.push_back(3.0001f);
+    }
+    
+  }
 }
 }
-
-#ifdef IGL_HEADER_ONLY
-#include "XMLSerializer.cpp"
-#else
-#endif
-
 #endif
 #endif

+ 298 - 0
include/igl/xml/test.cpp

@@ -0,0 +1,298 @@
+// #!/bin/bash
+// /../bin/ls > /dev/null
+// # BEGIN BASH SCRIPT
+// printf "//" | cat - $0 | g++ -g -liglxml -ligl -ltinyxml2 -I/opt/local/include/eigen3 -L$LIBIGL/external/tinyxml2 -I$LIBIGL/external/tinyxml2 -I$LIBIGL/include -L$LIBIGL/lib -o .main -x c++ - && ./.main $@
+// rm -f .main
+// # END BASH SCRIPT
+// exit
+
+
+#include "XMLSerializer.h"
+
+
+/*
+Use the following lines to run the XMLSerializer tests:
+igl::XMLSerializerTest* test = new igl::XMLSerializerTest();
+bool success = test->Test();
+delete test;
+*/
+bool igl::XMLSerializerTest::Test()
+{
+  // test vars 0
+  char testChar0 = 'a';
+  char* testCharArray0 = "testCharArray0";
+  std::string testString0 = "testString0";
+  bool testBool0 = true;
+  unsigned int testUnsigned0 = 13;
+  int testInt0 = 1000;
+  float testFloat0 = 0.00001f;
+  double testDouble0 = 0.01000000005;
+
+  //std::array<float,2> testArray0 = {{0.001f,1.001f}};
+
+  std::pair<int,bool> testPair0;
+  testPair0.first = 5;
+  testPair0.second = true;
+
+  std::vector<int> testVector0;
+  testVector0.push_back(1);
+  testVector0.push_back(2);
+  testVector0.push_back(3);
+
+  Eigen::Matrix3i testDenseMatrix0;
+  //testDenseMatrix0 = Eigen::Matrix3i::Identity();
+
+  Eigen::SparseMatrix<double> testSparseMatrix0(3,3);
+  std::vector<Eigen::Triplet<double> > triplets;
+  triplets.push_back(Eigen::Triplet<double>(0,0,1));
+  triplets.push_back(Eigen::Triplet<double>(1,1,2));
+  triplets.push_back(Eigen::Triplet<double>(2,2,3));
+  testSparseMatrix0.setFromTriplets(triplets.begin(),triplets.end());
+
+  igl::XMLSerializerTest* testObject0 = new igl::XMLSerializerTest();
+
+  std::vector<std::pair<int,bool>*> testComplex10;
+  testComplex10.push_back(&testPair0);
+  testComplex10.push_back(&testPair0);
+
+  std::vector<igl::XMLSerializerTest*> testComplex20;
+  testComplex20.push_back(testObject0);
+  testComplex20.push_back(testObject0);
+  
+  // test vars 1
+  char testChar1 = 'b';
+  char* testCharArray1 = "testCharArray1";
+  std::string testString1 = "testString1";
+  bool testBool1 = false;
+  unsigned int testUnsigned1 = 12;
+  int testInt1 = -1000;
+  float testFloat1 = -0.00001f;
+  double testDouble1 = -0.000000000001;
+
+  //std::array<float,2> testArray1 = {{-0.001f,-1.001f}};
+
+  std::pair<int,bool> testPair1;
+  testPair1.first = -5;
+  testPair1.second = false;
+
+  std::vector<int> testVector1;
+  testVector1.push_back(-1);
+  testVector1.push_back(-2);
+  testVector1.push_back(-3);
+
+  Eigen::Matrix3i testDenseMatrix1;
+  //testDenseMatrix1 = Eigen::Matrix3i::Identity();
+  //testDenseMatrix1 *= 2;
+
+  Eigen::SparseMatrix<double> testSparseMatrix1(3,3);
+  triplets.clear();
+  triplets.push_back(Eigen::Triplet<double>(0,0,-1));
+  triplets.push_back(Eigen::Triplet<double>(1,1,-2));
+  triplets.push_back(Eigen::Triplet<double>(2,2,-3));
+  testSparseMatrix1.setFromTriplets(triplets.begin(),triplets.end());
+
+  igl::XMLSerializerTest* testObject1 = new igl::XMLSerializerTest();
+  testObject1->testInt = 3;
+  testObject1->testVector.clear();
+
+  std::vector<std::pair<int,bool>*> testComplex11;
+  testComplex11.push_back(&testPair1);
+  testComplex11.push_back(&testPair1);
+
+  std::vector<igl::XMLSerializerTest*> testComplex21;
+  testComplex21.push_back(testObject1);
+  testComplex21.push_back(testObject1);
+  
+  // test Serializer
+  bool testResult = true;
+  
+  // test static functions
+  
+  // check static updating
+  int testInt = 5;
+  testResult &= igl::XMLSerializer::SaveObject(testInt0,"test.xml");
+  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test","test.xml",false);
+  testResult &= igl::XMLSerializer::LoadObject(testInt,"test.xml");
+  testResult &= testInt0 == testInt;
+
+  // check static overwriting
+  testInt = 3;
+  testResult &= igl::XMLSerializer::SaveObject(testInt0,"test.xml");
+  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test","test.xml",true);
+  testResult &= igl::XMLSerializer::LoadObject(testInt,"test.xml") == false;
+  testResult &= testInt0 != testInt;
+
+  // check static based type saving
+  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test0","test.xml",true);
+  testResult &= igl::XMLSerializer::SaveObject(testCharArray0,"testCharArray","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testString0,"testString","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testBool0,"testBool","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testUnsigned0,"testUnsigned","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testInt0,"testInt","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testFloat0,"testFloat","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testDouble0,"testDouble","test0","test.xml",false);
+  //testResult &= igl::XMLSerializer::SaveObject(testArray0,"testArray","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testPair0,"testPair","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testVector0,"testVector","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testDenseMatrix0,"testDense","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testSparseMatrix0,"testSparse","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testObject0,"testObject","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testComplex10,"testComplex1","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testComplex20,"testComplex2","test1","test.xml",false);
+
+  testResult &= igl::XMLSerializer::LoadObject(testChar1,"testChar","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testCharArray1,"testCharArray","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testString1,"testString","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testBool1,"testBool","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testUnsigned1,"testUnsigned","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testInt1,"testInt","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testFloat1,"testFloat","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testDouble1,"testDouble","test0","test.xml");
+  //testResult &= igl::XMLSerializer::LoadObject(testArray1,"testArray","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testPair1,"testPair","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testVector1,"testVector","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testDenseMatrix1,"testDense","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testSparseMatrix1,"testSparse","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testObject1,"testObject","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testComplex11,"testComplex1","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testComplex21,"testComplex2","test1","test.xml");
+
+  testResult &= testChar0 == testChar1;
+  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
+  testResult &= testString0 == testString1;
+  testResult &= testBool0 == testBool1;
+  testResult &= testUnsigned0 == testUnsigned1;
+  testResult &= testInt0 == testInt1;
+  testResult &= testFloat0 == testFloat1;
+  testResult &= testDouble0 == testDouble1;
+  /*for(unsigned int i=0;i<testArray0.size();i++)
+    testResult &= testArray0[i] == testArray1[i];*/
+  testResult &= testPair0.first == testPair1.first;
+  testResult &= testPair0.second == testPair1.second;
+  testResult &= testVector0.size() == testVector1.size();
+  for(unsigned int i=0;i<testVector0.size();i++)
+    testResult &= testVector0[i] == testVector1[i];
+  testResult &= (testDenseMatrix0-testDenseMatrix1).sum() == 0;
+  testResult &= (testSparseMatrix0-testSparseMatrix1).norm() == 0;
+  testResult &= testObject0->testInt == testObject1->testInt;
+  testResult &= testObject0->testVector.size() == testObject1->testVector.size();
+  for(unsigned int i=0;i<testObject0->testVector.size();i++)
+    testResult &= testObject0->testVector[i] == testObject1->testVector[i];
+  testResult &= testComplex10.size() == testComplex11.size();
+  for(unsigned int i=0;i<testComplex10.size();i++)
+  {
+    testResult &= testComplex10[i]->first == testComplex11[0]->first;
+    testResult &= testComplex10[i]->second == testComplex11[0]->second;
+  }
+  testResult &= testComplex20.size() == testComplex21.size();
+  for(unsigned int i=0;i<testComplex20.size();i++)
+  {
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
+    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
+       testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
+  }
+
+  igl::XMLSerializer* s = new igl::XMLSerializer("test0");
+
+  // clear file
+  testResult &= s->Save("test.xml",true);
+
+  testResult &= s->Add(testChar0,"testChar");
+  testResult &= s->Add(testCharArray0,"testCharArray");
+  testResult &= s->Add(testString0,"testString");
+  testResult &= s->Add(testBool0,"testBool");
+  testResult &= s->Add(testUnsigned0,"testUnsigned");
+  testResult &= s->Add(testInt0,"testInt");
+  testResult &= s->Add(testFloat0,"testFloat");
+  testResult &= s->Add(testDouble0,"testDouble");
+
+  s->SetCurrentGroup("test1");
+
+  //testResult &= s->Add(testArray0,"testArray");
+  testResult &= s->Add(testPair0,"testPair");
+  testResult &= s->Add(testVector0,"testVector");
+  testResult &= s->Add(testDenseMatrix0,"testDenseMatrix");
+  testResult &= s->Add(testSparseMatrix0,"testSparseMatrix");
+  testResult &= s->Add(testObject0,"testObject");
+  testResult &= s->Add(testComplex10,"testComplex1");
+  testResult &= s->Add(testComplex20,"testComplex2");
+  
+  // Test single attribute save load
+  testResult &= s->Save("testComplex2","test1","test.xml",true);
+  testResult &= s->Load("testComplex2","test1","test.xml");
+  
+  testResult &= testComplex20.size() == testComplex21.size();
+  for(unsigned int i=0;i<testComplex20.size();i++)
+  {
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
+    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
+        testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
+  }
+
+  // Test group save load without overriding
+  testResult &= s->Save("test0","test.xml",false);
+  testResult &= s->Load("test0","test.xml");
+  testResult &= s->Load("testComplex2","test1","test.xml");
+
+  testResult &= testChar0 == testChar1;
+  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
+  testResult &= testString0 == testString1;
+  testResult &= testBool0 == testBool1;
+  testResult &= testUnsigned0 == testUnsigned1;
+  testResult &= testInt0 == testInt1;
+  testResult &= testFloat0 == testFloat1;
+  testResult &= testDouble0 == testDouble1;
+
+  // Test full serialization save load
+  testResult &= s->Save("test.xml",true);
+  testResult &= s->Load("test.xml");
+  
+  testResult &= testChar0 == testChar1;
+  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
+  testResult &= testString0 == testString1;
+  testResult &= testBool0 == testBool1;
+  testResult &= testUnsigned0 == testUnsigned1;
+  testResult &= testInt0 == testInt1;
+  testResult &= testFloat0 == testFloat1;
+  testResult &= testDouble0 == testDouble1;
+  /*for(unsigned int i=0;i<testArray0.size();i++)
+    testResult &= testArray0[i] == testArray1[i];*/
+  testResult &= testPair0.first == testPair1.first;
+  testResult &= testPair0.second == testPair1.second;
+  testResult &= testVector0.size() == testVector1.size();
+  for(unsigned int i=0;i<testVector0.size();i++)
+    testResult &= testVector0[i] == testVector1[i];
+  testResult &= (testDenseMatrix0-testDenseMatrix1).sum() == 0;
+  testResult &= (testSparseMatrix0-testSparseMatrix1).norm() == 0;
+  testResult &= testObject0->testInt == testObject1->testInt;
+  testResult &= testObject0->testVector.size() == testObject1->testVector.size();
+  for(unsigned int i=0;i<testObject0->testVector.size();i++)
+    testResult &= testObject0->testVector[i] == testObject1->testVector[i];
+  testResult &= testComplex10.size() == testComplex11.size();
+  for(unsigned int i=0;i<testComplex10.size();i++)
+  {
+    testResult &= testComplex10[i]->first == testComplex11[0]->first;
+    testResult &= testComplex10[i]->second == testComplex11[0]->second;
+  }
+  testResult &= testComplex20.size() == testComplex21.size();
+  for(unsigned int i=0;i<testComplex20.size();i++)
+  {
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
+    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
+        testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
+  }
+
+  delete s;
+  printf("done with test.\n");
+
+  return testResult;
+}
+
+int main(int argc, char * argv[])
+{
+  igl::XMLSerializerTest test;
+  return !test.Test();
+}