Files
boost_endian/include/boost/endian/conversion2.hpp
T

154 lines
4.4 KiB
C++

// boost/endian/conversion.hpp -------------------------------------------------------//
// Copyright Beman Dawes 2010, 2011
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_ENDIAN_CONVERSION2_HPP
#define BOOST_ENDIAN_CONVERSION2_HPP
#include <boost/detail/endian.hpp>
#include <boost/cstdint.hpp>
#include <algorithm>
//--------------------------------------------------------------------------------------//
//
// This header explores
// -- value returning interface approach suggested by Phil Endecott.
// -- additional reorder overloads for floating point types as requested by Vicente
// Botet and others.
// -- reorder implementation approach suggested by tymofey, with avoidance of
// undefined behavior as suggested by Giovanni Piero Deretta, and a further
// refinement suggested by Pyry Jahkola.
// -- general reorder function template to meet requests for UDT support by
// Vicente Botet and others.
// -- general reorder function template implementation approach using std::reverse
// suggested by Mathias Gaunard
//
//--------------------------------------------------------------------------------------//
//------------------------------------- synopsis ---------------------------------------//
namespace boost
{
namespace endian2
{
// reverse byte order (i.e. endianness)
inline int16_t reorder(int16_t x);
inline int32_t reorder(int32_t x);
inline int64_t reorder(int64_t x);
inline uint16_t reorder(uint16_t x);
inline uint32_t reorder(uint32_t x);
inline uint64_t reorder(uint64_t x);
// TODO: Need implementation
// TODO: Need to verify the return does not invoke undefined behavior (as might happen
// if there are unutterable floating point values, such as happens with the unutterable
// pointer values on some architectures
inline float reorder(float x);
inline double reorder(double x);
// TODO: Would pass by value be better for the following functions?
template <class T>
inline T reorder(const T& x);
template <class T>
inline T big(const T& x);
// Return: x if native endianness is big, otherwise reorder(x);
template <class T>
inline T little(const T& x);
// Return: x if native endianness is little, otherwise reorder(x);
//----------------------------------- implementation -----------------------------------//
inline int16_t reorder(int16_t x)
{
return (static_cast<uint16_t>(x) << 8)
| (static_cast<uint16_t>(x) >> 8);
}
inline int32_t reorder(int32_t x)
{
uint32_t step16;
step16 = static_cast<uint32_t>(x) << 16 | static_cast<uint32_t>(x) >> 16;
return
((static_cast<uint32_t>(step16) << 8) & 0xff00ff00)
| ((static_cast<uint32_t>(step16) >> 8) & 0x00ff00ff);
}
inline int64_t reorder(int64_t x)
{
uint64_t step32, step16;
step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32;
step16 = (step32 & 0x0000FFFF0000FFFF) << 16
| (step32 & 0xFFFF0000FFFF0000) >> 16;
return static_cast<int64_t>((step16 & 0x00FF00FF00FF00FF) << 8
| (step16 & 0xFF00FF00FF00FF00) >> 8);
}
inline uint16_t reorder(uint16_t x)
{
return (x << 8)
| (x >> 8);
}
inline uint32_t reorder(uint32_t x)
{
uint32_t step16;
step16 = x << 16 | x >> 16;
return
((step16 << 8) & 0xff00ff00)
| ((step16 >> 8) & 0x00ff00ff);
}
inline uint64_t reorder(uint64_t x)
{
uint64_t step32, step16;
step32 = x << 32 | x >> 32;
step16 = (step32 & 0x0000FFFF0000FFFF) << 16
| (step32 & 0xFFFF0000FFFF0000) >> 16;
return (step16 & 0x00FF00FF00FF00FF) << 8
| (step16 & 0xFF00FF00FF00FF00) >> 8;
}
template <class T>
inline T reorder(const T& x)
{
T tmp;
std::reverse(
reinterpret_cast<const char*>(&x),
reinterpret_cast<const char*>(&x) + sizeof(T),
reinterpret_cast<char*>(&tmp));
return tmp;
}
template <class T>
inline T big(const T& x)
{
# ifdef BOOST_BIG_ENDIAN
return x;
# else
return reorder(x);
# endif
}
template <class T>
inline T little(const T& x)
{
# ifdef BOOST_LITTLE_ENDIAN
return x;
# else
return reorder(x);
# endif
}
} // namespace endian2
} // namespace boost
#endif // BOOST_ENDIAN_CONVERSION2_HPP