Merge Atomics branch into Master
parent
370483c7aa
commit
e961c2da5b
16
config.h
16
config.h
|
|
@ -759,6 +759,18 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ATOMICS 1
|
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||||
#endif // atomics
|
#endif // atomics
|
||||||
|
|
||||||
|
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; and Intel 12.0.
|
||||||
|
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
|
||||||
|
#if (CRYPTOPP_MSC_VERSION >= 1700)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1200)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_GCC_VERSION >= 40400)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#endif // synchronization
|
||||||
|
|
||||||
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
||||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
|
@ -767,8 +779,10 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
# if __has_feature(cxx_alignof)
|
# if __has_feature(cxx_alignas)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
# endif
|
||||||
|
# if __has_feature(cxx_alignof)
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
# endif
|
# endif
|
||||||
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
||||||
|
|
|
||||||
|
|
@ -757,6 +757,18 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ATOMICS 1
|
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||||
#endif // atomics
|
#endif // atomics
|
||||||
|
|
||||||
|
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; and Intel 12.0.
|
||||||
|
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
|
||||||
|
#if (CRYPTOPP_MSC_VERSION >= 1700)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1200)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_GCC_VERSION >= 40400)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#endif // synchronization
|
||||||
|
|
||||||
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
||||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
|
@ -765,8 +777,10 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
# if __has_feature(cxx_alignof)
|
# if __has_feature(cxx_alignas)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
# endif
|
||||||
|
# if __has_feature(cxx_alignof)
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
# endif
|
# endif
|
||||||
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
||||||
|
|
|
||||||
103
misc.h
103
misc.h
|
|
@ -68,7 +68,7 @@
|
||||||
#if CRYPTOPP_DOXYGEN_PROCESSING
|
#if CRYPTOPP_DOXYGEN_PROCESSING
|
||||||
//! \brief The maximum value of a machine word
|
//! \brief The maximum value of a machine word
|
||||||
//! \details SIZE_MAX provides the maximum value of a machine word. The value is
|
//! \details SIZE_MAX provides the maximum value of a machine word. The value is
|
||||||
//! \p 0xffffffff on 32-bit machines, and \p 0xffffffffffffffff on 64-bit machines.
|
//! \p 0xffffffff on 32-bit machines, and \p 0xffffffffffffffff on 64-bit machines.
|
||||||
//! Internally, SIZE_MAX is defined as __SIZE_MAX__ if __SIZE_MAX__ is defined. If not
|
//! Internally, SIZE_MAX is defined as __SIZE_MAX__ if __SIZE_MAX__ is defined. If not
|
||||||
//! defined, then SIZE_T_MAX is tried. If neither __SIZE_MAX__ nor SIZE_T_MAX is
|
//! defined, then SIZE_T_MAX is tried. If neither __SIZE_MAX__ nor SIZE_T_MAX is
|
||||||
//! is defined, the library uses std::numeric_limits<size_t>::max(). The library
|
//! is defined, the library uses std::numeric_limits<size_t>::max(). The library
|
||||||
|
|
@ -93,7 +93,7 @@
|
||||||
#endif // CRYPTOPP_DOXYGEN_PROCESSING
|
#endif // CRYPTOPP_DOXYGEN_PROCESSING
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
||||||
// Forward declaration for IntToString specialization
|
// Forward declaration for IntToString specialization
|
||||||
class Integer;
|
class Integer;
|
||||||
|
|
||||||
|
|
@ -236,10 +236,12 @@ struct NewObject
|
||||||
//! \tparam T the class or type
|
//! \tparam T the class or type
|
||||||
//! \tparam F the object factory for T
|
//! \tparam F the object factory for T
|
||||||
//! \tparam instance the initiali instance count
|
//! \tparam instance the initiali instance count
|
||||||
//! \details This class safely initializes a static object in a multithreaded environment
|
//! \details This class safely initializes a static object in a multithreaded environment. For C++03
|
||||||
//! without using locks (for portability). Note that if two threads call Ref() at the same
|
//! and below it will do so without using locks for portability. If two threads call Ref() at the same
|
||||||
//! time, they may get back different references, and one object may end up being memory
|
//! time, they may get back different references, and one object may end up being memory leaked. This
|
||||||
//! leaked. This is by design.
|
//! is by design. For C++11 and above, a standard double-checked locking pattern with memory fences
|
||||||
|
//! is used. The locks and fences are standard and do not hinder portability.
|
||||||
|
//! \sa <A HREF="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/">Double-Checked Locking is Fixed In C++11</A>
|
||||||
template <class T, class F = NewObject<T>, int instance=0>
|
template <class T, class F = NewObject<T>, int instance=0>
|
||||||
class Singleton
|
class Singleton
|
||||||
{
|
{
|
||||||
|
|
@ -256,28 +258,29 @@ private:
|
||||||
//! \brief Return a reference to the inner Singleton object
|
//! \brief Return a reference to the inner Singleton object
|
||||||
//! \details Ref() is used to create the object using the object factory. The
|
//! \details Ref() is used to create the object using the object factory. The
|
||||||
//! object is only created once with the limitations discussed in the class documentation.
|
//! object is only created once with the limitations discussed in the class documentation.
|
||||||
#if defined(CRYPTOPP_CXX11_ATOMICS)
|
//! \sa <A HREF="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/">Double-Checked Locking is Fixed In C++11</A>
|
||||||
|
#if defined(CRYPTOPP_CXX11_ATOMICS) && defined(CRYPTOPP_CXX11_SYNCHRONIZATION)
|
||||||
template <class T, class F, int instance>
|
template <class T, class F, int instance>
|
||||||
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
||||||
{
|
{
|
||||||
static volatile simple_ptr<T> s_pObject;
|
static std::mutex s_mutex;
|
||||||
T *p = s_pObject.m_p;
|
static std::atomic<T*> s_pObject;
|
||||||
|
|
||||||
|
T *p = s_pObject.load(std::memory_order_relaxed);
|
||||||
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
return *p;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(s_mutex);
|
||||||
|
p = s_pObject.load(std::memory_order_relaxed);
|
||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
return *p;
|
return *p;
|
||||||
|
|
||||||
T *newObject = m_objectFactory();
|
T *newObject = m_objectFactory();
|
||||||
p = s_pObject.m_p;
|
s_pObject.store(newObject, std::memory_order_relaxed);
|
||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
|
||||||
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
delete newObject;
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_pObject.m_p = newObject;
|
|
||||||
std::atomic_thread_fence(std::memory_order_release);
|
std::atomic_thread_fence(std::memory_order_release);
|
||||||
|
|
||||||
return *newObject;
|
return *newObject;
|
||||||
|
|
@ -333,9 +336,9 @@ const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
||||||
//! \details memcpy_s() will assert the pointers src and dest are not NULL
|
//! \details memcpy_s() will assert the pointers src and dest are not NULL
|
||||||
//! in debug builds. Passing NULL for either pointer is undefined behavior.
|
//! in debug builds. Passing NULL for either pointer is undefined behavior.
|
||||||
inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
|
inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
|
||||||
{
|
{
|
||||||
// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55
|
// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55
|
||||||
|
|
||||||
// Pointers must be valid; otherwise undefined behavior
|
// Pointers must be valid; otherwise undefined behavior
|
||||||
assert(dest != NULL); assert(src != NULL);
|
assert(dest != NULL); assert(src != NULL);
|
||||||
// Destination buffer must be large enough to satsify request
|
// Destination buffer must be large enough to satsify request
|
||||||
|
|
@ -377,7 +380,7 @@ inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t cou
|
||||||
inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
|
inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
|
||||||
{
|
{
|
||||||
// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55
|
// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55
|
||||||
|
|
||||||
// Pointers must be valid; otherwise undefined behavior
|
// Pointers must be valid; otherwise undefined behavior
|
||||||
assert(dest != NULL); assert(src != NULL);
|
assert(dest != NULL); assert(src != NULL);
|
||||||
// Destination buffer must be large enough to satsify request
|
// Destination buffer must be large enough to satsify request
|
||||||
|
|
@ -497,7 +500,7 @@ std::string IntToString(T value, unsigned int base = 10)
|
||||||
static const unsigned int HIGH_BIT = (1U << 31);
|
static const unsigned int HIGH_BIT = (1U << 31);
|
||||||
const char CH = !!(base & HIGH_BIT) ? 'A' : 'a';
|
const char CH = !!(base & HIGH_BIT) ? 'A' : 'a';
|
||||||
base &= ~HIGH_BIT;
|
base &= ~HIGH_BIT;
|
||||||
|
|
||||||
assert(base >= 2);
|
assert(base >= 2);
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
return "0";
|
return "0";
|
||||||
|
|
@ -647,9 +650,9 @@ inline unsigned int TrailingZeros(word32 v)
|
||||||
return (unsigned int)result;
|
return (unsigned int)result;
|
||||||
#else
|
#else
|
||||||
// from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
|
// from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
|
||||||
static const int MultiplyDeBruijnBitPosition[32] =
|
static const int MultiplyDeBruijnBitPosition[32] =
|
||||||
{
|
{
|
||||||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||||
};
|
};
|
||||||
return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27];
|
return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27];
|
||||||
|
|
@ -840,7 +843,7 @@ inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
|
||||||
//! is defined, then the function returns 1.
|
//! is defined, then the function returns 1.
|
||||||
template <class T>
|
template <class T>
|
||||||
inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround
|
inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround
|
||||||
{
|
{
|
||||||
// GCC 4.6 (circa 2008) and above aggressively uses vectorization.
|
// GCC 4.6 (circa 2008) and above aggressively uses vectorization.
|
||||||
#if defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS)
|
#if defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS)
|
||||||
if (sizeof(T) < 16)
|
if (sizeof(T) < 16)
|
||||||
|
|
@ -989,7 +992,7 @@ inline void IncrementCounterByOne(byte *inout, unsigned int size)
|
||||||
inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int size)
|
inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int size)
|
||||||
{
|
{
|
||||||
assert(output != NULL); assert(input != NULL); assert(size < INT_MAX);
|
assert(output != NULL); assert(input != NULL); assert(size < INT_MAX);
|
||||||
|
|
||||||
int i, carry;
|
int i, carry;
|
||||||
for (i=int(size-1), carry=1; i>=0 && carry; i--)
|
for (i=int(size-1), carry=1; i>=0 && carry; i--)
|
||||||
carry = ((output[i] = input[i]+1) == 0);
|
carry = ((output[i] = input[i]+1) == 0);
|
||||||
|
|
@ -1024,7 +1027,7 @@ inline void ConditionalSwapPointers(bool c, T &a, T &b)
|
||||||
// and https://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data
|
// and https://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data
|
||||||
|
|
||||||
//! \brief Sets each element of an array to 0
|
//! \brief Sets each element of an array to 0
|
||||||
//! \param buf an array of elements
|
//! \param buf an array of elements
|
||||||
//! \param n the number of elements in the array
|
//! \param n the number of elements in the array
|
||||||
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal
|
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
@ -1039,7 +1042,7 @@ void SecureWipeBuffer(T *buf, size_t n)
|
||||||
#if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)
|
#if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)
|
||||||
|
|
||||||
//! \brief Sets each byte of an array to 0
|
//! \brief Sets each byte of an array to 0
|
||||||
//! \param buf an array of bytes
|
//! \param buf an array of bytes
|
||||||
//! \param n the number of elements in the array
|
//! \param n the number of elements in the array
|
||||||
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
||||||
template<> inline void SecureWipeBuffer(byte *buf, size_t n)
|
template<> inline void SecureWipeBuffer(byte *buf, size_t n)
|
||||||
|
|
@ -1053,7 +1056,7 @@ template<> inline void SecureWipeBuffer(byte *buf, size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief Sets each 16-bit element of an array to 0
|
//! \brief Sets each 16-bit element of an array to 0
|
||||||
//! \param buf an array of 16-bit words
|
//! \param buf an array of 16-bit words
|
||||||
//! \param n the number of elements in the array
|
//! \param n the number of elements in the array
|
||||||
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
||||||
template<> inline void SecureWipeBuffer(word16 *buf, size_t n)
|
template<> inline void SecureWipeBuffer(word16 *buf, size_t n)
|
||||||
|
|
@ -1067,7 +1070,7 @@ template<> inline void SecureWipeBuffer(word16 *buf, size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief Sets each 32-bit element of an array to 0
|
//! \brief Sets each 32-bit element of an array to 0
|
||||||
//! \param buf an array of 32-bit words
|
//! \param buf an array of 32-bit words
|
||||||
//! \param n the number of elements in the array
|
//! \param n the number of elements in the array
|
||||||
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
||||||
template<> inline void SecureWipeBuffer(word32 *buf, size_t n)
|
template<> inline void SecureWipeBuffer(word32 *buf, size_t n)
|
||||||
|
|
@ -1081,7 +1084,7 @@ template<> inline void SecureWipeBuffer(word32 *buf, size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief Sets each 64-bit element of an array to 0
|
//! \brief Sets each 64-bit element of an array to 0
|
||||||
//! \param buf an array of 64-bit words
|
//! \param buf an array of 64-bit words
|
||||||
//! \param n the number of elements in the array
|
//! \param n the number of elements in the array
|
||||||
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
|
||||||
template<> inline void SecureWipeBuffer(word64 *buf, size_t n)
|
template<> inline void SecureWipeBuffer(word64 *buf, size_t n)
|
||||||
|
|
@ -1147,7 +1150,7 @@ inline void SecureWipeArray(T *buf, size_t n)
|
||||||
SecureWipeBuffer((byte *)(void *)buf, n * sizeof(T));
|
SecureWipeBuffer((byte *)(void *)buf, n * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief Converts a wide character C-string to a multibyte string
|
//! \brief Converts a wide character C-string to a multibyte string
|
||||||
//! \param str C-string consiting of wide characters
|
//! \param str C-string consiting of wide characters
|
||||||
//! \param throwOnError specifies the function should throw an InvalidArgument exception on error
|
//! \param throwOnError specifies the function should throw an InvalidArgument exception on error
|
||||||
//! \returns str converted to a multibyte string or an empty string.
|
//! \returns str converted to a multibyte string or an empty string.
|
||||||
|
|
@ -1267,7 +1270,7 @@ template <class T> inline T rotlFixed(T x, unsigned int y)
|
||||||
{
|
{
|
||||||
// Portable rotate that reduces to single instruction...
|
// Portable rotate that reduces to single instruction...
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
|
||||||
// https://software.intel.com/en-us/forums/topic/580884
|
// https://software.intel.com/en-us/forums/topic/580884
|
||||||
// and https://llvm.org/bugs/show_bug.cgi?id=24226
|
// and https://llvm.org/bugs/show_bug.cgi?id=24226
|
||||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||||
static const unsigned int MASK = THIS_SIZE-1;
|
static const unsigned int MASK = THIS_SIZE-1;
|
||||||
|
|
@ -1288,7 +1291,7 @@ template <class T> inline T rotrFixed(T x, unsigned int y)
|
||||||
{
|
{
|
||||||
// Portable rotate that reduces to single instruction...
|
// Portable rotate that reduces to single instruction...
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
|
||||||
// https://software.intel.com/en-us/forums/topic/580884
|
// https://software.intel.com/en-us/forums/topic/580884
|
||||||
// and https://llvm.org/bugs/show_bug.cgi?id=24226
|
// and https://llvm.org/bugs/show_bug.cgi?id=24226
|
||||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||||
static const unsigned int MASK = THIS_SIZE-1;
|
static const unsigned int MASK = THIS_SIZE-1;
|
||||||
|
|
@ -1364,7 +1367,7 @@ template <class T> inline T rotrMod(T x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotlFixed will assert in Debug builds if is outside the allowed range.
|
//! \note rotlFixed will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
|
template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
|
||||||
{
|
{
|
||||||
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
||||||
|
|
@ -1378,7 +1381,7 @@ template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotrFixed will assert in Debug builds if is outside the allowed range.
|
//! \note rotrFixed will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
|
template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
|
||||||
{
|
{
|
||||||
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
||||||
|
|
@ -1392,7 +1395,7 @@ template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotlVariable will assert in Debug builds if is outside the allowed range.
|
//! \note rotlVariable will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
|
template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
|
||||||
{
|
{
|
||||||
assert(y < 8*sizeof(x));
|
assert(y < 8*sizeof(x));
|
||||||
|
|
@ -1405,7 +1408,7 @@ template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotrVariable will assert in Debug builds if is outside the allowed range.
|
//! \note rotrVariable will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
|
template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
|
||||||
{
|
{
|
||||||
assert(y < 8*sizeof(x));
|
assert(y < 8*sizeof(x));
|
||||||
|
|
@ -1447,7 +1450,7 @@ template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotrFixed will assert in Debug builds if is outside the allowed range.
|
//! \note rotrFixed will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
|
template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
|
||||||
{
|
{
|
||||||
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
||||||
|
|
@ -1461,7 +1464,7 @@ template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotrFixed will assert in Debug builds if is outside the allowed range.
|
//! \note rotrFixed will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
|
template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
|
||||||
{
|
{
|
||||||
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
|
||||||
|
|
@ -1475,7 +1478,7 @@ template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotlVariable will assert in Debug builds if is outside the allowed range.
|
//! \note rotlVariable will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
|
template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
|
||||||
{
|
{
|
||||||
assert(y < 8*sizeof(x));
|
assert(y < 8*sizeof(x));
|
||||||
|
|
@ -1488,7 +1491,7 @@ template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
|
||||||
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
|
||||||
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
|
||||||
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||||
//! \note rotrVariable will assert in Debug builds if is outside the allowed range.
|
//! \note rotrVariable will assert in Debug builds if is outside the allowed range.
|
||||||
template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y)
|
template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y)
|
||||||
{
|
{
|
||||||
assert(y < 8*sizeof(x));
|
assert(y < 8*sizeof(x));
|
||||||
|
|
@ -1808,26 +1811,26 @@ inline T ConditionalByteReverse(ByteOrder order, T value)
|
||||||
//! reversed.
|
//! reversed.
|
||||||
//! \details The follwoing program should help illustrate the behavior.
|
//! \details The follwoing program should help illustrate the behavior.
|
||||||
//! <pre>vector<word32> v1, v2;
|
//! <pre>vector<word32> v1, v2;
|
||||||
//!
|
//!
|
||||||
//! v1.push_back(1);
|
//! v1.push_back(1);
|
||||||
//! v1.push_back(2);
|
//! v1.push_back(2);
|
||||||
//! v1.push_back(3);
|
//! v1.push_back(3);
|
||||||
//! v1.push_back(4);
|
//! v1.push_back(4);
|
||||||
//!
|
//!
|
||||||
//! v2.resize(v1.size());
|
//! v2.resize(v1.size());
|
||||||
//! ByteReverse<word32>(&v2[0], &v1[0], 16);
|
//! ByteReverse<word32>(&v2[0], &v1[0], 16);
|
||||||
//!
|
//!
|
||||||
//! cout << "V1: ";
|
//! cout << "V1: ";
|
||||||
//! for(unsigned int i = 0; i < v1.size(); i++)
|
//! for(unsigned int i = 0; i < v1.size(); i++)
|
||||||
//! cout << std::hex << v1[i] << " ";
|
//! cout << std::hex << v1[i] << " ";
|
||||||
//! cout << endl;
|
//! cout << endl;
|
||||||
//!
|
//!
|
||||||
//! cout << "V2: ";
|
//! cout << "V2: ";
|
||||||
//! for(unsigned int i = 0; i < v2.size(); i++)
|
//! for(unsigned int i = 0; i < v2.size(); i++)
|
||||||
//! cout << std::hex << v2[i] << " ";
|
//! cout << std::hex << v2[i] << " ";
|
||||||
//! cout << endl;</pre>
|
//! cout << endl;</pre>
|
||||||
//! The program above results in the follwoing output.
|
//! The program above results in the follwoing output.
|
||||||
//! <pre>V1: 00000001 00000002 00000003 00000004
|
//! <pre>V1: 00000001 00000002 00000003 00000004
|
||||||
//! V2: 01000000 02000000 03000000 04000000</pre>
|
//! V2: 01000000 02000000 03000000 04000000</pre>
|
||||||
//! \sa ConditionalByteReverse
|
//! \sa ConditionalByteReverse
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
@ -2225,7 +2228,7 @@ template <bool overflow> struct SafeShifter;
|
||||||
//! \class SafeShifter<true>
|
//! \class SafeShifter<true>
|
||||||
//! \brief Shifts a value in the presence of overflow
|
//! \brief Shifts a value in the presence of overflow
|
||||||
//! \details the \p true template parameter indicates overflow would occur.
|
//! \details the \p true template parameter indicates overflow would occur.
|
||||||
//! In this case, SafeShifter clamps the value and returns 0.
|
//! In this case, SafeShifter clamps the value and returns 0.
|
||||||
template<> struct SafeShifter<true>
|
template<> struct SafeShifter<true>
|
||||||
{
|
{
|
||||||
//! \brief Right shifts a value that overflows
|
//! \brief Right shifts a value that overflows
|
||||||
|
|
@ -2256,7 +2259,7 @@ template<> struct SafeShifter<true>
|
||||||
//! \class SafeShifter<false>
|
//! \class SafeShifter<false>
|
||||||
//! \brief Shifts a value in the absence of overflow
|
//! \brief Shifts a value in the absence of overflow
|
||||||
//! \details the \p false template parameter indicates overflow would \a not occur.
|
//! \details the \p false template parameter indicates overflow would \a not occur.
|
||||||
//! In this case, SafeShifter returns the shfted value.
|
//! In this case, SafeShifter returns the shfted value.
|
||||||
template<> struct SafeShifter<false>
|
template<> struct SafeShifter<false>
|
||||||
{
|
{
|
||||||
//! \brief Right shifts a value that does not overflow
|
//! \brief Right shifts a value that does not overflow
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue