monotone

monotone Mtn Source Tree

Root/cryptopp/misc.h

1#ifndef CRYPTOPP_MISC_H
2#define CRYPTOPP_MISC_H
3
4#include "config.h"
5#include "cryptlib.h"
6#include <assert.h>
7#include <string.h>// CodeWarrior doesn't have memory.h
8#include <algorithm>
9#include <string>
10
11#ifdef INTEL_INTRINSICS
12#include <stdlib.h>
13#endif
14
15NAMESPACE_BEGIN(CryptoPP)
16
17// ************** compile-time assertion ***************
18
19template <bool b>
20struct CompileAssert
21{
22static char dummy[2*b-1];
23};
24
25#ifdef __GNUC__
26#define UNUSED __attribute__((__unused__))
27#else
28#define UNUSED
29#endif
30
31#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
32#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) \
33 UNUSED static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
34#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
35#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
36
37// ************** misc classes ***************
38
39class Empty
40{
41};
42
43template <class BASE1, class BASE2>
44class TwoBases : public BASE1, public BASE2
45{
46};
47
48template <class BASE1, class BASE2, class BASE3>
49class ThreeBases : public BASE1, public BASE2, public BASE3
50{
51};
52
53template <class T>
54class ObjectHolder
55{
56protected:
57T m_object;
58};
59
60class NotCopyable
61{
62public:
63NotCopyable() {}
64private:
65 NotCopyable(const NotCopyable &);
66 void operator=(const NotCopyable &);
67};
68
69// ************** misc functions ***************
70
71// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
72template <class _Tp> inline const _Tp& STDMIN(const _Tp& __a, const _Tp& __b)
73{
74return __b < __a ? __b : __a;
75}
76
77template <class _Tp> inline const _Tp& STDMAX(const _Tp& __a, const _Tp& __b)
78{
79return __a < __b ? __b : __a;
80}
81
82#define RETURN_IF_NONZERO(x) unsigned int returnedValue = x; if (returnedValue) return returnedValue
83
84// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack
85#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
86// these may be faster on other CPUs/compilers
87// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
88// #define GETBYTE(x, y) (((byte *)&(x))[y])
89
90unsigned int Parity(unsigned long);
91unsigned int BytePrecision(unsigned long);
92unsigned int BitPrecision(unsigned long);
93unsigned long Crop(unsigned long, unsigned int size);
94
95inline unsigned int BitsToBytes(unsigned int bitCount)
96{
97return ((bitCount+7)/(8));
98}
99
100inline unsigned int BytesToWords(unsigned int byteCount)
101{
102return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
103}
104
105inline unsigned int BitsToWords(unsigned int bitCount)
106{
107return ((bitCount+WORD_BITS-1)/(WORD_BITS));
108}
109
110void xorbuf(byte *buf, const byte *mask, unsigned int count);
111void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count);
112
113template <class T>
114inline bool IsPowerOf2(T n)
115{
116return n > 0 && (n & (n-1)) == 0;
117}
118
119template <class T1, class T2>
120inline T2 ModPowerOf2(T1 a, T2 b)
121{
122assert(IsPowerOf2(b));
123return T2(a) & (b-1);
124}
125
126template <class T>
127inline T RoundDownToMultipleOf(T n, T m)
128{
129return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
130}
131
132template <class T>
133inline T RoundUpToMultipleOf(T n, T m)
134{
135return RoundDownToMultipleOf(n+m-1, m);
136}
137
138template <class T>
139inline unsigned int GetAlignment(T *dummy=NULL)// VC60 workaround
140{
141#if (_MSC_VER >= 1300)
142return __alignof(T);
143#elif defined(__GNUC__)
144return __alignof__(T);
145#else
146return sizeof(T);
147#endif
148}
149
150inline bool IsAlignedOn(const void *p, unsigned int alignment)
151{
152return IsPowerOf2(alignment) ? ModPowerOf2((unsigned int)p, alignment) == 0 : (unsigned int)p % alignment == 0;
153}
154
155template <class T>
156inline bool IsAligned(const void *p, T *dummy=NULL)// VC60 workaround
157{
158return IsAlignedOn(p, GetAlignment<T>());
159}
160
161#ifdef IS_LITTLE_ENDIAN
162typedef LittleEndian NativeByteOrder;
163#else
164typedef BigEndian NativeByteOrder;
165#endif
166
167inline ByteOrder GetNativeByteOrder()
168{
169return NativeByteOrder::ToEnum();
170}
171
172inline bool NativeByteOrderIs(ByteOrder order)
173{
174return order == GetNativeByteOrder();
175}
176
177template <class T>// can't use <sstream> because GCC 2.95.2 doesn't have it
178std::string IntToString(T a, unsigned int base = 10)
179{
180if (a == 0)
181return "0";
182bool negate = false;
183if (a < 0)
184{
185negate = true;
186a = 0-a;// VC .NET does not like -a
187}
188std::string result;
189while (a > 0)
190{
191T digit = a % base;
192result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
193a /= base;
194}
195if (negate)
196result = "-" + result;
197return result;
198}
199
200template <class T1, class T2>
201inline T1 SaturatingSubtract(T1 a, T2 b)
202{
203CRYPTOPP_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0);// T1 is unsigned type
204CRYPTOPP_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1);// T2 is unsigned type
205return T1((a > b) ? (a - b) : 0);
206}
207
208template <class T>
209inline CipherDir GetCipherDir(const T &obj)
210{
211return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
212}
213
214// ************** rotate functions ***************
215
216template <class T> inline T rotlFixed(T x, unsigned int y)
217{
218assert(y < sizeof(T)*8);
219return (x<<y) | (x>>(sizeof(T)*8-y));
220}
221
222template <class T> inline T rotrFixed(T x, unsigned int y)
223{
224assert(y < sizeof(T)*8);
225return (x>>y) | (x<<(sizeof(T)*8-y));
226}
227
228template <class T> inline T rotlVariable(T x, unsigned int y)
229{
230assert(y < sizeof(T)*8);
231return (x<<y) | (x>>(sizeof(T)*8-y));
232}
233
234template <class T> inline T rotrVariable(T x, unsigned int y)
235{
236assert(y < sizeof(T)*8);
237return (x>>y) | (x<<(sizeof(T)*8-y));
238}
239
240template <class T> inline T rotlMod(T x, unsigned int y)
241{
242y %= sizeof(T)*8;
243return (x<<y) | (x>>(sizeof(T)*8-y));
244}
245
246template <class T> inline T rotrMod(T x, unsigned int y)
247{
248y %= sizeof(T)*8;
249return (x>>y) | (x<<(sizeof(T)*8-y));
250}
251
252#ifdef INTEL_INTRINSICS
253
254#pragma intrinsic(_lrotl, _lrotr)
255
256template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
257{
258assert(y < 32);
259return y ? _lrotl(x, y) : x;
260}
261
262template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
263{
264assert(y < 32);
265return y ? _lrotr(x, y) : x;
266}
267
268template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
269{
270assert(y < 32);
271return _lrotl(x, y);
272}
273
274template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
275{
276assert(y < 32);
277return _lrotr(x, y);
278}
279
280template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
281{
282return _lrotl(x, y);
283}
284
285template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
286{
287return _lrotr(x, y);
288}
289
290#endif // #ifdef INTEL_INTRINSICS
291
292#ifdef PPC_INTRINSICS
293
294template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
295{
296assert(y < 32);
297return y ? __rlwinm(x,y,0,31) : x;
298}
299
300template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
301{
302assert(y < 32);
303return y ? __rlwinm(x,32-y,0,31) : x;
304}
305
306template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
307{
308assert(y < 32);
309return (__rlwnm(x,y,0,31));
310}
311
312template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
313{
314assert(y < 32);
315return (__rlwnm(x,32-y,0,31));
316}
317
318template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
319{
320return (__rlwnm(x,y,0,31));
321}
322
323template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
324{
325return (__rlwnm(x,32-y,0,31));
326}
327
328#endif // #ifdef PPC_INTRINSICS
329
330// ************** endian reversal ***************
331
332template <class T>
333inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
334{
335if (order == LITTLE_ENDIAN_ORDER)
336return GETBYTE(value, index);
337else
338return GETBYTE(value, sizeof(T)-index-1);
339}
340
341inline byte ByteReverse(byte value)
342{
343return value;
344}
345
346inline word16 ByteReverse(word16 value)
347{
348return rotlFixed(value, 8U);
349}
350
351inline word32 ByteReverse(word32 value)
352{
353#ifdef PPC_INTRINSICS
354// PPC: load reverse indexed instruction
355return (word32)__lwbrx(&value,0);
356#elif defined(FAST_ROTATE)
357// 5 instructions with rotate instruction, 9 without
358return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
359#else
360// 6 instructions with rotate instruction, 8 without
361value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
362return rotlFixed(value, 16U);
363#endif
364}
365
366#ifdef WORD64_AVAILABLE
367inline word64 ByteReverse(word64 value)
368{
369#ifdef SLOW_WORD64
370return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
371#else
372value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
373value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
374return rotlFixed(value, 32U);
375#endif
376}
377#endif
378
379inline byte BitReverse(byte value)
380{
381value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
382value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
383return rotlFixed(value, 4);
384}
385
386inline word16 BitReverse(word16 value)
387{
388value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
389value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
390value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
391return ByteReverse(value);
392}
393
394inline word32 BitReverse(word32 value)
395{
396value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
397value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
398value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
399return ByteReverse(value);
400}
401
402#ifdef WORD64_AVAILABLE
403inline word64 BitReverse(word64 value)
404{
405#ifdef SLOW_WORD64
406return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
407#else
408value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
409value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
410value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
411return ByteReverse(value);
412#endif
413}
414#endif
415
416template <class T>
417inline T BitReverse(T value)
418{
419if (sizeof(T) == 1)
420return (T)BitReverse((byte)value);
421else if (sizeof(T) == 2)
422return (T)BitReverse((word16)value);
423else if (sizeof(T) == 4)
424return (T)BitReverse((word32)value);
425else
426{
427#ifdef WORD64_AVAILABLE
428assert(sizeof(T) == 8);
429return (T)BitReverse((word64)value);
430#else
431assert(false);
432return 0;
433#endif
434}
435}
436
437template <class T>
438inline T ConditionalByteReverse(ByteOrder order, T value)
439{
440return NativeByteOrderIs(order) ? value : ByteReverse(value);
441}
442
443template <class T>
444void ByteReverse(T *out, const T *in, unsigned int byteCount)
445{
446assert(byteCount % sizeof(T) == 0);
447unsigned int count = byteCount/sizeof(T);
448for (unsigned int i=0; i<count; i++)
449out[i] = ByteReverse(in[i]);
450}
451
452template <class T>
453inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, unsigned int byteCount)
454{
455if (!NativeByteOrderIs(order))
456ByteReverse(out, in, byteCount);
457else if (in != out)
458memcpy(out, in, byteCount);
459}
460
461template <class T>
462inline void GetUserKey(ByteOrder order, T *out, unsigned int outlen, const byte *in, unsigned int inlen)
463{
464const unsigned int U = sizeof(T);
465assert(inlen <= outlen*U);
466memcpy(out, in, inlen);
467memset((byte *)out+inlen, 0, outlen*U-inlen);
468ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
469}
470
471inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, byte*)
472{
473return block[0];
474}
475
476inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word16*)
477{
478return (order == BIG_ENDIAN_ORDER)
479? block[1] | (block[0] << 8)
480: block[0] | (block[1] << 8);
481}
482
483inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word32*)
484{
485return (order == BIG_ENDIAN_ORDER)
486? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
487: word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
488}
489
490template <class T>
491inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL)
492{
493return UnalignedGetWordNonTemplate(order, block, dummy);
494}
495
496inline void UnalignedPutWord(ByteOrder order, byte *block, byte value, const byte *xorBlock = NULL)
497{
498block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
499}
500
501inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, const byte *xorBlock = NULL)
502{
503if (order == BIG_ENDIAN_ORDER)
504{
505block[0] = GETBYTE(value, 1);
506block[1] = GETBYTE(value, 0);
507}
508else
509{
510block[0] = GETBYTE(value, 0);
511block[1] = GETBYTE(value, 1);
512}
513
514if (xorBlock)
515{
516block[0] ^= xorBlock[0];
517block[1] ^= xorBlock[1];
518}
519}
520
521inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const byte *xorBlock = NULL)
522{
523if (order == BIG_ENDIAN_ORDER)
524{
525block[0] = GETBYTE(value, 3);
526block[1] = GETBYTE(value, 2);
527block[2] = GETBYTE(value, 1);
528block[3] = GETBYTE(value, 0);
529}
530else
531{
532block[0] = GETBYTE(value, 0);
533block[1] = GETBYTE(value, 1);
534block[2] = GETBYTE(value, 2);
535block[3] = GETBYTE(value, 3);
536}
537
538if (xorBlock)
539{
540block[0] ^= xorBlock[0];
541block[1] ^= xorBlock[1];
542block[2] ^= xorBlock[2];
543block[3] ^= xorBlock[3];
544}
545}
546
547template <class T>
548inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
549{
550if (assumeAligned)
551{
552assert(IsAligned<T>(block));
553return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
554}
555else
556return UnalignedGetWord<T>(order, block);
557}
558
559template <class T>
560inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
561{
562result = GetWord<T>(assumeAligned, order, block);
563}
564
565template <class T>
566inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
567{
568if (assumeAligned)
569{
570assert(IsAligned<T>(block));
571if (xorBlock)
572*reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ *reinterpret_cast<const T *>(xorBlock);
573else
574*reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value);
575}
576else
577UnalignedPutWord(order, block, value, xorBlock);
578}
579
580template <class T, class B, bool A=true>
581class GetBlock
582{
583public:
584GetBlock(const void *block)
585: m_block((const byte *)block) {}
586
587template <class U>
588inline GetBlock<T, B, A> & operator()(U &x)
589{
590CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
591x = GetWord<T>(A, B::ToEnum(), m_block);
592m_block += sizeof(T);
593return *this;
594}
595
596private:
597const byte *m_block;
598};
599
600template <class T, class B, bool A=true>
601class PutBlock
602{
603public:
604PutBlock(const void *xorBlock, void *block)
605: m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
606
607template <class U>
608inline PutBlock<T, B, A> & operator()(U x)
609{
610PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
611m_block += sizeof(T);
612if (m_xorBlock)
613m_xorBlock += sizeof(T);
614return *this;
615}
616
617private:
618const byte *m_xorBlock;
619byte *m_block;
620};
621
622template <class T, class B, bool A=true>
623struct BlockGetAndPut
624{
625// function needed because of C++ grammatical ambiguity between expression-statements and declarations
626static inline GetBlock<T, B, A> Get(const void *block) {return GetBlock<T, B, A>(block);}
627typedef PutBlock<T, B, A> Put;
628};
629
630template <class T>
631std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
632{
633if (!NativeByteOrderIs(order))
634value = ByteReverse(value);
635
636return std::string((char *)&value, sizeof(value));
637}
638
639template <class T>
640T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
641{
642T value = 0;
643memcpy(&value, str.data(), STDMIN(sizeof(value), str.size()));
644return NativeByteOrderIs(order) ? value : ByteReverse(value);
645}
646
647// ************** help remove warning on g++ ***************
648
649template <bool overflow> struct SafeShifter;
650
651template<> struct SafeShifter<true>
652{
653template <class T>
654static inline T RightShift(T value, unsigned int bits)
655{
656return 0;
657}
658
659template <class T>
660static inline T LeftShift(T value, unsigned int bits)
661{
662return 0;
663}
664};
665
666template<> struct SafeShifter<false>
667{
668template <class T>
669static inline T RightShift(T value, unsigned int bits)
670{
671return value >> bits;
672}
673
674template <class T>
675static inline T LeftShift(T value, unsigned int bits)
676{
677return value << bits;
678}
679};
680
681template <unsigned int bits, class T>
682inline T SafeRightShift(T value)
683{
684return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
685}
686
687template <unsigned int bits, class T>
688inline T SafeLeftShift(T value)
689{
690return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
691}
692
693NAMESPACE_END
694
695#endif // MISC_H

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status