From 44e25e09ca07a8d094dc65c21eddb5900095d47c Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 7 Jul 2015 20:34:59 -1000 Subject: [PATCH] updated MemoryCopyWriter --- include/Athena/MemoryWriter.hpp | 33 ++++++++++++++-- src/Athena/MemoryWriter.cpp | 67 +++++++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 15 deletions(-) diff --git a/include/Athena/MemoryWriter.hpp b/include/Athena/MemoryWriter.hpp index 59a1550..62d6f96 100644 --- a/include/Athena/MemoryWriter.hpp +++ b/include/Athena/MemoryWriter.hpp @@ -27,7 +27,7 @@ public: * \param data The existing buffer * \param length The length of the existing buffer */ - explicit MemoryWriter(atUint8* data = nullptr, atUint64 length = 0x10); + explicit MemoryWriter(atUint8* data, atUint64 length); /*! \brief Sets the buffers position relative to the specified position.
* It seeks relative to the current position by default. @@ -103,12 +103,11 @@ public: void writeUBytes(const atUint8* data, atUint64 len); protected: + MemoryWriter() {} atUint8* m_data; atUint64 m_length; atUint64 m_position; std::string m_filepath; //!< Path to the target file -private: - void resize(atUint64 newSize); }; class MemoryCopyWriter : public MemoryWriter @@ -120,7 +119,7 @@ public: * \param data The existing buffer * \param length The length of the existing buffer */ - explicit MemoryCopyWriter(atUint8* data, atUint64 length); + explicit MemoryCopyWriter(atUint8* data=nullptr, atUint64 length=0x10); /*! \brief This constructor creates an instance from a file on disk. * @@ -128,10 +127,36 @@ public: */ MemoryCopyWriter(const std::string& filename); + /*! \brief Sets the buffers position relative to the specified position.
+ * It seeks relative to the current position by default. + * \param position where in the buffer to seek + * \param origin The Origin to seek \sa SeekOrigin + */ + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + + /*! \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. + * \param data The new buffer. + * \param length The length of the new buffer. + * \throw IOException + */ void setData(const atUint8* data, atUint64 length); + /*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length + * however it's undefined behavior to try and write a buffer which is smaller than the given length. + * + * \param data The buffer to write + * \param length The amount to write + */ + void writeUBytes(const atUint8* data, atUint64 len); + protected: std::unique_ptr m_dataCopy; +private: + void resize(atUint64 newSize); }; } diff --git a/src/Athena/MemoryWriter.cpp b/src/Athena/MemoryWriter.cpp index b2ff4e5..fb46d87 100644 --- a/src/Athena/MemoryWriter.cpp +++ b/src/Athena/MemoryWriter.cpp @@ -31,8 +31,11 @@ MemoryWriter::MemoryWriter(atUint8* data, atUint64 length) } MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) - : MemoryWriter(data, length) { + m_data = data; + m_length = length; + m_position = 0; + if (length == 0) THROW_INVALID_OPERATION_EXCEPTION("length cannot be 0"); @@ -58,6 +61,42 @@ MemoryCopyWriter::MemoryCopyWriter(const std::string& filename) } void MemoryWriter::seek(atInt64 position, SeekOrigin origin) +{ + switch (origin) + { + case SeekOrigin::Begin: + if (position < 0) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + if ((atUint64)position > m_length) + THROW_IO_EXCEPTION("data exceeds available buffer space"); + + m_position = position; + break; + + case SeekOrigin::Current: + if ((((atInt64)m_position + position) < 0)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + if (m_position + position > m_length) + THROW_IO_EXCEPTION("data exceeds available buffer space"); + + m_position += position; + break; + + case SeekOrigin::End: + if (((atInt64)m_length - position) < 0) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + if ((atUint64)position > m_length) + THROW_IO_EXCEPTION("data exceeds available buffer space"); + + m_position = m_length - position; + break; + } +} + +void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) { switch (origin) { @@ -155,9 +194,19 @@ void MemoryWriter::save(const std::string& filename) void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) { - if (!isOpen()) - resize(sizeof(atUint8) * length); + if (!data) + THROW_INVALID_DATA_EXCEPTION("data cannnot be NULL"); + if (m_position + length > m_length) + THROW_IO_EXCEPTION("data length exceeds available buffer space"); + + memcpy((atInt8*)(m_data + m_position), data, length); + + m_position += length; +} + +void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) +{ if (!data) THROW_INVALID_DATA_EXCEPTION("data cannnot be NULL"); @@ -169,7 +218,7 @@ void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) m_position += length; } -void MemoryWriter::resize(atUint64 newSize) +void MemoryCopyWriter::resize(atUint64 newSize) { if (newSize < m_length) THROW_INVALID_OPERATION_EXCEPTION("Stream::resize() -> New size cannot be less to the old size."); @@ -178,13 +227,9 @@ void MemoryWriter::resize(atUint64 newSize) atUint8* newArray = new atUint8[newSize]; memset(newArray, 0, newSize); - if (m_data) - { - memcpy(newArray, m_data, m_length); - - // Delete the old one - delete[] m_data; - } + if (m_dataCopy) + memcpy(newArray, m_dataCopy.get(), m_length); + m_dataCopy.reset(newArray); // Swap the pointer and size out for the new ones. m_data = newArray;