From ce0f1ae8e9e0e01d8f3518a6e224c0006518097c Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 6 Aug 2021 15:41:33 +0300 Subject: [PATCH] Bug: boost::archive::text_iarchive fails if archive created by newer version of boost::archive library --- src/SMESHUtils/CMakeLists.txt | 2 + src/SMESHUtils/SMESH_BoostTxtArchive.cxx | 152 ++++++++++++++++++++ src/SMESHUtils/SMESH_BoostTxtArchive.hxx | 95 ++++++++++++ src/SMESH_I/SMESH_Gen_i.cxx | 8 +- src/StdMeshers/StdMeshers_BlockRenumber.cxx | 27 ++-- 5 files changed, 264 insertions(+), 20 deletions(-) create mode 100644 src/SMESHUtils/SMESH_BoostTxtArchive.cxx create mode 100644 src/SMESHUtils/SMESH_BoostTxtArchive.hxx diff --git a/src/SMESHUtils/CMakeLists.txt b/src/SMESHUtils/CMakeLists.txt index 652f469de..8eb4e3b68 100644 --- a/src/SMESHUtils/CMakeLists.txt +++ b/src/SMESHUtils/CMakeLists.txt @@ -61,6 +61,7 @@ SET(SMESHUtils_HEADERS SMESH_ControlPnt.hxx SMESH_Delaunay.hxx SMESH_Indexer.hxx + SMESH_BoostTxtArchive.hxx ) # --- sources --- @@ -84,6 +85,7 @@ SET(SMESHUtils_SOURCES SMESH_Offset.cxx SMESH_Slot.cxx SMESH_PolyLine.cxx + SMESH_BoostTxtArchive.cxx ) # --- rules --- diff --git a/src/SMESHUtils/SMESH_BoostTxtArchive.cxx b/src/SMESHUtils/SMESH_BoostTxtArchive.cxx new file mode 100644 index 000000000..9e29c5479 --- /dev/null +++ b/src/SMESHUtils/SMESH_BoostTxtArchive.cxx @@ -0,0 +1,152 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESH_BoostTxtArchive.cxx +// Created : Thu Aug 5 21:19:31 2021 +// Author : Edward AGAPOV (eap) + +#include "SMESH_BoostTxtArchive.hxx" + +#include +#include +#include + + +using namespace SMESHUtils; + +BoostTxtArchive::BoostTxtArchive( const std::string& s ): + myArchiveReader( nullptr ), + myString( s ), + myStringFixed( false ), + myStream( nullptr ), + myOwnStream( true ) +{ + myStream = new std::istringstream( myString ); + makeReader(); +} + +BoostTxtArchive::BoostTxtArchive( std::istream& stream ): + myArchiveReader( nullptr ), + myStringFixed( false ), + myStream( &stream ), + myOwnStream( false ) +{ + if ( std::istringstream * sstrm = dynamic_cast< std::istringstream* >( &stream )) + myString = sstrm->str(); + + makeReader(); +} + +BoostTxtArchive::~BoostTxtArchive() +{ + delete myArchiveReader; myArchiveReader = nullptr; + if ( myOwnStream ) + delete myStream; +} + +void BoostTxtArchive::makeReader() +{ + myArchiveReader = nullptr; + try + { + myArchiveReader = new boost::archive::text_iarchive( *myStream ); + } + catch (...) + { + if ( fixString() ) + try + { + myArchiveReader = new boost::archive::text_iarchive( *myStream ); + } + catch(...) + { + myArchiveReader = nullptr; + } + } +} + +namespace +{ + //================================================================================ + /*! + * \brief Return archive created by current version of boost::archive + */ + //================================================================================ + + std::string getCurrentVersionArchive( BoostTxtArchive & bta) + { + std::ostringstream strm; + boost::archive::text_oarchive archive( strm ); + archive << bta; + return strm.str(); + } +} + +//================================================================================ +/*! + * \brief Change boost::archive library version in myString to be equal to + * the current library version + * \return bool - return true if the version is changed + */ +//================================================================================ + +bool BoostTxtArchive::fixString() +{ + if ( myStringFixed ) + return false; + myStringFixed = true; + + const char* sub = "serialization::archive "; + const size_t subLen = 23; + + size_t where1 = myString.find( sub ); + if ( where1 == std::string::npos ) + return false; + + std::string nowString = getCurrentVersionArchive( *this ); + size_t where2 = nowString.find( sub ); + if ( where2 == std::string::npos ) + return false; + + bool sameVersion = true; + for ( size_t i1 = where1 + subLen, i2 = where2 + subLen; + i2 < nowString.size(); + ++i1, ++i2 ) + { + if ( myString[ i1 ] != nowString[ i2 ] ) + { + sameVersion = false; + myString[ i1 ] = nowString[ i2 ]; + } + if ( isspace( myString[ i1 ])) + break; + } + + if ( !sameVersion ) + { + if ( myOwnStream ) + delete myStream; + myStream = new std::istringstream( myString ); + myOwnStream = true; + } + + return !sameVersion; +} diff --git a/src/SMESHUtils/SMESH_BoostTxtArchive.hxx b/src/SMESHUtils/SMESH_BoostTxtArchive.hxx new file mode 100644 index 000000000..cb5071f69 --- /dev/null +++ b/src/SMESHUtils/SMESH_BoostTxtArchive.hxx @@ -0,0 +1,95 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESH_BoostTxtArchive.hxx +// Created : Thu Aug 5 19:10:24 2021 +// Author : Edward AGAPOV (eap) + + +#ifndef __SMESH_BoostTxtArchive_HXX__ +#define __SMESH_BoostTxtArchive_HXX__ + +#include "SMESH_Utils.hxx" + +#include + +namespace SMESHUtils +{ + /*! + * \brief Load an object from a string created by boost::archive::text_oarchive. + * + * Try to workaround the issue that loading fails if the archive string + * is created by a newer version of boost::archive library. + * + * Usage: ObjType obj; BoostTxtArchive( arcString ) >> obj; + */ + class SMESHUtils_EXPORT BoostTxtArchive + { + public: + + BoostTxtArchive( const std::string& s ); + BoostTxtArchive( std::istream& stream ); + ~BoostTxtArchive(); + + template< class T > + BoostTxtArchive & operator>>( T & t ) + { + if ( myArchiveReader ) + try + { + (*myArchiveReader) >> t; + } + catch (...) + { + if ( fixString() ) + try + { + (*myArchiveReader) >> t; + } + catch(...) + { + } + } + return *this; + } + + private: + + void makeReader(); + bool fixString(); + + boost::archive::text_iarchive* myArchiveReader; + std::string myString; // archive to read + bool myStringFixed; // is archive version changed + std::istream* myStream; // stream holding myString + bool myOwnStream; // is myStream created by me + + // persistence used to create a current version archive + friend class boost::serialization::access; + template + void serialize(Archive & /*ar*/, const unsigned int /*version*/) + { + } + }; +} + + +#endif diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 363e8d7aa..677e7fb99 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -102,6 +102,7 @@ #include "SMESH_PreMeshInfo.hxx" #include "SMESH_PythonDump.hxx" #include "SMESH_ControlsDef.hxx" +#include // to pass CORBA exception through SMESH_TRY #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; } @@ -5995,13 +5996,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, aDataset->ReadFromDisk((char*) dataString.data() ); aDataset->CloseOnDisk(); - std::istringstream istream( dataString.data() ); - boost::archive::text_iarchive archive( istream ); std::list< std::list< std::string > > orderEntryLists; - try { - archive >> orderEntryLists; - } - catch (...) {} + SMESHUtils::BoostTxtArchive( dataString ) >> orderEntryLists; TListOfListOfInt anOrderIds; for ( const std::list< std::string >& entryList : orderEntryLists ) diff --git a/src/StdMeshers/StdMeshers_BlockRenumber.cxx b/src/StdMeshers/StdMeshers_BlockRenumber.cxx index 9dea567d4..df74a1665 100644 --- a/src/StdMeshers/StdMeshers_BlockRenumber.cxx +++ b/src/StdMeshers/StdMeshers_BlockRenumber.cxx @@ -26,14 +26,15 @@ #include "StdMeshers_BlockRenumber.hxx" -#include "SMDS_EdgePosition.hxx" -#include "SMDS_FacePosition.hxx" -#include "SMESHDS_Mesh.hxx" -#include "SMESHDS_SubMesh.hxx" -#include "SMESH_Algo.hxx" -#include "SMESH_Mesh.hxx" -#include "SMESH_MesherHelper.hxx" -#include "SMESH_TryCatch.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -41,7 +42,6 @@ #include #include -#include //============================================================================= /*! @@ -203,11 +203,11 @@ TopoDS_Vertex StdMeshers_RenumberHelper::GetVertex000( const TopTools_MapOfShape } //======================================================================= -//function : GetVertex000 -//purpose : Find default vertex at (0,0,0) local position +//function : GetVertexAtPoint +//purpose : Return the VERTEX of solid at given point //======================================================================= -TopoDS_Vertex StdMeshers_RenumberHelper::GetVertexAtPoint( const TopoDS_Shape& solid, +TopoDS_Vertex StdMeshers_RenumberHelper::GetVertexAtPoint( const TopoDS_Shape& solid, const TopoDS_Shape& point ) { if ( !solid.IsNull() && !point.IsNull() && point.ShapeType() == TopAbs_VERTEX ) @@ -296,8 +296,7 @@ istream & StdMeshers_BlockRenumber::LoadFrom(istream & load) { SMESH_TRY; - boost::archive::text_iarchive archive( load ); - archive >> *this; + SMESHUtils::BoostTxtArchive( load ) >> *this; SMESH_CATCH( SMESH::doNothing ); -- 2.39.2