Add VectorWriter

This commit is contained in:
Jack Andersen 2018-08-24 22:38:23 -10:00
parent f898d7843a
commit 7f28214e9f
3 changed files with 163 additions and 0 deletions

View File

@ -41,6 +41,7 @@ add_library(athena-core
src/athena/Utility.cpp src/athena/Utility.cpp
src/athena/MemoryReader.cpp src/athena/MemoryReader.cpp
src/athena/MemoryWriter.cpp src/athena/MemoryWriter.cpp
src/athena/VectorWriter.cpp
src/athena/FileWriterGeneric.cpp src/athena/FileWriterGeneric.cpp
src/athena/Global.cpp src/athena/Global.cpp
src/athena/Checksums.cpp src/athena/Checksums.cpp
@ -65,6 +66,7 @@ add_library(athena-core
include/athena/FileWriter.hpp include/athena/FileWriter.hpp
include/athena/MemoryReader.hpp include/athena/MemoryReader.hpp
include/athena/MemoryWriter.hpp include/athena/MemoryWriter.hpp
include/athena/VectorWriter.hpp
include/athena/Checksums.hpp include/athena/Checksums.hpp
include/athena/ChecksumsLiterals.hpp include/athena/ChecksumsLiterals.hpp
include/athena/Compression.hpp include/athena/Compression.hpp

View File

@ -0,0 +1,63 @@
#ifndef VECTORWRITER_HPP
#define VECTORWRITER_HPP
#include <string>
#include <memory>
#include <functional>
#include <vector>
#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.<br />
* 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<uint8_t>& 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<uint8_t> m_data;
atUint64 m_position = 0;
};
}
#endif // VECTORWRITER_HPP

View File

@ -0,0 +1,98 @@
#include "athena/VectorWriter.hpp"
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
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<atInt8*>(&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<atInt8*>(&m_data[insertPos]), data, length);
m_position += length;
}
}
} // Athena