#ifdef _WIN32
#include <windows.h>
+ #include <share.h>
#endif
#include <OSD_OpenFile.hxx>
#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
+
+//! Auxiliary function converting C++ ios open mode flags to C fopen() flags.
+static int OSD_OpenFile_iosMode2FileFlags (::std::ios_base::openmode theMode)
+{
+ int aFlags = 0;
+ if (theMode & ::std::ios_base::in)
+ {
+ aFlags |= O_RDONLY;
+ }
+ if (theMode & ::std::ios_base::out)
+ {
+ aFlags |= O_WRONLY;
+ aFlags |= O_CREAT;
+ if (theMode & ::std::ios_base::app)
+ {
+ aFlags |= O_APPEND;
+ }
+ if (theMode & ::std::ios_base::trunc)
+ {
+ aFlags |= O_TRUNC;
+ }
+ }
+#ifdef _WIN32
+ if (theMode & ::std::ios_base::binary)
+ {
+ aFlags |= O_BINARY;
+ }
+ else
+ {
+ aFlags |= O_TEXT;
+ }
+#endif
+ return aFlags;
+}
+
+// ==============================================
+// function : OSD_OpenFile
+// purpose : Opens file
+// ==============================================
+int OSD_OpenFileDescriptor (const TCollection_ExtendedString& theName,
+ ::std::ios_base::openmode theMode)
+{
+ int aFileDesc = -1;
+ const int aFlags = OSD_OpenFile_iosMode2FileFlags (theMode);
+#if defined(_WIN32)
+ const errno_t anErrCode = _wsopen_s (&aFileDesc, theName.ToWideString(), aFlags, _SH_DENYNO, _S_IREAD | _S_IWRITE);
+ if (anErrCode != 0)
+ {
+ return -1;
+ }
+#else
+ NCollection_Utf8String aString (theName.ToExtString());
+ aFileDesc = open (aString.ToCString(), aFlags);
+#endif
+ return aFileDesc;
+}
// ==============================================
// function : OSD_OpenFile
#include <TCollection_ExtendedString.hxx>
#include <NCollection_UtfString.hxx>
+#if defined(_WIN32) && defined(__GLIBCXX__)
+ #include <ext/stdio_filebuf.h> // __gnu_cxx::stdio_filebuf
+#endif
+
//! Function opens the file.
//! @param theName name of file encoded in UTF-16
//! @param theMode opening mode
//! @return stat.st_ctime value
__Standard_API Standard_Time OSD_FileStatCTime (const char* theName);
-//! Function opens the file stream.
-//! @param theStream stream to open
-//! @param theName name of file encoded in UTF-8
+//! Open file descriptor for specified UTF-16 file path.
+//! @param theName name of file encoded in UTF-16
//! @param theMode opening mode
-template <typename T>
-inline void OSD_OpenStream (T& theStream,
- const char* theName,
+//! @return file descriptor on success or -1 on error
+__Standard_API int OSD_OpenFileDescriptor (const TCollection_ExtendedString& theName,
+ ::std::ios_base::openmode theMode);
+
+//! Function opens the file buffer.
+//! @param theFileBuf file buffer to open
+//! @param theName name of file encoded in UTF-16
+//! @param theMode opening mode
+//! @return true if success, false otherwise
+inline bool OSD_OpenStream (::std::filebuf& theFileBuf,
+ const TCollection_ExtendedString& theName,
const std::ios_base::openmode theMode)
{
-#if defined(_WIN32) && defined(_MSC_VER)
- // file name is treated as UTF-8 string and converted to UTF-16 one
- const TCollection_ExtendedString aFileNameW (theName, Standard_True);
- theStream.open (aFileNameW.ToWideString(), theMode);
+#if defined(_WIN32)
+ #if defined(__GLIBCXX__)
+ // if file buffer is already open, open() should fail according to C++ standard
+ if (theFileBuf.is_open())
+ return false;
+ // __gnu_cxx::stdio_filebuf is a std::filebuf providing extra constructor taking FILE* or file descriptor;
+ // It does not modify virtual methods or add any fields - so we can safely use swap (or move operator) here.
+ // MinGW does not provide open() methods taking wchar_t* or file descriptor - thus, creating __gnu_cxx::stdio_filebuf
+ // is the only way for opening such files since _wfopen()/_wsopen_s() from C world are available.
+ const int aFileDesc = OSD_OpenFileDescriptor (theName.ToWideString(), theMode);
+ __gnu_cxx::stdio_filebuf<char> aGccBuf (aFileDesc, theMode);
+ if (aGccBuf.is_open())
+ {
+ theFileBuf.swap (aGccBuf);
+ return true;
+ }
+ return false;
+ #else
+ return theFileBuf.open (theName.ToWideString(), theMode) != 0;
+ #endif
#else
- theStream.open (theName, theMode);
+ // conversion to UTF-8 for linux
+ NCollection_Utf8String aString (theName.ToExtString());
+ return theFileBuf.open (aString.ToCString(), theMode) != 0;
#endif
}
const TCollection_ExtendedString& theName,
const std::ios_base::openmode theMode)
{
-#if defined(_WIN32) && defined(_MSC_VER)
+#if defined(_WIN32)
+ #if defined(__GLIBCXX__)
+ // Use hackish code for opening wchar_t* file paths on MinGW,
+ // which considers implementation details of std::filebuf within std::fstream/std::ifstream/std::ofstream.
+ // Should be removed when MinGW will be improved to support wchar_t file paths natively within C++ streams.
+ if (! OSD_OpenStream (*theStream.rdbuf(), theName, theMode))
+ {
+ theStream.setstate (std::ios_base::failbit);
+ }
+ else
+ {
+ theStream.clear();
+ }
+ #else
theStream.open (theName.ToWideString(), theMode);
+ #endif
#else
// conversion in UTF-8 for linux
NCollection_Utf8String aString (theName.ToExtString());
#endif
}
+//! Function opens the file stream.
+//! @param theStream stream to open
+//! @param theName name of file encoded in UTF-8
+//! @param theMode opening mode
+template <typename T>
+inline void OSD_OpenStream (T& theStream,
+ const char* theName,
+ const std::ios_base::openmode theMode)
+{
+#if defined(_WIN32)
+ // redirect to method taking UTF-16 string
+ const TCollection_ExtendedString aFileNameW (theName, Standard_True);
+ OSD_OpenStream (theStream, aFileNameW, theMode);
+#else
+ theStream.open (theName, theMode);
+#endif
+}
+
extern "C" {
#endif // __cplusplus