Unstable work in progress.

Change names to reverse_bytes and convert_bytes.
Add runtime convert_bytes function.
compile-time generic byte order conversion.
This commit is contained in:
Beman
2013-05-10 07:36:21 -04:00
parent 803bd72f68
commit cd9117941f

View File

@@ -8,8 +8,10 @@
#ifndef BOOST_ENDIAN_CONVERTERS_HPP #ifndef BOOST_ENDIAN_CONVERTERS_HPP
#define BOOST_ENDIAN_CONVERTERS_HPP #define BOOST_ENDIAN_CONVERTERS_HPP
#include "boost/config.hpp"
#include <boost/detail/endian.hpp> #include <boost/detail/endian.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/detail/scoped_enum_emulation.hpp>
#include <algorithm> #include <algorithm>
//------------------------------------- synopsis ---------------------------------------// //------------------------------------- synopsis ---------------------------------------//
@@ -18,50 +20,64 @@ namespace boost
{ {
namespace endian namespace endian
{ {
BOOST_SCOPED_ENUM_START(order) { big, little, native }; BOOST_SCOPED_ENUM_END
// runtime byte order conversion
template <class T>
inline T convert_bytes(T from, BOOST_SCOPED_ENUM(order) from_order,
BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT;
// compile-time generic byte order conversion
template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To, class T>
inline T convert_bytes(T from) BOOST_NOEXCEPT;
// reverse byte order (i.e. endianness) // reverse byte order (i.e. endianness)
// value returning interface approach suggested by Phil Endecott. // value returning interface approach suggested by Phil Endecott.
inline int16_t reverse_bytes(int16_t x) BOOST_NOEXCEPT;
inline int32_t reverse_bytes(int32_t x) BOOST_NOEXCEPT;
inline int64_t reverse_bytes(int64_t x) BOOST_NOEXCEPT;
inline uint16_t reverse_bytes(uint16_t x) BOOST_NOEXCEPT;
inline uint32_t reverse_bytes(uint32_t x) BOOST_NOEXCEPT;
inline uint64_t reverse_bytes(uint64_t x) BOOST_NOEXCEPT;
inline int16_t reorder(int16_t x); // reverse_bytes overloads for floating point types as requested by Vicente
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);
// additional reorder overloads for floating point types as requested by Vicente
// Botet and others. // Botet and others.
// TODO: Need implementation // TODO: Need implementation
// TODO: Need to verify the return does not invoke undefined behavior (as might happen // 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 // if there are unutterable floating point values, such as happens with the unutterable
// pointer values on some architectures // pointer values that cause an immediate abort on some legacy architectures
inline float reorder(float x); // TODO: Track progress of Floating-Point Typedefs Having Specified Widths proposal (N3626)
inline double reorder(double x); // and add boost equivalent from Paul, Chris, John, if available
inline float reverse_bytes(float x) BOOST_NOEXCEPT;
inline double reverse_bytes(double x) BOOST_NOEXCEPT;
// general reorder function template to meet requests for UDT support by Vicente // general reverse_bytes function template to meet requests for UDT support by Vicente
// Botet and others. // Botet and others.
template <class T> template <class T>
inline T reorder(T x); inline T reverse_bytes(T x) BOOST_NOEXCEPT; // convert little to big or visa versa
// reverse bytes if native endian order is not big
template <class T> template <class T>
inline T big(T x); inline T big(T x) BOOST_NOEXCEPT;
// Return: x if native endian order is big, otherwise reorder(x); // Return: x if native endian order is big, otherwise reverse_bytes(x)
// reverse bytes if native endian order is not little
template <class T> template <class T>
inline T little(T x); inline T little(T x) BOOST_NOEXCEPT;
// Return: x if native endian order is little, otherwise reorder(x); // Return: x if native endian order is little, otherwise reverse_bytes(x);
//----------------------------------- implementation -----------------------------------// //----------------------------------- implementation -----------------------------------//
// -- reorder implementation approach suggested by tymofey, with avoidance of // -- reverse_bytes implementation approach suggested by tymofey, with avoidance of
// undefined behavior as suggested by Giovanni Piero Deretta, and a further // undefined behavior as suggested by Giovanni Piero Deretta, and a further
// refinement suggested by Pyry Jahkola. // refinement suggested by Pyry Jahkola.
inline int16_t reorder(int16_t x) inline int16_t reverse_bytes(int16_t x) BOOST_NOEXCEPT
{ {
return (static_cast<uint16_t>(x) << 8) return (static_cast<uint16_t>(x) << 8)
| (static_cast<uint16_t>(x) >> 8); | (static_cast<uint16_t>(x) >> 8);
} }
inline int32_t reorder(int32_t x) inline int32_t reverse_bytes(int32_t x) BOOST_NOEXCEPT
{ {
uint32_t step16; uint32_t step16;
step16 = static_cast<uint32_t>(x) << 16 | static_cast<uint32_t>(x) >> 16; step16 = static_cast<uint32_t>(x) << 16 | static_cast<uint32_t>(x) >> 16;
@@ -70,7 +86,7 @@ namespace endian
| ((static_cast<uint32_t>(step16) >> 8) & 0x00ff00ff); | ((static_cast<uint32_t>(step16) >> 8) & 0x00ff00ff);
} }
inline int64_t reorder(int64_t x) inline int64_t reverse_bytes(int64_t x) BOOST_NOEXCEPT
{ {
uint64_t step32, step16; uint64_t step32, step16;
step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32; step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32;
@@ -80,13 +96,13 @@ namespace endian
| (step16 & 0xFF00FF00FF00FF00) >> 8); | (step16 & 0xFF00FF00FF00FF00) >> 8);
} }
inline uint16_t reorder(uint16_t x) inline uint16_t reverse_bytes(uint16_t x) BOOST_NOEXCEPT
{ {
return (x << 8) return (x << 8)
| (x >> 8); | (x >> 8);
} }
inline uint32_t reorder(uint32_t x) inline uint32_t reverse_bytes(uint32_t x) BOOST_NOEXCEPT
{ {
uint32_t step16; uint32_t step16;
step16 = x << 16 | x >> 16; step16 = x << 16 | x >> 16;
@@ -95,7 +111,7 @@ namespace endian
| ((step16 >> 8) & 0x00ff00ff); | ((step16 >> 8) & 0x00ff00ff);
} }
inline uint64_t reorder(uint64_t x) inline uint64_t reverse_bytes(uint64_t x) BOOST_NOEXCEPT
{ {
uint64_t step32, step16; uint64_t step32, step16;
step32 = x << 32 | x >> 32; step32 = x << 32 | x >> 32;
@@ -106,10 +122,10 @@ namespace endian
} }
// general reorder function template implementation approach using std::reverse // general reverse_bytes function template implementation approach using std::reverse
// suggested by Mathias Gaunard // suggested by Mathias Gaunard
template <class T> template <class T>
inline T reorder(T x) inline T reverse_bytes(T x) BOOST_NOEXCEPT
{ {
T tmp; T tmp;
std::reverse( std::reverse(
@@ -120,22 +136,22 @@ namespace endian
} }
template <class T> template <class T>
inline T big(T x) inline T big(T x) BOOST_NOEXCEPT
{ {
# ifdef BOOST_BIG_ENDIAN # ifdef BOOST_BIG_ENDIAN
return x; return x;
# else # else
return reorder(x); return reverse_bytes(x);
# endif # endif
} }
template <class T> template <class T>
inline T little(T x) inline T little(T x) BOOST_NOEXCEPT
{ {
# ifdef BOOST_LITTLE_ENDIAN # ifdef BOOST_LITTLE_ENDIAN
return x; return x;
# else # else
return reorder(x); return reverse_bytes(x);
# endif # endif
} }