forked from boostorg/endian
Add unaligned floating point types and supporting infrastructure.
This commit is contained in:
1 parent
a7ba65f830
commit
dff7c1254e
9 files changed
+270
-18
No files matched your search
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user