[fnd] Implement Windows 64bit size_t support in SimpleFile.

This commit is contained in:
jakcron 2018-05-25 22:54:30 +08:00
parent 57d03b6076
commit 93509fac5a
2 changed files with 239 additions and 6 deletions

View file

@ -1,7 +1,11 @@
#pragma once #pragma once
#include <fnd/IFile.h> #include <fnd/IFile.h>
#include <string> #include <string>
#ifdef _WIN32
#include <Windows.h>
#else
#include <cstdio> #include <cstdio>
#endif
namespace fnd namespace fnd
{ {
@ -34,9 +38,16 @@ namespace fnd
bool mOpen; bool mOpen;
OpenMode mMode; OpenMode mMode;
FILE* mFp;
const char* getOpenModeStr(OpenMode mMode); #ifdef _WIN32
HANDLE mFileHandle;
DWORD getOpenModeFlag(OpenMode mode) const;
DWORD getShareModeFlag(OpenMode mode) const;
DWORD getCreationModeFlag(OpenMode mode) const;
#else
FILE* mFp;
const char* getOpenModeStr(OpenMode mode);
#endif
}; };
} }

View file

@ -1,11 +1,16 @@
#include <fnd/SimpleFile.h> #include <fnd/SimpleFile.h>
#include <fnd/StringConv.h>
using namespace fnd; using namespace fnd;
SimpleFile::SimpleFile() : SimpleFile::SimpleFile() :
mOpen(false), mOpen(false),
mMode(Read), mMode(Read),
#ifdef _WIN32
mFileHandle()
#else
mFp(nullptr) mFp(nullptr)
#endif
{ {
} }
@ -16,6 +21,29 @@ SimpleFile::~SimpleFile()
void SimpleFile::open(const std::string& path, OpenMode mode) void SimpleFile::open(const std::string& path, OpenMode mode)
{ {
#ifdef _WIN32
// convert string to unicode
std::u16string unicodePath = fnd::StringConv::ConvertChar8ToChar16(path);
// save mode
mMode = mode;
// open file
mFileHandle = CreateFileW((LPCWSTR)unicodePath.c_str(),
getOpenModeFlag(mMode),
getShareModeFlag(mMode),
0,
getCreationModeFlag(mMode),
FILE_ATTRIBUTE_NORMAL,
NULL);
// check file handle
if (mFileHandle == INVALID_HANDLE_VALUE)
{
throw fnd::Exception(kModuleName, "Failed to open file.");
}
#else
//close(); //close();
mMode = mode; mMode = mode;
//printf("fopen(%s,%s);\n", path.c_str(), getOpenModeStr(mMode)); //printf("fopen(%s,%s);\n", path.c_str(), getOpenModeStr(mMode));
@ -23,46 +51,140 @@ void SimpleFile::open(const std::string& path, OpenMode mode)
if (mFp == nullptr) if (mFp == nullptr)
throw fnd::Exception(kModuleName, "Failed to open file."); throw fnd::Exception(kModuleName, "Failed to open file.");
mOpen = true; mOpen = true;
#endif
seek(0); seek(0);
} }
bool SimpleFile::isOpen() const bool SimpleFile::isOpen() const
{ {
return mOpen == true && mFp != nullptr; return mOpen == true;
} }
void SimpleFile::close() void SimpleFile::close()
{ {
if (isOpen()) if (isOpen())
{ {
#ifdef _WIN32
CloseHandle(mFileHandle);
#else
fclose(mFp); fclose(mFp);
mFp = nullptr;
#endif
} }
mFp = nullptr;
mOpen = false; mOpen = false;
} }
size_t SimpleFile::size() size_t SimpleFile::size()
{ {
size_t fsize = 0;
#ifdef _WIN32
if (mMode != Create)
{
LARGE_INTEGER win_fsize;
if (GetFileSizeEx(mFileHandle, &win_fsize) == false)
{
throw fnd::Exception(kModuleName, "Failed to check filesize");
}
fsize = win_fsize.QuadPart;
}
else
{
fsize = 0;
}
#else
size_t cur_pos = pos(); size_t cur_pos = pos();
fseek(mFp, 0, SEEK_END); fseek(mFp, 0, SEEK_END);
size_t fsize = pos(); fsize = pos();
seek(cur_pos); seek(cur_pos);
#endif
return fsize; return fsize;
} }
void SimpleFile::seek(size_t offset) void SimpleFile::seek(size_t offset)
{ {
#ifdef _WIN32
LARGE_INTEGER win_pos, out;
win_pos.QuadPart = offset;
if (SetFilePointerEx(
mFileHandle,
win_pos,
&out,
FILE_BEGIN
) == false || out.QuadPart != win_pos.QuadPart)
{
throw fnd::Exception(kModuleName, "Failed to change file offset");
}
#else
fseek(mFp, offset, SEEK_SET); fseek(mFp, offset, SEEK_SET);
#endif
} }
size_t SimpleFile::pos() size_t SimpleFile::pos()
{ {
#ifdef _WIN32
LARGE_INTEGER win_pos, out;
win_pos.QuadPart = 0;
if (SetFilePointerEx(
mFileHandle,
win_pos,
&out,
FILE_CURRENT
) == false)
{
throw fnd::Exception(kModuleName, "Failed to check file offset");
}
return out.QuadPart;
#else
return ftell(mFp); return ftell(mFp);
#endif
} }
void SimpleFile::read(byte_t* out, size_t len) void SimpleFile::read(byte_t* out, size_t len)
{ {
#ifdef _WIN32
LARGE_INTEGER win_len;
win_len.QuadPart = len;
static const DWORD kDwordHalf = (MAXDWORD / (DWORD)2) + 1; // 0x80000000
static const size_t kDwordFull = (size_t)kDwordHalf * (size_t)2; // 0x100000000
// if the size is greater than a DWORD, read it in parts,
for (LONG i = 0; i < win_len.HighPart; i++)
{
// since kDwordFull isn't a valid DWORD value, read in two parts
ReadFile(
mFileHandle,
out + i * kDwordFull,
kDwordHalf,
NULL,
NULL
);
ReadFile(
mFileHandle,
out + i * kDwordFull + kDwordHalf,
kDwordHalf,
NULL,
NULL
);
}
// read remainding low part
if (win_len.LowPart > 0)
{
ReadFile(
mFileHandle,
out + win_len.HighPart * kDwordFull,
win_len.LowPart,
NULL,
NULL
);
}
#else
fread(out, len, 1, mFp); fread(out, len, 1, mFp);
#endif
} }
void SimpleFile::read(byte_t* out, size_t offset, size_t len) void SimpleFile::read(byte_t* out, size_t offset, size_t len)
@ -73,7 +195,47 @@ void SimpleFile::read(byte_t* out, size_t offset, size_t len)
void SimpleFile::write(const byte_t* out, size_t len) void SimpleFile::write(const byte_t* out, size_t len)
{ {
#ifdef _WIN32
LARGE_INTEGER win_len;
win_len.QuadPart = len;
static const DWORD kDwordHalf = ((DWORD)MAXDWORD / (DWORD)2) + 1; // 0x80000000
static const size_t kDwordFull = (size_t)kDwordHalf * (size_t)2; // 0x100000000
// if the size is greater than a DWORD, read it in parts,
for (LONG i = 0; i < win_len.HighPart; i++)
{
// since kDwordFull isn't a valid DWORD value, read in two parts
WriteFile(
mFileHandle,
out + i * kDwordFull,
kDwordHalf,
NULL,
NULL
);
WriteFile(
mFileHandle,
out + i * kDwordFull + kDwordHalf,
kDwordHalf,
NULL,
NULL
);
}
// read remainding low part
if (win_len.LowPart > 0)
{
WriteFile(
mFileHandle,
out + win_len.HighPart * kDwordFull,
win_len.LowPart,
NULL,
NULL
);
}
#else
fwrite(out, len, 1, mFp); fwrite(out, len, 1, mFp);
#endif
} }
void SimpleFile::write(const byte_t* out, size_t offset, size_t len) void SimpleFile::write(const byte_t* out, size_t offset, size_t len)
@ -82,6 +244,65 @@ void SimpleFile::write(const byte_t* out, size_t offset, size_t len)
write(out, len); write(out, len);
} }
#ifdef _WIN32
DWORD SimpleFile::getOpenModeFlag(OpenMode mode) const
{
DWORD flag = 0;
switch (mode)
{
case (Read):
flag = GENERIC_READ;
break;
case (Edit):
flag = GENERIC_READ | GENERIC_WRITE;
break;
case (Create):
flag = GENERIC_WRITE;
break;
default:
throw fnd::Exception(kModuleName, "Unknown open mode");
}
return flag;
}
DWORD fnd::SimpleFile::getShareModeFlag(OpenMode mode) const
{
DWORD flag = 0;
switch (mode)
{
case (Read):
flag = FILE_SHARE_READ;
break;
case (Edit):
flag = FILE_SHARE_READ;
break;
case (Create):
flag = 0;
break;
default:
throw fnd::Exception(kModuleName, "Unknown open mode");
}
return flag;
}
DWORD fnd::SimpleFile::getCreationModeFlag(OpenMode mode) const
{
DWORD flag = 0;
switch (mode)
{
case (Read):
flag = OPEN_EXISTING;
break;
case (Edit):
flag = OPEN_EXISTING;
break;
case (Create):
flag = CREATE_ALWAYS;
break;
default:
throw fnd::Exception(kModuleName, "Unknown open mode");
}
return flag;
}
#else
const char* SimpleFile::getOpenModeStr(OpenMode mode) const char* SimpleFile::getOpenModeStr(OpenMode mode)
{ {
const char* str = ""; const char* str = "";
@ -100,4 +321,5 @@ const char* SimpleFile::getOpenModeStr(OpenMode mode)
throw fnd::Exception(kModuleName, "Unknown open mode"); throw fnd::Exception(kModuleName, "Unknown open mode");
} }
return str; return str;
} }
#endif