Win32 FileReader/Writer; minor refinements

This commit is contained in:
Jack Andersen 2016-09-18 13:45:19 -10:00
parent 8d2fbad265
commit d4d1bdabc6
10 changed files with 403 additions and 65 deletions

View File

@ -26,18 +26,20 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
endif() endif()
if(WIN32) if(WIN32)
list(APPEND CORE_EXTRA src/win32_largefilewrapper.c include/win32_largefilewrapper.h) list(APPEND CORE_EXTRA src/win32_largefilewrapper.c include/win32_largefilewrapper.h
elseif(APPLE OR GEKKO) src/athena/FileWriterWin32.cpp src/athena/FileReaderWin32.cpp)
else()
list(APPEND CORE_EXTRA src/athena/FileWriter.cpp src/athena/FileReader.cpp)
if(APPLE OR GEKKO)
list(APPEND CORE_EXTRA src/osx_largefilewrapper.c include/osx_largefilewrapper.h) list(APPEND CORE_EXTRA src/osx_largefilewrapper.c include/osx_largefilewrapper.h)
if(GEKKO) if(GEKKO)
list(APPEND CORE_EXTRA src/gekko_support.c include/gekko_support.h) list(APPEND CORE_EXTRA src/gekko_support.c include/gekko_support.h)
endif() endif()
endif() endif()
endif()
add_library(athena-core add_library(athena-core
src/athena/Utility.cpp src/athena/Utility.cpp
src/athena/FileReader.cpp
src/athena/FileWriter.cpp
src/athena/MemoryReader.cpp src/athena/MemoryReader.cpp
src/athena/MemoryWriter.cpp src/athena/MemoryWriter.cpp
src/athena/Global.cpp src/athena/Global.cpp

View File

@ -1,9 +1,14 @@
#ifndef FILESTREAM_HPP #ifndef FILESTREAM_HPP
#define FILESTREAM_HPP #define FILESTREAM_HPP
#if _WIN32
#include <windows.h>
#else
#include <stdio.h>
#endif
#include <string> #include <string>
#include <memory> #include <memory>
#include <stdio.h>
#include "athena/IStreamReader.hpp" #include "athena/IStreamReader.hpp"
namespace athena namespace athena
@ -38,7 +43,7 @@ public:
void open(); void open();
void close(); void close();
inline bool isOpen() const inline bool isOpen() const
{return m_fileHandle != NULL;} {return m_fileHandle != 0;}
bool save(); bool save();
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
atUint64 position() const; atUint64 position() const;
@ -46,14 +51,21 @@ public:
atUint64 readUBytesToBuf(void* buf, atUint64 len); atUint64 readUBytesToBuf(void* buf, atUint64 len);
void setCacheSize(const atInt32 blockSize); void setCacheSize(const atInt32 blockSize);
FILE* _fileHandle() {return m_fileHandle;}
#if _WIN32
using HandleType = HANDLE;
#else
using HandleType = FILE*;
#endif
HandleType _fileHandle() {return m_fileHandle;}
protected: protected:
#if _WIN32 #if _WIN32
std::wstring m_filename; std::wstring m_filename;
#else #else
std::string m_filename; std::string m_filename;
#endif #endif
FILE* m_fileHandle; HandleType m_fileHandle;
std::unique_ptr<atUint8[]> m_cacheData; std::unique_ptr<atUint8[]> m_cacheData;
atInt32 m_blockSize; atInt32 m_blockSize;
atInt32 m_curBlock; atInt32 m_curBlock;

View File

@ -1,8 +1,12 @@
#ifndef FILEWRITER_HPP #ifndef FILEWRITER_HPP
#define FILEWRITER_HPP #define FILEWRITER_HPP
#include "athena/IStreamWriter.hpp" #if _WIN32
#include <windows.h>
#else
#include <stdio.h> #include <stdio.h>
#endif
#include "athena/IStreamWriter.hpp"
namespace athena namespace athena
{ {
@ -35,20 +39,26 @@ public:
void open(bool overwrite = true); void open(bool overwrite = true);
void close(); void close();
inline bool isOpen() const inline bool isOpen() const
{return m_fileHandle != NULL;} {return m_fileHandle != 0;}
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
atUint64 position() const; atUint64 position() const;
atUint64 length() const; atUint64 length() const;
void writeUBytes(const atUint8* data, atUint64 len); void writeUBytes(const atUint8* data, atUint64 len);
FILE* _fileHandle() {return m_fileHandle;} #if _WIN32
using HandleType = HANDLE;
#else
using HandleType = FILE*;
#endif
HandleType _fileHandle() {return m_fileHandle;}
private: private:
#if _WIN32 #if _WIN32
std::wstring m_filename; std::wstring m_filename;
#else #else
std::string m_filename; std::string m_filename;
#endif #endif
FILE* m_fileHandle; HandleType m_fileHandle;
atUint8 m_currentByte; atUint8 m_currentByte;
atUint64 m_bytePosition; atUint64 m_bytePosition;
bool m_globalErr; bool m_globalErr;

View File

@ -1,8 +1,6 @@
#include "athena/FileReader.hpp" #include "athena/FileReader.hpp"
#if _WIN32 #if __APPLE__
#include "win32_largefilewrapper.h"
#elif __APPLE__
#include "osx_largefilewrapper.h" #include "osx_largefilewrapper.h"
#elif GEKKO #elif GEKKO
#include "gekko_support.h" #include "gekko_support.h"
@ -19,11 +17,7 @@ FileReader::FileReader(const std::string& filename, atInt32 cacheSize, bool glob
m_offset(0), m_offset(0),
m_globalErr(globalErr) m_globalErr(globalErr)
{ {
#if _WIN32
m_filename = utility::utf8ToWide(filename);
#else
m_filename = filename; m_filename = filename;
#endif
open(); open();
setCacheSize(cacheSize); setCacheSize(cacheSize);
} }
@ -34,11 +28,7 @@ FileReader::FileReader(const std::wstring& filename, atInt32 cacheSize, bool glo
m_offset(0), m_offset(0),
m_globalErr(globalErr) m_globalErr(globalErr)
{ {
#if _WIN32
m_filename = filename;
#else
m_filename = utility::wideToUtf8(filename); m_filename = utility::wideToUtf8(filename);
#endif
open(); open();
setCacheSize(cacheSize); setCacheSize(cacheSize);
} }
@ -51,11 +41,7 @@ FileReader::~FileReader()
void FileReader::open() void FileReader::open()
{ {
#if _WIN32
m_fileHandle = _wfopen(m_filename.c_str(), L"rb");
#else
m_fileHandle = fopen(m_filename.c_str(), "rb"); m_fileHandle = fopen(m_filename.c_str(), "rb");
#endif
if (!m_fileHandle) if (!m_fileHandle)
{ {
@ -197,7 +183,7 @@ atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len)
if (cacheSize + cacheOffset > m_blockSize) if (cacheSize + cacheOffset > m_blockSize)
cacheSize = m_blockSize - cacheOffset; cacheSize = m_blockSize - cacheOffset;
memcpy(dst, m_cacheData.get() + cacheOffset, cacheSize); memmove(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize; dst += cacheSize;
rem -= cacheSize; rem -= cacheSize;
cacheOffset = 0; cacheOffset = 0;

View File

@ -0,0 +1,227 @@
#include "athena/FileReader.hpp"
#include "win32_largefilewrapper.h"
namespace athena
{
namespace io
{
FileReader::FileReader(const std::string& filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr),
m_cacheData(nullptr),
m_offset(0),
m_globalErr(globalErr)
{
m_filename = utility::utf8ToWide(filename);
open();
setCacheSize(cacheSize);
}
FileReader::FileReader(const std::wstring& filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr),
m_cacheData(nullptr),
m_offset(0),
m_globalErr(globalErr)
{
m_filename = filename;
open();
setCacheSize(cacheSize);
}
FileReader::~FileReader()
{
if (isOpen())
close();
}
void FileReader::open()
{
m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (m_fileHandle == INVALID_HANDLE_VALUE)
{
m_fileHandle = 0;
std::string _filename = filename();
if (m_globalErr)
atError("File not found '%s'", _filename.c_str());
setError();
return;
}
// reset error
m_hasError = false;
}
void FileReader::close()
{
if (!m_fileHandle)
{
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
CloseHandle(m_fileHandle);
m_fileHandle = 0;
return;
}
void FileReader::seek(atInt64 pos, SeekOrigin origin)
{
if (!isOpen())
return;
// check block position
if (m_blockSize > 0)
{
atUint64 oldOff = m_offset;
switch(origin)
{
case SeekOrigin::Begin:
m_offset = pos;
break;
case SeekOrigin::Current:
m_offset += pos;
break;
case SeekOrigin::End:
m_offset = length() - pos;
break;
}
if (m_offset > length())
{
oldOff = m_offset;
if (m_globalErr)
atError("Unable to seek in file");
setError();
return;
}
size_t block = m_offset / m_blockSize;
if (block != m_curBlock)
{
LARGE_INTEGER li;
li.QuadPart = block * m_blockSize;
SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN);
ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr);
m_curBlock = (atInt32)block;
}
}
else
{
LARGE_INTEGER li;
li.QuadPart = pos;
if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin)))
{
if (m_globalErr)
atError("Unable to seek in file");
setError();
}
}
}
atUint64 FileReader::position() const
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open");
return 0;
}
if (m_blockSize > 0)
return m_offset;
else
{
LARGE_INTEGER li = {};
LARGE_INTEGER res;
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
return res.QuadPart;
}
}
atUint64 FileReader::length() const
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open");
return 0;
}
LARGE_INTEGER res;
GetFileSizeEx(m_fileHandle, &res);
return res.QuadPart;
}
atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len)
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open for reading");
setError();
return 0;
}
if (m_blockSize <= 0)
{
DWORD ret = 0;
ReadFile(m_fileHandle, buf, len, &ret, nullptr);
return ret;
}
else
{
LARGE_INTEGER fs;
GetFileSizeEx(m_fileHandle, &fs);
if (m_offset >= fs.QuadPart)
return 0;
if (m_offset + len >= fs.QuadPart)
len = fs.QuadPart - m_offset;
size_t block = m_offset / m_blockSize;
atUint64 cacheOffset = m_offset % m_blockSize;
atUint64 cacheSize;
atUint64 rem = len;
atUint8* dst = (atUint8*)buf;
while (rem)
{
if (block != m_curBlock)
{
LARGE_INTEGER li;
li.QuadPart = block * m_blockSize;
SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN);
ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr);
m_curBlock = (atInt32)block;
}
cacheSize = rem;
if (cacheSize + cacheOffset > m_blockSize)
cacheSize = m_blockSize - cacheOffset;
memmove(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize;
rem -= cacheSize;
cacheOffset = 0;
++block;
}
m_offset += len;
return dst - (atUint8*)buf;
}
}
void FileReader::setCacheSize(const atInt32 blockSize)
{
m_blockSize = blockSize;
if (m_blockSize > length())
m_blockSize = (atInt32)length();
m_curBlock = -1;
if (m_blockSize > 0)
m_cacheData.reset(new atUint8[m_blockSize]);
}
} // io
} // Athena

