opengenerals/processor/pc/BinaryBuffer.h
szdytom 6b0875ee34
complete ProcedureManager
Signed-off-by: szdytom <szdytom@qq.com>
2024-02-04 15:55:43 +08:00

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