@@ -74,10 +74,11 @@ class FileIo::Impl {
7474 // ! Mode of operation
7575 enum OpMode { opRead, opWrite, opSeek };
7676 // DATA
77- fs::path path_; // !< (Standard) path
78- std::string openMode_; // !< File open mode
79- FILE* fp_{}; // !< File stream pointer
80- OpMode opMode_{opSeek}; // !< File open mode
77+ fs::path path_; // !< (Standard) path
78+ std::string openMode_; // !< File open mode
79+ std::wstring wOpenMode_; // !< File open mode (wide)
80+ FILE* fp_{}; // !< File stream pointer
81+ OpMode opMode_{opSeek}; // !< File open mode
8182
8283#ifdef _WIN32
8384 HANDLE hFile_{}; // !< Duplicated fd
@@ -119,6 +120,19 @@ int FileIo::Impl::switchMode(OpMode opMode) {
119120
120121 bool reopen = true ;
121122 switch (opMode) {
123+ #ifdef _WIN32
124+ case opRead:
125+ // Flush if current mode allows reading, else reopen (in mode "r+b"
126+ // as in this case we know that we can write to the file)
127+ if (wOpenMode_.front () == L' r' || wOpenMode_.at (1 ) == L' +' )
128+ reopen = false ;
129+ break ;
130+ case opWrite:
131+ // Flush if current mode allows writing, else reopen
132+ if (wOpenMode_.front () != L' r' || wOpenMode_.at (1 ) == L' +' )
133+ reopen = false ;
134+ break ;
135+ #else
122136 case opRead:
123137 // Flush if current mode allows reading, else reopen (in mode "r+b"
124138 // as in this case we know that we can write to the file)
@@ -130,6 +144,7 @@ int FileIo::Impl::switchMode(OpMode opMode) {
130144 if (openMode_.front () != ' r' || openMode_.at (1 ) == ' +' )
131145 reopen = false ;
132146 break ;
147+ #endif
133148 case opSeek:
134149 reopen = false ;
135150 break ;
@@ -340,7 +355,11 @@ size_t FileIo::write(BasicIo& src) {
340355
341356void FileIo::transfer (BasicIo& src) {
342357 const bool wasOpen = (p_->fp_ != nullptr );
358+ #ifdef _WIN32
359+ const std::wstring lastMode (p_->wOpenMode_ );
360+ #else
343361 const std::string lastMode (p_->openMode_ );
362+ #endif
344363
345364 if (auto fileIo = dynamic_cast <FileIo*>(&src)) {
346365 // Optimization if src is another instance of FileIo
@@ -415,7 +434,7 @@ void FileIo::transfer(BasicIo& src) {
415434
416435 if (wasOpen) {
417436 if (open (lastMode) != 0 ) {
418- throw Error (ErrorCode::kerFileOpenFailed, path (), lastMode, strError ());
437+ throw Error (ErrorCode::kerFileOpenFailed, path (), strError ());
419438 }
420439 } else
421440 close ();
@@ -466,7 +485,11 @@ size_t FileIo::tell() const {
466485
467486size_t FileIo::size () const {
468487 // Flush and commit only if the file is open for writing
488+ #ifdef _WIN32
489+ if (p_->fp_ && (p_->wOpenMode_ .front () != L' r' || p_->wOpenMode_ .at (1 ) == L' +' )) {
490+ #else
469491 if (p_->fp_ && (p_->openMode_ .front () != ' r' || p_->openMode_ .at (1 ) == ' +' )) {
492+ #endif
470493 std::fflush (p_->fp_ );
471494#ifdef _MSC_VER
472495 // This is required on msvcrt before stat after writing to a file
@@ -482,26 +505,34 @@ size_t FileIo::size() const {
482505
483506int FileIo::open () {
484507 // Default open is in read-only binary mode
508+ #ifdef _WIN32
509+ return open (L" rb" );
510+ #else
485511 return open (" rb" );
512+ #endif
486513}
487514
488515int FileIo::open (const std::string& mode) {
489516 close ();
490517 p_->openMode_ = mode;
491518 p_->opMode_ = Impl::opSeek;
492- #ifdef _WIN32
493- wchar_t wmode[10 ];
494- MultiByteToWideChar (CP_UTF8, 0 , mode.c_str (), -1 , wmode, 10 );
495- if (_wfopen_s (&p_->fp_ , p_->path_ .c_str (), wmode))
496- return 1 ;
497- #else
498519 p_->fp_ = ::fopen (path ().c_str (), mode.c_str ());
499520 if (!p_->fp_ )
500521 return 1 ;
501- #endif
502522 return 0 ;
503523}
504524
525+ #ifdef _WIN32
526+ int FileIo::open (const std::wstring& mode) {
527+ close ();
528+ p_->wOpenMode_ = mode;
529+ p_->opMode_ = Impl::opSeek;
530+ if (_wfopen_s (&p_->fp_ , p_->path_ .c_str (), mode.c_str ()))
531+ return 1 ;
532+ return 0 ;
533+ }
534+ #endif
535+
505536bool FileIo::isopen () const {
506537 return p_->fp_ != nullptr ;
507538}
@@ -1648,6 +1679,17 @@ size_t writeFile(const DataBuf& buf, const std::string& path) {
16481679 }
16491680 return file.write (buf.c_data (), buf.size ());
16501681}
1682+
1683+ #ifdef _WIN32
1684+ DataBuf readFile (const std::wstring& path) {
1685+ FileIo file (path);
1686+ if (file.open (L" rb" ) != 0 )
1687+ throw Error (ErrorCode::kerFileOpenFailed, " wb" , strError ());
1688+ DataBuf buf (static_cast <size_t >(fs::file_size (path)));
1689+ file.read (buf.data (), buf.size ());
1690+ return buf;
1691+ }
1692+ #endif
16511693#endif
16521694
16531695#ifdef EXV_USE_CURL
0 commit comments