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;