View File

@ -1,8 +1,6 @@
#include "athena/FileWriter.hpp" #include "athena/FileWriter.hpp"
#if _WIN32 #if __APPLE__
#include "win32_largefilewrapper.h"
#elif __APPLE__
#include "osx_largefilewrapper.h" #include "osx_largefilewrapper.h"
#elif GEKKO #elif GEKKO
#include "gekko_support.h" #include "gekko_support.h"
@ -18,11 +16,7 @@ FileWriter::FileWriter(const std::string& filename, bool overwrite, bool globalE
m_bytePosition(0), m_bytePosition(0),
m_globalErr(globalErr) m_globalErr(globalErr)
{ {
#if _WIN32
m_filename = utility::utf8ToWide(filename);
#else
m_filename = filename; m_filename = filename;
#endif
open(overwrite); open(overwrite);
} }
@ -31,11 +25,7 @@ FileWriter::FileWriter(const std::wstring& filename, bool overwrite, bool global
m_bytePosition(0), m_bytePosition(0),
m_globalErr(globalErr) m_globalErr(globalErr)
{ {
#if _WIN32
m_filename = filename;
#else
m_filename = utility::wideToUtf8(filename); m_filename = utility::wideToUtf8(filename);
#endif
open(overwrite); open(overwrite);
} }
@ -47,19 +37,6 @@ FileWriter::~FileWriter()
void FileWriter::open(bool overwrite) void FileWriter::open(bool overwrite)
{ {
#if _WIN32
if (overwrite)
m_fileHandle = _wfopen(m_filename.c_str(), L"w+b");
else
{
m_fileHandle = _wfopen(m_filename.c_str(), L"r+b");
if (m_fileHandle)
{
fclose(m_fileHandle);
m_fileHandle = _wfopen(m_filename.c_str(), L"r+b");
}
}
#else
if (overwrite) if (overwrite)
m_fileHandle = fopen(m_filename.c_str(), "w+b"); m_fileHandle = fopen(m_filename.c_str(), "w+b");
else else
@ -71,7 +48,6 @@ void FileWriter::open(bool overwrite)
m_fileHandle = fopen(m_filename.c_str(), "r+b"); m_fileHandle = fopen(m_filename.c_str(), "r+b");
} }
} }
#endif
if (!m_fileHandle) if (!m_fileHandle)
{ {
@ -97,7 +73,6 @@ void FileWriter::close()
fclose(m_fileHandle); fclose(m_fileHandle);
m_fileHandle = NULL; m_fileHandle = NULL;
return;
} }
void FileWriter::seek(atInt64 pos, SeekOrigin origin) void FileWriter::seek(atInt64 pos, SeekOrigin origin)

