1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2024-12-28 00:15:06 +00:00
OpenMW/components/bgsm/stream.hpp

78 lines
2.2 KiB
C++

#ifndef OPENMW_COMPONENTS_BGSM_STREAM_HPP
#define OPENMW_COMPONENTS_BGSM_STREAM_HPP
#include <array>
#include <cassert>
#include <cstdint>
#include <istream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <components/files/istreamptr.hpp>
#include <components/misc/endianness.hpp>
#include <osg/Vec2f>
#include <osg/Vec3f>
#include <osg/Vec4f>
namespace Bgsm
{
template <std::size_t numInstances, typename T>
inline void readBufferOfType(Files::IStreamPtr& pIStream, T* dest)
{
static_assert(std::is_arithmetic_v<T>, "Buffer element type is not arithmetic");
pIStream->read(reinterpret_cast<char*>(dest), numInstances * sizeof(T));
if (pIStream->bad())
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") buffer of "
+ std::to_string(numInstances) + " instances");
if constexpr (Misc::IS_BIG_ENDIAN)
for (std::size_t i = 0; i < numInstances; i++)
Misc::swapEndiannessInplace(dest[i]);
}
template <std::size_t numInstances, typename T>
inline void readBufferOfType(Files::IStreamPtr& pIStream, T (&dest)[numInstances])
{
readBufferOfType<numInstances>(pIStream, static_cast<T*>(dest));
}
class BGSMStream
{
Files::IStreamPtr mStream;
public:
explicit BGSMStream(Files::IStreamPtr&& stream)
: mStream(std::move(stream))
{
}
void skip(size_t size) { mStream->ignore(size); }
/// Read into a single instance of type
template <class T>
void read(T& data)
{
readBufferOfType<1>(mStream, &data);
}
/// Read multiple instances of type into an array
template <class T, size_t size>
void readArray(std::array<T, size>& arr)
{
readBufferOfType<size>(mStream, arr.data());
}
};
template <>
void BGSMStream::read<osg::Vec2f>(osg::Vec2f& vec);
template <>
void BGSMStream::read<osg::Vec3f>(osg::Vec3f& vec);
template <>
void BGSMStream::read<osg::Vec4f>(osg::Vec4f& vec);
template <>
void BGSMStream::read<std::string>(std::string& str);
}
#endif