diff --git a/misc.h b/misc.h index 7261bfca..f3288c09 100644 --- a/misc.h +++ b/misc.h @@ -132,12 +132,11 @@ struct CompileAssert #if CRYPTOPP_DOXYGEN_PROCESSING //! \brief Counts elements in an array //! \param arr an array of elements -//! \details COUNTOF counts elements in an array. On Windows COUNTOF(x) is deinfed -//! to _countof(x) to ensure correct results for pointers. Since the library code -//! is cross-platform, Windows will ensure the safety on non-Windows platforms. +//! \details COUNTOF counts elements in an array. On Windows COUNTOF(x) is defined +//! to _countof(x) to ensure correct results for pointers. //! \note COUNTOF does not produce correct results with pointers, and an array must be used. -//! The library ensures correct application of COUNTOF by enlisting _countof on Windows -//! platforms. Microsoft's _countof fails to compile using pointers. +//! sizeof(x)/sizeof(x[0]) suffers the same problem. The risk is eliminated by using +//! _countof(x) on Windows. Windows will provide the immunity for other platforms. # define COUNTOF(arr) #else // VS2005 added _countof @@ -1707,18 +1706,41 @@ inline T ConditionalByteReverse(ByteOrder order, T value) return NativeByteOrderIs(order) ? value : ByteReverse(value); } -//! \brief Reverses bytes in an element among an array of elements +//! \brief Reverses bytes in an element from an array of elements //! \tparam T the class or type //! \param out the output array of elements //! \param in the input array of elements -//! \param byteCount the byte count of the arrays +//! \param byteCount the total number of bytes in the array //! \details Internally, ByteReverse visits each element in the in array //! calls ByteReverse on it, and writes the result to out. //! \details ByteReverse does not process tail byes, or bytes that are //! \a not part of a full element. If T is int (and int is 4 bytes), then -//! byteCount = 10 means only the first 8 bytes are reversed. -//! \note ByteReverse uses the number of bytes in the arrays, and not the count -//! of elements in the arrays. +//! byteCount = 10 means only the first 2 elements or 8 bytes are +//! reversed. +//! \details The follwoing program should help illustrate the behavior. +//!
vector v1, v2;
+//! 
+//! v1.push_back(1);
+//! v1.push_back(2);
+//! v1.push_back(3);
+//! v1.push_back(4);
+//! 
+//! v2.resize(v1.size());
+//! ByteReverse(&v2[0], &v1[0], 16);
+//! 
+//! cout << "V1: ";
+//! for(unsigned int i = 0; i < v1.size(); i++)
+//!   cout << std::hex << v1[i] << " ";
+//! cout << endl;
+//! 
+//! cout << "V2: ";
+//! for(unsigned int i = 0; i < v2.size(); i++)
+//!   cout << std::hex << v2[i] << " ";
+//! cout << endl;
+//! The program above results in the follwoing output. +//!
V1: 00000001 00000002 00000003 00000004 
+//! V2: 01000000 02000000 03000000 04000000
+//! \sa ConditionalByteReverse template void ByteReverse(T *out, const T *in, size_t byteCount) { @@ -1728,19 +1750,19 @@ void ByteReverse(T *out, const T *in, size_t byteCount) out[i] = ByteReverse(in[i]); } -//! \brief Reverses bytes in an element among an array of elements depending upon endianess +//! \brief Conditionally reverses bytes in an element from an array of elements //! \tparam T the class or type //! \param order the ByteOrder the data is represented //! \param out the output array of elements //! \param in the input array of elements //! \param byteCount the byte count of the arrays //! \details Internally, ByteReverse visits each element in the in array -//! calls ByteReverse on it, and writes the result to out. +//! calls ByteReverse on it depending on the desired endianess, and writes the result to out. //! \details ByteReverse does not process tail byes, or bytes that are //! \a not part of a full element. If T is int (and int is 4 bytes), then -//! byteCount = 10 means only the first 8 bytes are reversed. -//! \note ByteReverse uses the number of bytes in the arrays, and not the count -//! of elements in the arrays. +//! byteCount = 10 means only the first 2 elements or 8 bytes are +//! reversed. +//! \sa ByteReverse template inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount) { @@ -2048,10 +2070,24 @@ T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER) // ************** help remove warning on g++ *************** +//! \class SafeShifter +//! \brief Safely shift values when undefined behavior could occur +//! \tparam overflow boolean flag indicating if overflow is present +//! \details SafeShifter safely shifts values when undefined behavior could occur under C/C++ rules. +//! The class behaves much like a saturating arithmetic class, clamping values rather than allowing +//! the compiler to remove undefined behavior. template struct SafeShifter; +//! \class SafeShifter +//! \details the \p true template parameter indicates overflow would occur. +//! In this case, SafeShifter clamps the value and returns 0. template<> struct SafeShifter { + //! \brief Right shifts a value that overflows + //! \tparam T class or type + //! \return 0 + //! \details Since overflow == true, the value 0 is always returned. + //! \sa SafeLeftShift template static inline T RightShift(T value, unsigned int bits) { @@ -2059,6 +2095,11 @@ template<> struct SafeShifter return 0; } + //! \brief Left shifts a value that overflows + //! \tparam T class or type + //! \return 0 + //! \details Since overflow == true, the value 0 is always returned. + //! \sa SafeRightShift template static inline T LeftShift(T value, unsigned int bits) { @@ -2067,14 +2108,27 @@ template<> struct SafeShifter } }; +//! \class SafeShifter +//! \details the \p false template parameter indicates overflow would \a not occur. +//! In this case, SafeShifter returns the shfted value. template<> struct SafeShifter { + //! \brief Right shifts a value that does not overflow + //! \tparam T class or type + //! \return the shifted value + //! \details Since overflow == false, the shifted value is returned. + //! \sa SafeLeftShift template static inline T RightShift(T value, unsigned int bits) { return value >> bits; } + //! \brief Left shifts a value that does not overflow + //! \tparam T class or type + //! \return the shifted value + //! \details Since overflow == false, the shifted value is returned. + //! \sa SafeRightShift template static inline T LeftShift(T value, unsigned int bits) { @@ -2082,12 +2136,30 @@ template<> struct SafeShifter } }; +//! \class SafeRightShift +//! \brief Safely right shift values when undefined behavior could occur +//! \tparam bits the number of bit positions to shift the value +//! \tparam T class or type +//! \param value the value to right shift +//! \result the shifted value or 0 +//! \details SafeRightShift safely shifts the value to the right when undefined behavior +//! could occur under C/C++ rules. SafeRightShift will return the shifted value or 0 +//! if undefined behavior would occur. template inline T SafeRightShift(T value) { return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits); } +//! \class SafeLeftShift +//! \brief Safely left shift values when undefined behavior could occur +//! \tparam bits the number of bit positions to shift the value +//! \tparam T class or type +//! \param value the value to left shift +//! \result the shifted value or 0 +//! \details SafeLeftShift safely shifts the value to the left when undefined behavior +//! could occur under C/C++ rules. SafeLeftShift will return the shifted value or 0 +//! if undefined behavior would occur. template inline T SafeLeftShift(T value) {