View File

@ -0,0 +1,126 @@
#include "athena/FileWriter.hpp"
#include "win32_largefilewrapper.h"
namespace athena
{
namespace io
{
FileWriter::FileWriter(const std::string& filename, bool overwrite, bool globalErr)
: m_fileHandle(0),
m_bytePosition(0),
m_globalErr(globalErr)
{
m_filename = utility::utf8ToWide(filename);
open(overwrite);
}
FileWriter::FileWriter(const std::wstring& filename, bool overwrite, bool globalErr)
: m_fileHandle(0),
m_bytePosition(0),
m_globalErr(globalErr)
{
m_filename = filename;
open(overwrite);
}
FileWriter::~FileWriter()
{
if (isOpen())
close();
}
void FileWriter::open(bool overwrite)
{
if (overwrite)
{
m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
}
else
{
m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
}
if (m_fileHandle == INVALID_HANDLE_VALUE)
{
m_fileHandle = 0;
if (m_globalErr)
atError("Unable to open file '%s'", filename().c_str());
setError();
return;
}
// reset error
m_hasError = false;
}
void FileWriter::close()
{
if (!m_fileHandle)
{
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
CloseHandle(m_fileHandle);
m_fileHandle = 0;
}
void FileWriter::seek(atInt64 pos, SeekOrigin origin)
{
if (!isOpen())
{
if (m_globalErr)
atError("Unable to seek in file, not open");
setError();
return;
}
LARGE_INTEGER li;
li.QuadPart = pos;
if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin)))
{
if (m_globalErr)
atError("Unable to seek in file");
setError();
}
}
atUint64 FileWriter::position() const
{
LARGE_INTEGER li = {};
LARGE_INTEGER res;
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
return res.QuadPart;
}
atUint64 FileWriter::length() const
{
return utility::fileSize(m_filename);
}
void FileWriter::writeUBytes(const atUint8* data, atUint64 len)
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open for writing");
setError();
return;
}
DWORD ret = 0;
WriteFile(m_fileHandle, data, len, &ret, nullptr);
if (ret != len)
{
if (m_globalErr)
atError("Unable to write to stream");
setError();
}
}
}
} // Athena

