Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | 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 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