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 "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) static 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 CRYPTOPP_API Parity(unsigned long);
    00139 CRYPTOPP_DLL unsigned int CRYPTOPP_API BytePrecision(unsigned long);
    00140 CRYPTOPP_DLL unsigned int CRYPTOPP_API BitPrecision(unsigned long);
    00141 CRYPTOPP_DLL unsigned long CRYPTOPP_API 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 CRYPTOPP_API xorbuf(byte *buf, const byte *mask, unsigned int count);
    00164 CRYPTOPP_DLL void CRYPTOPP_API 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>
    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 inline void IncrementCounterByOne(byte *inout, unsigned int s)
    00270 {
    00271         for (int i=s-1, carry=1; i>=0 && carry; i--)
    00272                 carry = !++inout[i];
    00273 }
    00274
    00275 inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
    00276 {
    00277         int i, carry;
    00278         for (i=s-1, carry=1; i>=0 && carry; i--)
    00279                 carry = !(output[i] = input[i]+1);
    00280         memcpy(output, input, i+1);
    00281 }
    00282
    00283 // ************** rotate functions ***************
    00284
    00285 template <class T> inline T rotlFixed(T x, unsigned int y)
    00286 {
    00287         assert(y < sizeof(T)*8);
    00288         return (x<<y) | (x>>(sizeof(T)*8-y));
    00289 }
    00290
    00291 template <class T> inline T rotrFixed(T x, unsigned int y)
    00292 {
    00293         assert(y < sizeof(T)*8);
    00294         return (x>>y) | (x<<(sizeof(T)*8-y));
    00295 }
    00296
    00297 template <class T> inline T rotlVariable(T x, unsigned int y)
    00298 {
    00299         assert(y < sizeof(T)*8);
    00300         return (x<<y) | (x>>(sizeof(T)*8-y));
    00301 }
    00302
    00303 template <class T> inline T rotrVariable(T x, unsigned int y)
    00304 {
    00305         assert(y < sizeof(T)*8);
    00306         return (x>>y) | (x<<(sizeof(T)*8-y));
    00307 }
    00308
    00309 template <class T> inline T rotlMod(T x, unsigned int y)
    00310 {
    00311         y %= sizeof(T)*8;
    00312         return (x<<y) | (x>>(sizeof(T)*8-y));
    00313 }
    00314
    00315 template <class T> inline T rotrMod(T x, unsigned int y)
    00316 {
    00317         y %= sizeof(T)*8;
    00318         return (x>>y) | (x<<(sizeof(T)*8-y));
    00319 }
    00320
    00321 #ifdef INTEL_INTRINSICS
    00322
    00323 #pragma intrinsic(_lrotl, _lrotr)
    00324
    00325 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
    00326 {
    00327         assert(y < 32);
    00328         return y ? _lrotl(x, y) : x;
    00329 }
    00330
    00331 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
    00332 {
    00333         assert(y < 32);
    00334         return y ? _lrotr(x, y) : x;
    00335 }
    00336
    00337 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
    00338 {
    00339         assert(y < 32);
    00340         return _lrotl(x, y);
    00341 }
    00342
    00343 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
    00344 {
    00345         assert(y < 32);
    00346         return _lrotr(x, y);
    00347 }
    00348
    00349 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
    00350 {
    00351         return _lrotl(x, y);
    00352 }
    00353
    00354 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
    00355 {
    00356         return _lrotr(x, y);
    00357 }
    00358
    00359 #endif // #ifdef INTEL_INTRINSICS
    00360
    00361 #ifdef PPC_INTRINSICS
    00362
    00363 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
    00364 {
    00365         assert(y < 32);
    00366         return y ? __rlwinm(x,y,0,31) : x;
    00367 }
    00368
    00369 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
    00370 {
    00371         assert(y < 32);
    00372         return y ? __rlwinm(x,32-y,0,31) : x;
    00373 }
    00374
    00375 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
    00376 {
    00377         assert(y < 32);
    00378         return (__rlwnm(x,y,0,31));
    00379 }
    00380
    00381 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
    00382 {
    00383         assert(y < 32);
    00384         return (__rlwnm(x,32-y,0,31));
    00385 }
    00386
    00387 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
    00388 {
    00389         return (__rlwnm(x,y,0,31));
    00390 }
    00391
    00392 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
    00393 {
    00394         return (__rlwnm(x,32-y,0,31));
    00395 }
    00396
    00397 #endif // #ifdef PPC_INTRINSICS
    00398
    00399 // ************** endian reversal ***************
    00400
    00401 template <class T>
    00402 inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
    00403 {
    00404         if (order == LITTLE_ENDIAN_ORDER)
    00405                 return GETBYTE(value, index);
    00406         else
    00407                 return GETBYTE(value, sizeof(T)-index-1);
    00408 }
    00409
    00410 inline byte ByteReverse(byte value)
    00411 {
    00412         return value;
    00413 }
    00414
    00415 inline word16 ByteReverse(word16 value)
    00416 {
    00417         return rotlFixed(value, 8U);
    00418 }
    00419
    00420 inline word32 ByteReverse(word32 value)
    00421 {
    00422 #ifdef PPC_INTRINSICS
    00423         // PPC: load reverse indexed instruction
    00424         return (word32)__lwbrx(&value,0);
    00425 #elif defined(FAST_ROTATE)
    00426         // 5 instructions with rotate instruction, 9 without
    00427         return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
    00428 #else
    00429         // 6 instructions with rotate instruction, 8 without
    00430         value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
    00431         return rotlFixed(value, 16U);
    00432 #endif
    00433 }
    00434
    00435 #ifdef WORD64_AVAILABLE
    00436 inline word64 ByteReverse(word64 value)
    00437 {
    00438 #ifdef CRYPTOPP_SLOW_WORD64
    00439         return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
    00440 #else
    00441         value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
    00442         value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
    00443         return rotlFixed(value, 32U);
    00444 #endif
    00445 }
    00446 #endif
    00447
    00448 inline byte BitReverse(byte value)
    00449 {
    00450         value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
    00451         value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
    00452         return rotlFixed(value, 4);
    00453 }
    00454
    00455 inline word16 BitReverse(word16 value)
    00456 {
    00457         value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
    00458         value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
    00459         value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
    00460         return ByteReverse(value);
    00461 }
    00462
    00463 inline word32 BitReverse(word32 value)
    00464 {
    00465         value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
    00466         value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
    00467         value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
    00468         return ByteReverse(value);
    00469 }
    00470
    00471 #ifdef WORD64_AVAILABLE
    00472 inline word64 BitReverse(word64 value)
    00473 {
    00474 #ifdef CRYPTOPP_SLOW_WORD64
    00475         return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
    00476 #else
    00477         value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
    00478         value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
    00479         value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
    00480         return ByteReverse(value);
    00481 #endif
    00482 }
    00483 #endif
    00484
    00485 template <class T>
    00486 inline T BitReverse(T value)
    00487 {
    00488         if (sizeof(T) == 1)
    00489                 return (T)BitReverse((byte)value);
    00490         else if (sizeof(T) == 2)
    00491                 return (T)BitReverse((word16)value);
    00492         else if (sizeof(T) == 4)
    00493                 return (T)BitReverse((word32)value);
    00494         else
    00495         {
    00496 #ifdef WORD64_AVAILABLE
    00497                 assert(sizeof(T) == 8);
    00498                 return (T)BitReverse((word64)value);
    00499 #else
    00500                 assert(false);
    00501                 return 0;
    00502 #endif
    00503         }
    00504 }
    00505
    00506 template <class T>
    00507 inline T ConditionalByteReverse(ByteOrder order, T value)
    00508 {
    00509         return NativeByteOrderIs(order) ? value : ByteReverse(value);
    00510 }
    00511
    00512 template <class T>
    00513 void ByteReverse(T *out, const T *in, unsigned int byteCount)
    00514 {
    00515         assert(byteCount % sizeof(T) == 0);
    00516         unsigned int count = byteCount/sizeof(T);
    00517         for (unsigned int i=0; i<count; i++)
    00518                 out[i] = ByteReverse(in[i]);
    00519 }
    00520
    00521 template <class T>
    00522 inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, unsigned int byteCount)
    00523 {
    00524         if (!NativeByteOrderIs(order))
    00525                 ByteReverse(out, in, byteCount);
    00526         else if (in != out)
    00527                 memcpy(out, in, byteCount);
    00528 }
    00529
    00530 template <class T>
    00531 inline void GetUserKey(ByteOrder order, T *out, unsigned int outlen, const byte *in, unsigned int inlen)
    00532 {
    00533         const unsigned int U = sizeof(T);
    00534         assert(inlen <= outlen*U);
    00535         memcpy(out, in, inlen);
    00536         memset((byte *)out+inlen, 0, outlen*U-inlen);
    00537         ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
    00538 }
    00539
    00540 inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, byte*)
    00541 {
    00542         return block[0];
    00543 }
    00544
    00545 inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word16*)
    00546 {
    00547         return (order == BIG_ENDIAN_ORDER)
    00548                 ? block[1] | (block[0] << 8)
    00549                 : block[0] | (block[1] << 8);
    00550 }
    00551
    00552 inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word32*)
    00553 {
    00554         return (order == BIG_ENDIAN_ORDER)
    00555                 ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
    00556                 : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
    00557 }
    00558
    00559 #ifdef WORD64_AVAILABLE
    00560 inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word64*)
    00561 {
    00562         return (order == BIG_ENDIAN_ORDER)
    00563                 ?
    00564                 (word64(block[7]) |
    00565                 (word64(block[6]) <<  8) |
    00566                 (word64(block[5]) << 16) |
    00567                 (word64(block[4]) << 24) |
    00568                 (word64(block[3]) << 32) |
    00569                 (word64(block[2]) << 40) |
    00570                 (word64(block[1]) << 48) |
    00571                 (word64(block[0]) << 56))
    00572                 :
    00573                 (word64(block[0]) |
    00574                 (word64(block[1]) <<  8) |
    00575                 (word64(block[2]) << 16) |
    00576                 (word64(block[3]) << 24) |
    00577                 (word64(block[4]) << 32) |
    00578                 (word64(block[5]) << 40) |
    00579                 (word64(block[6]) << 48) |
    00580                 (word64(block[7]) << 56));
    00581 }
    00582 #endif
    00583
    00584 template <class T>
    00585 inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL)
    00586 {
    00587         return UnalignedGetWordNonTemplate(order, block, dummy);
    00588 }
    00589
    00590 inline void UnalignedPutWord(ByteOrder order, byte *block, byte value, const byte *xorBlock = NULL)
    00591 {
    00592         block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
    00593 }
    00594
    00595 inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, const byte *xorBlock = NULL)
    00596 {
    00597         if (order == BIG_ENDIAN_ORDER)
    00598         {
    00599                 block[0] = GETBYTE(value, 1);
    00600                 block[1] = GETBYTE(value, 0);
    00601         }
    00602         else
    00603         {
    00604                 block[0] = GETBYTE(value, 0);
    00605                 block[1] = GETBYTE(value, 1);
    00606         }
    00607
    00608         if (xorBlock)
    00609         {
    00610                 block[0] ^= xorBlock[0];
    00611                 block[1] ^= xorBlock[1];
    00612         }
    00613 }
    00614
    00615 inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const byte *xorBlock = NULL)
    00616 {
    00617         if (order == BIG_ENDIAN_ORDER)
    00618         {
    00619                 block[0] = GETBYTE(value, 3);
    00620                 block[1] = GETBYTE(value, 2);
    00621                 block[2] = GETBYTE(value, 1);
    00622                 block[3] = GETBYTE(value, 0);
    00623         }
    00624         else
    00625         {
    00626                 block[0] = GETBYTE(value, 0);
    00627                 block[1] = GETBYTE(value, 1);
    00628                 block[2] = GETBYTE(value, 2);
    00629                 block[3] = GETBYTE(value, 3);
    00630         }
    00631
    00632         if (xorBlock)
    00633         {
    00634                 block[0] ^= xorBlock[0];
    00635                 block[1] ^= xorBlock[1];
    00636                 block[2] ^= xorBlock[2];
    00637                 block[3] ^= xorBlock[3];
    00638         }
    00639 }
    00640
    00641 #ifdef WORD64_AVAILABLE
    00642 inline void UnalignedPutWord(ByteOrder order, byte *block, word64 value, const byte *xorBlock = NULL)
    00643 {
    00644         if (order == BIG_ENDIAN_ORDER)
    00645         {
    00646                 block[0] = GETBYTE(value, 7);
    00647                 block[1] = GETBYTE(value, 6);
    00648                 block[2] = GETBYTE(value, 5);
    00649                 block[3] = GETBYTE(value, 4);
    00650                 block[4] = GETBYTE(value, 3);
    00651                 block[5] = GETBYTE(value, 2);
    00652                 block[6] = GETBYTE(value, 1);
    00653                 block[7] = GETBYTE(value, 0);
    00654         }
    00655         else
    00656         {
    00657                 block[0] = GETBYTE(value, 0);
    00658                 block[1] = GETBYTE(value, 1);
    00659                 block[2] = GETBYTE(value, 2);
    00660                 block[3] = GETBYTE(value, 3);
    00661                 block[4] = GETBYTE(value, 4);
    00662                 block[5] = GETBYTE(value, 5);
    00663                 block[6] = GETBYTE(value, 6);
    00664                 block[7] = GETBYTE(value, 7);
    00665         }
    00666
    00667         if (xorBlock)
    00668         {
    00669                 block[0] ^= xorBlock[0];
    00670                 block[1] ^= xorBlock[1];
    00671                 block[2] ^= xorBlock[2];
    00672                 block[3] ^= xorBlock[3];
    00673                 block[4] ^= xorBlock[4];
    00674                 block[5] ^= xorBlock[5];
    00675                 block[6] ^= xorBlock[6];
    00676                 block[7] ^= xorBlock[7];
    00677         }
    00678 }
    00679 #endif
    00680
    00681 template <class T>
    00682 inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
    00683 {
    00684         if (assumeAligned)
    00685         {
    00686                 assert(IsAligned<T>(block));
    00687                 return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
    00688         }
    00689         else
    00690                 return UnalignedGetWord<T>(order, block);
    00691 }
    00692
    00693 template <class T>
    00694 inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
    00695 {
    00696         result = GetWord<T>(assumeAligned, order, block);
    00697 }
    00698
    00699 template <class T>
    00700 inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
    00701 {
    00702         if (assumeAligned)
    00703         {
    00704                 assert(IsAligned<T>(block));
    00705                 if (xorBlock)
    00706                         *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ *reinterpret_cast<const T *>(xorBlock);
    00707                 else
    00708                         *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value);
    00709         }
    00710         else
    00711                 UnalignedPutWord(order, block, value, xorBlock);
    00712 }
    00713
    00714 template <class T, class B, bool A=true>
    00715 class GetBlock
    00716 {
    00717 public:
    00718         GetBlock(const void *block)
    00719                 : m_block((const byte *)block) {}
    00720
    00721         template <class U>
    00722         inline GetBlock<T, B, A> & operator()(U &x)
    00723         {
    00724                 CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
    00725                 x = GetWord<T>(A, B::ToEnum(), m_block);
    00726                 m_block += sizeof(T);
    00727                 return *this;
    00728         }
    00729
    00730 private:
    00731         const byte *m_block;
    00732 };
    00733
    00734 template <class T, class B, bool A=true>
    00735 class PutBlock
    00736 {
    00737 public:
    00738         PutBlock(const void *xorBlock, void *block)
    00739                 : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
    00740
    00741         template <class U>
    00742         inline PutBlock<T, B, A> & operator()(U x)
    00743         {
    00744                 PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
    00745                 m_block += sizeof(T);
    00746                 if (m_xorBlock)
    00747                         m_xorBlock += sizeof(T);
    00748                 return *this;
    00749         }
    00750
    00751 private:
    00752         const byte *m_xorBlock;
    00753         byte *m_block;
    00754 };
    00755
    00756 template <class T, class B, bool A=true>
    00757 struct BlockGetAndPut
    00758 {
    00759         // function needed because of C++ grammatical ambiguity between expression-statements and declarations
    00760         static inline GetBlock<T, B, A> Get(const void *block) {return GetBlock<T, B, A>(block);}
    00761         typedef PutBlock<T, B, A> Put;
    00762 };
    00763
    00764 template <class T>
    00765 std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
    00766 {
    00767         if (!NativeByteOrderIs(order))
    00768                 value = ByteReverse(value);
    00769
    00770         return std::string((char *)&value, sizeof(value));
    00771 }
    00772
    00773 template <class T>
    00774 T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
    00775 {
    00776         T value = 0;
    00777         memcpy(&value, str.data(), STDMIN(sizeof(value), str.size()));
    00778         return NativeByteOrderIs(order) ? value : ByteReverse(value);
    00779 }
    00780
    00781 // ************** help remove warning on g++ ***************
    00782
    00783 template <bool overflow> struct SafeShifter;
    00784
    00785 template<> struct SafeShifter<true>
    00786 {
    00787         template <class T>
    00788         static inline T RightShift(T value, unsigned int bits)
    00789         {
    00790                 return 0;
    00791         }
    00792
    00793         template <class T>
    00794         static inline T LeftShift(T value, unsigned int bits)
    00795         {
    00796                 return 0;
    00797         }
    00798 };
    00799
    00800 template<> struct SafeShifter<false>
    00801 {
    00802         template <class T>
    00803         static inline T RightShift(T value, unsigned int bits)
    00804         {
    00805                 return value >> bits;
    00806         }
    00807
    00808         template <class T>
    00809         static inline T LeftShift(T value, unsigned int bits)
    00810         {
    00811                 return value << bits;
    00812         }
    00813 };
    00814
    00815 template <unsigned int bits, class T>
    00816 inline T SafeRightShift(T value)
    00817 {
    00818         return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
    00819 }
    00820
    00821 template <unsigned int bits, class T>
    00822 inline T SafeLeftShift(T value)
    00823 {
    00824         return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
    00825 }
    00826
    00827 NAMESPACE_END
    00828
    00829 #endif // MISC_H