View File

@ -65,7 +65,7 @@ MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length)
m_dataCopy.reset(new atUint8[m_length]); m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get(); m_data = m_dataCopy.get();
memcpy(m_dataCopy.get(), data, m_length); memmove(m_dataCopy.get(), data, m_length);
} }
void MemoryReader::seek(atInt64 position, SeekOrigin origin) void MemoryReader::seek(atInt64 position, SeekOrigin origin)
@ -127,7 +127,7 @@ void MemoryCopyReader::setData(const atUint8* data, atUint64 length)
{ {
m_dataCopy.reset(new atUint8[length]); m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get(); m_data = m_dataCopy.get();
memcpy(m_dataCopy.get(), data, length); memmove(m_dataCopy.get(), data, length);
m_length = length; m_length = length;
m_position = 0; m_position = 0;
} }
@ -136,7 +136,7 @@ atUint8* MemoryReader::data() const
{ {
atUint8* ret = new atUint8[m_length]; atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length); memset(ret, 0, m_length);
memcpy(ret, m_data, m_length); memmove(ret, m_data, m_length);
return ret; return ret;
} }
@ -151,7 +151,7 @@ atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
return 0; return 0;
} }
memcpy(buf, reinterpret_cast<const atUint8*>(m_data) + m_position, length); memmove(buf, reinterpret_cast<const atUint8*>(m_data) + m_position, length);
m_position += length; m_position += length;
return length; return length;
} }

