@@ -73,10 +73,11 @@ class FileIo::Impl {
7373 // ! Mode of operation
7474 enum OpMode { opRead, opWrite, opSeek };
7575 // DATA
76- fs::path path_; // !< (Standard) path
77- std::string openMode_; // !< File open mode
78- FILE* fp_{}; // !< File stream pointer
79- OpMode opMode_{opSeek}; // !< File open mode
76+ fs::path path_; // !< (Standard) path
77+ std::string openMode_; // !< File open mode
78+ std::wstring wOpenMode_; // !< File open mode (wide)
79+ FILE* fp_{}; // !< File stream pointer
80+ OpMode opMode_{opSeek}; // !< File open mode
8081
8182#if defined _WIN32
8283 HANDLE hFile_{}; // !< Duplicated fd
@@ -118,6 +119,19 @@ int FileIo::Impl::switchMode(OpMode opMode) {
118119
119120 bool reopen = true ;
120121 switch (opMode) {
122+ #ifdef _WIN32
123+ case opRead:
124+ // Flush if current mode allows reading, else reopen (in mode "r+b"
125+ // as in this case we know that we can write to the file)
126+ if (wOpenMode_.front () == L' r' || wOpenMode_.at (1 ) == L' +' )
127+ reopen = false ;
128+ break ;
129+ case opWrite:
130+ // Flush if current mode allows writing, else reopen
131+ if (wOpenMode_.front () != L' r' || wOpenMode_.at (1 ) == L' +' )
132+ reopen = false ;
133+ break ;
134+ #else
121135 case opRead:
122136 // Flush if current mode allows reading, else reopen (in mode "r+b"
123137 // as in this case we know that we can write to the file)
@@ -129,6 +143,7 @@ int FileIo::Impl::switchMode(OpMode opMode) {
129143 if (openMode_.front () != ' r' || openMode_.at (1 ) == ' +' )
130144 reopen = false ;
131145 break ;
146+ #endif
132147 case opSeek:
133148 reopen = false ;
134149 break ;
@@ -339,7 +354,11 @@ size_t FileIo::write(BasicIo& src) {
339354
340355void FileIo::transfer (BasicIo& src) {
341356 const bool wasOpen = (p_->fp_ != nullptr );
357+ #ifdef _WIN32
358+ const std::wstring lastMode (p_->wOpenMode_ );
359+ #else
342360 const std::string lastMode (p_->openMode_ );
361+ #endif
343362
344363 if (auto fileIo = dynamic_cast <FileIo*>(&src)) {
345364 // Optimization if src is another instance of FileIo
@@ -414,7 +433,7 @@ void FileIo::transfer(BasicIo& src) {
414433
415434 if (wasOpen) {
416435 if (open (lastMode) != 0 ) {
417- throw Error (ErrorCode::kerFileOpenFailed, path (), lastMode, strError ());
436+ throw Error (ErrorCode::kerFileOpenFailed, path (), strError ());
418437 }
419438 } else
420439 close ();
@@ -465,7 +484,11 @@ size_t FileIo::tell() const {
465484
466485size_t FileIo::size () const {
467486 // Flush and commit only if the file is open for writing
487+ #ifdef _WIN32
488+ if (p_->fp_ && (p_->wOpenMode_ .front () != L' r' || p_->wOpenMode_ .at (1 ) == L' +' )) {
489+ #else
468490 if (p_->fp_ && (p_->openMode_ .front () != ' r' || p_->openMode_ .at (1 ) == ' +' )) {
491+ #endif
469492 std::fflush (p_->fp_ );
470493#ifdef _MSC_VER
471494 // This is required on msvcrt before stat after writing to a file
@@ -481,26 +504,34 @@ size_t FileIo::size() const {
481504
482505int FileIo::open () {
483506 // Default open is in read-only binary mode
507+ #ifdef _WIN32
508+ return open (L" rb" );
509+ #else
484510 return open (" rb" );
511+ #endif
485512}
486513
487514int FileIo::open (const std::string& mode) {
488515 close ();
489516 p_->openMode_ = mode;
490517 p_->opMode_ = Impl::opSeek;
491- #ifdef _WIN32
492- wchar_t wmode[10 ];
493- MultiByteToWideChar (CP_UTF8, 0 , mode.c_str (), -1 , wmode, 10 );
494- if (_wfopen_s (&p_->fp_ , p_->path_ .c_str (), wmode))
495- return 1 ;
496- #else
497518 p_->fp_ = ::fopen (path ().c_str (), mode.c_str ());
498519 if (!p_->fp_ )
499520 return 1 ;
500- #endif
501521 return 0 ;
502522}
503523
524+ #ifdef _WIN32
525+ int FileIo::open (const std::wstring& mode) {
526+ close ();
527+ p_->wOpenMode_ = mode;
528+ p_->opMode_ = Impl::opSeek;
529+ if (_wfopen_s (&p_->fp_ , p_->path_ .c_str (), mode.c_str ()))
530+ return 1 ;
531+ return 0 ;
532+ }
533+ #endif
534+
504535bool FileIo::isopen () const {
505536 return p_->fp_ != nullptr ;
506537}
@@ -1647,6 +1678,17 @@ size_t writeFile(const DataBuf& buf, const std::string& path) {
16471678 }
16481679 return file.write (buf.c_data (), buf.size ());
16491680}
1681+
1682+ #ifdef _WIN32
1683+ DataBuf readFile (const std::wstring& path) {
1684+ FileIo file (path);
1685+ if (file.open (L" rb" ) != 0 )
1686+ throw Error (ErrorCode::kerFileOpenFailed, " wb" , strError ());
1687+ DataBuf buf (static_cast <size_t >(fs::file_size (path)));
1688+ file.read (buf.data (), buf.size ());
1689+ return buf;
1690+ }
1691+ #endif
16501692#endif
16511693
16521694#ifdef EXV_USE_CURL
0 commit comments