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