View File

@ -59,7 +59,7 @@ MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length)
m_dataCopy.reset(new atUint8[length]); m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get(); m_data = m_dataCopy.get();
if (data) if (data)
memcpy(m_data, data, length); memmove(m_data, data, length);
} }
MemoryCopyWriter::MemoryCopyWriter(const std::string& filename) MemoryCopyWriter::MemoryCopyWriter(const std::string& filename)
@ -202,7 +202,7 @@ void MemoryCopyWriter::setData(const atUint8* data, atUint64 length)
{ {
m_dataCopy.reset(new atUint8[length]); m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get(); m_data = m_dataCopy.get();
memcpy(m_data, data, length); memmove(m_data, data, length);
m_length = length; m_length = length;
m_position = 0; m_position = 0;
m_bufferOwned = false; m_bufferOwned = false;
@ -212,7 +212,7 @@ atUint8* MemoryWriter::data() const
{ {
atUint8* ret = new atUint8[m_length]; atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length); memset(ret, 0, m_length);
memcpy(ret, m_data, m_length); memmove(ret, m_data, m_length);
return ret; return ret;
} }
@ -280,7 +280,7 @@ void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length)
return; return;
} }
memcpy(reinterpret_cast<atInt8*>(m_data + m_position), data, length); memmove(reinterpret_cast<atInt8*>(m_data + m_position), data, length);
m_position += length; m_position += length;
} }
@ -297,7 +297,7 @@ void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length)
if (m_position + length > m_length) if (m_position + length > m_length)
resize(m_position + length); resize(m_position + length);
memcpy(reinterpret_cast<atInt8*>(m_data + m_position), data, length); memmove(reinterpret_cast<atInt8*>(m_data + m_position), data, length);
m_position += length; m_position += length;
} }
@ -315,7 +315,7 @@ void MemoryCopyWriter::resize(atUint64 newSize)
memset(newArray, 0, newSize); memset(newArray, 0, newSize);
if (m_dataCopy) if (m_dataCopy)
memcpy(newArray, m_dataCopy.get(), m_length); memmove(newArray, m_dataCopy.get(), m_length);
m_dataCopy.reset(newArray); m_dataCopy.reset(newArray);
// Swap the pointer and size out for the new ones. // Swap the pointer and size out for the new ones.

View File

@ -395,7 +395,7 @@ atUint8* getSha1(atUint8* stuff, atUint32 stuff_size)
if (!athena::utility::isSystemBigEndian()) if (!athena::utility::isSystemBigEndian())
val = athena::utility::swap32(val); val = athena::utility::swap32(val);
memcpy((char*)ret + (i * 4), &val, 4); memmove((char*)ret + (i * 4), &val, 4);
} }
return ret; return ret;