ソースを参照

Updated serialization tutorial

Former-commit-id: d6220213495f54ee9126cf5aee78dda20b962e11
schuellc 10 年 前
コミット
d8ac2b7189

+ 1 - 3
include/igl/file_dialog_open.cpp

@@ -42,13 +42,11 @@ IGL_INLINE std::string igl::file_dialog_open()
 
   OPENFILENAME ofn;       // common dialog box structure
   char szFile[260];       // buffer for file name
-  HWND hwnd;              // owner window
-  HANDLE hf;              // file handle
 
   // Initialize OPENFILENAME
   ZeroMemory(&ofn, sizeof(ofn));
   ofn.lStructSize = sizeof(ofn);
-  ofn.hwndOwner = NULL;//hwnd;
+  ofn.hwndOwner = NULL;
   ofn.lpstrFile = new char[100];
   // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
   // use the contents of szFile to initialize itself.

+ 0 - 2
include/igl/file_dialog_save.cpp

@@ -41,8 +41,6 @@ IGL_INLINE std::string igl::file_dialog_save()
 
   OPENFILENAME ofn;       // common dialog box structure
   char szFile[260];       // buffer for file name
-  HWND hwnd;              // owner window
-  HANDLE hf;              // file handle
 
   // Initialize OPENFILENAME
   ZeroMemory(&ofn, sizeof(ofn));

+ 59 - 24
include/igl/serialize.cpp

@@ -10,17 +10,20 @@
 namespace igl
 {
   template <typename T>
-  IGL_INLINE void serialize(const T& obj,const std::string& filename)
+  IGL_INLINE bool serialize(const T& obj,const std::string& filename)
   {
-    serialize(obj,"obj",filename);
+    return serialize(obj,"obj",filename,true);
   }
 
   template <typename T>
-  IGL_INLINE void serialize(const T& obj,const std::string& objectName,const std::string& filename,bool update)
+  IGL_INLINE bool serialize(const T& obj,const std::string& objectName,const std::string& filename,bool overwrite)
   {
+    bool success = false;
+    
     std::vector<char> buffer;
 
-    if(update)
+    // open existing file for updating objects
+    /*if(overwrite == false)
     {
       std::ifstream file(filename.c_str(),std::ios::binary);
 
@@ -35,9 +38,16 @@ namespace igl
 
         file.close();
       }
-    }
+    }*/
+
+    std::ios_base::openmode mode = std::ios::out | std::ios::binary;
 
-    std::ofstream file(filename.c_str(),std::ios::out | std::ios::binary);
+    if(overwrite)
+      mode |= std::ios::trunc;
+    else
+      mode |= std::ios::app;
+    
+    std::ofstream file(filename.c_str(),mode);
 
     if(file.is_open())
     {
@@ -46,15 +56,19 @@ namespace igl
       file.write(&buffer[0],buffer.size());
 
       file.close();
+
+      success = true;
     }
     else
     {
       std::cerr << "saving binary serialization failed!" << std::endl;
     }
+
+    return success;
   }
 
   template <typename T>
-  IGL_INLINE void serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer)
+  IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer)
   {
     static_assert(detail::is_serializable<T>::value,"'igl::serialize': type is not serializable");
 
@@ -64,14 +78,14 @@ namespace igl
     std::vector<char>::iterator it = tmp.begin();
     detail::serialize(obj,tmp,it);
 
-    std::string objectType(typeid(obj).name());
+    std::string objectType(typeid(obj).raw_name());
     size_t newObjectSize = tmp.size();
     size_t newHeaderSize = detail::getByteSize(objectName) + detail::getByteSize(objectType) + sizeof(size_t);
     size_t oldObjectSize = 0;
     size_t oldHeaderSize = 0;
 
-    // find object header
-    std::vector<char>::const_iterator citer = buffer.cbegin();
+    // find object header to replace existing object
+    /*std::vector<char>::const_iterator citer = buffer.cbegin();
     while(citer != buffer.cend())
     {
       std::vector<char>::const_iterator citerTemp = citer;
@@ -84,7 +98,7 @@ namespace igl
 
       if(name == objectName)
       {
-        if(type != typeid(obj).name())
+        if(type != typeid(obj).raw_name())
           std::cout << "object " + objectName + " was overwriten with different data type!" << std::endl;
 
         oldHeaderSize = citer - citerTemp;
@@ -121,7 +135,7 @@ namespace igl
       // copy back end part of buffer
       std::copy(endPartBuffer.begin(),endPartBuffer.end(),iter);
     }
-    else
+    else*/
     {
       size_t curSize = buffer.size();
       size_t newSize = curSize + newHeaderSize + newObjectSize;
@@ -138,23 +152,27 @@ namespace igl
       // copy serialized data to buffer
       iter = std::copy(tmp.begin(),tmp.end(),iter);
     }
+
+    return true;
   }
 
   template <typename T>
