#pragma once
#include <cstdint>
#include <cstdlib>
#include <cinttypes>
// Helper template for creating endian related classes
template <typename StorageType, typename HostType, size_t Shift1, size_t Shift2>
class EndianTypeTemplate
{
public:
operator HostType() const
{
return toHostEndian();
}
HostType toHostEndian() const
{
return (static_cast<HostType>(m_data[0]) << Shift1)
| (static_cast<HostType>(m_data[1]) << Shift2);
}
private:
StorageType m_data[2];
};
// 8-bit values don't really have endianess,
// but just for consistency we'll create the types
using le8_t = uint8_t;
using be8_t = uint8_t;
using le16_t = EndianTypeTemplate<le8_t, uint16_t, 0U, 8U>;
using be16_t = EndianTypeTemplate<be8_t, uint16_t, 8U, 0U>;
using le32_t = EndianTypeTemplate<le16_t, uint32_t, 0U, 16U>;
using be32_t = EndianTypeTemplate<be16_t, uint32_t, 16U, 0U>;
using le64_t = EndianTypeTemplate<le32_t, uint64_t, 0U, 32U>;
using be64_t = EndianTypeTemplate<be32_t, uint64_t, 32U, 0U>;
template <typename StorageType, typename EnumType>
class EnumToHostTemplate
{
public:
operator EnumType() const
{
return toHostEndian();
}
EnumType toHostEndian() const
{
return static_cast<EnumType>(m_value.toHostEndian());
}
private:
StorageType m_value;
};