#pragma once /** * \file DataBuffer.h * \brief File containing the sp::DataBuffer class */ #include #include #include #include #include #include #include #include #include #include #include #include namespace sp { /** * \class DataBuffer * \brief Class used to manipulate memory */ class DataBuffer { private: using Data = std::vector; private: Data m_Buffer; std::size_t m_ReadOffset; public: using iterator = Data::iterator; using const_iterator = Data::const_iterator; using reference = Data::reference; using const_reference = Data::const_reference; using difference_type = Data::difference_type; DataBuffer(); DataBuffer(std::size_t a_InitialSize); DataBuffer(const DataBuffer& other); DataBuffer(const DataBuffer& other, difference_type offset); DataBuffer(DataBuffer&& other); DataBuffer(const std::string& str); DataBuffer& operator=(const DataBuffer& other); DataBuffer& operator=(DataBuffer&& other); /** * \brief Append data to the buffer * \warning No endian checks */ template void Append(const T& a_Data) { std::size_t size = sizeof(a_Data); std::size_t end_pos = m_Buffer.size(); m_Buffer.resize(m_Buffer.size() + size); std::memcpy(&m_Buffer[end_pos], &a_Data, size); } /** * \brief Read data into a_Data * \warning No endian checks */ template void Read(T& a_Data) { assert(m_ReadOffset + sizeof(T) <= GetSize()); std::memcpy(&a_Data, m_Buffer.data() + m_ReadOffset, sizeof(T)); m_ReadOffset += sizeof(T); } /** * \brief Write some data to the buffer * \param buffer The buffer to write * \param amount The amount of data to write */ void WriteSome(const char* buffer, std::size_t amount); /** * \brief Write some data to the buffer * \param buffer The buffer to write * \param amount The amount of data to write */ void WriteSome(const std::uint8_t* buffer, std::size_t amount); /** * \brief Read some data from the buffer * \param buffer The buffer to Read * \param amount The amount of data from the buffer */ void ReadSome(char* buffer, std::size_t amount); /** * \brief Read some data from the buffer * \param buffer The buffer to Read * \param amount The amount of data from the buffer */ void ReadSome(std::uint8_t* buffer, std::size_t amount); /** * \brief Read some data from the buffer * \param buffer The buffer to Read * \param amount The amount of data from the buffer */ void ReadSome(DataBuffer& buffer, std::size_t amount); /** * \brief Resize the buffer * \param size The new size of the buffer */ void Resize(std::size_t size) { m_Buffer.resize(size); } /** * \brief Reserve some space in the buffer * \param amount The amount of space to reserve */ void Reserve(std::size_t amount) { m_Buffer.reserve(amount); } /** * \brief Clear the buffer */ void Clear() { m_Buffer.clear(); m_ReadOffset = 0; } /** * \brief When the buffer has been read entirely */ bool IsFinished() const { return m_ReadOffset >= m_Buffer.size(); } /** * \brief Get the buffer data */ std::uint8_t* data() { return m_Buffer.data(); } /** * \brief Get the buffer data */ const std::uint8_t* data() const { return m_Buffer.data(); } /** * \brief Get the read offset */ std::size_t GetReadOffset() const { return m_ReadOffset; } /** * \brief Set the read offset * \param pos The new read offset */ void SetReadOffset(std::size_t pos); /** * \brief Get the size of the buffer */ std::size_t GetSize() const; /** * \brief Get the remaining size of the buffer */ std::size_t GetRemaining() const; /** * \brief Read a file into the buffer * \param fileName The name of the file to read */ void ReadFile(const std::string& fileName); /** * \brief Write a file into the buffer * \param fileName The name of the file to write to */ void WriteFile(const std::string& fileName) const; /** * \brief Allocate the buffer on the heap * \warning Don't forget to free the data ! */ std::uint8_t* HeapAllocatedData() const { std::uint8_t* newBuffer = new std::uint8_t[GetSize()]; std::memcpy(newBuffer, data(), GetSize()); return newBuffer; } /** * \brief Operator == to compare two DataBuffer */ bool operator==(const DataBuffer& other) const { return m_Buffer == other.m_Buffer; } iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; }; /** * \brief Append data to the buffer from another const buffer * \param data The buffer to append */ DataBuffer& operator<<(DataBuffer& a_Buffer, const DataBuffer& data); } // namespace sp