Add binary deserialization helper class
This commit is contained in:
parent
e87c4508fc
commit
0bed4ae39f
1 changed files with 86 additions and 0 deletions
86
libs/util/include/psemek/util/binary_stream.hpp
Normal file
86
libs/util/include/psemek/util/binary_stream.hpp
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace psemek::util
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
inline void unexpected_end()
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Unexpected binary stream end");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct read_helper
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_copyable_v<T>);
|
||||||
|
|
||||||
|
static T read(std::string_view & data)
|
||||||
|
{
|
||||||
|
if (data.size() < sizeof(T))
|
||||||
|
unexpected_end();
|
||||||
|
|
||||||
|
T value;
|
||||||
|
std::copy(data.data(), data.data() + sizeof(T), reinterpret_cast<char *>(std::addressof(value)));
|
||||||
|
data.remove_prefix(sizeof(T));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct read_helper<std::vector<T>>
|
||||||
|
{
|
||||||
|
static T read(std::string_view & data)
|
||||||
|
{
|
||||||
|
std::uint32_t size = read_helper<std::uint32_t>::read(data);
|
||||||
|
|
||||||
|
std::vector<T> result;
|
||||||
|
|
||||||
|
if constexpr (std::is_trivially_copyable_v<T>)
|
||||||
|
{
|
||||||
|
if (data.size() < sizeof(T) * size)
|
||||||
|
unexpected_end();
|
||||||
|
|
||||||
|
result.resize(size);
|
||||||
|
std::copy(data.data(), data.data() + sizeof(T) * size, reinterpret_cast<char *>(result.data()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (std::uint32_t i = 0; i < size; ++i)
|
||||||
|
result.push_back(read_helper<T>::read(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct binary_istream
|
||||||
|
{
|
||||||
|
std::string_view data;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T read()
|
||||||
|
{
|
||||||
|
return detail::read_helper<T>::read(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * read_raw(std::size_t count)
|
||||||
|
{
|
||||||
|
if (data.size() < count)
|
||||||
|
detail::unexpected_end();
|
||||||
|
|
||||||
|
auto p = data.data();
|
||||||
|
data.remove_prefix(count);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue