Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

misc.h

00001 #ifndef CRYPTOPP_MISC_H
00002 #define CRYPTOPP_MISC_H
00003 
00004 #include "cryptopp_config.h"
00005 #include "cryptlib.h"
00006 #include <assert.h>
00007 #include <string.h>             // CodeWarrior doesn't have memory.h
00008 #include <algorithm>
00009 #include <string>
00010 
00011 #ifdef INTEL_INTRINSICS
00012 #include <stdlib.h>
00013 #endif
00014 
00015 NAMESPACE_BEGIN(CryptoPP)
00016 
00017 // ************** compile-time assertion ***************
00018 
00019 template <bool b>
00020 struct CompileAssert
00021 {
00022         static char dummy[2*b-1];
00023 };
00024 
00025 #define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
00026 #define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
00027 #define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
00028 #define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
00029 
00030 // ************** misc classes ***************
00031 
00032 class Empty
00033 {
00034 };
00035 
00036 template <class BASE1, class BASE2>
00037 class TwoBases : public BASE1, public BASE2
00038 {
00039 };
00040 
00041 template <class BASE1, class BASE2, class BASE3>
00042 class ThreeBases : public BASE1, public BASE2, public BASE3
00043 {
00044 };
00045 
00046 template <class T>
00047 class ObjectHolder
00048 {
00049 protected:
00050         T m_object;
00051 };
00052 
00053 class NotCopyable
00054 {
00055 public:
00056         NotCopyable() {}
00057 private:
00058     NotCopyable(const NotCopyable &);
00059     void operator=(const NotCopyable &);
00060 };
00061 
00062 // ************** misc functions ***************
00063 
00064 // can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
00065 template <class _Tp> inline const _Tp& STDMIN(const _Tp& __a, const _Tp& __b)
00066 {
00067         return __b < __a ? __b : __a;
00068 }
00069 
00070 template <class _Tp> inline const _Tp& STDMAX(const _Tp& __a, const _Tp& __b)
00071 {
00072         return  __a < __b ? __b : __a;
00073 }
00074 
00075 #define RETURN_IF_NONZERO(x) unsigned int returnedValue = x; if (returnedValue) return returnedValue
00076 
00077 // this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack
00078 #define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
00079 // these may be faster on other CPUs/compilers
00080 // #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
00081 // #define GETBYTE(x, y) (((byte *)&(x))[y])
00082 
00083 unsigned int Parity(unsigned long);
00084 unsigned int BytePrecision(unsigned long);
00085 unsigned int BitPrecision(unsigned long);
00086 unsigned long Crop(unsigned long, unsigned int size);
00087 
00088 inline unsigned int BitsToBytes(unsigned int bitCount)
00089 {
00090         return ((bitCount+7)/(8));
00091 }
00092 
00093 inline unsigned int BytesToWords(unsigned int byteCount)
00094 {
00095         return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
00096 }
00097 
00098 inline unsigned int BitsToWords(unsigned int bitCount)
00099 {
00100         return ((bitCount+WORD_BITS-1)/(WORD_BITS));
00101 }
00102 
00103 void xorbuf(byte *buf, const byte *mask, unsigned int count);
00104 void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count);
00105 
00106 template <class T>
00107 inline bool IsPowerOf2(T n)
00108 {
00109         return n > 0 && (n & (n-1)) == 0;
00110 }
00111 
00112 template <class T1, class T2>
00113 inline T2 ModPowerOf2(T1 a, T2 b)
00114 {
00115         assert(IsPowerOf2(b));
00116         return T2(a) & (b-1);
00117 }
00118 
00119 template <class T>
00120 inline T RoundDownToMultipleOf(T n, T m)
00121 {
00122         return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
00123 }
00124 
00125 template <class T>
00126 inline T RoundUpToMultipleOf(T n, T m)
00127 {
00128         return RoundDownToMultipleOf(n+m-1, m);
00129 }
00130 
00131 template <class T>
00132 inline unsigned int GetAlignment(T *dummy=NULL) // VC60 workaround
00133 {
00134 #if (_MSC_VER >= 1300)
00135         return __alignof(T);
00136 #elif defined(__GNUC__)
00137         return __alignof__(T);
00138 #else
00139         return sizeof(T);
00140 #endif
00141 }
00142 
00143 inline bool IsAlignedOn(const void *p, unsigned int alignment)
00144 {
00145         return IsPowerOf2(alignment) ? ModPowerOf2((unsigned int)p, alignment) == 0 : (unsigned int)p % alignment == 0;
00146 }
00147 
00148 template <class T>
00149 inline bool IsAligned(const void *p, T *dummy=NULL)     // VC60 workaround
00150 {
00151         return IsAlignedOn(p, GetAlignment<T>());
00152 }
00153 
00154 #ifdef IS_LITTLE_ENDIAN
00155         typedef LittleEndian NativeByteOrder;
00156 #else
00157         typedef BigEndian NativeByteOrder;
00158 #endif
00159 
00160 inline ByteOrder GetNativeByteOrder()
00161 {
00162         return NativeByteOrder::ToEnum();
00163 }
00164 
00165 inline bool NativeByteOrderIs(ByteOrder order)
00166 {
00167         return order == GetNativeByteOrder();
00168 }
00169 
00170 template <class T>              // can't use <sstream> because GCC 2.95.2 doesn't have it
00171 std::string IntToString(T a, unsigned int base = 10)
00172 {
00173         if (a == 0)
00174                 return "0";
00175         bool negate = false;
00176         if (a < 0)
00177         {
00178                 negate = true;
00179                 a = 0-a;        // VC .NET does not like -a
00180         }
00181         std::string result;
00182         while (a > 0)
00183         {
00184                 T digit = a % base;
00185                 result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
00186                 a /= base;
00187         }
00188         if (negate)
00189                 result = "-" + result;
00190         return result;
00191 }
00192 
00193 template <class T1, class T2>
00194 inline T1 SaturatingSubtract(T1 a, T2 b)
00195 {
00196         CRYPTOPP_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0);  // T1 is unsigned type
00197         CRYPTOPP_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1);  // T2 is unsigned type
00198         return T1((a > b) ? (a - b) : 0);
00199 }
00200 
00201 template <class T>
00202 inline CipherDir GetCipherDir(const T &obj)
00203 {
00204         return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
00205 }
00206 
00207 // ************** rotate functions ***************
00208 
00209 template <class T> inline T rotlFixed(T x, unsigned int y)
00210 {
00211         assert(y < sizeof(T)*8);
00212         return (x<<y) | (x>>(sizeof(T)*8-y));
00213 }
00214 
00215 template <class T> inline T rotrFixed(T x, unsigned int y)
00216 {
00217         assert(y < sizeof(T)*8);
00218         return (x>>y) | (x<<(sizeof(T)*8-y));
00219 }
00220 
00221 template <class T> inline T rotlVariable(T x, unsigned int y)
00222 {
00223         assert(y < sizeof(T)*8);
00224         return (x<<y) | (x>>(sizeof(T)*8-y));
00225 }
00226 
00227 template <class T> inline T rotrVariable(T x, unsigned int y)
00228 {
00229         assert(y < sizeof(T)*8);
00230         return (x>>y) | (x<<(sizeof(T)*8-y));
00231 }
00232 
00233 template <class T> inline T rotlMod(T x, unsigned int y)
00234 {
00235         y %= sizeof(T)*8;
00236         return (x<<y) | (x>>(sizeof(T)*8-y));
00237 }
00238 
00239 template <class T> inline T rotrMod(T x, unsigned int y)
00240 {
00241         y %= sizeof(T)*8;
00242         return (x>>y) | (x<<(sizeof(T)*8-y));
00243 }
00244 
00245 #ifdef INTEL_INTRINSICS
00246 
00247 #pragma intrinsic(_lrotl, _lrotr)
00248 
00249 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
00250 {
00251         assert(y < 32);
00252         return y ? _lrotl(x, y) : x;
00253 }
00254 
00255 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
00256 {
00257         assert(y < 32);
00258         return y ? _lrotr(x, y) : x;
00259 }
00260 
00261 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
00262 {
00263         assert(y < 32);
00264         return _lrotl(x, y);
00265 }
00266 
00267 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
00268 {
00269         assert(y < 32);
00270         return _lrotr(x, y);
00271 }
00272 
00273 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
00274 {
00275         return _lrotl(x, y);
00276 }
00277 
00278 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
00279 {
00280         return _lrotr(x, y);
00281 }
00282 
00283 #endif // #ifdef INTEL_INTRINSICS
00284 
00285 #ifdef PPC_INTRINSICS
00286 
00287 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
00288 {
00289         assert(y < 32);
00290         return y ? __rlwinm(x,y,0,31) : x;
00291 }
00292 
00293 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
00294 {
00295         assert(y < 32);
00296         return y ? __rlwinm(x,32-y,0,31) : x;
00297 }
00298 
00299 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
00300 {
00301         assert(y < 32);
00302         return (__rlwnm(x,y,0,31));
00303 }
00304 
00305 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
00306 {
00307         assert(y < 32);
00308         return (__rlwnm(x,32-y,0,31));
00309 }
00310 
00311 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
00312 {
00313         return (__rlwnm(x,y,0,31));
00314 }
00315 
00316 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
00317 {
00318         return (__rlwnm(x,32-y,0,31));
00319 }
00320 
00321 #endif // #ifdef PPC_INTRINSICS
00322 
00323 // ************** endian reversal ***************
00324 
00325 template <class T>
00326 inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
00327 {
00328         if (order == LITTLE_ENDIAN_ORDER)
00329                 return GETBYTE(value, index);
00330         else
00331                 return GETBYTE(value, sizeof(T)-index-1);
00332 }
00333 
00334 inline byte ByteReverse(byte value)
00335 {
00336         return value;
00337 }
00338 
00339 inline word16 ByteReverse(word16 value)
00340 {
00341         return rotlFixed(value, 8U);
00342 }
00343 
00344 inline word32 ByteReverse(word32 value)
00345 {
00346 #ifdef PPC_INTRINSICS
00347         // PPC: load reverse indexed instruction
00348         return (word32)__lwbrx(&value,0);
00349 #elif defined(FAST_ROTATE)
00350         // 5 instructions with rotate instruction, 9 without
00351         return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
00352 #else
00353         // 6 instructions with rotate instruction, 8 without
00354         value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
00355         return rotlFixed(value, 16U);
00356 #endif
00357 }
00358 
00359 #ifdef WORD64_AVAILABLE
00360 inline word64 ByteReverse(word64 value)
00361 {
00362 #ifdef SLOW_WORD64
00363         return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
00364 #else
00365         value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
00366         value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
00367         return rotlFixed(value, 32U);
00368 #endif
00369 }
00370 #endif
00371 
00372 inline byte BitReverse(byte value)
00373 {
00374         value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
00375         value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
00376         return rotlFixed(value, 4);
00377 }
00378 
00379 inline word16 BitReverse(word16 value)
00380 {
00381         value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
00382         value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
00383         value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
00384         return ByteReverse(value);
00385 }
00386 
00387 inline word32 BitReverse(word32 value)
00388 {
00389         value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
00390         value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
00391         value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
00392         return ByteReverse(value);
00393 }
00394 
00395 #ifdef WORD64_AVAILABLE
00396 inline word64 BitReverse(word64 value)
00397 {
00398 #ifdef SLOW_WORD64
00399         return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
00400 #else
00401         value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
00402         value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
00403         value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
00404         return ByteReverse(value);
00405 #endif
00406 }
00407 #endif
00408 
00409 template <class T>
00410 inline T BitReverse(T value)
00411 {
00412         if (sizeof(T) == 1)
00413                 return (T)BitReverse((byte)value);
00414         else if (sizeof(T) == 2)
00415                 return (T)BitReverse((word16)value);
00416         else if (sizeof(T) == 4)
00417                 return (T)BitReverse((word32)value);
00418         else
00419         {
00420 #ifdef WORD64_AVAILABLE
00421                 assert(sizeof(T) == 8);
00422                 return (T)BitReverse((word64)value);
00423 #else
00424                 assert(false);
00425                 return 0;
00426 #endif
00427         }
00428 }
00429 
00430 template <class T>
00431 inline T ConditionalByteReverse(ByteOrder order, T value)
00432 {
00433         return NativeByteOrderIs(order) ? value : ByteReverse(value);
00434 }
00435 
00436 template <class T>
00437 void ByteReverse(T *out, const T *in, unsigned int byteCount)
00438 {
00439         assert(byteCount % sizeof(T) == 0);
00440         unsigned int count = byteCount/sizeof(T);
00441         for (unsigned int i=0; i<count; i++)
00442                 out[i] = ByteReverse(in[i]);
00443 }
00444 
00445 template <class T>
00446 inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, unsigned int byteCount)
00447 {
00448         if (!NativeByteOrderIs(order))
00449                 ByteReverse(out, in, byteCount);
00450         else if (in != out)
00451                 memcpy(out, in, byteCount);
00452 }
00453 
00454 template <class T>
00455 inline void GetUserKey(ByteOrder order, T *out, unsigned int outlen, const byte *in, unsigned int inlen)
00456 {
00457         const unsigned int U = sizeof(T);
00458         assert(inlen <= outlen*U);
00459         memcpy(out, in, inlen);
00460         memset((byte *)out+inlen, 0, outlen*U-inlen);
00461         ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
00462 }
00463 
00464 inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, byte*)
00465 {
00466         return block[0];
00467 }
00468 
00469 inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word16*)
00470 {
00471         return (order == BIG_ENDIAN_ORDER)
00472                 ? block[1] | (block[0] << 8)
00473                 : block[0] | (block[1] << 8);
00474 }
00475 
00476 inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word32*)
00477 {
00478         return (order == BIG_ENDIAN_ORDER)
00479                 ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
00480                 : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
00481 }
00482 
00483 template <class T>
00484 inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL)
00485 {
00486         return UnalignedGetWordNonTemplate(order, block, dummy);
00487 }
00488 
00489 inline void UnalignedPutWord(ByteOrder order, byte *block, byte value, const byte *xorBlock = NULL)
00490 {
00491         block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
00492 }
00493 
00494 inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, const byte *xorBlock = NULL)
00495 {
00496         if (order == BIG_ENDIAN_ORDER)
00497         {
00498                 block[0] = GETBYTE(value, 1);
00499                 block[1] = GETBYTE(value, 0);
00500         }
00501         else
00502         {
00503                 block[0] = GETBYTE(value, 0);
00504                 block[1] = GETBYTE(value, 1);
00505         }
00506 
00507         if (xorBlock)
00508         {
00509                 block[0] ^= xorBlock[0];
00510                 block[1] ^= xorBlock[1];
00511         }
00512 }
00513 
00514 inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const byte *xorBlock = NULL)
00515 {
00516         if (order == BIG_ENDIAN_ORDER)
00517         {
00518                 block[0] = GETBYTE(value, 3);
00519                 block[1] = GETBYTE(value, 2);
00520                 block[2] = GETBYTE(value, 1);
00521                 block[3] = GETBYTE(value, 0);
00522         }
00523         else
00524         {
00525                 block[0] = GETBYTE(value, 0);
00526                 block[1] = GETBYTE(value, 1);
00527                 block[2] = GETBYTE(value, 2);
00528                 block[3] = GETBYTE(value, 3);
00529         }
00530 
00531         if (xorBlock)
00532         {
00533                 block[0] ^= xorBlock[0];
00534                 block[1] ^= xorBlock[1];
00535                 block[2] ^= xorBlock[2];
00536                 block[3] ^= xorBlock[3];
00537         }
00538 }
00539 
00540 template <class T>
00541 inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
00542 {
00543         if (assumeAligned)
00544         {
00545                 assert(IsAligned<T>(block));
00546                 return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
00547         }
00548         else
00549                 return UnalignedGetWord<T>(order, block);
00550 }
00551 
00552 template <class T>
00553 inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
00554 {
00555         result = GetWord<T>(assumeAligned, order, block);
00556 }
00557 
00558 template <class T>
00559 inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
00560 {
00561         if (assumeAligned)
00562         {
00563                 assert(IsAligned<T>(block));
00564                 if (xorBlock)
00565                         *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ *reinterpret_cast<const T *>(xorBlock);
00566                 else
00567                         *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value);
00568         }
00569         else
00570                 UnalignedPutWord(order, block, value, xorBlock);
00571 }
00572 
00573 template <class T, class B, bool A=true>
00574 class GetBlock
00575 {
00576 public:
00577         GetBlock(const void *block)
00578                 : m_block((const byte *)block) {}
00579 
00580         template <class U>
00581         inline GetBlock<T, B, A> & operator()(U &x)
00582         {
00583                 CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
00584                 x = GetWord<T>(A, B::ToEnum(), m_block);
00585                 m_block += sizeof(T);
00586                 return *this;
00587         }
00588 
00589 private:
00590         const byte *m_block;
00591 };
00592 
00593 template <class T, class B, bool A=true>
00594 class PutBlock
00595 {
00596 public:
00597         PutBlock(const void *xorBlock, void *block)
00598                 : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
00599 
00600         template <class U>
00601         inline PutBlock<T, B, A> & operator()(U x)
00602         {
00603                 PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
00604                 m_block += sizeof(T);
00605                 if (m_xorBlock)
00606                         m_xorBlock += sizeof(T);
00607                 return *this;
00608         }
00609 
00610 private:
00611         const byte *m_xorBlock;
00612         byte *m_block;
00613 };
00614 
00615 template <class T, class B, bool A=true>
00616 struct BlockGetAndPut
00617 {
00618         // function needed because of C++ grammatical ambiguity between expression-statements and declarations
00619         static inline GetBlock<T, B, A> Get(const void *block) {return GetBlock<T, B, A>(block);}
00620         typedef PutBlock<T, B, A> Put;
00621 };
00622 
00623 template <class T>
00624 std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
00625 {
00626         if (!NativeByteOrderIs(order))
00627                 value = ByteReverse(value);
00628 
00629         return std::string((char *)&value, sizeof(value));
00630 }
00631 
00632 template <class T>
00633 T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
00634 {
00635         T value = 0;
00636         memcpy(&value, str.data(), STDMIN(sizeof(value), str.size()));
00637         return NativeByteOrderIs(order) ? value : ByteReverse(value);
00638 }
00639 
00640 // ************** help remove warning on g++ ***************
00641 
00642 template <bool overflow> struct SafeShifter;
00643 
00644 template<> struct SafeShifter<true>
00645 {
00646         template <class T>
00647         static inline T RightShift(T value, unsigned int bits)
00648         {
00649                 return 0;
00650         }
00651 
00652         template <class T>
00653         static inline T LeftShift(T value, unsigned int bits)
00654         {
00655                 return 0;
00656         }
00657 };
00658 
00659 template<> struct SafeShifter<false>
00660 {
00661         template <class T>
00662         static inline T RightShift(T value, unsigned int bits)
00663         {
00664                 return value >> bits;
00665         }
00666 
00667         template <class T>
00668         static inline T LeftShift(T value, unsigned int bits)
00669         {
00670                 return value << bits;
00671         }
00672 };
00673 
00674 template <unsigned int bits, class T>
00675 inline T SafeRightShift(T value)
00676 {
00677         return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
00678 }
00679 
00680 template <unsigned int bits, class T>
00681 inline T SafeLeftShift(T value)
00682 {
00683         return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
00684 }
00685 
00686 NAMESPACE_END
00687 
00688 #endif // MISC_H

Generated on Sun Mar 14 20:44:27 2004 for Crypto++ by doxygen 1.3.6-20040222