From 113749c82f4c65321ce0b20266a88c1eedc8224e Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Wed, 7 Nov 2012 16:38:34 -0500 Subject: [PATCH] Make the windows based filestream actually use the MSDN file IO functions --- IO/src/FileStreamWin32.cpp | 140 ++++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 50 deletions(-) diff --git a/IO/src/FileStreamWin32.cpp b/IO/src/FileStreamWin32.cpp index 05bb087..176b519 100755 --- a/IO/src/FileStreamWin32.cpp +++ b/IO/src/FileStreamWin32.cpp @@ -1,8 +1,7 @@ #include "FileStream.h" +#include #include -#include -#include #include class FileStreamImpl { @@ -13,46 +12,39 @@ private: // the object gets destroyed. uint32 m_ReferenceCount; - FILE *m_FilePtr; + HANDLE m_Handle; public: FileStreamImpl(const CHAR *filename, EFileMode mode) : m_ReferenceCount(1) { - const char *modeStr = "r"; + DWORD dwDesiredAccess = GENERIC_READ; + DWORD dwShareMode = 0; switch(mode) { default: + case eFileMode_ReadBinary: case eFileMode_Read: // Do nothing. break; - case eFileMode_ReadBinary: - modeStr = "rb"; - break; - case eFileMode_Write: - modeStr = "w"; - break; - case eFileMode_WriteBinary: - modeStr = "wb"; + dwDesiredAccess = GENERIC_WRITE; break; case eFileMode_WriteAppend: - modeStr = "a"; - break; - case eFileMode_WriteBinaryAppend: - modeStr = "ab"; + dwDesiredAccess = FILE_APPEND_DATA; break; } - m_FilePtr = fopen(filename, modeStr); + m_Handle = CreateFile(filename, dwDesiredAccess, dwShareMode, NULL, 0, FILE_ATTRIBUTE_NORMAL, NULL); + assert(m_Handle != INVALID_HANDLE_VALUE); } ~FileStreamImpl() { - fclose(m_FilePtr); + CloseHandle(m_Handle); } void IncreaseReferenceCount() { m_ReferenceCount++; } @@ -60,15 +52,15 @@ public: uint32 GetReferenceCount() { return m_ReferenceCount; } - FILE *GetFilePtr() const { return m_FilePtr; } + HANDLE GetFileHandle() const { return m_Handle; } }; FileStream::FileStream(const CHAR *filename, EFileMode mode) : m_Impl(new FileStreamImpl(filename, mode)) , m_Mode(mode) { - strncpy(m_Filename, filename, kMaxFilenameSz); - m_Filename[kMaxFilenameSz - 1] = '\0'; + strncpy_s(m_Filename, filename, kMaxFilenameSz); + m_Filename[kMaxFilenameSz - 1] = CHAR('\0'); } FileStream::FileStream(const FileStream &other) @@ -76,7 +68,7 @@ FileStream::FileStream(const FileStream &other) , m_Mode(other.m_Mode) { m_Impl->IncreaseReferenceCount(); - strncpy(m_Filename, other.m_Filename, kMaxFilenameSz); + strncpy_s(m_Filename, other.m_Filename, kMaxFilenameSz); } FileStream &FileStream::operator=(const FileStream &other) { @@ -95,7 +87,7 @@ FileStream &FileStream::operator=(const FileStream &other) { m_Impl->IncreaseReferenceCount(); m_Mode = other.m_Mode; - strncpy(m_Filename, other.m_Filename, kMaxFilenameSz); + strncpy_s(m_Filename, other.m_Filename, kMaxFilenameSz); return *this; } @@ -120,21 +112,42 @@ int32 FileStream::Read(uint8 *buf, uint32 bufSz) { m_Mode == eFileMode_WriteAppend || m_Mode == eFileMode_WriteBinaryAppend ) { - fprintf(stderr, "Cannot read from file '%s': File opened for reading.", m_Filename); + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Cannot read from file '%s': File opened for reading.", m_Filename); + OutputDebugString(errStr); return -2; } - FILE *fp = m_Impl->GetFilePtr(); - if(NULL == fp) + HANDLE fp = m_Impl->GetFileHandle(); + if(INVALID_HANDLE_VALUE == fp) return -1; - uint32 amtRead = fread(buf, 1, bufSz, fp); - if(amtRead != bufSz && !feof(fp)) { - fprintf(stderr, "Error reading from file '%s'.", m_Filename); + DWORD oldPosition = SetFilePointer(fp, 0, NULL, FILE_CURRENT); + if(INVALID_SET_FILE_POINTER == oldPosition) { + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Error querying the file position before reading from file '%s'(0x%x).", m_Filename, GetLastError()); + OutputDebugString(errStr); + return -1; + } + + DWORD amtRead; + BOOL success = ReadFile(fp, buf, bufSz, &amtRead, NULL); + if(!success) { + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Error reading from file '%s'.", m_Filename); + OutputDebugString(errStr); return -1; } - return amtRead; + DWORD newPosition = SetFilePointer(fp, 0, NULL, FILE_CURRENT); + if(INVALID_SET_FILE_POINTER == newPosition) { + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Error querying the file position after reading from file '%s'(0x%x).", m_Filename, GetLastError()); + OutputDebugString(errStr); + return -1; + } + + return newPosition - oldPosition; } int32 FileStream::Write(const uint8 *buf, uint32 bufSz) { @@ -142,17 +155,42 @@ int32 FileStream::Write(const uint8 *buf, uint32 bufSz) { m_Mode == eFileMode_Read || m_Mode == eFileMode_ReadBinary ) { - fprintf(stderr, "Cannot write to file '%s': File opened for writing.", m_Filename); + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Cannot write to file '%s': File opened for writing.", m_Filename); + OutputDebugString(errStr); return -2; } - FILE *fp = m_Impl->GetFilePtr(); + HANDLE fp = m_Impl->GetFileHandle(); if(NULL == fp) return -1; - uint32 amtWritten = fwrite(buf, 1, bufSz, fp); - if(amtWritten != bufSz) { - fprintf(stderr, "Error writing to file '%s'.", m_Filename); + DWORD dwPos; + if(m_Mode == eFileMode_WriteBinaryAppend || m_Mode == eFileMode_WriteAppend) { + dwPos = SetFilePointer(fp, 0, NULL, FILE_END); + } + else { + dwPos = SetFilePointer(fp, 0, NULL, FILE_CURRENT); + } + + if(INVALID_SET_FILE_POINTER == dwPos) { + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Error querying the file position before reading to file '%s'(0x%x).", m_Filename, GetLastError()); + OutputDebugString(errStr); + return -1; + } + + while(!LockFile(fp, dwPos, 0, bufSz, 0)) Sleep(1); + + DWORD amtWritten; + BOOL success = WriteFile(fp, buf, bufSz, &amtWritten, NULL); + + UnlockFile(fp, dwPos, 0, bufSz, 0); + + if(!success) { + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Error writing to file '%s'.", m_Filename); + OutputDebugString(errStr); return -1; } @@ -160,18 +198,20 @@ int32 FileStream::Write(const uint8 *buf, uint32 bufSz) { } int64 FileStream::Tell() { - FILE *fp = m_Impl->GetFilePtr(); + HANDLE fp = m_Impl->GetFileHandle(); if(NULL == fp) { return -1; } - long int ret = ftell(fp); - if(-1L == ret) { - perror("Error opening file"); - return -1; + DWORD pos = SetFilePointer(fp, 0, NULL, FILE_CURRENT); + if(INVALID_SET_FILE_POINTER == pos) { + CHAR errStr[256]; + _sntprintf_s(errStr, 256, "Error querying the file position before reading to file '%s'(0x%x).", m_Filename, GetLastError()); + OutputDebugString(errStr); + return -1; } - return ret; + return pos; } bool FileStream::Seek(uint32 offset, ESeekPosition pos) { @@ -180,10 +220,10 @@ bool FileStream::Seek(uint32 offset, ESeekPosition pos) { if(m_Mode == eFileMode_WriteAppend || m_Mode == eFileMode_WriteBinaryAppend) return false; - FILE *fp = m_Impl->GetFilePtr(); + HANDLE fp = m_Impl->GetFileHandle(); if(NULL == fp) return false; - int origin = SEEK_SET; + DWORD origin = FILE_BEGIN; switch(pos) { default: case eSeekPosition_Beginning: @@ -191,23 +231,23 @@ bool FileStream::Seek(uint32 offset, ESeekPosition pos) { break; case eSeekPosition_Current: - origin = SEEK_CUR; + origin = FILE_CURRENT; break; case eSeekPosition_End: - origin = SEEK_END; + origin = FILE_END; break; } - if(fseek(fp, offset, origin)) + if(SetFilePointer(fp, offset, NULL, origin) == INVALID_SET_FILE_POINTER) return false; return true; } void FileStream::Flush() { - FILE *fp = m_Impl->GetFilePtr(); - if(NULL != fp) { - fflush(fp); - } + HANDLE fp = m_Impl->GetFileHandle(); + if(NULL == fp) return; + + FlushFileBuffers(fp); }