Sprout/sprout/endian_traits.hpp
2019-01-07 17:47:17 +09:00

138 lines
3.8 KiB
C++

/*=============================================================================
Copyright (c) 2011-2019 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_ENDIAN_TRAITS_HPP
#define SPROUT_ENDIAN_TRAITS_HPP
#include <climits>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/workaround/std/cstddef.hpp>
namespace sprout {
namespace detail {
template<typename T, typename Enable = void>
class default_big_endian_traits;
template<typename T>
class default_big_endian_traits<
T,
typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 1>::type
> {
public:
typedef T type;
public:
static SPROUT_CONSTEXPR std::size_t
size() {
return sizeof(type);
}
static SPROUT_CONSTEXPR unsigned char
get_byte(type const& t, std::size_t) {
return static_cast<unsigned char>(t);
}
static SPROUT_CXX14_CONSTEXPR void
set_byte(type& t, std::size_t, unsigned char value) {
t = static_cast<type>(value);
}
};
template<typename T>
class default_big_endian_traits<
T,
typename std::enable_if<std::is_integral<T>::value && !(sizeof(T) == 1)>::type
> {
public:
typedef T type;
public:
static SPROUT_CONSTEXPR std::size_t
size() {
return sizeof(type);
}
static SPROUT_CONSTEXPR unsigned char
get_byte(type const& t, std::size_t i) {
return static_cast<unsigned char>(
(t & (UCHAR_MAX << CHAR_BIT * ((size() - 1) - i)))
>> CHAR_BIT * ((size() - 1) - i)
);
}
static SPROUT_CXX14_CONSTEXPR void
set_byte(type& t, std::size_t i, unsigned char value) {
t &= ~(UCHAR_MAX << CHAR_BIT * ((size() - 1) - i));
t |= (value << CHAR_BIT * ((size() - 1) - i));
}
};
template<typename T, typename Enable = void>
class default_little_endian_traits;
template<typename T>
class default_little_endian_traits<
T,
typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 1>::type
> {
public:
typedef T type;
public:
static SPROUT_CONSTEXPR std::size_t size() {
return sizeof(type);
}
static SPROUT_CONSTEXPR unsigned char get_byte(type const& t, std::size_t) {
return static_cast<unsigned char>(t);
}
static SPROUT_CXX14_CONSTEXPR void
set_byte(type& t, std::size_t, unsigned char value) {
t = static_cast<type>(value);
}
};
template<typename T>
class default_little_endian_traits<
T,
typename std::enable_if<std::is_integral<T>::value && !(sizeof(T) == 1)>::type
> {
public:
typedef T type;
public:
static SPROUT_CONSTEXPR std::size_t size() {
return sizeof(type);
}
static SPROUT_CONSTEXPR unsigned char get_byte(type const& t, std::size_t i) {
return static_cast<unsigned char>(
(t & (UCHAR_MAX << CHAR_BIT * i))
>> CHAR_BIT * i
);
}
static SPROUT_CXX14_CONSTEXPR void
set_byte(type& t, std::size_t i, unsigned char value) {
t &= ~(UCHAR_MAX << CHAR_BIT * i);
t |= (value << CHAR_BIT * i);
}
};
} // namespace detail
//
// big_endian_traits
//
template<typename T>
class big_endian_traits
: public sprout::detail::default_big_endian_traits<T>
{};
//
// little_endian_traits
//
template<typename T>
class little_endian_traits
: public sprout::detail::default_little_endian_traits<T>
{};
//
// endian_traits
//
template<typename T>
class endian_traits
: public sprout::big_endian_traits<T>
{};
} // namespace sprout
#endif // #ifndef SPROUT_ENDIAN_TRAITS_HPP