-  IGL_INLINE void deserialize(T& obj,const std::string& filename)
+  IGL_INLINE bool deserialize(T& obj,const std::string& filename)
   {
-    deserialize(obj,"obj",filename);
+    return deserialize(obj,"obj",filename);
   }
 
   template <typename T>
-  IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::string& filename)
+  IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::string& filename)
   {
+    bool success = false;
+
     std::ifstream file(filename.c_str(),std::ios::binary);
 
     if(file.is_open())
     {
       file.seekg(0,std::ios::end);
-      int size = file.tellg();
+      std::streamoff size = file.tellg();
       file.seekg(0,std::ios::beg);
 
       std::vector<char> buffer(size);
@@ -162,19 +180,26 @@ namespace igl
 
       deserialize(obj,objectName,buffer);
       file.close();
+      
+      success = true;
     }
     else
     {
       std::cerr << "Loading binary serialization failed!" << std::endl;
     }
+
+    return success;
   }
 
   template <typename T>
-  IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::vector<char>& buffer)
-  {
+  IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::vector<char>& buffer)
+  {   
     static_assert(detail::is_serializable<T>::value,"'igl::deserialize': type is not deserializable");
 
+    bool success = false;
+
     // find suitable object header
+    std::vector<char>::const_iterator objectIter = buffer.end();
     std::vector<char>::const_iterator iter = buffer.begin();
     while(iter != buffer.end())
     {
@@ -185,16 +210,26 @@ namespace igl
       detail::deserialize(type,iter);
       detail::deserialize(size,iter);
 
-      if(name == objectName && type == typeid(obj).name())
-        break;
-      else
-        iter+=size;
+      if(name == objectName && type == typeid(obj).raw_name())
+      {
+        objectIter = iter;
+        //break; // find first suitable object header
+      }
+
+      iter+=size;
     }
 
-    if(iter != buffer.end())
-      detail::deserialize(obj,iter);
+    if(objectIter != buffer.end())
+    {
+      detail::deserialize(obj,objectIter);
+      success = true;
+    }
     else
+    {
       obj = T();
+    }
+
+    return success;
   }
 
   IGL_INLINE bool Serializable::PreSerialization() const

+ 8 - 7
include/igl/serialize.h

@@ -46,16 +46,17 @@ namespace igl
   // Inputs:
   //   obj        object to serialize
   //   objectName unique object name,used for the identification
+  //   overwrite  set to true to overwrite an existing file
   //   filename   name of the file containing the serialization
   // Outputs:
   //   buffer     binary serialization
   //
   template <typename T>
-  IGL_INLINE void serialize(const T& obj,const std::string& filename);
+  IGL_INLINE bool serialize(const T& obj,const std::string& filename);
   template <typename T>
-  IGL_INLINE void serialize(const T& obj,const std::string& objectName,const std::string& filename,bool update = false);
+  IGL_INLINE bool serialize(const T& obj,const std::string& objectName,const std::string& filename,bool overwrite = false);
   template <typename T>
