178 lines
5.4 KiB
C++
178 lines
5.4 KiB
C++
#pragma once
|
|
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <cassert>
|
|
#include <string>
|
|
|
|
namespace td {
|
|
|
|
class DataBuffer {
|
|
private:
|
|
typedef std::vector<std::uint8_t> Data;
|
|
Data m_Buffer;
|
|
std::size_t m_ReadOffset;
|
|
|
|
public:
|
|
typedef Data::iterator iterator;
|
|
typedef Data::const_iterator const_iterator;
|
|
typedef Data::reference reference;
|
|
typedef Data::const_reference const_reference;
|
|
|
|
DataBuffer();
|
|
DataBuffer(const DataBuffer& other);
|
|
DataBuffer(const DataBuffer& other, Data::difference_type offset);
|
|
DataBuffer(DataBuffer&& other);
|
|
DataBuffer(const std::string& str);
|
|
|
|
DataBuffer& operator=(const DataBuffer& other);
|
|
DataBuffer& operator=(DataBuffer&& other);
|
|
|
|
template <typename T>
|
|
void Append(T data) {
|
|
std::size_t size = sizeof(data);
|
|
std::size_t end_pos = m_Buffer.size();
|
|
m_Buffer.resize(m_Buffer.size() + size);
|
|
memcpy(&m_Buffer[end_pos], &data, size);
|
|
}
|
|
|
|
template <typename T>
|
|
DataBuffer& operator<<(T data) {
|
|
// Switch to big endian
|
|
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
|
Append(data);
|
|
return *this;
|
|
}
|
|
|
|
DataBuffer& operator<<(std::string str) {
|
|
m_Buffer.insert(m_Buffer.end(), str.begin(), str.end());
|
|
return *this;
|
|
}
|
|
|
|
DataBuffer& operator<<(DataBuffer& data) {
|
|
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
|
return *this;
|
|
}
|
|
|
|
DataBuffer& operator<<(const DataBuffer& data) {
|
|
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
DataBuffer& operator>>(T& data) {
|
|
assert(m_ReadOffset + sizeof(T) <= GetSize());
|
|
data = *(reinterpret_cast<T*>(&m_Buffer[m_ReadOffset]));
|
|
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
|
m_ReadOffset += sizeof(T);
|
|
return *this;
|
|
}
|
|
|
|
DataBuffer& operator>>(DataBuffer& data) {
|
|
data.Resize(GetSize() - m_ReadOffset);
|
|
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
|
|
m_ReadOffset = m_Buffer.size();
|
|
return *this;
|
|
}
|
|
|
|
DataBuffer& operator>>(std::string& str) {
|
|
std::size_t stringSize = strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
|
|
str.resize(stringSize);
|
|
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset),
|
|
m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset + stringSize), str.begin());
|
|
m_ReadOffset += stringSize;
|
|
return *this;
|
|
}
|
|
|
|
void WriteSome(const char* buffer, std::size_t amount) {
|
|
std::size_t end_pos = m_Buffer.size();
|
|
m_Buffer.resize(m_Buffer.size() + amount);
|
|
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
|
}
|
|
|
|
void WriteSome(const std::uint8_t* buffer, std::size_t amount) {
|
|
std::size_t end_pos = m_Buffer.size();
|
|
m_Buffer.resize(m_Buffer.size() + amount);
|
|
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
|
}
|
|
|
|
void ReadSome(char* buffer, std::size_t amount) {
|
|
assert(m_ReadOffset + amount <= GetSize());
|
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
|
m_ReadOffset += amount;
|
|
}
|
|
|
|
void ReadSome(std::uint8_t* buffer, std::size_t amount) {
|
|
assert(m_ReadOffset + amount <= GetSize());
|
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
|
m_ReadOffset += amount;
|
|
}
|
|
|
|
void ReadSome(DataBuffer& buffer, std::size_t amount) {
|
|
assert(m_ReadOffset + amount <= GetSize());
|
|
buffer.Resize(amount);
|
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
|
m_ReadOffset += amount;
|
|
}
|
|
|
|
void ReadSome(std::string& buffer, std::size_t amount) {
|
|
assert(m_ReadOffset + amount <= GetSize());
|
|
buffer.resize(amount);
|
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
|
m_ReadOffset += amount;
|
|
}
|
|
|
|
void Resize(std::size_t size) {
|
|
m_Buffer.resize(size);
|
|
}
|
|
|
|
void Reserve(std::size_t amount) {
|
|
m_Buffer.reserve(amount);
|
|
}
|
|
|
|
void erase(iterator it) {
|
|
m_Buffer.erase(it);
|
|
}
|
|
|
|
void Clear() {
|
|
m_Buffer.clear();
|
|
m_ReadOffset = 0;
|
|
}
|
|
|
|
bool IsFinished() const {
|
|
return m_ReadOffset >= m_Buffer.size();
|
|
}
|
|
|
|
std::uint8_t* data() {
|
|
return m_Buffer.data();
|
|
}
|
|
|
|
const std::uint8_t* data() const {
|
|
return m_Buffer.data();
|
|
}
|
|
|
|
std::size_t GetReadOffset() const { return m_ReadOffset; }
|
|
void SetReadOffset(std::size_t pos);
|
|
|
|
std::string ToString() const;
|
|
std::size_t GetSize() const;
|
|
bool IsEmpty() const;
|
|
std::size_t GetRemaining() const;
|
|
|
|
iterator begin();
|
|
iterator end();
|
|
const_iterator begin() const;
|
|
const_iterator end() const;
|
|
|
|
reference operator[](Data::size_type i) { return m_Buffer[i]; }
|
|
const_reference operator[](Data::size_type i) const { return m_Buffer[i]; }
|
|
|
|
bool ReadFile(const std::string& fileName);
|
|
bool WriteFile(const std::string& fileName);
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
|
|
|
|
} // ns td
|