diff --git a/include/athena/FileWriter.hpp b/include/athena/FileWriter.hpp index 1683b40..636b872 100644 --- a/include/athena/FileWriter.hpp +++ b/include/athena/FileWriter.hpp @@ -66,6 +66,56 @@ private: atUint64 m_bytePosition; bool m_globalErr; }; + +class TransactionalFileWriter : public IStreamWriter +{ +#if _WIN32 + std::wstring m_filename; +#else + std::string m_filename; +#endif + bool m_overwrite, m_globalErr; + std::vector m_deferredBuffer; + atUint64 m_position = 0; +public: + TransactionalFileWriter(const std::string& filename, bool overwrite = true, bool globalErr=true) + : m_overwrite(overwrite), m_globalErr(globalErr) + { +#if _WIN32 + m_filename = utility::utf8ToWide(m_filename); +#else + m_filename = filename; +#endif + } + TransactionalFileWriter(const std::wstring& filename, bool overwrite = true, bool globalErr=true) + : m_overwrite(overwrite), m_globalErr(globalErr) + { +#if _WIN32 + m_filename = filename; +#else + m_filename = utility::wideToUtf8(filename); +#endif + } + + void flush() + { + if (m_deferredBuffer.size()) + { + FileWriter w(m_filename, m_overwrite, m_globalErr); + w.writeUBytes(m_deferredBuffer.data(), m_deferredBuffer.size()); + cancel(); + } + } + + void cancel() { m_deferredBuffer.clear(); m_position = 0; } + + inline atUint64 position() const { return m_position; } + inline atUint64 length() const { return m_deferredBuffer.size(); } + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + void writeUBytes(const atUint8* data, atUint64 len); + + ~TransactionalFileWriter() { flush(); } +}; } } // Athena diff --git a/src/athena/FileWriter.cpp b/src/athena/FileWriter.cpp index 2c0407f..4b1f153 100644 --- a/src/athena/FileWriter.cpp +++ b/src/athena/FileWriter.cpp @@ -16,7 +16,11 @@ FileWriter::FileWriter(const std::string& filename, bool overwrite, bool globalE m_bytePosition(0), m_globalErr(globalErr) { +#if _WIN32 + m_filename = utility::utf8ToWide(m_filename); +#else m_filename = filename; +#endif open(overwrite); } @@ -25,7 +29,11 @@ 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); } @@ -121,5 +129,33 @@ void FileWriter::writeUBytes(const atUint8* data, atUint64 len) } } +void TransactionalFileWriter::seek(atInt64 pos, SeekOrigin origin) +{ + switch (origin) + { + case SeekOrigin::Begin: + m_position = pos; + break; + case SeekOrigin::Current: + m_position += pos; + break; + case SeekOrigin::End: + break; + } +} + +void TransactionalFileWriter::writeUBytes(const atUint8* data, atUint64 len) +{ + atUint64 neededSz = m_position + len; + if (neededSz > m_deferredBuffer.size()) + { + m_deferredBuffer.reserve(neededSz * 2); + m_deferredBuffer.resize(neededSz); + } + + memmove(m_deferredBuffer.data() + m_position, data, len); + m_position += len; +} + } } // Athena