131 lines
2.6 KiB
C++
131 lines
2.6 KiB
C++
#ifndef OG_BINARY_BUFFER_H_
|
|
#define OG_BINARY_BUFFER_H_
|
|
|
|
#include <cstdint>
|
|
#include <tuple>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <deque>
|
|
#include <concepts>
|
|
#include <string_view>
|
|
#include <iostream>
|
|
|
|
using byte = unsigned char;
|
|
|
|
inline namespace {
|
|
|
|
template <typename T>
|
|
concept IsTupleLike = requires(T t) {
|
|
std::tuple_size<T>::value;
|
|
};
|
|
|
|
template <typename T>
|
|
concept IsBasicType = std::integral<T> || std::is_enum<T>::value
|
|
|| std::same_as<T, float> || std::same_as<T, double>;
|
|
|
|
template <typename T>
|
|
concept IsTupleConvertable = requires(T t) {
|
|
IsTupleLike<decltype(t.asTuple())>;
|
|
};
|
|
|
|
static_assert(IsTupleLike<std::tuple<int, int, int>>);
|
|
|
|
}
|
|
|
|
class BinaryBuffer {
|
|
public:
|
|
BinaryBuffer();
|
|
BinaryBuffer(std::size_t n, const byte *buf);
|
|
|
|
template <typename T>
|
|
requires IsBasicType<T>
|
|
BinaryBuffer& operator>>(T& x) {
|
|
if (sizeof(T) <= data.size()) {
|
|
auto ptr = reinterpret_cast<byte*>(&x);
|
|
for (std::size_t i = 0; i < sizeof(T); ++i) {
|
|
ptr[i] = data.front();
|
|
data.pop_front();
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
requires IsBasicType<T>
|
|
BinaryBuffer& operator<<(const T& x) {
|
|
auto ptr = reinterpret_cast<const byte*>(&x);
|
|
for (std::size_t i = 0; i < sizeof(T); ++i) {
|
|
data.push_back(ptr[i]);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
BinaryBuffer& operator<<(const std::vector<T>& x) {
|
|
uint32_t len = x.size();
|
|
*this << len;
|
|
for (const T& element : x)
|
|
*this << element;
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
BinaryBuffer& operator>>(std::vector<T>& x) {
|
|
uint32_t len;
|
|
*this >> len;
|
|
x.resize(len);
|
|
for (std::uint32_t i = 0; i < len; ++i)
|
|
*this >> x[i];
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
requires IsTupleLike<T>
|
|
BinaryBuffer& operator<<(const T& x) {
|
|
std::apply([this](const auto&... elements) {
|
|
(*this << ... << elements);
|
|
}, x);
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
requires IsTupleLike<T>
|
|
BinaryBuffer& operator>>(T& x) {
|
|
std::apply([this](auto&... elements) {
|
|
(*this >> ... >> elements);
|
|
}, x);
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
requires IsTupleConvertable<T>
|
|
BinaryBuffer& operator<<(const T &x) {
|
|
*this << x.asTuple();
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
requires IsTupleConvertable<T>
|
|
BinaryBuffer& operator>>(T &x) {
|
|
*this >> x.asTuple();
|
|
return *this;
|
|
}
|
|
|
|
BinaryBuffer& operator<<(const std::string_view &);
|
|
BinaryBuffer& operator>>(std::string&);
|
|
|
|
std::size_t size() const;
|
|
bool empty() const;
|
|
void writeTo(std::FILE *out) const;
|
|
|
|
friend std::ostream& operator<<(std::ostream &, const BinaryBuffer &);
|
|
|
|
private:
|
|
std::deque<byte> data;
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream &, const BinaryBuffer &);
|
|
|
|
#endif
|
|
|