-  IGL_INLINE void serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer);
+  IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer);
 
   // Deserializes the given data from a file or buffer back to the provided object
   //
@@ -69,11 +70,11 @@ namespace igl
   //   obj        object to load back serialization to
   //
   template <typename T>
-  IGL_INLINE void deserialize(T& obj,const std::string& filename);
+  IGL_INLINE bool deserialize(T& obj,const std::string& filename);
   template <typename T>
-  IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::string& filename);
+  IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::string& filename);
   template <typename T>
-  IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::vector<char>& buffer);
+  IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::vector<char>& buffer);
 
   // User defined types have to derive from the class Serializable
   // and add their member variables in InitSerialization like the
@@ -131,7 +132,7 @@ namespace igl
     IGL_INLINE virtual bool PreDeserialization();
     IGL_INLINE virtual void PostDeserialization();
 
-    // Default implementation of Serializable interface
+    // Default implementation of SerializableBase interface
     IGL_INLINE void Serialize(std::vector<char>& buffer) const;
     IGL_INLINE void Deserialize(const std::vector<char>& buffer);
 

+ 38 - 9
include/igl/xml/serialization_test.cpp

@@ -30,9 +30,9 @@ namespace igl
 
     void InitSerialization()
     {
-      Add(ts,"ts");
-      Add(tvt,"tvt",true);
-      Add(tt,"tt",true);
+      Add(ts,"ts",false);
+      Add(tvt,"tvt");
+      Add(tt,"tt");
     }
   };
 
@@ -139,6 +139,7 @@ namespace igl
 
     Eigen::Matrix<float,3,3> tDenseMatrixIn;
     tDenseMatrixIn << Eigen::Matrix<float,3,3>::Random();
+    tDenseMatrixIn.coeffRef(0,0) = 1.00001;
     Eigen::Matrix<float,3,3> tDenseMatrixOut;
 
     Eigen::Matrix<float,3,3,Eigen::RowMajor> tDenseRowMatrixIn;
@@ -201,9 +202,23 @@ namespace igl
     assert(tstrIn == tstrOut);
 
     // updating
