Add unaligned floating point types and supporting infrastructure.

This commit is contained in:
Beman committed 2013-05-26 08:25:10 -04:00
1 parent a7ba65f830
commit dff7c1254e
9 files changed
+270 -18

No files matched your search

+51 -3
View File
@@ -126,13 +126,23 @@ namespace endian
//----------------------------------- end synopsis -------------------------------------//
namespace detail
// This function is unsafe for general use, so is placed in namespace detail.
// These functions are unsafe for general use, so is placed in namespace detail.
// Think of what happens if you reverse_value a std::pair<int16_t, int_16_t>; the bytes
// from first end up in second and the bytes from second end up in first. Not good!
{
// general reverse_value function template useful in testing
template <class T>
inline T reverse_value(T x) BOOST_NOEXCEPT; // convert little to big or visa versa
// conditional unaligned reverse copy, patterned after std::reverse_copy
template <class T>
inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
template <class T>
inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
template <class T>
inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
template <class T>
inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
}
//--------------------------------------------------------------------------------------//
@@ -237,7 +247,7 @@ namespace endian
return *(const double*)&tmp;
}
namespace detail // this function is unsafe for general use, so placed in namespace detail
namespace detail
{
// general reverse_value function template implementation approach using std::reverse
// suggested by Mathias Gaunard
@@ -250,7 +260,45 @@ namespace endian
reinterpret_cast<char*>(&tmp) + sizeof(T));
return tmp;
}
}
template <class T>
inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT
{
# ifdef BOOST_BIG_ENDIAN
std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
# else
std::reverse_copy(reinterpret_cast<const char*>(&from),
reinterpret_cast<const char*>(&from)+sizeof(T), to);
# endif
}
template <class T>
inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
{
# ifdef BOOST_BIG_ENDIAN
std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
# else
std::reverse_copy(from, from+sizeof(T), reinterpret_cast<char*>(&to));
# endif
}
template <class T>
inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT
{
# ifdef BOOST_LITTLE_ENDIAN
std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
# else
std::reverse_copy(reinterpret_cast<const char*>(&from),
reinterpret_cast<const char*>(&from)+sizeof(T), to);
# endif
}
template <class T>
inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
{
# ifdef BOOST_LITTLE_ENDIAN
std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
# else
std::reverse_copy(from, from+sizeof(T), reinterpret_cast<char*>(&to));
# endif
}
}
template <class ReversibleValue >
inline ReversibleValue big_endian_value(ReversibleValue x) BOOST_NOEXCEPT
+109
View File
@@ -88,6 +88,14 @@ namespace endian
typedef boost::endian::endian<order::little, float, 32, align::yes> little_float32_t;
typedef boost::endian::endian<order::little, double, 64, align::yes> little_float64_t;
// unaligned big endian floating point types
typedef boost::endian::endian<order::big, float, 32, align::no> big_float32un_t;
typedef boost::endian::endian<order::big, double, 64, align::no> big_float64un_t;
// unaligned little endian floating point types
typedef boost::endian::endian<order::little, float, 32, align::no> little_float32un_t;
typedef boost::endian::endian<order::little, double, 64, align::no> little_float64un_t;
// aligned big endian signed integer types
typedef endian<order::big, int16_t, 16, align::yes> big_int16_t;
typedef endian<order::big, int32_t, 32, align::yes> big_int32_t;
@@ -182,6 +190,7 @@ namespace endian
{
namespace detail
{
// Unrolled loops for loading and storing streams of bytes.
template <typename T, std::size_t n_bytes,
@@ -312,6 +321,106 @@ namespace endian
private:
char m_value[n_bits/8];
};
// unaligned float big endian specialization
template <>
class endian< order::big, float, 32, align::no >
: cover_operators< endian< order::big, float, 32 >, float >
{
public:
typedef float value_type;
# ifndef BOOST_ENDIAN_NO_CTORS
endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian(value_type val) BOOST_NOEXCEPT
{ detail::big_reverse_copy(val, m_value); }
# endif
endian & operator=(value_type val) BOOST_NOEXCEPT
{ detail::big_reverse_copy(val, m_value); return *this; }
operator value_type() const BOOST_NOEXCEPT
{
value_type tmp;
detail::big_reverse_copy(m_value, tmp);
return tmp;
}
const char* data() const BOOST_NOEXCEPT { return m_value; }
private:
char m_value[sizeof(value_type)];
};
// unaligned double big endian specialization
template <>
class endian< order::big, double, 64, align::no >
: cover_operators< endian< order::big, double, 64 >, double >
{
public:
typedef double value_type;
# ifndef BOOST_ENDIAN_NO_CTORS
endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian(value_type val) BOOST_NOEXCEPT
{ detail::big_reverse_copy(val, m_value); }
# endif
endian & operator=(value_type val) BOOST_NOEXCEPT
{ detail::big_reverse_copy(val, m_value); return *this; }
operator value_type() const BOOST_NOEXCEPT
{
value_type tmp;
detail::big_reverse_copy(m_value, tmp);
return tmp;
}
const char* data() const BOOST_NOEXCEPT { return m_value; }
private:
char m_value[sizeof(value_type)];
};
// unaligned float little endian specialization
template <>
class endian< order::little, float, 32, align::no >
: cover_operators< endian< order::little, float, 32 >, float >
{
public:
typedef float value_type;
# ifndef BOOST_ENDIAN_NO_CTORS
endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian(value_type val) BOOST_NOEXCEPT
{ detail::little_reverse_copy(val, m_value); }
# endif
endian & operator=(value_type val) BOOST_NOEXCEPT
{ detail::little_reverse_copy(val, m_value); return *this; }
operator value_type() const BOOST_NOEXCEPT
{
value_type tmp;
detail::little_reverse_copy(m_value, tmp);
return tmp;
}
const char* data() const BOOST_NOEXCEPT { return m_value; }
private:
char m_value[sizeof(value_type)];
};
// unaligned double little endian specialization
template <>
class endian< order::little, double, 64, align::no >
: cover_operators< endian< order::little, double, 64 >, double >
{
public:
typedef double value_type;
# ifndef BOOST_ENDIAN_NO_CTORS
endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian(value_type val) BOOST_NOEXCEPT
{ detail::little_reverse_copy(val, m_value); }
# endif
endian & operator=(value_type val) BOOST_NOEXCEPT
{ detail::little_reverse_copy(val, m_value); return *this; }
operator value_type() const BOOST_NOEXCEPT
{
value_type tmp;
detail::little_reverse_copy(m_value, tmp);
return tmp;
}
const char* data() const BOOST_NOEXCEPT { return m_value; }
private:
char m_value[sizeof(value_type)];
};
// unaligned little endian specialization
template <typename T, std::size_t n_bits>