Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
2.5 kB · 83 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384#ifndef OPENMW_COMPONENTS_SERIALIZATION_BINARYREADER_H#define OPENMW_COMPONENTS_SERIALIZATION_BINARYREADER_H
#include <components/misc/endianness.hpp>
#include <algorithm>#include <cassert>#include <cstddef>#include <cstring>#include <stdexcept>#include <type_traits>
namespace Serialization{ struct NotEnoughData : std::runtime_error { NotEnoughData() : std::runtime_error("Not enough data") { } };
class BinaryReader { public: explicit BinaryReader(const std::byte* pos, const std::byte* end) : mPos(pos) , mEnd(end) { assert(mPos <= mEnd); }
BinaryReader(const BinaryReader&) = delete;
template <class Format, class T> void operator()(Format&& format, T& value) { if constexpr (std::is_enum_v<T>) (*this)(std::forward<Format>(format), static_cast<std::underlying_type_t<T>&>(value)); else if constexpr (std::is_arithmetic_v<T>) { if (mEnd - mPos < static_cast<std::ptrdiff_t>(sizeof(T))) throw NotEnoughData(); std::memcpy(&value, mPos, sizeof(T)); mPos += sizeof(T); value = Misc::toLittleEndian(value); } else if constexpr (std::is_pointer_v<T>) value = reinterpret_cast<T>(mPos); else { format(*this, value); } }
template <class Format, class T> auto operator()(Format&& format, T* data, std::size_t count) { if constexpr (std::is_enum_v<T>) (*this)(std::forward<Format>(format), reinterpret_cast<std::underlying_type_t<T>*>(data), count); else if constexpr (std::is_arithmetic_v<T>) { const std::size_t size = sizeof(T) * count; if (mEnd - mPos < static_cast<std::ptrdiff_t>(size)) throw NotEnoughData(); std::memcpy(data, mPos, size); mPos += size; if constexpr (!Misc::IS_LITTLE_ENDIAN) std::for_each(data, data + count, [&](T& v) { v = Misc::fromLittleEndian(v); }); } else { format(*this, data, count); } }
private: const std::byte* mPos; const std::byte* const mEnd; };}
#endif