-    igl::serialize(tsIn,"tsIn",file);
-    igl::serialize(tVector1In,"tVector1In",file,true);
-    igl::serialize(tVector2In,"tsIn",file,true);
+    igl::serialize(tbIn,"tb",file,true);
+    igl::serialize(tcIn,"tc",file);
+    igl::serialize(tiIn,"ti",file);
+    tiIn++;
+    igl::serialize(tiIn,"ti",file);
+    tiIn++;
+    igl::serialize(tiIn,"ti",file);
+    igl::deserialize(tbOut,"tb",file);
+    igl::deserialize(tcOut,"tc",file);
+    igl::deserialize(tiOut,"ti",file);
+    assert(tbIn == tbOut);
+    assert(tcIn == tcOut);
+    assert(tiIn == tiOut);
+
+    igl::serialize(tsIn,"tsIn",file,true);
+    igl::serialize(tVector1In,"tVector1In",file);
+    igl::serialize(tVector2In,"tsIn",file);
     igl::deserialize(tVector2Out,"tsIn",file);
     for(unsigned int i=0;i<tVector2In.size();i++)
     {
@@ -345,9 +360,23 @@ namespace igl
     assert(tstrIn == tstrOut);
 
     // updating
-    igl::serialize_xml(tsIn,"tsIn",file);
-    igl::serialize_xml(tVector1In,"tVector1In",file,false,true);
-    igl::serialize_xml(tVector2In,"tsIn",file,false,true);
+    igl::serialize_xml(tbIn,"tb",file,false,true);
+    igl::serialize_xml(tcIn,"tc",file);
+    igl::serialize_xml(tiIn,"ti",file);
+    tiIn++;
+    igl::serialize_xml(tiIn,"ti",file);
+    tiIn++;
+    igl::serialize_xml(tiIn,"ti",file);
+    igl::deserialize_xml(tbOut,"tb",file);
+    igl::deserialize_xml(tcOut,"tc",file);
+    igl::deserialize_xml(tiOut,"ti",file);
+    assert(tbIn == tbOut);
+    assert(tcIn == tcOut);
+    assert(tiIn == tiOut);
+
+    igl::serialize_xml(tsIn,"tsIn",file,false,true);
+    igl::serialize_xml(tVector1In,"tVector1In",file);
+    igl::serialize_xml(tVector2In,"tsIn",file);
     igl::deserialize_xml(tVector2Out,"tsIn",file);
     for(unsigned int i=0;i<tVector2In.size();i++)
     {

+ 3 - 3
include/igl/xml/serialize_xml.cpp

@@ -12,15 +12,15 @@ namespace igl
   template <typename T>
   IGL_INLINE void serialize_xml(const T& obj,const std::string& filename)
   {
-    serialize_xml(obj,"object",filename,0);
+    serialize_xml(obj,"object",filename,false,true);
   }
 
   template <typename T>
-  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename,bool binary,bool update)
+  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename,bool binary,bool overwrite)
   {
     tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
 
-    if(update)
+    if(overwrite == false)
     {
       // Check if file exists
       tinyxml2::XMLError error = doc->LoadFile(filename.c_str());

+ 4 - 4
include/igl/xml/serialize_xml.h

@@ -45,7 +45,7 @@ namespace igl
   //   objectName unique object name,used for the identification
   //   filename   name of the file containing the serialization
   //   binary     set to true to serialize the object in binary format (faster for big data)
-  //   overwrite  set to true to update the serialization in an existing xml file
+  //   overwrite  set to true to overwrite an existing xml file
   //   element    tinyxml2 virtual representation of the current xml node
   // Outputs:
   //   doc        contains current tinyxml2 virtual representation of the xml data
@@ -53,7 +53,7 @@ namespace igl
   template <typename T>
   IGL_INLINE void serialize_xml(const T& obj,const std::string& filename);
   template <typename T>
-  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename, bool binary = false,bool update = false);
+  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename, bool binary = false,bool overwrite = false);
   template <typename T>
   IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,bool binary = false);
 
@@ -66,7 +66,7 @@ namespace igl
   //   objectName unique object name,used for the identification
   //   filename   name of the file containing the serialization
   //   binary     set to true to serialize the object in binary format (faster for big data)
-  //   overwrite  set to true to update the serialization in an existing xml file
+  //   overwrite  set to true to overwrite an existing xml file
   //   doc        contains current tinyxml2 virtual representation of the xml data
   //   element    tinyxml2 virtual representation of the current xml node
   // Outputs:
@@ -132,7 +132,7 @@ namespace igl
     IGL_INLINE virtual bool PreDeserialization();
     IGL_INLINE virtual void PostDeserialization();
 
-    // Default implementation of XMLSerializable interface
+    // Default implementation of XMLSerializableBase interface
     IGL_INLINE void Serialize(std::vector<char>& buffer) const;
     IGL_INLINE void Deserialize(const std::vector<char>& buffer);
     IGL_INLINE void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const;

+ 43 - 26
tutorial/601_Serialization/main.cpp

@@ -1,17 +1,14 @@
 #include <igl/readOFF.h>
 #include <iostream>
 
-#include <igl/xml/XMLSerializer.h>
-#include <igl/xml/XMLSerialization.h>
+#include <igl/serialize.h>
+#include <igl/xml/serialize_xml.h>
 
 Eigen::MatrixXd V;
 Eigen::MatrixXi F;
 
