2021-03-23 17:44:27 +03:00
// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
2016-04-06 17:24:26 +03:00
//
// 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
//
# include "MED_Factory.hxx"
# include "MED_Utilities.hxx"
# include "MED_Wrapper.hxx"
2019-03-13 11:17:57 +03:00
# include <Basics_Utils.hxx>
2016-04-06 17:24:26 +03:00
# include <stdio.h>
# include <errno.h>
# include <sstream>
2018-10-09 17:26:15 +02:00
# include <fstream>
2016-04-06 17:24:26 +03:00
# include <med.h>
extern " C "
{
# ifndef WIN32
# include <unistd.h>
# endif
}
2018-07-18 15:51:37 +02:00
# include <utilities.h>
2016-04-06 17:24:26 +03:00
2018-08-29 14:47:50 +03:00
# ifdef WIN32
# include <windows.h>
# endif
2018-10-09 17:26:15 +02:00
// -------------------------------------------------------------------------------------------------------------------
// --- MED file compatibility: write using a lower major version implies append on an empty file of the target version
2019-10-03 17:06:11 +02:00
//
// *******************************************************************************************************************
// ==> This file must be modified when MED version changes:
// MED_MAJOR_NUM and MED_MINOR_NUM are defined in an external include from MED prerequisite: med.h
// When MED_MAJOR_NUM or MED_MINOR_NUM changes, MED_MAJOR_EXPECTED and MED_MINOR_EXPECTED must be set accordingly
// and MED_VERSIONS_APPEND_COMPATIBLE must be updated: The lower compatible versions may change with a new MED version
// If the major version of MED change (for instance 4 --> 5) and if MED allows to append meshes in MED-4.x format,
// Empty file content for MED-4.x should be provided (EMPTY_FILE_4x) and method CreateEmptyMEDFile should be updated.
// *******************************************************************************************************************
2018-10-09 17:26:15 +02:00
2018-10-03 15:08:45 +02:00
# define MED_MAJOR_EXPECTED 4
2020-02-17 15:49:46 +03:00
# define MED_MINOR_EXPECTED 1
2018-10-03 15:08:45 +02:00
# if MED_MAJOR_NUM != MED_MAJOR_EXPECTED
2019-10-03 17:06:11 +02:00
# error "MED major version does not correspond to the expected version, fix the minor and major compatibility values in CheckCompatibility method (MED_VERSIONS_APPEND_COMPATIBLE) and set the correct expected version (MED_MAJOR_EXPECTED, MED_MINOR_EXPECTED)"
2018-10-03 15:08:45 +02:00
# endif
2019-10-03 17:06:11 +02:00
# if MED_MINOR_NUM != MED_MINOR_EXPECTED
# error "MED minor version does not correspond to the expected version, fix the minor and major compatibility values in CheckCompatibility method (MED_VERSIONS_APPEND_COMPATIBLE) and set the correct expected version above (MED_MAJOR_EXPECTED, MED_MINOR_EXPECTED)"
2018-10-03 15:08:45 +02:00
# endif
2020-02-17 15:49:46 +03:00
# define MED_VERSIONS_APPEND_COMPATIBLE {41, 40, 32, 33} // --- 10*major + minor (the 3rd digit, release, is not used here,
// med uses always the latest available)
// --- The first in the list should be the default: current version
2018-08-29 14:47:50 +03:00
2016-04-06 17:24:26 +03:00
namespace MED
{
bool exists ( const std : : string & fileName )
{
# ifdef WIN32
2018-08-29 14:47:50 +03:00
# ifdef UNICODE
2019-03-11 18:35:25 +03:00
int size_needed = MultiByteToWideChar ( CP_UTF8 , 0 , fileName . c_str ( ) , strlen ( fileName . c_str ( ) ) , NULL , 0 ) ;
wchar_t * path = new wchar_t [ size_needed + 1 ] ;
MultiByteToWideChar ( CP_UTF8 , 0 , fileName . c_str ( ) , strlen ( fileName . c_str ( ) ) , path , size_needed ) ;
path [ size_needed ] = ' \0 ' ;
2018-08-29 14:47:50 +03:00
# else
2019-03-11 18:35:25 +03:00
cosnt char * path = xmlPath . c_str ( ) ;
2018-08-29 14:47:50 +03:00
# endif
2019-03-11 18:35:25 +03:00
bool res = ( GetFileAttributes ( path ) ! = INVALID_FILE_ATTRIBUTES ) ;
2018-09-27 14:34:01 +03:00
# ifdef UNICODE
2019-03-11 18:35:25 +03:00
delete path ;
2018-09-27 14:34:01 +03:00
# endif
2019-03-11 18:35:25 +03:00
return res ;
2016-04-06 17:24:26 +03:00
# else
return ( access ( fileName . c_str ( ) , F_OK ) = = 0 ) ;
# endif
}
2018-10-03 15:08:45 +02:00
/*!
* Return the list of med versions compatibles for write / append ,
* encoded in 10 * major + minor ( for instance , code for med 3.2 .1 is 32 )
*/
std : : vector < int > GetMEDVersionsAppendCompatible ( )
{
int mvok [ ] = MED_VERSIONS_APPEND_COMPATIBLE ;
std : : vector < int > MEDVersionsOK ( mvok , mvok + sizeof ( mvok ) / sizeof ( int ) ) ;
2019-10-02 17:33:03 +03:00
int curVersion = MED_MAJOR_NUM * 10 + MED_MINOR_NUM ;
if ( MEDVersionsOK [ 0 ] ! = curVersion )
MEDVersionsOK . insert ( MEDVersionsOK . begin ( ) , curVersion ) ;
2018-10-03 15:08:45 +02:00
return MEDVersionsOK ;
}
/*!
* \ brief : Check read or write ( append ) Compatibility of a med file
* \ param [ in ] : fileName - the file to read or to append to
* \ param [ in ] : isforAppend - when true , check if the med file version is OK to append a mesh ,
* when false , check if the med file is readable .
*/
2018-07-18 15:51:37 +02:00
bool CheckCompatibility ( const std : : string & fileName , bool isForAppend )
2016-04-06 17:24:26 +03:00
{
bool ok = false ;
2019-10-02 17:33:03 +03:00
std : : vector < int > medVersionsOK = GetMEDVersionsAppendCompatible ( ) ;
2016-04-06 17:24:26 +03:00
// check that file is accessible
if ( exists ( fileName ) ) {
// check HDF5 && MED compatibility
med_bool hdfok , medok ;
2018-07-18 15:51:37 +02:00
med_err r0 = MEDfileCompatibility ( fileName . c_str ( ) , & hdfok , & medok ) ;
2018-10-03 15:08:45 +02:00
MESSAGE ( r0 < < " " < < hdfok < < " " < < medok ) ;
2018-07-18 15:51:37 +02:00
if ( r0 = = 0 & & hdfok & & medok ) {
2016-04-06 17:24:26 +03:00
med_idt aFid = MEDfileOpen ( fileName . c_str ( ) , MED_ACC_RDONLY ) ;
if ( aFid > = 0 ) {
med_int major , minor , release ;
med_err ret = MEDfileNumVersionRd ( aFid , & major , & minor , & release ) ;
2018-10-03 15:08:45 +02:00
MESSAGE ( ret < < " " < < major < < " . " < < minor < < " . " < < release ) ;
2016-04-06 17:24:26 +03:00
if ( ret > = 0 ) {
2018-07-18 15:51:37 +02:00
bool isReadOnly = ! isForAppend ;
2018-10-03 15:08:45 +02:00
if ( isReadOnly )
2016-04-06 17:24:26 +03:00
ok = true ;
2018-10-03 15:08:45 +02:00
else {
int medVersion = 10 * major + minor ;
2019-10-02 17:33:03 +03:00
for ( size_t ii = 0 ; ii < medVersionsOK . size ( ) ; ii + + )
2018-10-03 15:08:45 +02:00
if ( medVersionsOK [ ii ] = = medVersion ) {
ok = true ;
break ;
}
}
2016-04-06 17:24:26 +03:00
}
}
MEDfileClose ( aFid ) ;
}
}
return ok ;
}
bool GetMEDVersion ( const std : : string & fileName , int & major , int & minor , int & release )
{
bool ok = false ;
major = minor = release = 0 ;
med_idt aFid = MEDfileOpen ( fileName . c_str ( ) , MED_ACC_RDONLY ) ;
if ( aFid > = 0 ) {
med_int _major , _minor , _release ;
med_err ret = MEDfileNumVersionRd ( aFid , & _major , & _minor , & _release ) ;
if ( ret = = 0 ) {
major = _major ;
minor = _minor ;
release = _release ;
ok = true ;
}
MEDfileClose ( aFid ) ;
}
return ok ;
}
std : : string GetMEDVersion ( const std : : string & fileName )
{
std : : string version ;
int major , minor , release ;
if ( GetMEDVersion ( fileName , major , minor , release ) ) {
std : : ostringstream os ;
os < < major < < " . " < < minor < < " . " < < release ;
version = os . str ( ) ;
}
return version ;
}
PWrapper CrWrapperR ( const std : : string & fileName )
{
if ( ! CheckCompatibility ( fileName ) ) {
EXCEPTION ( std : : runtime_error , " Cannot open file ' " < < fileName < < " '. " ) ;
}
2021-04-26 21:53:20 +02:00
return new MED : : TWrapper ( fileName , false , nullptr ) ;
2016-04-06 17:24:26 +03:00
}
2021-04-26 21:53:20 +02:00
PWrapper CrWrapperW ( const std : : string & fileName , int theVersion , TFileInternal * tfileInst )
2016-04-06 17:24:26 +03:00
{
2018-10-09 15:06:17 +02:00
bool isCreated = false ;
2018-07-18 15:51:37 +02:00
if ( ! CheckCompatibility ( fileName , true ) )
2019-03-11 18:35:25 +03:00
{
remove ( fileName . c_str ( ) ) ;
isCreated = true ;
}
2020-03-30 10:58:06 +02:00
med_int wantedMajor = MED_MAJOR_NUM ;
med_int wantedMinor = MED_MINOR_NUM ;
2020-04-06 21:53:23 +02:00
// when non managed version of file is requested : ignore it and take the latest version
std : : vector < int > versionsOK ( GetMEDVersionsAppendCompatible ( ) ) ;
bool isVersionRequestedOK ( std : : find ( versionsOK . begin ( ) , versionsOK . end ( ) , theVersion ) ! = versionsOK . end ( ) ) ;
if ( isCreated & & isVersionRequestedOK )
2019-03-11 18:35:25 +03:00
{
2020-04-06 21:53:23 +02:00
wantedMajor = theVersion / 10 ;
wantedMinor = theVersion % 10 ;
2019-03-11 18:35:25 +03:00
}
2021-04-26 21:53:20 +02:00
return new MED : : TWrapper ( fileName , true , tfileInst , wantedMajor , wantedMinor ) ;
2016-04-06 17:24:26 +03:00
}
}