diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bc3de4..a0f7132 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,18 +26,20 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") endif() if(WIN32) -list(APPEND CORE_EXTRA src/win32_largefilewrapper.c include/win32_largefilewrapper.h) -elseif(APPLE OR GEKKO) +list(APPEND CORE_EXTRA src/win32_largefilewrapper.c include/win32_largefilewrapper.h + 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) if(GEKKO) list(APPEND CORE_EXTRA src/gekko_support.c include/gekko_support.h) endif() endif() +endif() add_library(athena-core src/athena/Utility.cpp - src/athena/FileReader.cpp - src/athena/FileWriter.cpp src/athena/MemoryReader.cpp src/athena/MemoryWriter.cpp src/athena/Global.cpp diff --git a/include/athena/FileReader.hpp b/include/athena/FileReader.hpp index 70aa67b..932ce4d 100644 --- a/include/athena/FileReader.hpp +++ b/include/athena/FileReader.hpp @@ -1,9 +1,14 @@ #ifndef FILESTREAM_HPP #define FILESTREAM_HPP +#if _WIN32 +#include +#else +#include +#endif + #include #include -#include #include "athena/IStreamReader.hpp" namespace athena @@ -38,7 +43,7 @@ public: void open(); void close(); inline bool isOpen() const - {return m_fileHandle != NULL;} + {return m_fileHandle != 0;} bool save(); void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); atUint64 position() const; @@ -46,14 +51,21 @@ public: atUint64 readUBytesToBuf(void* buf, atUint64 len); 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: #if _WIN32 std::wstring m_filename; #else std::string m_filename; #endif - FILE* m_fileHandle; + HandleType m_fileHandle; std::unique_ptr m_cacheData; atInt32 m_blockSize; atInt32 m_curBlock; diff --git a/include/athena/FileWriter.hpp b/include/athena/FileWriter.hpp index f1222c7..41ac8d0 100644 --- a/include/athena/FileWriter.hpp +++ b/include/athena/FileWriter.hpp @@ -1,8 +1,12 @@ #ifndef FILEWRITER_HPP #define FILEWRITER_HPP -#include "athena/IStreamWriter.hpp" +#if _WIN32 +#include +#else #include +#endif +#include "athena/IStreamWriter.hpp" namespace athena { @@ -35,20 +39,26 @@ public: void open(bool overwrite = true); void close(); inline bool isOpen() const - {return m_fileHandle != NULL;} + {return m_fileHandle != 0;} void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); atUint64 position() const; atUint64 length() const; 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: #if _WIN32 std::wstring m_filename; #else std::string m_filename; #endif - FILE* m_fileHandle; + HandleType m_fileHandle; atUint8 m_currentByte; atUint64 m_bytePosition; bool m_globalErr; diff --git a/src/athena/FileReader.cpp b/src/athena/FileReader.cpp index c6459f4..9aeefed 100644 --- a/src/athena/FileReader.cpp +++ b/src/athena/FileReader.cpp @@ -1,8 +1,6 @@ #include "athena/FileReader.hpp" -#if _WIN32 -#include "win32_largefilewrapper.h" -#elif __APPLE__ +#if __APPLE__ #include "osx_largefilewrapper.h" #elif GEKKO #include "gekko_support.h" @@ -19,11 +17,7 @@ FileReader::FileReader(const std::string& filename, atInt32 cacheSize, bool glob m_offset(0), m_globalErr(globalErr) { -#if _WIN32 - m_filename = utility::utf8ToWide(filename); -#else m_filename = filename; -#endif open(); setCacheSize(cacheSize); } @@ -34,11 +28,7 @@ FileReader::FileReader(const std::wstring& filename, atInt32 cacheSize, bool glo m_offset(0), m_globalErr(globalErr) { -#if _WIN32 - m_filename = filename; -#else m_filename = utility::wideToUtf8(filename); -#endif open(); setCacheSize(cacheSize); } @@ -51,11 +41,7 @@ FileReader::~FileReader() void FileReader::open() { -#if _WIN32 - m_fileHandle = _wfopen(m_filename.c_str(), L"rb"); -#else m_fileHandle = fopen(m_filename.c_str(), "rb"); -#endif if (!m_fileHandle) { @@ -197,7 +183,7 @@ atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) if (cacheSize + cacheOffset > m_blockSize) cacheSize = m_blockSize - cacheOffset; - memcpy(dst, m_cacheData.get() + cacheOffset, cacheSize); + memmove(dst, m_cacheData.get() + cacheOffset, cacheSize); dst += cacheSize; rem -= cacheSize; cacheOffset = 0; diff --git a/src/athena/FileReaderWin32.cpp b/src/athena/FileReaderWin32.cpp new file mode 100644 index 0000000..252cca8 --- /dev/null +++ b/src/athena/FileReaderWin32.cpp @@ -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 diff --git a/src/athena/FileWriter.cpp b/src/athena/FileWriter.cpp index 484059f..77215c9 100644 --- a/src/athena/FileWriter.cpp +++ b/src/athena/FileWriter.cpp @@ -1,8 +1,6 @@ #include "athena/FileWriter.hpp" -#if _WIN32 -#include "win32_largefilewrapper.h" -#elif __APPLE__ +#if __APPLE__ #include "osx_largefilewrapper.h" #elif GEKKO #include "gekko_support.h" @@ -18,11 +16,7 @@ FileWriter::FileWriter(const std::string& filename, bool overwrite, bool globalE m_bytePosition(0), m_globalErr(globalErr) { -#if _WIN32 - m_filename = utility::utf8ToWide(filename); -#else m_filename = filename; -#endif open(overwrite); } @@ -31,11 +25,7 @@ FileWriter::FileWriter(const std::wstring& filename, bool overwrite, bool global m_bytePosition(0), m_globalErr(globalErr) { -#if _WIN32 - m_filename = filename; -#else m_filename = utility::wideToUtf8(filename); -#endif open(overwrite); } @@ -47,19 +37,6 @@ FileWriter::~FileWriter() 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) m_fileHandle = fopen(m_filename.c_str(), "w+b"); else @@ -71,7 +48,6 @@ void FileWriter::open(bool overwrite) m_fileHandle = fopen(m_filename.c_str(), "r+b"); } } -#endif if (!m_fileHandle) { @@ -97,7 +73,6 @@ void FileWriter::close() fclose(m_fileHandle); m_fileHandle = NULL; - return; } void FileWriter::seek(atInt64 pos, SeekOrigin origin) diff --git a/src/athena/FileWriterWin32.cpp b/src/athena/FileWriterWin32.cpp new file mode 100644 index 0000000..198d796 --- /dev/null +++ b/src/athena/FileWriterWin32.cpp @@ -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 diff --git a/src/athena/MemoryReader.cpp b/src/athena/MemoryReader.cpp index 0d60548..d642ab8 100644 --- a/src/athena/MemoryReader.cpp +++ b/src/athena/MemoryReader.cpp @@ -65,7 +65,7 @@ MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) m_dataCopy.reset(new atUint8[m_length]); 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) @@ -127,7 +127,7 @@ void MemoryCopyReader::setData(const atUint8* data, atUint64 length) { m_dataCopy.reset(new atUint8[length]); m_data = m_dataCopy.get(); - memcpy(m_dataCopy.get(), data, length); + memmove(m_dataCopy.get(), data, length); m_length = length; m_position = 0; } @@ -136,7 +136,7 @@ atUint8* MemoryReader::data() const { atUint8* ret = new atUint8[m_length]; memset(ret, 0, m_length); - memcpy(ret, m_data, m_length); + memmove(ret, m_data, m_length); return ret; } @@ -151,7 +151,7 @@ atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) return 0; } - memcpy(buf, reinterpret_cast(m_data) + m_position, length); + memmove(buf, reinterpret_cast(m_data) + m_position, length); m_position += length; return length; } diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index a3df929..7b7cd66 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -59,7 +59,7 @@ MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) m_dataCopy.reset(new atUint8[length]); m_data = m_dataCopy.get(); if (data) - memcpy(m_data, data, length); + memmove(m_data, data, length); } 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_data = m_dataCopy.get(); - memcpy(m_data, data, length); + memmove(m_data, data, length); m_length = length; m_position = 0; m_bufferOwned = false; @@ -212,7 +212,7 @@ atUint8* MemoryWriter::data() const { atUint8* ret = new atUint8[m_length]; memset(ret, 0, m_length); - memcpy(ret, m_data, m_length); + memmove(ret, m_data, m_length); return ret; } @@ -280,7 +280,7 @@ void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) return; } - memcpy(reinterpret_cast(m_data + m_position), data, length); + memmove(reinterpret_cast(m_data + m_position), data, length); m_position += length; } @@ -297,7 +297,7 @@ void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) if (m_position + length > m_length) resize(m_position + length); - memcpy(reinterpret_cast(m_data + m_position), data, length); + memmove(reinterpret_cast(m_data + m_position), data, length); m_position += length; } @@ -315,7 +315,7 @@ void MemoryCopyWriter::resize(atUint64 newSize) memset(newArray, 0, newSize); if (m_dataCopy) - memcpy(newArray, m_dataCopy.get(), m_length); + memmove(newArray, m_dataCopy.get(), m_length); m_dataCopy.reset(newArray); // Swap the pointer and size out for the new ones. diff --git a/src/sha1.cpp b/src/sha1.cpp index 6bb81ed..5ad04b1 100644 --- a/src/sha1.cpp +++ b/src/sha1.cpp @@ -395,7 +395,7 @@ atUint8* getSha1(atUint8* stuff, atUint32 stuff_size) if (!athena::utility::isSystemBigEndian()) val = athena::utility::swap32(val); - memcpy((char*)ret + (i * 4), &val, 4); + memmove((char*)ret + (i * 4), &val, 4); } return ret;