-class State : public ::igl::XMLSerialization
+struct State : public igl::Serializable
 {
-public:
-  State() : XMLSerialization("dummy") {}
-
   Eigen::MatrixXd V;
   Eigen::MatrixXi F;
   std::vector<int> ids;
@@ -20,39 +17,59 @@ public:
   // register the fields you want to serialize
   void InitSerialization()
   {
-    xmlSerializer->Add(V  , "V");
-    xmlSerializer->Add(F  , "F");
-    xmlSerializer->Add(ids, "ids");
+    this->Add(V  , "V");
+    this->Add(F  , "F");
+    this->Add(ids, "ids");
   }
-
 };
 
 int main(int argc, char *argv[])
 {
-  State state;
+  std::string binaryFile = "binData";
+  std::string xmlFile = "data.xml";
+
+  bool b = true;
+  unsigned int num = 10;
+  std::vector<float> vec = {0.1f,0.002f,5.3f};
+
+  // use overwrite = true for first serialization to create a new file
+  igl::serialize(b,"B",binaryFile,true);
+  // appends serialization to existing file
+  igl::serialize(num,"Number",binaryFile);
+  igl::serialize(vec,"VectorName",binaryFile);
+
+  // deserialize back to variables
+  igl::deserialize(b,"B",binaryFile);
+  igl::deserialize(num,"Number",binaryFile);
+  igl::deserialize(vec,"VectorName",binaryFile);
+
+  State stateIn, stateOut;
 
   // Load a mesh in OFF format
-  igl::readOFF("../shared/2triangles.off", state.V, state.F);
+  igl::readOFF("../../shared/2triangles.off",stateIn.V,stateIn.F);
 
   // Save some integers in a vector
-  state.ids.push_back(6);
-  state.ids.push_back(7);
+  stateIn.ids.push_back(6);
+  stateIn.ids.push_back(7);
 
-  // Serialize to XML the state of the application
-  ::igl::XMLSerializer serializer_save("601_Serialization");
-  serializer_save.Add(state,"State");
-  serializer_save.Save("temp.xml",true);
+  // Serialize the state of the application
+  igl::serialize(stateIn,"State",binaryFile,true);
 
   // Load the state from the same XML file
-  State loaded_state;
-  ::igl::XMLSerializer serializer_load("601_Serialization");
-  serializer_load.Add(loaded_state,"State");
-  serializer_load.Load("temp.xml");
+  igl::deserialize(stateOut,"State",binaryFile);
 
   // Plot the state
-  std::cout << "Vertices: " << std::endl << loaded_state.V << std::endl;
-  std::cout << "Faces:    " << std::endl << loaded_state.F << std::endl;
+  std::cout << "Vertices: " << std::endl << stateOut.V << std::endl;
+  std::cout << "Faces:    " << std::endl << stateOut.F << std::endl;
   std::cout << "ids:      " << std::endl
-            << loaded_state.ids[0] << " " << loaded_state.ids[1] << std::endl;
-
+            << stateOut.ids[0] << " " << stateOut.ids[1] << std::endl;
+			
+  // XML serialization
+  
+  // binary = false, overwrite = true
+  igl::serialize_xml(vec,"VectorXML",xmlFile,false,true);
+  // binary = true, overwrite = false
+  igl::serialize_xml(vec,"VectorBin",xmlFile,true,false);
+  igl::deserialize_xml(vec,"VectorXML",xmlFile);
+  igl::deserialize_xml(vec,"VectorBin",xmlFile);
 }

+ 1 - 1
tutorial/CMakeLists.txt

@@ -63,7 +63,7 @@ endif(LIBCOMISO_FOUND)
 add_subdirectory("509_Planarization")
 
 # Chapter 6
-#add_subdirectory("601_Serialization")
+add_subdirectory("601_Serialization")
 if(MATLAB_FOUND)
 add_subdirectory("602_Matlab")
 endif(MATLAB_FOUND)

+ 1 - 1
tutorial/tutorial.md.REMOVED.git-id

@@ -1 +1 @@
-09501b3f2820f82cbdc6b7f13355b5b8c8901131
+7bc77710f76fc13d95bbc9cf2c7166de255f541b