Newer
Older
Import / research / units / EndianTypes.hpp
#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;
};