misc.h

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

Generated on Thu Mar 30 22:11:44 2006 for Crypto++ by  doxygen 1.4.6