Skip to content

Commit

Permalink
backport fix #276 (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
vcloarec authored Jul 16, 2020
1 parent 4398eca commit fbd746c
Show file tree
Hide file tree
Showing 6 changed files with 311 additions and 30 deletions.
80 changes: 52 additions & 28 deletions mdal/frmts/mdal_selafin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

MDAL::SerafinStreamReader::SerafinStreamReader() = default;

void MDAL::SerafinStreamReader::initialize( const std::string &fileName )
bool MDAL::SerafinStreamReader::initialize( const std::string &fileName )
{
mFileName = fileName;
if ( !MDAL::fileExists( mFileName ) )
Expand All @@ -42,8 +42,23 @@ void MDAL::SerafinStreamReader::initialize( const std::string &fileName )
mFileSize = mIn.tellg();
mIn.seekg( 0, mIn.beg );

mStreamInFloatPrecision = getStreamPrecision();
mIsNativeLittleEndian = MDAL::isNativeLittleEndian();
mChangeEndianness = MDAL::isNativeLittleEndian();

//Check if need to change the endianness
// read first size_t that has to be 80
size_t firstInt = read_sizet();
mIn.seekg( 0, mIn.beg );
if ( firstInt != 80 )
{
mChangeEndianness = !mChangeEndianness;
//Retry
firstInt = read_sizet();
if ( firstInt != 80 )
throw MDAL::Error( MDAL_Status::Err_UnknownFormat, "File " + mFileName + " could not be open" );
mIn.seekg( 0, mIn.beg );
}

return readHeader();
}

bool MDAL::SerafinStreamReader::getStreamPrecision( )
Expand All @@ -68,6 +83,27 @@ bool MDAL::SerafinStreamReader::getStreamPrecision( )
return ret;
}

bool MDAL::SerafinStreamReader::readHeader()
{
std::string header = read_string( 80 );
std::string varType = header.substr( 72, 8 );
varType = trim( varType );

if ( varType == "SERAFIN" )
mStreamInFloatPrecision = true;
else if ( varType == "SERAFIND" )
mStreamInFloatPrecision = false;
else
throw MDAL::Error( MDAL_Status::Err_UnknownFormat, "Not found stream precision" );

return true;
}

bool MDAL::SerafinStreamReader::streamInFloatPrecision() const
{
return mStreamInFloatPrecision;
}

