From 7f28214e9f825222fbd45a3c29dae7d32b07793b Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 24 Aug 2018 22:38:23 -1000 Subject: [PATCH] Add VectorWriter --- CMakeLists.txt | 2 + include/athena/VectorWriter.hpp | 63 +++++++++++++++++++++ src/athena/VectorWriter.cpp | 98 +++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 include/athena/VectorWriter.hpp create mode 100644 src/athena/VectorWriter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b61e438..f255066 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ add_library(athena-core src/athena/Utility.cpp src/athena/MemoryReader.cpp src/athena/MemoryWriter.cpp + src/athena/VectorWriter.cpp src/athena/FileWriterGeneric.cpp src/athena/Global.cpp src/athena/Checksums.cpp @@ -65,6 +66,7 @@ add_library(athena-core include/athena/FileWriter.hpp include/athena/MemoryReader.hpp include/athena/MemoryWriter.hpp + include/athena/VectorWriter.hpp include/athena/Checksums.hpp include/athena/ChecksumsLiterals.hpp include/athena/Compression.hpp diff --git a/include/athena/VectorWriter.hpp b/include/athena/VectorWriter.hpp new file mode 100644 index 0000000..d31c06f --- /dev/null +++ b/include/athena/VectorWriter.hpp @@ -0,0 +1,63 @@ +#ifndef VECTORWRITER_HPP +#define VECTORWRITER_HPP + +#include +#include +#include +#include +#include "athena/IStreamWriter.hpp" + +namespace athena::io +{ + +/*! @class VectorWriter + * @brief A Stream class for writing data to a STL vector + * + * A Class for writing binary data to an STL vector, + * all work is done using a std::vector, and not written directly to the disk + * @sa Stream + */ +class VectorWriter : public IStreamWriter +{ +public: + /*! @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 Returns the current position in the stream. + * + * @return Int64 The current position in the stream. + */ + inline atUint64 position() const { return m_position; } + + /*! @brief Returns the length of the stream. + * + * @return Int64 The length of the stream. + */ + inline atUint64 length() const { return m_data.size(); } + + inline bool isOpen() const { return true; } + + /*! @brief Obtains reference to underlying std::vector store */ + const std::vector& data() const { return m_data; } + + /*! @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. + * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead. + * + * @param data The buffer to write + * @param length The amount to write + */ + void writeUBytes(const atUint8* data, atUint64 len); + +protected: + std::vector m_data; + atUint64 m_position = 0; +}; + +} + +#endif // VECTORWRITER_HPP diff --git a/src/athena/VectorWriter.cpp b/src/athena/VectorWriter.cpp new file mode 100644 index 0000000..0bc14de --- /dev/null +++ b/src/athena/VectorWriter.cpp @@ -0,0 +1,98 @@ +#include "athena/VectorWriter.hpp" + +#include +#include +#include +#include + +namespace athena::io +{ + +void VectorWriter::seek(atInt64 position, SeekOrigin origin) +{ + switch (origin) + { + case SeekOrigin::Begin: + if (position < 0) + { + atError("Position outside stream bounds"); + setError(); + return; + } + + if ((atUint64)position > m_data.size()) + { + atError("data exceeds vector size"); + setError(); + return; + } + + m_position = position; + break; + + case SeekOrigin::Current: + if ((((atInt64)m_position + position) < 0)) + { + atError("Position outside stream bounds"); + setError(); + return; + } + + if (m_position + position > m_data.size()) + { + atError("data exceeds vector size"); + setError(); + return; + } + + m_position += position; + break; + + case SeekOrigin::End: + if (((atInt64)m_data.size() - position) < 0) + { + atError("Position outside stream bounds"); + setError(); + return; + } + + if ((atUint64)position > m_data.size()) + { + atError("data exceeds vector size"); + setError(); + return; + } + + m_position = m_data.size() - position; + break; + } +} + +void VectorWriter::writeUBytes(const atUint8* data, atUint64 length) +{ + if (!data) + { + atError("data cannnot be NULL"); + setError(); + return; + } + + if (m_position < m_data.size()) + { + size_t delta = std::min(m_data.size() - m_position, length); + memmove(reinterpret_cast(&m_data[m_position]), data, delta); + data += delta; + length -= delta; + m_position += delta; + } + + if (length != 0) + { + size_t insertPos = m_data.size(); + m_data.resize(insertPos + length); + memmove(reinterpret_cast(&m_data[insertPos]), data, length); + m_position += length; + } +} + +} // Athena