diff --git a/include/athena/IStreamWriter.hpp b/include/athena/IStreamWriter.hpp index afabd68..579b551 100644 --- a/include/athena/IStreamWriter.hpp +++ b/include/athena/IStreamWriter.hpp @@ -99,7 +99,7 @@ public: * @param data The buffer to write * @param length The amount to write */ - inline void writeBytes(const atInt8* data, atUint64 len) {writeUBytes((atUint8*)data, len);} + inline void writeBytes(const void* data, atUint64 len) {writeUBytes((atUint8*)data, len);} /** @brief Writes an Int16 to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. diff --git a/include/athena/MemoryWriter.hpp b/include/athena/MemoryWriter.hpp index ee757e2..2ad2c2a 100644 --- a/include/athena/MemoryWriter.hpp +++ b/include/athena/MemoryWriter.hpp @@ -23,12 +23,14 @@ class MemoryWriter : public IStreamWriter { public: + virtual ~MemoryWriter(); + /*! \brief This constructor references an existing buffer to write to in-place. * * \param data The existing buffer * \param length The length of the existing buffer */ - explicit MemoryWriter(atUint8* data, atUint64 length); + explicit MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership = false); /*! \brief Sets the buffers position relative to the specified position.
* It seeks relative to the current position by default. @@ -54,23 +56,18 @@ public: inline bool isOpen() const {return true;} - /*! \brief Sets the buffer to the given one, deleting the current one.
- * BEWARE: As this deletes the current buffer it WILL cause a loss of data - * if that was not the intent.
- * Once you pass the data to setData DO NOT delete the buffer - * as Stream now owns the address, this is done to keep memory usage down. + /*! \brief Sets the buffer to the given one, deleting the current one if it owns it.
* \param data The new buffer. * \param length The length of the new buffer. + * \param takeOwnership Whether the Stream now owns the buffer. * \throw IOException */ - void setData(atUint8* data, atUint64 length); + void setData(atUint8* data, atUint64 length, bool takeOwnership = false); /*! \brief Returns a copy of the current buffer.
* Changes to the copy do not affect the buffer so it's perfectly safe to * directly edit the buffer and use setData to set the new information.
- * However once you pass the data to setData DO NOT delete the buffer - * as Stream now owns the address, this is done to keep memory usage down. * \return Uint8* The copy of the buffer. */ atUint8* data() const; @@ -108,6 +105,7 @@ protected: atUint8* m_data; atUint64 m_length; atUint64 m_position; + bool m_bufferOwned; std::string m_filepath; //!< Path to the target file }; diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index 7b87502..d8fd6c0 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -14,10 +14,11 @@ namespace athena namespace io { -MemoryWriter::MemoryWriter(atUint8* data, atUint64 length) +MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership) : m_data((atUint8*)data), m_length(length), - m_position(0) + m_position(0), + m_bufferOwned(takeOwnership) { if (!data) { @@ -34,11 +35,20 @@ MemoryWriter::MemoryWriter(atUint8* data, atUint64 length) } } +MemoryWriter::~MemoryWriter() +{ + if (m_bufferOwned) + delete m_data; + m_data = nullptr; + m_length = 0; +} + MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) { m_data = data; m_length = length; m_position = 0; + m_bufferOwned = false; if (length == 0) { @@ -46,7 +56,6 @@ MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) setError(); return; } - m_dataCopy.reset(new atUint8[length]); m_data = m_dataCopy.get(); if (data) @@ -54,13 +63,13 @@ MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) } MemoryCopyWriter::MemoryCopyWriter(const std::string& filename) - : MemoryWriter(NULL, 0) { m_filepath = filename; m_length = 0x10; m_position = 0; m_dataCopy.reset(new atUint8[m_length]); m_data = m_dataCopy.get(); + m_bufferOwned = false; if (!m_data) { @@ -68,16 +77,14 @@ MemoryCopyWriter::MemoryCopyWriter(const std::string& filename) setError(); return; } - - memset(m_data, 0, m_length); } void MemoryWriter::seek(atInt64 position, SeekOrigin origin) { switch (origin) { - case SeekOrigin::Begin: - if (position < 0) + case SeekOrigin::Begin: + if (position < 0) { atError("Position outside stream bounds"); setError(); @@ -180,11 +187,15 @@ void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) } } -void MemoryWriter::setData(atUint8* data, atUint64 length) +void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership) { + if (m_bufferOwned) + delete m_data; + m_data = (atUint8*)data; m_length = length; m_position = 0; + m_bufferOwned = takeOwnership; } void MemoryCopyWriter::setData(const atUint8* data, atUint64 length) @@ -194,6 +205,7 @@ void MemoryCopyWriter::setData(const atUint8* data, atUint64 length) memcpy(m_data, data, length); m_length = length; m_position = 0; + m_bufferOwned = false; } atUint8* MemoryWriter::data() const