|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tfile.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
bool IsWindowsNT() {
|
|
Toshihiro Shimizu |
890ddd |
return (LONG)GetVersion()>=0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
using namespace TFileConsts;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TFile::TFile(const TFilePath &fname, uint32 flags)
|
|
Toshihiro Shimizu |
890ddd |
: m_hFile(NULL), m_ec(0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
open_internal(fname, /*NULL,*/ flags);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TFile::~TFile()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
close();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TFile::open(const TFilePath &fname, uint32 flags)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return open_internal(fname, flags);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TFile::open_internal(const TFilePath &fname, /*const wchar_t *pwszFilename,*/ uint32 flags)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
close();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// At least one of the read/write flags must be set.
|
|
Toshihiro Shimizu |
890ddd |
assert(flags & (kRead | kWrite));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DWORD dwDesiredAccess = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kRead)
|
|
Toshihiro Shimizu |
890ddd |
dwDesiredAccess = GENERIC_READ;
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kWrite)
|
|
Toshihiro Shimizu |
890ddd |
dwDesiredAccess |= GENERIC_WRITE;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Win32 docs are screwed here -- FILE_SHARE_xxx is the inverse of a deny flag.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kDenyRead)
|
|
Toshihiro Shimizu |
890ddd |
dwShareMode = FILE_SHARE_WRITE;
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kDenyWrite)
|
|
Toshihiro Shimizu |
890ddd |
dwShareMode &= ~FILE_SHARE_WRITE;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// One of the creation flags must be set.
|
|
Toshihiro Shimizu |
890ddd |
assert(flags & kCreationMask);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DWORD dwCreationDisposition;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
uint32 creationType = flags & kCreationMask;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
switch (creationType) {
|
|
Toshihiro Shimizu |
890ddd |
case kOpenExisting:
|
|
Toshihiro Shimizu |
890ddd |
dwCreationDisposition = OPEN_EXISTING;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case kOpenAlways:
|
|
Toshihiro Shimizu |
890ddd |
dwCreationDisposition = OPEN_ALWAYS;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case kCreateAlways:
|
|
Toshihiro Shimizu |
890ddd |
dwCreationDisposition = CREATE_ALWAYS;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case kCreateNew:
|
|
Toshihiro Shimizu |
890ddd |
dwCreationDisposition = CREATE_NEW;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case kTruncateExisting:
|
|
Toshihiro Shimizu |
890ddd |
dwCreationDisposition = TRUNCATE_EXISTING;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
default:
|
|
Toshihiro Shimizu |
890ddd |
assert(0);
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert((flags & (kSequential | kRandomAccess)) != (kSequential | kRandomAccess));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kSequential)
|
|
Toshihiro Shimizu |
890ddd |
dwAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kRandomAccess)
|
|
Toshihiro Shimizu |
890ddd |
dwAttributes |= FILE_FLAG_RANDOM_ACCESS;
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kWriteThrough)
|
|
Toshihiro Shimizu |
890ddd |
dwAttributes |= FILE_FLAG_WRITE_THROUGH;
|
|
Toshihiro Shimizu |
890ddd |
if (flags & kUnbuffered)
|
|
Toshihiro Shimizu |
890ddd |
dwAttributes |= FILE_FLAG_NO_BUFFERING;
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
if (pwszFilename && !IsWindowsNT())
|
|
Toshihiro Shimizu |
890ddd |
pszFilename = VDFastTextWToA(pwszFilename);
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
//if (pszFilename)
|
|
Toshihiro Shimizu |
890ddd |
m_hFile = CreateFileW(fname.getWideString().c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwAttributes, NULL);
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
m_hFile = CreateFileW(pwszFilename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwAttributes, NULL);
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
//VDFastTextFree();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// INVALID_HANDLE_VALUE isn't NULL. *sigh*
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_hFile == INVALID_HANDLE_VALUE) {
|
|
Toshihiro Shimizu |
890ddd |
m_hFile = NULL;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_ec = GetLastError();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_ec == ERROR_FILE_NOT_FOUND)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_ec == ERROR_PATH_NOT_FOUND && creationType == kOpenExisting)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
VDStringA fname(TFileSplitPathRight(pszFilename?VDString(pszFilename):VDTextWToA(VDStringW(pwszFilename))));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
throw MyWin32Error("Cannot open file \"%s\":\n%%s", err, fname.c_str());
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_FilePosition = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TFile::close()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_hFile) {
|
|
Toshihiro Shimizu |
890ddd |
HANDLE h = m_hFile;
|
|
Toshihiro Shimizu |
890ddd |
m_hFile = NULL;
|
|
Toshihiro Shimizu |
890ddd |
if (!CloseHandle(h)) {
|
|
Toshihiro Shimizu |
890ddd |
m_ec = GetLastError();
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TFile::truncate()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
DWORD rc = SetEndOfFile(m_hFile);
|
|
Toshihiro Shimizu |
890ddd |
if (rc)
|
|
Toshihiro Shimizu |
890ddd |
m_ec = GetLastError();
|
|
Toshihiro Shimizu |
890ddd |
return 0 != rc;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TINT32 TFile::read(void *buffer, TINT32 length)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
DWORD dwActual;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!ReadFile(m_hFile, buffer, (DWORD)length, &dwActual, NULL)) {
|
|
Toshihiro Shimizu |
890ddd |
m_ec = GetLastError();
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_FilePosition += dwActual;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return dwActual;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TINT32 TFile::write(const void *buffer, TINT32 length)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
DWORD dwActual;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!WriteFile(m_hFile, buffer, (DWORD)length, &dwActual, NULL) || dwActual != (DWORD)length) {
|
|
Toshihiro Shimizu |
890ddd |
m_ec = GetLastError();
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_FilePosition += dwActual;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return dwActual;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TFile::seek(TINT64 newPos, SeekMode mode)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
DWORD dwMode;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
switch (mode) {
|
|
Toshihiro Shimizu |
890ddd |
case seekStart:
|
|
Toshihiro Shimizu |
890ddd |
dwMode = FILE_BEGIN;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case seekCur:
|
|
Toshihiro Shimizu |
890ddd |
dwMode = FILE_CURRENT;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case seekEnd:
|
|
Toshihiro Shimizu |
890ddd |
dwMode = FILE_END;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
default:
|
|
Toshihiro Shimizu |
890ddd |
assert(0);
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
union {
|
|
Toshihiro Shimizu |
890ddd |
TINT64 pos;
|
|
Toshihiro Shimizu |
890ddd |
LONG l[2];
|
|
Toshihiro Shimizu |
890ddd |
} u = {newPos};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
u.l[0] = SetFilePointer(m_hFile, u.l[0], &u.l[1], dwMode);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (u.l[0] == -1 && GetLastError() != NO_ERROR) {
|
|
Toshihiro Shimizu |
890ddd |
m_ec = GetLastError();
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_FilePosition = u.pos;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TFile::skip(TINT64 delta)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!delta)
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
char buf[1024];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (delta <= sizeof buf)
|
|
Toshihiro Shimizu |
890ddd |
return (TINT32)delta == read(buf, (TINT32)delta);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
return seek(delta, seekCur);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TINT64 TFile::size()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
union {
|
|
Toshihiro Shimizu |
890ddd |
UINT64 siz;
|
|
Toshihiro Shimizu |
890ddd |
DWORD l[2];
|
|
Toshihiro Shimizu |
890ddd |
} u;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
u.l[0] = GetFileSize(m_hFile, &u.l[1]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DWORD err;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (u.l[0] == (DWORD)-1L && (err = GetLastError()) != NO_ERROR)
|
|
Toshihiro Shimizu |
890ddd |
//throw MyWin32Error("Error retrieving file size: %%s", err);
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_ec = GetLastError();
|
|
Toshihiro Shimizu |
890ddd |
return (TINT64)(-1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return (TINT64)u.siz;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TINT64 TFile::tell()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_FilePosition;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TFile::isOpen()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_hFile != 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
string TFile::getLastError()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
LPVOID lpMsgBuf;
|
|
Toshihiro Shimizu |
890ddd |
FormatMessage(
|
|
Toshihiro Shimizu |
890ddd |
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
Toshihiro Shimizu |
890ddd |
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
Toshihiro Shimizu |
890ddd |
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
Toshihiro Shimizu |
890ddd |
NULL,
|
|
Toshihiro Shimizu |
890ddd |
m_ec,
|
|
Toshihiro Shimizu |
890ddd |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
Toshihiro Shimizu |
890ddd |
(LPTSTR)&lpMsgBuf,
|
|
Toshihiro Shimizu |
890ddd |
0,
|
|
Toshihiro Shimizu |
890ddd |
NULL);
|
|
Toshihiro Shimizu |
890ddd |
string s = string(reinterpret_cast<char *="">(lpMsgBuf));</char>
|
|
Toshihiro Shimizu |
890ddd |
LocalFree(lpMsgBuf);
|
|
Toshihiro Shimizu |
890ddd |
return s;
|
|
Toshihiro Shimizu |
890ddd |
}
|