diff --git a/include/igl/file_dialog_open.cpp b/include/igl/file_dialog_open.cpp index e0bf9618d..14c8a98af 100644 --- a/include/igl/file_dialog_open.cpp +++ b/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. diff --git a/include/igl/file_dialog_save.cpp b/include/igl/file_dialog_save.cpp index 0ed06c0f4..22940f586 100644 --- a/include/igl/file_dialog_save.cpp +++ b/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)); diff --git a/include/igl/serialize.cpp b/include/igl/serialize.cpp index 64dd92e69..5b64b41b8 100644 --- a/include/igl/serialize.cpp +++ b/include/igl/serialize.cpp @@ -10,17 +10,20 @@ namespace igl { template - 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 - 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 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::ofstream file(filename.c_str(),std::ios::out | std::ios::binary); + std::ios_base::openmode mode = 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 - IGL_INLINE void serialize(const T& obj,const std::string& objectName,std::vector& buffer) + IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector& buffer) { static_assert(detail::is_serializable::value,"'igl::serialize': type is not serializable"); @@ -64,14 +78,14 @@ namespace igl std::vector::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::const_iterator citer = buffer.cbegin(); + // find object header to replace existing object + /*std::vector::const_iterator citer = buffer.cbegin(); while(citer != buffer.cend()) { std::vector::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 - 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 - 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 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 - IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::vector& buffer) - { + IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::vector& buffer) + { static_assert(detail::is_serializable::value,"'igl::deserialize': type is not deserializable"); + bool success = false; + // find suitable object header + std::vector::const_iterator objectIter = buffer.end(); std::vector::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 diff --git a/include/igl/serialize.h b/include/igl/serialize.h index 3e581331d..32f5398df 100644 --- a/include/igl/serialize.h +++ b/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 - IGL_INLINE void serialize(const T& obj,const std::string& filename); + IGL_INLINE bool serialize(const T& obj,const std::string& filename); template - 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 - IGL_INLINE void serialize(const T& obj,const std::string& objectName,std::vector& buffer); + IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector& 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 - IGL_INLINE void deserialize(T& obj,const std::string& filename); + IGL_INLINE bool deserialize(T& obj,const std::string& filename); template - 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 - IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::vector& buffer); + IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::vector& 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& buffer) const; IGL_INLINE void Deserialize(const std::vector& buffer); diff --git a/include/igl/xml/serialization_test.cpp b/include/igl/xml/serialization_test.cpp index 89e9e25a6..1d60aabe6 100644 --- a/include/igl/xml/serialization_test.cpp +++ b/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 tDenseMatrixIn; tDenseMatrixIn << Eigen::Matrix::Random(); + tDenseMatrixIn.coeffRef(0,0) = 1.00001; Eigen::Matrix tDenseMatrixOut; Eigen::Matrix 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 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 - 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()); diff --git a/include/igl/xml/serialize_xml.h b/include/igl/xml/serialize_xml.h index d109741ce..128753a86 100644 --- a/include/igl/xml/serialize_xml.h +++ b/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 IGL_INLINE void serialize_xml(const T& obj,const std::string& filename); template - 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 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& buffer) const; IGL_INLINE void Deserialize(const std::vector& buffer); IGL_INLINE void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const; diff --git a/tutorial/601_Serialization/main.cpp b/tutorial/601_Serialization/main.cpp index 5dd3f6d05..30e772eab 100755 --- a/tutorial/601_Serialization/main.cpp +++ b/tutorial/601_Serialization/main.cpp @@ -1,17 +1,14 @@ #include #include -#include -#include +#include +#include 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 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 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); } diff --git a/tutorial/CMakeLists.txt b/tutorial/CMakeLists.txt index 34e859dc9..13b38c56f 100644 --- a/tutorial/CMakeLists.txt +++ b/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) diff --git a/tutorial/tutorial.md.REMOVED.git-id b/tutorial/tutorial.md.REMOVED.git-id index 5b05785d4..326073a1e 100644 --- a/tutorial/tutorial.md.REMOVED.git-id +++ b/tutorial/tutorial.md.REMOVED.git-id @@ -1 +1 @@ -09501b3f2820f82cbdc6b7f13355b5b8c8901131 \ No newline at end of file +7bc77710f76fc13d95bbc9cf2c7166de255f541b \ No newline at end of file