Skip to content

Commit

Permalink
fix netCdf derived driver if there is special char on the file name (…
Browse files Browse the repository at this point in the history
…Windows) (#429)
  • Loading branch information
vcloarec committed Sep 18, 2022
1 parent 3d36908 commit e397b50
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 16 deletions.
4 changes: 2 additions & 2 deletions mdal/frmts/mdal_netcdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ int NetCDFFile::handle() const

void NetCDFFile::openFile( const std::string &fileName, bool write )
{
int res = nc_open( fileName.c_str(), write ? NC_WRITE : NC_NOWRITE, &mNcid );
int res = nc_open( MDAL::systemFileName( fileName ).c_str(), write ? NC_WRITE : NC_NOWRITE, &mNcid );
if ( res != NC_NOERR )
{
throw MDAL::Error( MDAL_Status::Err_UnknownFormat, "Could not open file " + fileName );
Expand Down Expand Up @@ -484,7 +484,7 @@ bool NetCDFFile::hasDimension( const std::string &name ) const

void NetCDFFile::createFile( const std::string &fileName )
{
int res = nc_create( fileName.c_str(), NC_CLOBBER, &mNcid );
int res = nc_create( MDAL::systemFileName( fileName ).c_str(), NC_CLOBBER, &mNcid );
if ( res != NC_NOERR )
{
throw MDAL::Error( MDAL_Status::Err_FailToWriteToDisk, nc_strerror( res ) );
Expand Down
57 changes: 47 additions & 10 deletions mdal/mdal_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
#include <ctime>
#include <stdlib.h>

#if defined _WIN32
#ifdef _WIN32
#define UNICODE
#include <locale>
#include <codecvt>
#include <stringapiset.h>
#endif

std::string MDAL::getEnvVar( const std::string &varname, const std::string &defaultVal )
Expand All @@ -37,7 +38,7 @@ std::string MDAL::getEnvVar( const std::string &varname, const std::string &defa

bool MDAL::openInputFile( std::ifstream &inputFileStream, const std::string &fileName, std::ios_base::openmode mode )
{
#if defined _MSC_VER
#ifdef _WIN32
std::wstring_convert< std::codecvt_utf8_utf16< wchar_t > > converter;
std::wstring wStr = converter.from_bytes( fileName );
inputFileStream.open( wStr, std::ifstream::in | mode );
Expand All @@ -52,7 +53,7 @@ std::ifstream MDAL::openInputFile( const std::string &fileName, std::ios_base::o
{
std::ifstream ret;

#if defined _MSC_VER
#ifdef _WIN32
std::wstring_convert< std::codecvt_utf8_utf16< wchar_t > > converter;
std::wstring wStr = converter.from_bytes( fileName );
ret.open( wStr, mode );
Expand All @@ -67,7 +68,7 @@ std::ofstream MDAL::openOutputFile( const std::string &fileName, std::ios_base::
{
std::ofstream ret;

#if defined _MSC_VER
#ifdef _WIN32
std::wstring_convert< std::codecvt_utf8_utf16< wchar_t > > converter;
std::wstring wStr = converter.from_bytes( fileName );
ret.open( wStr, mode );
Expand Down Expand Up @@ -262,7 +263,7 @@ std::string MDAL::fileExtension( const std::string &path )
std::string MDAL::pathJoin( const std::string &path1, const std::string &path2 )
{
//https://stackoverflow.com/questions/6297738/how-to-build-a-full-path-string-safely-from-separate-strings#6297807
#ifdef _MSC_VER
#ifdef _WIN32
return path1 + "\\" + path2;
#else
return path1 + "/" + path2;
Expand Down Expand Up @@ -291,7 +292,7 @@ bool MDAL::contains( const std::string &str, const std::string &substr, Contains
substr.begin(), substr.end(),
[]( char ch1, char ch2 )
{
#ifdef _MSC_VER
#ifdef _WIN32
return toupper( ch1 ) == toupper( ch2 );
#else
return std::toupper( ch1 ) == std::toupper( ch2 );
Expand Down Expand Up @@ -342,7 +343,7 @@ std::string MDAL::leftJustified( const std::string &str, size_t width, char fill
std::string MDAL::toLower( const std::string &std )
{
std::string res( std );
#ifdef WIN32
#ifdef _WIN32
//silence algorithm(1443): warning C4244: '=': conversion from 'int' to 'char'
std::transform( res.begin(), res.end(), res.begin(),
[]( char c ) {return static_cast<char>( ::tolower( c ) );} );
Expand Down Expand Up @@ -400,6 +401,42 @@ std::string MDAL::trim( const std::string &s, const std::string &delimiters )
return ltrim( rtrim( s, delimiters ), delimiters );
}

#ifdef _WIN32
static std::string utf8ToWin32Recode( const std::string &utf8String )
{
//from GDAL: ./port/cpl_recode_stub.cpp, CPLWin32Recode()

// Compute length in wide characters
int wlen = MultiByteToWideChar( CP_UTF8, 0, utf8String.c_str(), -1, nullptr, 0 );

// do the conversion to wide char
std::wstring wstr;
wstr.resize( MDAL::toSizeT( wlen ) + 1 );
wstr.data()[wlen] = 0;
MultiByteToWideChar( CP_UTF8, 0, utf8String.c_str(), -1, wstr.data(), wstr.size() );

int len = WideCharToMultiByte( CP_ACP, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr );

std::string ret;
ret.resize( MDAL::toSizeT( len ) + 1 );

WideCharToMultiByte( CP_ACP, 0, wstr.c_str(), -1, ret.data(), ret.size(), nullptr, nullptr );

return ret;
}
#endif

std::string MDAL::systemFileName( const std::string &utf8FileName )
{
std::string ret;
#ifdef _WIN32
ret = utf8ToWin32Recode( utf8FileName );
#else
ret = utf8FileName;
#endif
return ret;
}

// http://www.cplusplus.com/faq/sequences/strings/trim/
std::string MDAL::ltrim( const std::string &s, const std::string &delimiters )
{
Expand Down Expand Up @@ -1041,7 +1078,7 @@ MDAL::Library::Library( std::string libraryFile )
MDAL::Library::~Library()
{
d->mRef--;
#ifdef WIN32
#ifdef _WIN32
if ( d->mLibrary && d->mRef == 0 )
FreeLibrary( d->mLibrary );
#else
Expand Down Expand Up @@ -1075,7 +1112,7 @@ bool MDAL::Library::isValid()
std::vector<std::string> MDAL::Library::libraryFilesInDir( const std::string &dirPath )
{
std::vector<std::string> filesList;
#if defined(WIN32)
#ifdef _WIN32
WIN32_FIND_DATA data;
HANDLE hFind;
std::string pattern = dirPath;
Expand Down Expand Up @@ -1120,7 +1157,7 @@ bool MDAL::Library::loadLibrary()
//should we allow only one successful loading?
if ( d->mLibrary )
return false;
#ifdef WIN32
#ifdef _WIN32
UINT uOldErrorMode =
SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
d->mLibrary = LoadLibrary( d->mLibraryFile.c_str() );
Expand Down
9 changes: 6 additions & 3 deletions mdal/mdal_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <cmath>
#include <functional>

#if defined (WIN32)
#ifdef _WIN32
#include <windows.h>
#undef min
#undef max
Expand Down Expand Up @@ -139,6 +139,9 @@ namespace MDAL
const std::string &s,
const std::string &delimiters = " \f\n\r\t\v" );

//! Returns a string file path encoded consistently with the system from a string encoded with UTF-8
std::string systemFileName( const std::string &utf8FileName );

// extent
BBox computeExtent( const Vertices &vertices );

Expand Down Expand Up @@ -277,7 +280,7 @@ namespace MDAL
{
if ( !isValid() )
return std::function<T( Ts ... args )>();
#ifdef WIN32
#ifdef _WIN32
FARPROC proc = GetProcAddress( d->mLibrary, symbolName.c_str() );

if ( !proc )
Expand Down Expand Up @@ -308,7 +311,7 @@ namespace MDAL
private:
struct Data
{
#ifdef WIN32
#ifdef _WIN32
HINSTANCE mLibrary = nullptr;
#else
void *mLibrary = nullptr;
Expand Down
Binary file added tests/data/ugrid/special@char/àeé.nc
Binary file not shown.
12 changes: 11 additions & 1 deletion tests/test_ugrid.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
MDAL - Mesh Data Abstraction Library (MIT License)
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
*/
Expand Down Expand Up @@ -1170,6 +1170,16 @@ TEST( MeshUgridTest, unlockWhenClose )
ASSERT_FALSE( fileExists( tmpUgridFile ) );
}

TEST( MeshUgridTest, SpecialChar )
{
std::string path = test_file( u8"/ugrid/special@char/àeé.nc" );
EXPECT_EQ( MDAL_MeshNames( path.c_str() ), "Ugrid:\"" + path + "\":mesh1d;;Ugrid:\"" + path + "\":mesh2d" );
MDAL_MeshH m = MDAL_LoadMesh( path.c_str() );
ASSERT_NE( m, nullptr );

MDAL_CloseMesh( m );
}

int main( int argc, char **argv )
{
testing::InitGoogleTest( &argc, argv );
Expand Down

0 comments on commit e397b50

Please sign in to comment.