std::string MDAL::SerafinStreamReader::read_string( size_t len )
{
size_t length = read_sizet();
Expand Down Expand Up @@ -150,13 +186,13 @@ double MDAL::SerafinStreamReader::read_double( )
if ( mStreamInFloatPrecision )
{
float ret_f;
if ( !readValue( ret_f, mIn, mIsNativeLittleEndian ) )
if ( !readValue( ret_f, mIn, mChangeEndianness ) )
throw MDAL::Error( MDAL_Status::Err_UnknownFormat, "Reading double failed" );
ret = static_cast<double>( ret_f );
}
else
{
if ( !readValue( ret, mIn, mIsNativeLittleEndian ) )
if ( !readValue( ret, mIn, mChangeEndianness ) )
throw MDAL::Error( MDAL_Status::Err_UnknownFormat, "Reading double failed" );
}
return ret;
Expand All @@ -170,7 +206,7 @@ int MDAL::SerafinStreamReader::read_int( )
if ( mIn.read( reinterpret_cast< char * >( &data ), 4 ) )
if ( !mIn )
throw MDAL::Error( MDAL_Status::Err_UnknownFormat, "Unable to open stream for reading int" );
if ( mIsNativeLittleEndian )
if ( mChangeEndianness )
{
std::reverse( reinterpret_cast< char * >( &data ), reinterpret_cast< char * >( &data ) + 4 );
}
Expand Down Expand Up @@ -341,8 +377,8 @@ void MDAL::DriverSelafin::parseFile( std::vector<std::string> &var_names,
- NBV(1)+NBV(2) records containing the results tables for each variable at time
*/
data.resize( var_names.size() );

size_t nTimesteps = mReader.remainingBytes() / ( 12 + ( 4 + ( *nPoint ) * 4 + 4 ) * var_names.size() );
size_t realSize = mReader.streamInFloatPrecision() ? 4 : 8;
size_t nTimesteps = mReader.remainingBytes() / ( 8 + realSize + ( 4 + ( *nPoint ) * realSize + 4 ) * var_names.size() );
for ( size_t nT = 0; nT < nTimesteps; ++nT )
{
std::vector<double> times = mReader.read_double_arr( 1 );
Expand Down Expand Up @@ -536,28 +572,16 @@ bool MDAL::DriverSelafin::canReadMesh( const std::string &uri )
{
if ( !MDAL::fileExists( uri ) ) return false;

std::ifstream in( uri, std::ifstream::in | std::ifstream::binary );
if ( !in ) return false;

// The first four bytes of the file should contain the values (in hexadecimal): 00 00 00 50.
// This actually indicates the start of a string of length 80 in the file.
// At position 84 in the file, the eight next bytes should read (in hexadecimal): 00 00 00 50 00 00 00 04.
unsigned char data[ 92 ];
in.read( reinterpret_cast< char * >( &data ), 92 );
if ( !in )
return false;

if ( data[0] != 0 || data[1] != 0 ||
data[2] != 0 || data[3] != 0x50 )
return false;

if ( data[84 + 0] != 0 || data[84 + 1] != 0 ||
data[84 + 2] != 0 || data[84 + 3] != 0x50 ||
data[84 + 4] != 0 || data[84 + 5] != 0 ||
data[84 + 6] != 0 || data[84 + 7] != 8 )
try
{
SerafinStreamReader reader;
return reader.initialize( uri );
}
catch ( MDAL::Error )
{
return false;
}

return true;
}

std::unique_ptr<MDAL::Mesh> MDAL::DriverSelafin::load( const std::string &meshFile, const std::string & )
Expand Down
11 changes: 9 additions & 2 deletions mdal/frmts/mdal_selafin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
#include "mdal_memory_data_model.hpp"
#include "mdal.h"
#include "mdal_driver.hpp"
#include "mdal_utils.hpp"

namespace MDAL
{
class SerafinStreamReader
{
public:
SerafinStreamReader();
void initialize( const std::string &fileName );
bool initialize( const std::string &fileName );

std::string read_string( size_t len );
std::vector<double> read_double_arr( size_t len );
Expand All @@ -35,6 +36,10 @@ namespace MDAL
size_t read_sizet( );

size_t remainingBytes();

//! Return true if is float precision
bool streamInFloatPrecision() const;

private:
void ignore_array_length( );
std::string read_string_without_length( size_t len );
Expand All @@ -43,9 +48,11 @@ namespace MDAL

std::string mFileName;
bool mStreamInFloatPrecision = true;
bool mIsNativeLittleEndian = true;
bool mChangeEndianness = true;
long long mFileSize = -1;
std::ifstream mIn;

bool readHeader();
};

/**
Expand Down
33 changes: 33 additions & 0 deletions tests/data/slf/README.TXT
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
test_sd_6
---------

format: double precision floating point
CRS: EPSG 25832

created with: Janet (v2.24.00)
number of timesteps: 1
parameters: X, Y, B, W


test_sd_7
---------

format: double precision floating point
CRS: EPSG 25832

created with: Telemac2D (v7p2r0)
number of timesteps: 11
parameters: X, Y, U, V, H, S, B, Q, M, W, L, US

where
- U="velocity along x axis (m/s)"
- V="velocity along y axis (m/s)"
- H="water depth (m)"
- S="free surface elevation (m)"
- B="bottom elevation (m)"
- F="Froude number "
- M="scalar velocity (m/s)"
- W="friction coefficient"
- L="Courant number "
- US="friction velocity "

Binary file added tests/data/slf/test_sd_6.slf
Binary file not shown.
Binary file added tests/data/slf/test_sd_7.slf
Binary file not shown.
Loading

0 comments on commit fbd746c

Please sign in to comment.