summaryrefslogtreecommitdiff
path: root/boost/endian
diff options
context:
space:
mode:
Diffstat (limited to 'boost/endian')
-rw-r--r--boost/endian/arithmetic.hpp18
-rw-r--r--boost/endian/buffers.hpp58
-rw-r--r--boost/endian/conversion.hpp37
-rw-r--r--boost/endian/detail/config.hpp6
-rw-r--r--boost/endian/detail/cover_operators.hpp24
-rw-r--r--boost/endian/detail/intrinsic.hpp2
-rw-r--r--boost/endian/detail/lightweight_test.hpp2
7 files changed, 85 insertions, 62 deletions
diff --git a/boost/endian/arithmetic.hpp b/boost/endian/arithmetic.hpp
index d8bcbe62b4..e20d25b3b4 100644
--- a/boost/endian/arithmetic.hpp
+++ b/boost/endian/arithmetic.hpp
@@ -21,8 +21,8 @@
#ifndef BOOST_ENDIAN_ARITHMETIC_HPP
#define BOOST_ENDIAN_ARITHMETIC_HPP
-#if defined(_MSC_VER)
-# pragma warning(push)
+#if defined(_MSC_VER)
+# pragma warning(push)
# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
#endif
@@ -300,7 +300,7 @@ namespace endian
# ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
@@ -325,7 +325,7 @@ namespace endian
# ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
@@ -361,7 +361,7 @@ namespace endian
this->m_value = ::boost::endian::native_to_big(val);
}
-# endif
+# endif
endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
{
this->m_value = ::boost::endian::native_to_big(val);
@@ -390,7 +390,7 @@ namespace endian
# endif
this->m_value = ::boost::endian::native_to_little(val);
}
-# endif
+# endif
endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
{
this->m_value = ::boost::endian::native_to_little(val);
@@ -406,8 +406,8 @@ namespace endian
# pragma pack(pop)
#endif
-#if defined(_MSC_VER)
-# pragma warning(pop)
-#endif
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
#endif // BOOST_ENDIAN_ARITHMETIC_HPP
diff --git a/boost/endian/buffers.hpp b/boost/endian/buffers.hpp
index b48b8de7d4..258bbecb54 100644
--- a/boost/endian/buffers.hpp
+++ b/boost/endian/buffers.hpp
@@ -21,8 +21,8 @@
#ifndef BOOST_ENDIAN_BUFFERS_HPP
#define BOOST_ENDIAN_BUFFERS_HPP
-#if defined(_MSC_VER)
-# pragma warning(push)
+#if defined(_MSC_VER)
+# pragma warning(push)
# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
#endif
@@ -38,11 +38,16 @@
#include <boost/predef/detail/endian_compat.h>
#include <boost/endian/conversion.hpp>
#include <boost/type_traits/is_signed.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/type_identity.hpp>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/scoped_enum.hpp>
#include <iosfwd>
#include <climits>
+#include <cstring>
# if CHAR_BIT != 8
# error Platforms with CHAR_BIT != 8 are not supported
@@ -195,7 +200,7 @@ namespace endian
return os << x.value();
}
- // Stream extractor
+ // Stream extractor
template <class charT, class traits, BOOST_SCOPED_ENUM(order) Order, class T,
std::size_t n_bits, BOOST_SCOPED_ENUM(align) A>
std::basic_istream<charT, traits>&
@@ -221,20 +226,27 @@ namespace endian
{
typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
+ // shifting a negative number is flagged by -fsanitize=undefined
+ // so use the corresponding unsigned type for the shifts
+
+ typedef typename boost::conditional<
+ boost::is_integral<T>::value,
+ boost::make_unsigned<T>, boost::type_identity<T> >::type::type U;
+
static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
- { return static_cast<T>(*(bytes - 1) | (next::load_big(bytes - 1) << 8)); }
+ { return static_cast<T>(*(bytes - 1) | (static_cast<U>(next::load_big(bytes - 1)) << 8)); }
static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
- { return static_cast<T>(*bytes | (next::load_little(bytes + 1) << 8)); }
+ { return static_cast<T>(*bytes | (static_cast<U>(next::load_little(bytes + 1)) << 8)); }
static void store_big(char* bytes, T value) BOOST_NOEXCEPT
{
*(bytes - 1) = static_cast<char>(value);
- next::store_big(bytes - 1, static_cast<T>(value >> 8));
+ next::store_big(bytes - 1, static_cast<T>(static_cast<U>(value) >> 8));
}
static void store_little(char* bytes, T value) BOOST_NOEXCEPT
{
*bytes = static_cast<char>(value);
- next::store_little(bytes + 1, static_cast<T>(value >> 8));
+ next::store_little(bytes + 1, static_cast<T>(static_cast<U>(value) >> 8));
}
};
@@ -284,7 +296,12 @@ namespace endian
// case since sizeof(T) and n_bytes are known at compile
// time.
{
- return *reinterpret_cast<T const *>(bytes);
+ // Avoids -fsanitize=undefined violations due to unaligned loads
+ // All major x86 compilers optimize a short-sized memcpy into a single instruction
+
+ T t;
+ std::memcpy( &t, bytes, sizeof(T) );
+ return t;
}
# endif
return unrolled_byte_loops<T, n_bytes>::load_little
@@ -310,7 +327,10 @@ namespace endian
// case since sizeof(T) and n_bytes are known at compile
// time.
{
- *reinterpret_cast<T *>(bytes) = value;
+ // Avoids -fsanitize=undefined violations due to unaligned stores
+ // All major x86 compilers optimize a short-sized memcpy into a single instruction
+
+ std::memcpy( bytes, &value, sizeof(T) );
return;
}
# endif
@@ -346,7 +366,7 @@ namespace endian
# ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "big, unaligned, "
@@ -365,7 +385,7 @@ namespace endian
return *this;
}
value_type value() const BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "big, unaligned, " << n_bits << "-bits, convert("
@@ -388,7 +408,7 @@ namespace endian
# ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "little, unaligned, " << n_bits << "-bits, construct("
@@ -400,7 +420,7 @@ namespace endian
endian_buffer & operator=(T val) BOOST_NOEXCEPT
{ detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
value_type value() const BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "little, unaligned, " << n_bits << "-bits, convert("
@@ -435,14 +455,14 @@ namespace endian
m_value = ::boost::endian::native_to_big(val);
}
-# endif
+# endif
endian_buffer& operator=(T val) BOOST_NOEXCEPT
{
m_value = ::boost::endian::native_to_big(val);
return *this;
}
//operator value_type() const BOOST_NOEXCEPT
- //{
+ //{
// return ::boost::endian::big_to_native(m_value);
//}
value_type value() const BOOST_NOEXCEPT
@@ -480,7 +500,7 @@ namespace endian
m_value = ::boost::endian::native_to_little(val);
}
-# endif
+# endif
endian_buffer& operator=(T val) BOOST_NOEXCEPT
{
m_value = ::boost::endian::native_to_little(val);
@@ -508,8 +528,8 @@ namespace endian
# pragma pack(pop)
#endif
-#if defined(_MSC_VER)
-# pragma warning(pop)
-#endif
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
#endif // BOOST_ENDIAN_BUFFERS_HPP
diff --git a/boost/endian/conversion.hpp b/boost/endian/conversion.hpp
index fc0e1a2360..9dc40231d4 100644
--- a/boost/endian/conversion.hpp
+++ b/boost/endian/conversion.hpp
@@ -48,12 +48,12 @@ namespace endian
// by argument dependent lookup (ADL). //
// //
//--------------------------------------------------------------------------------------//
-
+
// customization for exact-length arithmetic types. See doc/conversion.html/#FAQ.
// Note: The omission of a overloads for the arithmetic type (typically long, or
// long long) not assigned to one of the exact length typedefs is a deliberate
// design decision. Such overloads would be non-portable and thus error prone.
-
+
inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT;
inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT;
inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT;
@@ -112,7 +112,7 @@ namespace endian
// //
// user-defined types (UDTs) //
// //
- // All reverse in place function templates are required to be implemented in terms //
+ // All reverse in place function templates are required to be implemented in terms //
// of an unqualified call to "endian_reverse_inplace(x)", a function reversing //
// the endianness of x, which is a non-const reference. This provides a //
// customization point for any UDT that provides a "reverse_inplace" free-function //
@@ -146,7 +146,7 @@ namespace endian
// generic conditional reverse in place
template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
class EndianReversibleInplace>
- inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
+ inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
// runtime reverse in place
template <class EndianReversibleInplace>
@@ -199,33 +199,35 @@ namespace endian
{
return x;
}
-
+
inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT
{
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
+# ifdef BOOST_ENDIAN_NO_INTRINSICS
return (static_cast<uint16_t>(x) << 8)
| (static_cast<uint16_t>(x) >> 8);
# else
- return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(static_cast<uint16_t>(x));
+ return static_cast<int16_t>(
+ BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(static_cast<uint16_t>(x)));
# endif
}
inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT
{
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
+# ifdef BOOST_ENDIAN_NO_INTRINSICS
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);
# else
- return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast<uint32_t>(x));
+ return static_cast<int32_t>(
+ BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast<uint32_t>(x)));
# endif
}
inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT
{
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
+# ifdef BOOST_ENDIAN_NO_INTRINSICS
uint64_t step32, step16;
step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32;
step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
@@ -233,10 +235,11 @@ namespace endian
return static_cast<int64_t>((step16 & 0x00FF00FF00FF00FFULL) << 8
| (step16 & 0xFF00FF00FF00FF00ULL) >> 8);
# else
- return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(static_cast<uint64_t>(x));
+ return static_cast<int64_t>(
+ BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(static_cast<uint64_t>(x)));
# endif
}
-
+
inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT
{
return x;
@@ -244,7 +247,7 @@ namespace endian
inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT
{
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
+# ifdef BOOST_ENDIAN_NO_INTRINSICS
return (x << 8)
| (x >> 8);
# else
@@ -252,9 +255,9 @@ namespace endian
# endif
}
- inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT
+ inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT
{
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
+# ifdef BOOST_ENDIAN_NO_INTRINSICS
uint32_t step16;
step16 = x << 16 | x >> 16;
return
@@ -267,7 +270,7 @@ namespace endian
inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT
{
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
+# ifdef BOOST_ENDIAN_NO_INTRINSICS
uint64_t step32, step16;
step32 = x << 32 | x >> 32;
step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
@@ -402,7 +405,7 @@ namespace endian
namespace detail
{
- // Primary template and specializations support generic
+ // Primary template and specializations support generic
// endian_reverse_inplace().
// See rationale in endian_reverse_inplace() below.
template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
diff --git a/boost/endian/detail/config.hpp b/boost/endian/detail/config.hpp
index 8ece0a1e9f..6d446fa5d5 100644
--- a/boost/endian/detail/config.hpp
+++ b/boost/endian/detail/config.hpp
@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
-//--------------------------------------------------------------------------------------//
+//--------------------------------------------------------------------------------------//
#ifndef BOOST_ENDIAN_CONFIG_HPP
#define BOOST_ENDIAN_CONFIG_HPP
@@ -31,14 +31,14 @@
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ENDIAN_DYN_LINK)
# if defined(BOOST_ENDIAN_SOURCE)
# define BOOST_ENDIAN_DECL BOOST_SYMBOL_EXPORT
-# else
+# else
# define BOOST_ENDIAN_DECL BOOST_SYMBOL_IMPORT
# endif
#else
# define BOOST_ENDIAN_DECL
#endif
-// enable automatic library variant selection ----------------------------------------//
+// enable automatic library variant selection ----------------------------------------//
#if !defined(BOOST_ENDIAN_SOURCE) && !defined(BOOST_ALL_NO_LIB) \
&& !defined(BOOST_ENDIAN_NO_LIB)
diff --git a/boost/endian/detail/cover_operators.hpp b/boost/endian/detail/cover_operators.hpp
index f4fd052803..a16545e498 100644
--- a/boost/endian/detail/cover_operators.hpp
+++ b/boost/endian/detail/cover_operators.hpp
@@ -9,8 +9,8 @@
#ifndef BOOST_ENDIAN_COVER_OPERATORS_HPP
#define BOOST_ENDIAN_COVER_OPERATORS_HPP
-#if defined(_MSC_VER)
-# pragma warning(push)
+#if defined(_MSC_VER)
+# pragma warning(push)
# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
#endif
@@ -61,7 +61,7 @@ namespace boost
friend bool operator==(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x == y; }
friend bool operator<(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x < y; }
# endif
-
+
// The basic arithmetic operations.
friend D& operator+=(D& x, ArithmeticT y) BOOST_NOEXCEPT
{ return x = static_cast<ArithmeticT>(+x + y); }
@@ -83,13 +83,13 @@ namespace boost
{ return x = static_cast<ArithmeticT>(+x << y); }
friend D& operator>>=(D& x, ArithmeticT y) BOOST_NOEXCEPT
{ return x = static_cast<ArithmeticT>(+x >> y); }
-
+
// A few binary arithmetic operations not covered by operators base class.
friend ArithmeticT operator<<(const D& x, ArithmeticT y) BOOST_NOEXCEPT
{ return static_cast<ArithmeticT>(+x << y); }
friend ArithmeticT operator>>(const D& x, ArithmeticT y) BOOST_NOEXCEPT
{ return static_cast<ArithmeticT>(+x >> y); }
-
+
// Auto-increment and auto-decrement can be defined in terms of the
// arithmetic operations.
friend D& operator++(D& x) BOOST_NOEXCEPT { return x += 1; }
@@ -97,13 +97,13 @@ namespace boost
# ifdef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
friend D operator++(D& x, int) BOOST_NOEXCEPT
- {
+ {
D tmp(x);
x += 1;
return tmp;
}
friend D operator--(D& x, int) BOOST_NOEXCEPT
- {
+ {
D tmp(x);
x -= 1;
return tmp;
@@ -117,10 +117,10 @@ namespace boost
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const D& x)
{
- return os << +x;
+ return os << +x;
}
- // Stream extractor
+ // Stream extractor
template <class charT, class traits>
friend std::basic_istream<charT, traits>&
operator>>(std::basic_istream<charT, traits>& is, D& x)
@@ -135,8 +135,8 @@ namespace boost
} // namespace endian
} // namespace boost
-#if defined(_MSC_VER)
-# pragma warning(pop)
-#endif
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
#endif // BOOST_ENDIAN_COVER_OPERATORS_HPP
diff --git a/boost/endian/detail/intrinsic.hpp b/boost/endian/detail/intrinsic.hpp
index 0abd0ad435..f110276b10 100644
--- a/boost/endian/detail/intrinsic.hpp
+++ b/boost/endian/detail/intrinsic.hpp
@@ -46,7 +46,7 @@
# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) __builtin_bswap32(x)
# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) __builtin_bswap64(x)
-// Linux systems provide the byteswap.h header, with
+// Linux systems provide the byteswap.h header, with
#elif defined(__linux__)
// don't check for obsolete forms defined(linux) and defined(__linux) on the theory that
// compilers that predefine only these are so old that byteswap.h probably isn't present.
diff --git a/boost/endian/detail/lightweight_test.hpp b/boost/endian/detail/lightweight_test.hpp
index eba315c954..ba0eee2f7c 100644
--- a/boost/endian/detail/lightweight_test.hpp
+++ b/boost/endian/detail/lightweight_test.hpp
@@ -45,7 +45,7 @@ struct report_errors_reminder
~report_errors_reminder()
{
- BOOST_ASSERT(called_report_errors_function); // verify report_errors() was called
+ BOOST_ASSERT(called_report_errors_function); // verify report_errors() was called
}
};