ReactOS 0.4.16-dev-853-g88d9285
safeint_internal.h
Go to the documentation of this file.
1/***
2*safeint_internal.h - Internal details for SafeInt (see safeint.h)
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* Private internal details for SafeInt.
8* The constructs and functions in Microsoft::Utilities::details are not
9* meant to be used by external code and can change at any time.
10*
11****/
12
13#pragma once
14
15#include <crtdbg.h>
16
17#pragma pack(push, _CRT_PACKING)
18
19namespace msl
20{
21
22namespace utilities
23{
24
25namespace details
26{
27#pragma warning(push)
28#pragma warning(disable:4702)
29
30template < typename T >
31class DependentFalse { public: enum{ value = false }; };
32
33template < typename T > class NumericType;
34
35template <> class NumericType<bool> { public: enum{ isBool = true, isFloat = false, isInt = false }; };
36template <> class NumericType<char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
37template <> class NumericType<unsigned char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
38template <> class NumericType<signed char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
39template <> class NumericType<short> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
40template <> class NumericType<unsigned short> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
41#ifdef _NATIVE_WCHAR_T_DEFINED
42template <> class NumericType<wchar_t> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
43#endif /* _NATIVE_WCHAR_T_DEFINED */
44template <> class NumericType<int> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
45template <> class NumericType<unsigned int> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
46template <> class NumericType<long> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
47template <> class NumericType<unsigned long> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
48template <> class NumericType<__int64> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
49template <> class NumericType<unsigned __int64> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
50template <> class NumericType<float> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
51template <> class NumericType<double> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
52template <> class NumericType<long double> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
53// Catch-all for anything not supported
54template < typename T > class NumericType { public: enum{ isBool = false, isFloat = false, isInt = false }; };
55
56
57template < typename T > class IntTraits
58{
59public:
60 static_assert( NumericType<T>::isInt || NumericType<T>::isBool, "non-integral type T" );
61 enum
62 {
63#pragma warning(suppress:4804)
64 isSigned = ( (T)(-1) < 0 ),
65 is64Bit = ( sizeof(T) == 8 ),
66 is32Bit = ( sizeof(T) == 4 ),
67 is16Bit = ( sizeof(T) == 2 ),
68 is8Bit = ( sizeof(T) == 1 ),
69 isLT32Bit = ( sizeof(T) < 4 ),
70 isLT64Bit = ( sizeof(T) < 8 ),
71 isInt8 = ( sizeof(T) == 1 && isSigned ),
72 isUint8 = ( sizeof(T) == 1 && !isSigned ),
73 isInt16 = ( sizeof(T) == 2 && isSigned ),
74 isUint16 = ( sizeof(T) == 2 && !isSigned ),
75 isInt32 = ( sizeof(T) == 4 && isSigned ),
76 isUint32 = ( sizeof(T) == 4 && !isSigned ),
77 isInt64 = ( sizeof(T) == 8 && isSigned ),
78 isUint64 = ( sizeof(T) == 8 && !isSigned ),
79 bitCount = ( sizeof(T)*8 ),
80#pragma warning(suppress:4804)
82 };
83
84#pragma warning(push)
85#pragma warning(disable:4310)
86#pragma warning(disable:4804) // suppress warning about '<<' being an unsafe operation when T is bool
87 const static T maxInt = isSigned ? ((T)~((T)1 << (T)(bitCount-1))) : ((T)(~(T)0));
88 const static T minInt = isSigned ? ((T)((T)1 << (T)(bitCount-1))) : ((T)0);
89#pragma warning(pop)
90};
91
92// this is strictly internal and not to be used as a policy in SafeInt<>
94{
95 static void SafeIntOnOverflow()
96 {
97 }
98
99 static void SafeIntOnDivZero()
100 {
101 }
102};
103
104template < typename T, typename U > class SafeIntCompare
105{
106public:
107 enum
108 {
111 isLikeSigned = (static_cast<bool>(IntTraits< T >::isSigned) == static_cast<bool>(IntTraits< U >::isSigned)),
112 isCastOK = ((isLikeSigned && sizeof(T) >= sizeof(U)) ||
113 (IntTraits< T >::isSigned && sizeof(T) > sizeof(U))),
116 };
117};
118
119template < typename U > class SafeIntCompare< float, U >
120{
121public:
122 enum
123 {
127 isCastOK = true
128 };
129};
130
131template < typename U > class SafeIntCompare< double, U >
132{
133public:
134 enum
135 {
139 isCastOK = true
140 };
141};
142
143template < typename U > class SafeIntCompare< long double, U >
144{
145public:
146 enum
147 {
151 isCastOK = true
152 };
153};
154
155//all of the arithmetic operators can be solved by the same code within
156//each of these regions without resorting to compile-time constant conditionals
157//most operators collapse the problem into less than the 22 zones, but this is used
158//as the first cut
159//using this also helps ensure that we handle all of the possible cases correctly
160
161template < typename T, typename U > class IntRegion
162{
163public:
164 enum
165 {
166 //unsigned-unsigned zone
172 //unsigned-signed
179 //signed-signed
186 //signed-unsigned
193 };
194};
195
196// useful function to help with getting the magnitude of a negative number
198{
203
204template < typename T >
206{
207public:
208 enum
209 {
212 };
213};
214
215template < typename T, int Method = GetAbsMethod< T >::method > class AbsValueHelper;
216
217template < typename T > class AbsValueHelper < T, AbsMethodInt >
218{
219public:
220 static unsigned __int32 Abs( T t ) throw()
221 {
222 _ASSERTE( t < 0 );
223 return (unsigned __int32)-t;
224 }
225};
226
227template < typename T > class AbsValueHelper < T, AbsMethodInt64 >
228{
229public:
230 static unsigned __int64 Abs( T t ) throw()
231 {
232 _ASSERTE( t < 0 );
233 return (unsigned __int64)-t;
234 }
235};
236
237template < typename T > class AbsValueHelper < T, AbsMethodNoop >
238{
239public:
240 static T Abs( T t ) throw()
241 {
242 // Why are you calling Abs on an unsigned number ???
243 _ASSERTE( ("AbsValueHelper::Abs should not be called with an unsigned integer type", 0) );
244 return t;
245 }
246};
247
248template < typename T, typename E, bool fSigned > class NegationHelper;
249
250template < typename T, typename E > class NegationHelper < T, E, true > // Signed
251{
252public:
254 {
255 // corner case
257 {
258 // cast prevents unneeded checks in the case of small ints
259 ret = -t;
260 return SafeIntNoError;
261 }
262 E::SafeIntOnOverflow();
264 }
265};
266
267
268template < typename T, typename E > class NegationHelper < T, E, false > // unsigned
269{
270public:
271 static SafeIntError Negative( T t, T& ret ) throw()
272 {
274
275#pragma warning(suppress:4127)
277
278#pragma warning(suppress:4146)
279 ret = -t;
280 return SafeIntNoError;
281 }
282};
283
284//core logic to determine casting behavior
286{
296
297template < typename ToType, typename FromType >
299{
300public:
301 enum
302 {
305
310
314
317 sizeof( FromType ) >= sizeof( ToType ) ) ||
319 sizeof( FromType ) > sizeof( ToType ) ) ) ? CastCheckGTMax :
320
323 sizeof( ToType ) >= sizeof( FromType ) ) ? CastCheckLTZero :
324
327 };
328};
329
330template < typename T, typename U, typename E,
332
333template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastOK >
334{
335public:
336 static SafeIntError Cast( U u, T& t ) throw()
337 {
338 t = (T)u;
339 return SafeIntNoError;
340 }
341};
342
343// special case floats and doubles
344// tolerate loss of precision
345template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastFromFloat >
346{
347public:
348 static SafeIntError Cast( U u, T& t )
349 {
350 if( u <= (U)IntTraits< T >::maxInt &&
352 {
353 t = (T)u;
354 return SafeIntNoError;
355 }
356
357 E::SafeIntOnOverflow();
359 }
360};
361
362// Match on any method where a bool is cast to type T
363template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastFromBool >
364{
365public:
366 static SafeIntError Cast( bool b, T& t ) throw()
367 {
368 t = (T)( b ? 1 : 0 );
369 return SafeIntNoError;
370 }
371};
372
373template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastToBool >
374{
375public:
376 static SafeIntError Cast( T t, bool& b ) throw()
377 {
378 b = !!t;
379 return SafeIntNoError;
380 }
381};
382
383template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckLTZero >
384{
385public:
386 static SafeIntError Cast( U u, T& t )
387 {
388 if( u < 0 )
389 {
390 E::SafeIntOnOverflow();
392 }
393
394 t = (T)u;
395 return SafeIntNoError;
396 }
397};
398
399template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckGTMax >
400{
401public:
402 static SafeIntError Cast( U u, T& t )
403 {
405 {
406 E::SafeIntOnOverflow();
408 }
409
410 t = (T)u;
411 return SafeIntNoError;
412 }
413};
414
415template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckMinMaxUnsigned >
416{
417public:
418 static SafeIntError Cast( U u, T& t )
419 {
420 // U is signed - T could be either signed or unsigned
421 if( u > IntTraits< T >::maxInt || u < 0 )
422 {
423 E::SafeIntOnOverflow();
425 }
426
427 t = (T)u;
428 return SafeIntNoError;
429 }
430};
431
432template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckMinMaxSigned >
433{
434public:
435 static SafeIntError Cast( U u, T& t )
436 {
437 // T, U are signed
439 {
440 E::SafeIntOnOverflow();
442 }
443
444 t = (T)u;
445 return SafeIntNoError;
446 }
447};
448
449//core logic to determine whether a comparison is valid, or needs special treatment
451{
458
459template < typename T, typename U >
461{
462public:
463 enum
464 {
465#if _SAFEINT_USE_ANSI_CONVERSIONS
467#else /* _SAFEINT_USE_ANSI_CONVERSIONS */
469 ( ( IntTraits< T >::isSigned && sizeof(T) < 8 && sizeof(U) < 4 ) ||
470 ( IntTraits< U >::isSigned && sizeof(T) < 4 && sizeof(U) < 8 ) ) ? ComparisonMethod_CastInt :
471 ( ( IntTraits< T >::isSigned && sizeof(U) < 8 ) ||
475#endif /* _SAFEINT_USE_ANSI_CONVERSIONS */
476 };
477};
478
479template <typename T, typename U, int Method = ValidComparison< T, U >::method > class EqualityTest;
480
481template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_Ok >
482{
483public:
484 static bool IsEquals( const T t, const U u ) throw() { return ( t == u ); }
485};
486
487template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_CastInt >
488{
489public:
490 static bool IsEquals( const T t, const U u ) throw() { return ( (int)t == (int)u ); }
491};
492
493template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_CastInt64 >
494{
495public:
496 static bool IsEquals( const T t, const U u ) throw() { return ( (__int64)t == (__int64)u ); }
497};
498
499template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_UnsignedT >
500{
501public:
502 static bool IsEquals( const T t, const U u ) throw()
503 {
504 //one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
505 if( u < 0 )
506 {
507 return false;
508 }
509
510 //else safe to cast to type T
511 return ( t == (T)u );
512 }
513};
514
515template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_UnsignedU>
516{
517public:
518 static bool IsEquals( const T t, const U u ) throw()
519 {
520 //one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
521 if( t < 0 )
522 {
523 return false;
524 }
525
526 //else safe to cast to type U
527 return ( (U)t == u );
528 }
529};
530
531template <typename T, typename U, int Method = ValidComparison< T, U >::method > class GreaterThanTest;
532
533template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_Ok >
534{
535public:
536 static bool GreaterThan( const T t, const U u ) throw() { return ( t > u ); }
537};
538
539template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_CastInt >
540{
541public:
542 static bool GreaterThan( const T t, const U u ) throw() { return ( (int)t > (int)u ); }
543};
544
545template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_CastInt64 >
546{
547public:
548 static bool GreaterThan( const T t, const U u ) throw() { return ( (__int64)t > (__int64)u ); }
549};
550
551template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_UnsignedT >
552{
553public:
554 static bool GreaterThan( const T t, const U u ) throw()
555 {
556 // one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
557 if( u < 0 )
558 {
559 return SafeIntNoError;
560 }
561
562 // else safe to cast to type T
563 return ( t > (T)u );
564 }
565};
566
567template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_UnsignedU >
568{
569public:
570 static bool GreaterThan( const T t, const U u ) throw()
571 {
572 // one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
573 if( t < 0 )
574 {
575 return false;
576 }
577
578 // else safe to cast to type U
579 return ( (U)t > u );
580 }
581};
582
583// Modulus is simpler than comparison, but follows much the same logic
584// using this set of functions, it can't fail except in a div 0 situation
585template <typename T, typename U, typename E, int Method = ValidComparison< T, U >::method > class ModulusHelper;
586
587template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_Ok>
588{
589public:
590 static SafeIntError Modulus( const T& t, const U& u, T& result )
591 {
592 if(u == 0)
593 {
594 E::SafeIntOnDivZero();
595 return SafeIntDivideByZero;
596 }
597
598 // trap corner case
599#pragma warning(suppress:4127)
601 {
602 if(u == -1)
603 {
604 result = 0;
605 return SafeIntNoError;
606 }
607 }
608
609 result = (T)(t % u);
610 return SafeIntNoError;
611 }
612};
613
614template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_CastInt>
615{
616public:
617 static SafeIntError Modulus( const T& t, const U& u, T& result )
618 {
619 if(u == 0)
620 {
621 E::SafeIntOnDivZero();
622 return SafeIntDivideByZero;
623 }
624
625 // trap corner case
626#pragma warning(suppress:4127)
628 {
629 if(u == -1)
630 {
631 result = 0;
632 return SafeIntNoError;
633 }
634 }
635
636 result = (T)(t % u);
637 return SafeIntNoError;
638 }
639};
640
641template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_CastInt64>
642{
643public:
644 static SafeIntError Modulus( const T& t, const U& u, T& result )
645 {
646 if(u == 0)
647 {
648 E::SafeIntOnDivZero();
649 return SafeIntDivideByZero;
650 }
651
652#pragma warning(suppress:4127)
653 if(IntTraits< U >::isSigned && u == -1)
654 {
655 result = 0;
656 }
657 else
658 {
659 result = (T)((__int64)t % (__int64)u);
660 }
661
662 return SafeIntNoError;
663 }
664};
665
666// T is unsigned __int64, U is any signed int
667template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_UnsignedT>
668{
669public:
670 static SafeIntError Modulus( const T& t, const U& u, T& result )
671 {
672 if(u == 0)
673 {
674 E::SafeIntOnDivZero();
675 return SafeIntDivideByZero;
676 }
677
678 // u could be negative - if so, need to convert to positive
679 // casts below are always safe due to the way modulus works
680 if(u < 0)
681 {
683 }
684 else
685 {
686 result = (T)(t % u);
687 }
688
689 return SafeIntNoError;
690 }
691};
692
693// U is unsigned __int64, T any signed int
694template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_UnsignedU>
695{
696public:
697 static SafeIntError Modulus( const T& t, const U& u, T& result )
698 {
699 if(u == 0)
700 {
701 E::SafeIntOnDivZero();
702 return SafeIntDivideByZero;
703 }
704
705 //t could be negative - if so, need to convert to positive
706 if(t < 0)
707 {
708 result = -(T)( AbsValueHelper< T >::Abs( t ) % u );
709 }
710 else
711 {
712 result = (T)((T)t % u);
713 }
714
715 return SafeIntNoError;
716 }
717};
718
719//core logic to determine method to check multiplication
721{
722 MultiplicationState_CastInt = 0, // One or both signed, smaller than 32-bit
723 MultiplicationState_CastInt64, // One or both signed, smaller than 64-bit
724 MultiplicationState_CastUint, // Both are unsigned, smaller than 32-bit
725 MultiplicationState_CastUint64, // Both are unsigned, both 32-bit or smaller
726 MultiplicationState_Uint64Uint, // Both are unsigned, lhs 64-bit, rhs 32-bit or smaller
727 MultiplicationState_Uint64Uint64, // Both are unsigned int64
728 MultiplicationState_Uint64Int, // lhs is unsigned int64, rhs int32
729 MultiplicationState_Uint64Int64, // lhs is unsigned int64, rhs signed int64
730 MultiplicationState_UintUint64, // Both are unsigned, lhs 32-bit or smaller, rhs 64-bit
731 MultiplicationState_UintInt64, // lhs unsigned 32-bit or less, rhs int64
732 MultiplicationState_Int64Uint, // lhs int64, rhs unsigned int32
733 MultiplicationState_Int64Int64, // lhs int64, rhs int64
734 MultiplicationState_Int64Int, // lhs int64, rhs int32
735 MultiplicationState_IntUint64, // lhs int, rhs unsigned int64
736 MultiplicationState_IntInt64, // lhs int, rhs int64
737 MultiplicationState_Int64Uint64, // lhs int64, rhs uint64
740
741template < typename T, typename U >
743{
744public:
745 enum
746 {
747 // unsigned-unsigned
755 // unsigned-signed
762 // signed-signed
769 // signed-unsigned
777 };
778};
779
780template <typename T, typename U, typename E, int Method = MultiplicationMethod< T, U >::method > class MultiplicationHelper;
781
782template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastInt>
783{
784public:
785 //accepts signed, both less than 32-bit
786 static SafeIntError Multiply( const T& t, const U& u, T& ret )
787 {
788 int tmp = t * u;
789
791 {
792 E::SafeIntOnOverflow();
794 }
795
796 ret = (T)tmp;
797 return SafeIntNoError;
798 }
799};
800
801template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastUint >
802{
803public:
804 //accepts unsigned, both less than 32-bit
805 static SafeIntError Multiply( const T& t, const U& u, T& ret )
806 {
807 unsigned int tmp = t * u;
808
809 if( tmp > IntTraits< T >::maxInt )
810 {
811 E::SafeIntOnOverflow();
813 }
814
815 ret = (T)tmp;
816 return SafeIntNoError;
817 }
818};
819
820template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastInt64>
821{
822public:
823 //mixed signed or both signed where at least one argument is 32-bit, and both a 32-bit or less
824 static SafeIntError Multiply( const T& t, const U& u, T& ret )
825 {
826 __int64 tmp = (__int64)t * (__int64)u;
827
829 {
830 E::SafeIntOnOverflow();
832 }
833
834 ret = (T)tmp;
835 return SafeIntNoError;
836 }
837};
838
839template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastUint64>
840{
841public:
842 //both unsigned where at least one argument is 32-bit, and both are 32-bit or less
843 static SafeIntError Multiply( const T& t, const U& u, T& ret )
844 {
845 unsigned __int64 tmp = (unsigned __int64)t * (unsigned __int64)u;
846
847 if(tmp > (unsigned __int64)IntTraits< T >::maxInt)
848 {
849 E::SafeIntOnOverflow();
851 }
852
853 ret = (T)tmp;
854 return SafeIntNoError;
855 }
856};
857
858// T = left arg and return type
859// U = right arg
860template < typename T, typename U, typename E > class LargeIntRegMultiply;
861
862template< typename E > class LargeIntRegMultiply< unsigned __int64, unsigned __int64, E >
863{
864public:
865 static SafeIntError RegMultiply( const unsigned __int64& a, const unsigned __int64& b, unsigned __int64& ret )
866 {
867 unsigned __int32 aHigh, aLow, bHigh, bLow;
868
869 // Consider that a*b can be broken up into:
870 // (aHigh * 2^32 + aLow) * (bHigh * 2^32 + bLow)
871 // => (aHigh * bHigh * 2^64) + (aLow * bHigh * 2^32) + (aHigh * bLow * 2^32) + (aLow * bLow)
872 // Note - same approach applies for 128 bit math on a 64-bit system
873
874 aHigh = (unsigned __int32)(a >> 32);
875 aLow = (unsigned __int32)a;
876 bHigh = (unsigned __int32)(b >> 32);
877 bLow = (unsigned __int32)b;
878
879 ret = 0;
880
881 if(aHigh == 0)
882 {
883 if(bHigh != 0)
884 {
885 ret = (unsigned __int64)aLow * (unsigned __int64)bHigh;
886 }
887 }
888 else if(bHigh == 0)
889 {
890 if(aHigh != 0)
891 {
892 ret = (unsigned __int64)aHigh * (unsigned __int64)bLow;
893 }
894 }
895 else
896 {
897 E::SafeIntOnOverflow();
899 }
900
901 if(ret != 0)
902 {
903 unsigned __int64 tmp;
904
905 if((unsigned __int32)(ret >> 32) != 0)
906 {
907 E::SafeIntOnOverflow();
909 }
910
911 ret <<= 32;
912 tmp = (unsigned __int64)aLow * (unsigned __int64)bLow;
913 ret += tmp;
914
915 if(ret < tmp)
916 {
917 E::SafeIntOnOverflow();
919 }
920
921 return SafeIntNoError;
922 }
923
924 ret = (unsigned __int64)aLow * (unsigned __int64)bLow;
925 return SafeIntNoError;
926 }
927};
928
929template< typename E > class LargeIntRegMultiply< unsigned __int64, unsigned __int32, E >
930{
931public:
932 static SafeIntError RegMultiply( const unsigned __int64& a, unsigned __int32 b, unsigned __int64& ret )
933 {
934 unsigned __int32 aHigh, aLow;
935
936 // Consider that a*b can be broken up into:
937 // (aHigh * 2^32 + aLow) * b
938 // => (aHigh * b * 2^32) + (aLow * b)
939
940 aHigh = (unsigned __int32)(a >> 32);
941 aLow = (unsigned __int32)a;
942
943 ret = 0;
944
945 if(aHigh != 0)
946 {
947 ret = (unsigned __int64)aHigh * (unsigned __int64)b;
948
949 unsigned __int64 tmp;
950
951 if((unsigned __int32)(ret >> 32) != 0)
952 {
953 E::SafeIntOnOverflow();
955 }
956
957 ret <<= 32;
958 tmp = (unsigned __int64)aLow * (unsigned __int64)b;
959 ret += tmp;
960
961 if(ret < tmp)
962 {
963 E::SafeIntOnOverflow();
965 }
966
967 return SafeIntNoError;
968 }
969
970 ret = (unsigned __int64)aLow * (unsigned __int64)b;
971 return SafeIntNoError;
972 }
973};
974
975template< typename E > class LargeIntRegMultiply< unsigned __int64, signed __int32, E >
976{
977public:
978 static SafeIntError RegMultiply( const unsigned __int64& a, signed __int32 b, unsigned __int64& ret )
979 {
980 if( b < 0 && a != 0 )
981 {
982 E::SafeIntOnOverflow();
984 }
985
987 }
988};
989
990template< typename E > class LargeIntRegMultiply< unsigned __int64, signed __int64, E >
991{
992public:
993 static SafeIntError RegMultiply( const unsigned __int64& a, signed __int64 b, unsigned __int64& ret )
994 {
995 if( b < 0 && a != 0 )
996 {
997 E::SafeIntOnOverflow();
999 }
1000
1002 }
1003};
1004
1005template< typename E > class LargeIntRegMultiply< signed __int32, unsigned __int64, E >
1006{
1007public:
1008 static SafeIntError RegMultiply( signed __int32 a, const unsigned __int64& b, signed __int32& ret )
1009 {
1010 unsigned __int32 bHigh, bLow;
1011 bool fIsNegative = false;
1012
1013 // Consider that a*b can be broken up into:
1014 // (aHigh * 2^32 + aLow) * (bHigh * 2^32 + bLow)
1015 // => (aHigh * bHigh * 2^64) + (aLow * bHigh * 2^32) + (aHigh * bLow * 2^32) + (aLow * bLow)
1016
1017 bHigh = (unsigned __int32)(b >> 32);
1018 bLow = (unsigned __int32)b;
1019
1020 ret = 0;
1021
1022 if(bHigh != 0 && a != 0)
1023 {
1024 E::SafeIntOnOverflow();
1026 }
1027
1028 if( a < 0 )
1029 {
1030 a = -a;
1031 fIsNegative = true;
1032 }
1033
1034 unsigned __int64 tmp = (unsigned __int32)a * (unsigned __int64)bLow;
1035
1036
1037 if( !fIsNegative )
1038 {
1039 if( tmp <= (unsigned __int64)IntTraits< signed __int32 >::maxInt )
1040 {
1041 ret = (signed __int32)tmp;
1042 return SafeIntNoError;
1043 }
1044 }
1045 else
1046 {
1047 if( tmp <= (unsigned __int64)IntTraits< signed __int32 >::maxInt+1 )
1048 {
1049 ret = -( (signed __int32)tmp );
1050 return SafeIntNoError;
1051 }
1052 }
1053
1054 E::SafeIntOnOverflow();
1056 }
1057};
1058
1059template < typename E > class LargeIntRegMultiply< unsigned __int32, unsigned __int64, E >
1060{
1061public:
1062 static SafeIntError RegMultiply( unsigned __int32 a, const unsigned __int64& b, unsigned __int32& ret )
1063 {
1064 // Consider that a*b can be broken up into:
1065 // (bHigh * 2^32 + bLow) * a
1066 // => (bHigh * a * 2^32) + (bLow * a)
1067 // In this case, the result must fit into 32-bits
1068 // If bHigh != 0 && a != 0, immediate error.
1069
1070 if( (unsigned __int32)(b >> 32) != 0 && a != 0 )
1071 {
1072 E::SafeIntOnOverflow();
1074 }
1075
1076 unsigned __int64 tmp = b * (unsigned __int64)a;
1077
1078 if( (unsigned __int32)(tmp >> 32) != 0 ) // overflow
1079 {
1080 E::SafeIntOnOverflow();
1082 }
1083
1084 ret = (unsigned __int32)tmp;
1085 return SafeIntNoError;
1086 }
1087};
1088
1089template < typename E > class LargeIntRegMultiply< unsigned __int32, signed __int64, E >
1090{
1091public:
1092 static SafeIntError RegMultiply( unsigned __int32 a, const signed __int64& b, unsigned __int32& ret )
1093 {
1094 if( b < 0 && a != 0 )
1095 {
1096 E::SafeIntOnOverflow();
1098 }
1099
1101 }
1102};
1103
1104template < typename E > class LargeIntRegMultiply< signed __int64, signed __int64, E >
1105{
1106public:
1107 static SafeIntError RegMultiply( const signed __int64& a, const signed __int64& b, signed __int64& ret )
1108 {
1109 bool aNegative = false;
1110 bool bNegative = false;
1111
1112 unsigned __int64 tmp;
1113 __int64 a1 = a;
1114 __int64 b1 = b;
1115
1116 if( a1 < 0 )
1117 {
1118 aNegative = true;
1119 a1 = -a1;
1120 }
1121
1122 if( b1 < 0 )
1123 {
1124 bNegative = true;
1125 b1 = -b1;
1126 }
1127
1129 RegMultiply( (unsigned __int64)a1, (unsigned __int64)b1, tmp ) == SafeIntNoError )
1130 {
1131 // The unsigned multiplication didn't overflow
1132 if( aNegative ^ bNegative )
1133 {
1134 // Result must be negative
1135 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1136 {
1137 ret = -(signed __int64)tmp;
1138 return SafeIntNoError;
1139 }
1140 }
1141 else
1142 {
1143 // Result must be positive
1144 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1145 {
1146 ret = (signed __int64)tmp;
1147 return SafeIntNoError;
1148 }
1149 }
1150 }
1151
1152 E::SafeIntOnOverflow();
1154 }
1155};
1156
1157template < typename E > class LargeIntRegMultiply< signed __int64, unsigned __int32, E >
1158{
1159public:
1160 static SafeIntError RegMultiply( const signed __int64& a, unsigned __int32 b, signed __int64& ret )
1161 {
1162 bool aNegative = false;
1163 unsigned __int64 tmp;
1164 __int64 a1 = a;
1165
1166 if( a1 < 0 )
1167 {
1168 aNegative = true;
1169 a1 = -a1;
1170 }
1171
1173 {
1174 // The unsigned multiplication didn't overflow
1175 if( aNegative )
1176 {
1177 // Result must be negative
1178 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1179 {
1180 ret = -(signed __int64)tmp;
1181 return SafeIntNoError;
1182 }
1183 }
1184 else
1185 {
1186 // Result must be positive
1187 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1188 {
1189 ret = (signed __int64)tmp;
1190 return SafeIntNoError;
1191 }
1192 }
1193 }
1194
1195 E::SafeIntOnOverflow();
1197 }
1198};
1199
1200template < typename E > class LargeIntRegMultiply< signed __int64, signed __int32, E >
1201{
1202public:
1203 static SafeIntError RegMultiply( const signed __int64& a, signed __int32 b, signed __int64& ret )
1204 {
1205 bool aNegative = false;
1206 bool bNegative = false;
1207
1208 unsigned __int64 tmp;
1209 __int64 a1 = a;
1210 __int64 b1 = b;
1211
1212 if( a1 < 0 )
1213 {
1214 aNegative = true;
1215 a1 = -a1;
1216 }
1217
1218 if( b1 < 0 )
1219 {
1220 bNegative = true;
1221 b1 = -b1;
1222 }
1223
1225 RegMultiply( (unsigned __int64)a1, (unsigned __int32)b1, tmp ) == SafeIntNoError )
1226 {
1227 // The unsigned multiplication didn't overflow
1228 if( aNegative ^ bNegative )
1229 {
1230 // Result must be negative
1231 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1232 {
1233 ret = -(signed __int64)tmp;
1234 return SafeIntNoError;
1235 }
1236 }
1237 else
1238 {
1239 // Result must be positive
1240 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1241 {
1242 ret = (signed __int64)tmp;
1243 return SafeIntNoError;
1244 }
1245 }
1246 }
1247
1248 E::SafeIntOnOverflow();
1250 }
1251};
1252
1253template < typename E > class LargeIntRegMultiply< signed __int32, signed __int64, E >
1254{
1255public:
1256 static SafeIntError RegMultiply( signed __int32 a, const signed __int64& b, signed __int32& ret )
1257 {
1258 bool aNegative = false;
1259 bool bNegative = false;
1260
1261 unsigned __int32 tmp;
1262 __int64 b1 = b;
1263
1264 if( a < 0 )
1265 {
1266 aNegative = true;
1267 a = -a;
1268 }
1269
1270 if( b1 < 0 )
1271 {
1272 bNegative = true;
1273 b1 = -b1;
1274 }
1275
1277 RegMultiply( (unsigned __int32)a, (unsigned __int64)b1, tmp ) == SafeIntNoError )
1278 {
1279 // The unsigned multiplication didn't overflow
1280 if( aNegative ^ bNegative )
1281 {
1282 // Result must be negative
1283 if( tmp <= (unsigned __int32)IntTraits< signed __int32 >::minInt )
1284 {
1285#pragma warning(suppress:4146)
1286 ret = -tmp;
1287 return SafeIntNoError;
1288 }
1289 }
1290 else
1291 {
1292 // Result must be positive
1293 if( tmp <= (unsigned __int32)IntTraits< signed __int32 >::maxInt )
1294 {
1295 ret = (signed __int32)tmp;
1296 return SafeIntNoError;
1297 }
1298 }
1299 }
1300
1301 E::SafeIntOnOverflow();
1303 }
1304};
1305
1306template < typename E > class LargeIntRegMultiply< signed __int64, unsigned __int64, E >
1307{
1308public:
1309 static SafeIntError RegMultiply( const signed __int64& a, const unsigned __int64& b, signed __int64& ret )
1310 {
1311 bool aNegative = false;
1312
1313 unsigned __int64 tmp;
1314 __int64 a1 = a;
1315
1316 if( a1 < 0 )
1317 {
1318 aNegative = true;
1319 a1 = -a1;
1320 }
1321
1323 RegMultiply( (unsigned __int64)a1, (unsigned __int64)b, tmp ) == SafeIntNoError )
1324 {
1325 // The unsigned multiplication didn't overflow
1326 if( aNegative )
1327 {
1328 // Result must be negative
1329 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1330 {
1331 ret = -((signed __int64)tmp);
1332 return SafeIntNoError;
1333 }
1334 }
1335 else
1336 {
1337 // Result must be positive
1338 if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1339 {
1340 ret = (signed __int64)tmp;
1341 return SafeIntNoError;
1342 }
1343 }
1344 }
1345
1346 E::SafeIntOnOverflow();
1348 }
1349};
1350
1352{
1353public:
1354 static SafeIntError Multiply( const unsigned __int64& t, const unsigned __int64& u, unsigned __int64& ret )
1355 {
1357 }
1358};
1359
1360template < typename U, typename E > class MultiplicationHelper<unsigned __int64, U, E, MultiplicationState_Uint64Uint >
1361{
1362public:
1363 //U is any unsigned int 32-bit or less
1364 static SafeIntError Multiply( const unsigned __int64& t, const U& u, unsigned __int64& ret )
1365 {
1367 }
1368};
1369
1370// converse of the previous function
1371template < typename T, typename E > class MultiplicationHelper< T, unsigned __int64, E, MultiplicationState_UintUint64 >
1372{
1373public:
1374 // T is any unsigned int up to 32-bit
1375 static SafeIntError Multiply( const T& t, const unsigned __int64& u, T& ret )
1376 {
1377 unsigned __int32 tmp;
1378
1381 {
1382 return SafeIntNoError;
1383 }
1384
1385 E::SafeIntOnOverflow();
1387 }
1388};
1389
1390template < typename U, typename E > class MultiplicationHelper< unsigned __int64, U, E, MultiplicationState_Uint64Int >
1391{
1392public:
1393 //U is any signed int, up to 64-bit
1394 static SafeIntError Multiply(const unsigned __int64& t, const U& u, unsigned __int64& ret)
1395 {
1397 }
1398};
1399
1401{
1402public:
1403 static SafeIntError Multiply(const unsigned __int64& t, const __int64& u, unsigned __int64& ret)
1404 {
1406 }
1407};
1408
1409template < typename T, typename E > class MultiplicationHelper< T, __int64, E, MultiplicationState_UintInt64 >
1410{
1411public:
1412 //T is unsigned up to 32-bit
1413 static SafeIntError Multiply( const T& t, const __int64& u, T& ret )
1414 {
1415 unsigned __int32 tmp;
1416
1419 {
1420 return SafeIntNoError;
1421 }
1422
1423 E::SafeIntOnOverflow();
1425 }
1426};
1427
1428template < typename U, typename E > class MultiplicationHelper<__int64, U, E, MultiplicationState_Int64Uint >
1429{
1430public:
1431 //U is unsigned up to 32-bit
1432 static SafeIntError Multiply( const __int64& t, const U& u, __int64& ret )
1433 {
1435 }
1436};
1437
1439{
1440public:
1441 static SafeIntError Multiply( const __int64& t, const __int64& u, __int64& ret )
1442 {
1444 }
1445};
1446
1447template < typename U, typename E > class MultiplicationHelper<__int64, U, E, MultiplicationState_Int64Int>
1448{
1449public:
1450 //U is signed up to 32-bit
1452 {
1454 }
1455};
1456
1457template < typename T, typename E > class MultiplicationHelper< T, unsigned __int64, E, MultiplicationState_IntUint64 >
1458{
1459public:
1460 //T is signed up to 32-bit
1461 static SafeIntError Multiply(T t, const unsigned __int64& u, T& ret)
1462 {
1463 __int32 tmp;
1464
1467 {
1468 return SafeIntNoError;
1469 }
1470
1471 E::SafeIntOnOverflow();
1473 }
1474};
1475
1477{
1478public:
1479 //U is signed up to 32-bit
1480 static SafeIntError Multiply( const __int64& t, const unsigned __int64& u, __int64& ret )
1481 {
1483 }
1484};
1485
1486template < typename T, typename E > class MultiplicationHelper< T, __int64, E, MultiplicationState_IntInt64>
1487{
1488public:
1489 //T is signed, up to 32-bit
1490 static SafeIntError Multiply( T t, const __int64& u, T& ret )
1491 {
1492 __int32 tmp;
1493
1496 {
1497 return SafeIntNoError;
1498 }
1499
1500 E::SafeIntOnOverflow();
1502 }
1503};
1504
1506{
1514
1515template < typename T, typename U > class DivisionMethod
1516{
1517public:
1518 enum
1519 {
1529};
1530
1531template < typename T, typename U, typename E, int Method = DivisionMethod< T, U >::method > class DivisionHelper;
1532
1533template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_OK >
1534{
1535public:
1536 static SafeIntError Divide( const T& t, const U& u, T& result )
1537 {
1538 if( u == 0 )
1539 {
1540 E::SafeIntOnDivZero();
1541 return SafeIntDivideByZero;
1542 }
1543
1544 result = (T)( t/u );
1545 return SafeIntNoError;
1546 }
1547};
1548
1549template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_UnsignedSigned>
1550{
1551public:
1552 static SafeIntError Divide( const T& t, const U& u, T& result )
1553 {
1554 if( u > 0 )
1555 {
1556 result = (T)( t/u );
1557 return SafeIntNoError;
1558 }
1559
1560 if( u == 0 )
1561 {
1562 E::SafeIntOnDivZero();
1563 return SafeIntDivideByZero;
1564 }
1565
1566 // it is always an error to try and divide an unsigned number by a negative signed number
1567 // unless u is bigger than t
1568 if( AbsValueHelper< U >::Abs( u ) > t )
1569 {
1570 result = 0;
1571 return SafeIntNoError;
1572 }
1573
1574 E::SafeIntOnOverflow();
1576 }
1577};
1578
1579template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedUnsigned32 >
1580{
1581public:
1582 static SafeIntError Divide( const T& t, const U& u, T& result )
1583 {
1584 if( u == 0 )
1585 {
1586 E::SafeIntOnDivZero();
1587 return SafeIntDivideByZero;
1588 }
1589
1590 // Test for t > 0
1591 // If t < 0, must explicitly upcast, or implicit upcast to ulong will cause errors
1592 // As it turns out, 32-bit division is about twice as fast, which justifies the extra conditional
1593 if( t > 0 )
1594 result = (T)( t/u );
1595 else
1596 result = (T)( (__int64)t/(__int64)u );
1597
1598 return SafeIntNoError;
1599 }
1600};
1601
1602template < typename T, typename E > class DivisionHelper< T, unsigned __int64, E, DivisionState_SignedUnsigned64 >
1603{
1604public:
1605 static SafeIntError Divide( const T& t, const unsigned __int64& u, T& result )
1606 {
1607 if( u == 0 )
1608 {
1609 E::SafeIntOnDivZero();
1610 return SafeIntDivideByZero;
1611 }
1612
1613 if( u <= (unsigned __int64)IntTraits< T >::maxInt )
1614 {
1615 // Else u can safely be cast to T
1616#pragma warning(suppress:4127)
1617 if( sizeof( T ) < sizeof( __int64 ) )
1618 result = (T)( (int)t/(int)u );
1619 else
1620 result = (T)((__int64)t/(__int64)u);
1621 }
1622 else // Corner case
1624 {
1625 // Min int divided by its own magnitude is -1
1626 result = -1;
1627 }
1628 else
1629 {
1630 result = 0;
1631 }
1632 return SafeIntNoError;
1633 }
1634};
1635
1636template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedUnsigned>
1637{
1638public:
1639 // T is any signed, U is unsigned and smaller than 32-bit
1640 // In this case, standard operator casting is correct
1641 static SafeIntError Divide( const T& t, const U& u, T& result )
1642 {
1643 if( u == 0 )
1644 {
1645 E::SafeIntOnDivZero();
1646 return SafeIntDivideByZero;
1647 }
1648
1649 result = (T)( t/u );
1650 return SafeIntNoError;
1651 }
1652};
1653
1654template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedSigned>
1655{
1656public:
1657 static SafeIntError Divide( const T& t, const U& u, T& result )
1658 {
1659 if( u == 0 )
1660 {
1661 E::SafeIntOnDivZero();
1662 return SafeIntDivideByZero;
1663 }
1664
1665 // Must test for corner case
1666 if( t == IntTraits< T >::minInt && u == -1 )
1667 {
1668 E::SafeIntOnOverflow();
1670 }
1671
1672 result = (T)( t/u );
1673 return SafeIntNoError;
1674 }
1675};
1676
1678{
1696
1697template< typename T, typename U >
1699{
1700public:
1701 enum
1702 {
1703 //unsigned-unsigned
1709 //unsigned-signed
1716 //signed-signed
1723 //signed-unsigned
1732};
1733
1734template < typename T, typename U, typename E, int Method = AdditionMethod< T, U >::method > class AdditionHelper;
1735
1736template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastIntCheckMax >
1737{
1738public:
1739 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1740 {
1741 //16-bit or less unsigned addition
1742 __int32 tmp = lhs + rhs;
1743
1744 if( tmp <= (__int32)IntTraits< T >::maxInt )
1745 {
1746 result = (T)tmp;
1747 return SafeIntNoError;
1748 }
1749
1750 E::SafeIntOnOverflow();
1752 }
1753};
1754
1755template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUintCheckOverflow >
1756{
1757public:
1758 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1759 {
1760 // 32-bit or less - both are unsigned
1761 unsigned __int32 tmp = (unsigned __int32)lhs + (unsigned __int32)rhs;
1762
1763 //we added didn't get smaller
1764 if( tmp >= lhs )
1765 {
1766 result = (T)tmp;
1767 return SafeIntNoError;
1768 }
1769 E::SafeIntOnOverflow();
1771 }
1772};
1773
1774template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUintCheckOverflowMax>
1775{
1776public:
1777 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1778 {
1779 // 32-bit or less - both are unsigned
1780 unsigned __int32 tmp = (unsigned __int32)lhs + (unsigned __int32)rhs;
1781
1782 // We added and it didn't get smaller or exceed maxInt
1783 if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
1784 {
1785 result = (T)tmp;
1786 return SafeIntNoError;
1787 }
1788 E::SafeIntOnOverflow();
1790 }
1791};
1792
1793template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckOverflow>
1794{
1795public:
1796 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1797 {
1798 // lhs unsigned __int64, rhs unsigned
1799 unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1800
1801 // We added and it didn't get smaller
1802 if(tmp >= lhs)
1803 {
1804 result = (T)tmp;
1805 return SafeIntNoError;
1806 }
1807
1808 E::SafeIntOnOverflow();
1810 }
1811};
1812
1813template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckOverflowMax >
1814{
1815public:
1816 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1817 {
1818 //lhs unsigned __int64, rhs unsigned
1819 unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1820
1821 // We added and it didn't get smaller
1822 if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
1823 {
1824 result = (T)tmp;
1825 return SafeIntNoError;
1826 }
1827
1828 E::SafeIntOnOverflow();
1830 }
1831};
1832
1833template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastIntCheckMinMax >
1834{
1835public:
1836 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1837 {
1838 // 16-bit or less - one or both are signed
1839 __int32 tmp = lhs + rhs;
1840
1842 {
1843 result = (T)tmp;
1844 return SafeIntNoError;
1845 }
1846
1847 E::SafeIntOnOverflow();
1849 }
1850};
1851
1852#pragma warning(push)
1853#pragma warning(disable:4702)
1854template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckMinMax >
1855{
1856public:
1857 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1858 {
1859 // 32-bit or less - one or both are signed
1860 __int64 tmp = (__int64)lhs + (__int64)rhs;
1861
1863 {
1864 result = (T)tmp;
1865 return SafeIntNoError;
1866 }
1867
1868 E::SafeIntOnOverflow();
1870 // return E::SafeIntOnOverflow2();
1871 }
1872};
1873#pragma warning(pop)
1874
1875template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckMax >
1876{
1877public:
1878 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1879 {
1880 // 32-bit or less - lhs signed, rhs unsigned
1881 __int64 tmp = (__int64)lhs + (__int64)rhs;
1882
1883 if( tmp <= IntTraits< T >::maxInt )
1884 {
1885 result = (T)tmp;
1886 return SafeIntNoError;
1887 }
1888
1889 E::SafeIntOnOverflow();
1891 }
1892};
1893
1894template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckMinMax >
1895{
1896public:
1897 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1898 {
1899 // lhs is unsigned __int64, rhs signed
1900 unsigned __int64 tmp;
1901
1902 if( rhs < 0 )
1903 {
1904 // So we're effectively subtracting
1905 tmp = AbsValueHelper< U >::Abs( rhs );
1906
1907 if( tmp <= lhs )
1908 {
1909 result = lhs - tmp;
1910 return SafeIntNoError;
1911 }
1912 }
1913 else
1914 {
1915 // now we know that rhs can be safely cast into an unsigned __int64
1916 tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1917
1918 // We added and it did not become smaller
1919 if( tmp >= lhs )
1920 {
1921 result = (T)tmp;
1922 return SafeIntNoError;
1923 }
1924 }
1925
1926 E::SafeIntOnOverflow();
1928 }
1929};
1930
1931template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckMinMax2>
1932{
1933public:
1934 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1935 {
1936 // lhs is unsigned and < 64-bit, rhs signed __int64
1937 if( rhs < 0 )
1938 {
1939 if( lhs >= (unsigned __int64)( -rhs ) )//negation is safe, since rhs is 64-bit
1940 {
1941 result = (T)( lhs + rhs );
1942 return SafeIntNoError;
1943 }
1944 }
1945 else
1946 {
1947 // now we know that rhs can be safely cast into an unsigned __int64
1948 unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1949
1950 // special case - rhs cannot be larger than 0x7fffffffffffffff, lhs cannot be larger than 0xffffffff
1951 // it is not possible for the operation above to overflow, so just check max
1952 if( tmp <= IntTraits< T >::maxInt )
1953 {
1954 result = (T)tmp;
1955 return SafeIntNoError;
1956 }
1957 }
1958 E::SafeIntOnOverflow();
1960 }
1961};
1962
1963template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflow>
1964{
1965public:
1966 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1967 {
1968 // lhs is signed __int64, rhs signed
1969 __int64 tmp = (__int64)lhs + (__int64)rhs;
1970
1971 if( lhs >= 0 )
1972 {
1973 // mixed sign cannot overflow
1974 if( rhs >= 0 && tmp < lhs )
1975 {
1976 E::SafeIntOnOverflow();
1978 }
1979 }
1980 else
1981 {
1982 // lhs negative
1983 if( rhs < 0 && tmp > lhs )
1984 {
1985 E::SafeIntOnOverflow();
1987 }
1988 }
1989
1990 result = (T)tmp;
1991 return SafeIntNoError;
1992 }
1993};
1994
1995template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflowMinMax>
1996{
1997public:
1998 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1999 {
2000 //rhs is signed __int64, lhs signed
2001 __int64 tmp;
2002
2004 Addition( (__int64)lhs, (__int64)rhs, tmp ) == SafeIntNoError &&
2005 tmp <= IntTraits< T >::maxInt &&
2006 tmp >= IntTraits< T >::minInt )
2007 {
2008 result = (T)tmp;
2009 return SafeIntNoError;
2010 }
2011
2012 E::SafeIntOnOverflow();
2014 }
2015};
2016
2017template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflowMax >
2018{
2019public:
2020 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
2021 {
2022 //lhs is signed __int64, rhs unsigned < 64-bit
2023 __int64 tmp = lhs + (__int64)rhs;
2024
2025 if( tmp >= lhs )
2026 {
2027 result = (T)tmp;
2028 return SafeIntNoError;
2029 }
2030
2031 E::SafeIntOnOverflow();
2033 }
2034};
2035
2037{
2038public:
2039 static SafeIntError Addition( const __int64& lhs, const unsigned __int64& rhs, __int64& result )
2040 {
2041 // rhs is unsigned __int64, lhs __int64
2042 __int64 tmp = lhs + (__int64)rhs;
2043
2044 if( tmp >= lhs )
2045 {
2046 result = tmp;
2047 return SafeIntNoError;
2048 }
2049
2050 E::SafeIntOnOverflow();
2052 }
2053};
2054
2055template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_ManualCheck >
2056{
2057public:
2058 static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
2059 {
2060 // rhs is unsigned __int64, lhs signed, 32-bit or less
2061
2062 if( (unsigned __int32)( rhs >> 32 ) == 0 )
2063 {
2064 // Now it just happens to work out that the standard behavior does what we want
2065 // Adding explicit casts to show exactly what's happening here
2066 __int32 tmp = (__int32)( (unsigned __int32)rhs + (unsigned __int32)lhs );
2067
2068 if( tmp >= lhs &&
2070 return SafeIntNoError;
2071 }
2072
2073 E::SafeIntOnOverflow();
2075 }
2076};
2077
2079{
2092 // states for SubtractionMethod2
2105
2106template < typename T, typename U > class SubtractionMethod
2107{
2108public:
2109 enum
2110 {
2111 // unsigned-unsigned
2117 // unsigned-signed
2124 // signed-signed
2131 // signed-unsigned
2140};
2141
2142// this is for the case of U - SafeInt< T, E >
2143template < typename T, typename U > class SubtractionMethod2
2144{
2145public:
2146 enum
2147 {
2148 // unsigned-unsigned
2154 // unsigned-signed
2161 // signed-signed
2168 // signed-unsigned
2177};
2178
2179template < typename T, typename U, typename E, int Method = SubtractionMethod< T, U >::method > class SubtractionHelper;
2180
2181template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_BothUnsigned >
2182{
2183public:
2184 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2185 {
2186 // both are unsigned - easy case
2187 if( rhs <= lhs )
2188 {
2189 result = (T)( lhs - rhs );
2190 return SafeIntNoError;
2191 }
2192
2193 E::SafeIntOnOverflow();
2195 }
2196};
2197
2198template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_BothUnsigned2 >
2199{
2200public:
2201 static SafeIntError Subtract( const T& lhs, const U& rhs, U& result )
2202 {
2203 // both are unsigned - easy case
2204 // Except we do have to check for overflow - lhs could be larger than result can hold
2205 if( rhs <= lhs )
2206 {
2207 T tmp = (T)(lhs - rhs);
2209 }
2210
2211 E::SafeIntOnOverflow();
2213 }
2214};
2215
2216template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastIntCheckMinMax >
2217{
2218public:
2219 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2220 {
2221 // both values are 16-bit or less
2222 // rhs is signed, so could end up increasing or decreasing
2223 __int32 tmp = lhs - rhs;
2224
2226 {
2227 result = (T)tmp;
2228 return SafeIntNoError;
2229 }
2230
2231 E::SafeIntOnOverflow();
2233 }
2234};
2235
2236template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_CastIntCheckMinMax2 >
2237{
2238public:
2239 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2240 {
2241 // both values are 16-bit or less
2242 // rhs is signed, so could end up increasing or decreasing
2243 __int32 tmp = lhs - rhs;
2244
2246 }
2247};
2248
2249template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastIntCheckMin >
2250{
2251public:
2252 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2253 {
2254 // both values are 16-bit or less
2255 // rhs is unsigned - check only minimum
2256 __int32 tmp = lhs - rhs;
2257
2258 if( tmp >= (__int32)IntTraits< T >::minInt )
2259 {
2260 result = (T)tmp;
2261 return SafeIntNoError;
2262 }
2263
2264 E::SafeIntOnOverflow();
2266 }
2267};
2268
2269template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastInt64CheckMinMax >
2270{
2271public:
2272 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2273 {
2274 // both values are 32-bit or less
2275 // rhs is signed, so could end up increasing or decreasing
2276 __int64 tmp = (__int64)lhs - (__int64)rhs;
2277
2279 }
2280};
2281
2282template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_CastInt64CheckMinMax2 >
2283{
2284public:
2285 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2286 {
2287 // both values are 32-bit or less
2288 // rhs is signed, so could end up increasing or decreasing
2289 __int64 tmp = (__int64)lhs - (__int64)rhs;
2290
2292 }
2293};
2294
2295template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastInt64CheckMin >
2296{
2297public:
2298 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2299 {
2300 // both values are 32-bit or less
2301 // rhs is unsigned - check only minimum
2302 __int64 tmp = (__int64)lhs - (__int64)rhs;
2303
2304 if( tmp >= (__int64)IntTraits< T >::minInt )
2305 {
2306 result = (T)tmp;
2307 return SafeIntNoError;
2308 }
2309
2310 E::SafeIntOnOverflow();
2312 }
2313};
2314
2315template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Uint64Int >
2316{
2317public:
2318 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2319 {
2320 // lhs is an unsigned __int64, rhs signed
2321 // must first see if rhs is positive or negative
2322 if( rhs >= 0 )
2323 {
2324 if( (unsigned __int64)rhs <= lhs )
2325 {
2326 result = (T)( lhs - (unsigned __int64)rhs );
2327 return SafeIntNoError;
2328 }
2329 }
2330 else
2331 {
2332 // we're now effectively adding
2333 T tmp = lhs + AbsValueHelper< U >::Abs( rhs );
2334
2335 if(tmp >= lhs)
2336 {
2337 result = tmp;
2338 return SafeIntNoError;
2339 }
2340 }
2341
2342 E::SafeIntOnOverflow();
2344 }
2345};
2346
2347template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Uint64Int2 >
2348{
2349public:
2350 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2351 {
2352 // U is unsigned __int64, T is signed
2353 if( rhs < 0 )
2354 {
2355 // treat this as addition
2356 unsigned __int64 tmp;
2357
2358 tmp = lhs + (unsigned __int64)AbsValueHelper< T >::Abs( rhs );
2359
2360 // must check for addition overflow and max
2361 if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
2362 {
2363 result = (T)tmp;
2364 return SafeIntNoError;
2365 }
2366 }
2367 else if( (unsigned __int64)rhs > lhs ) // now both are positive, so comparison always works
2368 {
2369 // result is negative
2370 // implies that lhs must fit into T, and result cannot overflow
2371 // Also allows us to drop to 32-bit math, which is faster on a 32-bit system
2372 result = (T)lhs - (T)rhs;
2373 return SafeIntNoError;
2374 }
2375 else
2376 {
2377 // result is positive
2378 unsigned __int64 tmp = (unsigned __int64)lhs - (unsigned __int64)rhs;
2379
2380 if( tmp <= IntTraits< T >::maxInt )
2381 {
2382 result = (T)tmp;
2383 return SafeIntNoError;
2384 }
2385 }
2386
2387 E::SafeIntOnOverflow();
2389 }
2390};
2391
2392template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_UintInt64 >
2393{
2394public:
2395 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2396 {
2397 // lhs is an unsigned int32 or smaller, rhs signed __int64
2398 // must first see if rhs is positive or negative
2399 if( rhs >= 0 )
2400 {
2401 if( (unsigned __int64)rhs <= lhs )
2402 {
2403 result = (T)( lhs - (T)rhs );
2404 return SafeIntNoError;
2405 }
2406 }
2407 else
2408 {
2409 // we're now effectively adding
2410 // since lhs is 32-bit, and rhs cannot exceed 2^63
2411 // this addition cannot overflow
2412 unsigned __int64 tmp = lhs + (unsigned __int64)( -rhs ); // negation safe
2413
2414 // but we could exceed MaxInt
2415 if(tmp <= IntTraits< T >::maxInt)
2416 {
2417 result = (T)tmp;
2418 return SafeIntNoError;
2419 }
2420 }
2421
2422 E::SafeIntOnOverflow();
2424 }
2425};
2426
2427template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_UintInt642 >
2428{
2429public:
2430 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2431 {
2432 // U unsigned 32-bit or less, T __int64
2433 if( rhs >= 0 )
2434 {
2435 // overflow not possible
2436 result = (T)( (__int64)lhs - rhs );
2437 return SafeIntNoError;
2438 }
2439 else
2440 {
2441 // we effectively have an addition
2442 // which cannot overflow internally
2443 unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)( -rhs );
2444
2445 if( tmp <= (unsigned __int64)IntTraits< T >::maxInt )
2446 {
2447 result = (T)tmp;
2448 return SafeIntNoError;
2449 }
2450 }
2451
2452 E::SafeIntOnOverflow();
2454 }
2455};
2456
2457template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Int64Int >
2458{
2459public:
2460 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2461 {
2462 // lhs is an __int64, rhs signed (up to 64-bit)
2463 // we have essentially 4 cases:
2464 //
2465 // 1) lhs positive, rhs positive - overflow not possible
2466 // 2) lhs positive, rhs negative - equivalent to addition - result >= lhs or error
2467 // 3) lhs negative, rhs positive - check result <= lhs
2468 // 4) lhs negative, rhs negative - overflow not possible
2469
2470 __int64 tmp = lhs - rhs;
2471
2472 // Note - ideally, we can order these so that true conditionals
2473 // lead to success, which enables better pipelining
2474 // It isn't practical here
2475 if( ( lhs >= 0 && rhs < 0 && tmp < lhs ) || // condition 2
2476 ( rhs >= 0 && tmp > lhs ) ) // condition 3
2477 {
2478 E::SafeIntOnOverflow();
2480 }
2481
2482 result = (T)tmp;
2483 return SafeIntNoError;
2484 }
2485};
2486
2487template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Int64Int2 >
2488{
2489public:
2490 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2491 {
2492 // lhs __int64, rhs any signed int (including __int64)
2493 __int64 tmp = lhs - rhs;
2494
2495 // we have essentially 4 cases:
2496 //
2497 // 1) lhs positive, rhs positive - overflow not possible in tmp
2498 // 2) lhs positive, rhs negative - equivalent to addition - result >= lhs or error
2499 // 3) lhs negative, rhs positive - check result <= lhs
2500 // 4) lhs negative, rhs negative - overflow not possible in tmp
2501
2502 if( lhs >= 0 )
2503 {
2504 // if both positive, overflow to negative not possible
2505 // which is why we'll explicitly check maxInt, and not call SafeCast
2506#pragma warning(suppress:4127)
2508 ( rhs < 0 && tmp < lhs ) )
2509 {
2510 E::SafeIntOnOverflow();
2512 }
2513 }
2514 else
2515 {
2516 // lhs negative
2517#pragma warning(suppress:4127)
2519 ( rhs >=0 && tmp > lhs ) )
2520 {
2521 E::SafeIntOnOverflow();
2523 }
2524 }
2525
2526 result = (T)tmp;
2527 return SafeIntNoError;
2528 }
2529};
2530
2531template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_IntInt64 >
2532{
2533public:
2534 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2535 {
2536 // lhs is a 32-bit int or less, rhs __int64
2537 // we have essentially 4 cases:
2538 //
2539 // lhs positive, rhs positive - rhs could be larger than lhs can represent
2540 // lhs positive, rhs negative - additive case - check tmp >= lhs and tmp > max int
2541 // lhs negative, rhs positive - check tmp <= lhs and tmp < min int
2542 // lhs negative, rhs negative - addition cannot internally overflow, check against max
2543
2544 __int64 tmp = (__int64)lhs - rhs;
2545
2546 if( lhs >= 0 )
2547 {
2548 // first case
2549 if( rhs >= 0 )
2550 {
2551 if( tmp >= IntTraits< T >::minInt )
2552 {
2553 result = (T)tmp;
2554 return SafeIntNoError;
2555 }
2556 }
2557 else
2558 {
2559 // second case
2560 if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
2561 {
2562 result = (T)tmp;
2563 return SafeIntNoError;
2564 }
2565 }
2566 }
2567 else
2568 {
2569 // lhs < 0
2570 // third case
2571 if( rhs >= 0 )
2572 {
2573 if( tmp <= lhs && tmp >= IntTraits< T >::minInt )
2574 {
2575 result = (T)tmp;
2576 return SafeIntNoError;
2577 }
2578 }
2579 else
2580 {
2581 // fourth case
2582 if( tmp <= IntTraits< T >::maxInt )
2583 {
2584 result = (T)tmp;
2585 return SafeIntNoError;
2586 }
2587 }
2588 }
2589
2590 E::SafeIntOnOverflow();
2592 }
2593};
2594
2595template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_IntInt642 >
2596{
2597public:
2598 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2599 {
2600 // lhs is any signed int32 or smaller, rhs is int64
2601 __int64 tmp = (__int64)lhs - rhs;
2602
2603 if( ( lhs >= 0 && rhs < 0 && tmp < lhs ) ||
2604 ( rhs > 0 && tmp > lhs ) )
2605 {
2606 E::SafeIntOnOverflow();
2608 //else OK
2609 }
2610
2611 result = (T)tmp;
2612 return SafeIntNoError;
2613 }
2614};
2615
2616template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Int64Uint >
2617{
2618public:
2619 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2620 {
2621 // lhs is a 64-bit int, rhs unsigned int32 or smaller
2622
2623 __int64 tmp = lhs - (__int64)rhs;
2624
2625 if( tmp <= lhs )
2626 {
2627 result = (T)tmp;
2628 return SafeIntNoError;
2629 }
2630
2631 E::SafeIntOnOverflow();
2633 }
2634};
2635
2636template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Int64Uint2 >
2637{
2638public:
2639 // lhs is __int64, rhs is unsigned 32-bit or smaller
2640 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2641 {
2642 __int64 tmp = lhs - (__int64)rhs;
2643
2644 if( tmp <= IntTraits< T >::maxInt && tmp >= IntTraits< T >::minInt )
2645 {
2646 result = (T)tmp;
2647 return SafeIntNoError;
2648 }
2649
2650 E::SafeIntOnOverflow();
2652 }
2653};
2654
2655template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_IntUint64 >
2656{
2657public:
2658 static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2659 {
2660 // lhs is any signed int, rhs unsigned int64
2661 // check against available range
2662
2663 // We need the absolute value of IntTraits< T >::minInt
2664 // This will give it to us without extraneous compiler warnings
2665 const unsigned __int64 AbsMinIntT = (unsigned __int64)IntTraits< T >::maxInt + 1;
2666
2667 if( lhs < 0 )
2668 {
2669 if( rhs <= AbsMinIntT - AbsValueHelper< T >::Abs( lhs ) )
2670 {
2671 result = (T)( lhs - rhs );
2672 return SafeIntNoError;
2673 }
2674 }
2675 else
2676 {
2677 if( rhs <= AbsMinIntT + (unsigned __int64)lhs )
2678 {
2679 result = (T)( lhs - rhs );
2680 return SafeIntNoError;
2681 }
2682 }
2683
2684 E::SafeIntOnOverflow();
2686 }
2687};
2688
2689template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_IntUint642 >
2690{
2691public:
2692 static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2693 {
2694 // We run into upcasting problems on comparison - needs 2 checks
2695 if( lhs >= 0 && (T)lhs >= rhs )
2696 {
2697 result = (T)((U)lhs - (U)rhs);
2698 return SafeIntNoError;
2699 }
2700
2701 E::SafeIntOnOverflow();
2703 }
2704};
2705
2707{
2708public:
2709 static SafeIntError Subtract( const __int64& lhs, const unsigned __int64& rhs, __int64& result )
2710 {
2711 // if we subtract, and it gets larger, there's a problem
2712 __int64 tmp = lhs - (__int64)rhs;
2713
2714 if( tmp <= lhs )
2715 {
2716 result = tmp;
2717 return SafeIntNoError;
2718 }
2719 E::SafeIntOnOverflow();
2721 }
2722};
2723
2725{
2726public:
2727 // If lhs is negative, immediate problem - return must be positive, and subtracting only makes it
2728 // get smaller. If rhs > lhs, then it would also go negative, which is the other case
2729 static SafeIntError Subtract( const __int64& lhs, const unsigned __int64& rhs, unsigned __int64& result )
2730 {
2731 if( lhs >= 0 && (unsigned __int64)lhs >= rhs )
2732 {
2733 result = (unsigned __int64)lhs - rhs;
2734 return SafeIntNoError;
2735 }
2736
2737 E::SafeIntOnOverflow();
2739 }
2740};
2741
2743{
2749
2750template < typename T, typename U > class BinaryMethod
2751{
2752public:
2753 enum
2754 {
2755 // If both operands are unsigned OR
2756 // return type is smaller than rhs OR
2757 // return type is larger and rhs is unsigned
2758 // Then binary operations won't produce unexpected results
2759 method = ( sizeof( T ) <= sizeof( U ) ||
2766};
2767
2768template < typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryAndHelper;
2769
2770template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_OK >
2771{
2772public:
2773 static T And( T lhs, U rhs ){ return (T)( lhs & rhs ); }
2774};
2775
2776template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int8 >
2777{
2778public:
2779 static T And( T lhs, U rhs )
2780 {
2781 // cast forces sign extension to be zeros
2782 _SAFEINT_BINARY_ASSERT( ( lhs & rhs ) == ( lhs & (unsigned __int8)rhs ) );
2783 return (T)( lhs & (unsigned __int8)rhs );
2784 }
2785};
2786
2787template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int16 >
2788{
2789public:
2790 static T And( T lhs, U rhs )
2791 {
2792 //cast forces sign extension to be zeros
2793 _SAFEINT_BINARY_ASSERT( ( lhs & rhs ) == ( lhs & (unsigned __int16)rhs ) );
2794 return (T)( lhs & (unsigned __int16)rhs );
2795 }
2796};
2797
2798template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int32 >
2799{
2800public:
2801 static T And( T lhs, U rhs )
2802 {
2803 //cast forces sign extension to be zeros
2804 _SAFEINT_BINARY_ASSERT( ( lhs & rhs ) == ( lhs & (unsigned __int32)rhs ) );
2805 return (T)( lhs & (unsigned __int32)rhs );
2806 }
2807};
2808
2809template < typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryOrHelper;
2810
2811template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_OK >
2812{
2813public:
2814 static T Or( T lhs, U rhs ){ return (T)( lhs | rhs ); }
2815};
2816
2817template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int8 >
2818{
2819public:
2820 static T Or( T lhs, U rhs )
2821 {
2822 //cast forces sign extension to be zeros
2823 _SAFEINT_BINARY_ASSERT( ( lhs | rhs ) == ( lhs | (unsigned __int8)rhs ) );
2824 return (T)( lhs | (unsigned __int8)rhs );
2825 }
2826};
2827
2828template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int16 >
2829{
2830public:
2831 static T Or( T lhs, U rhs )
2832 {
2833 //cast forces sign extension to be zeros
2834 _SAFEINT_BINARY_ASSERT( ( lhs | rhs ) == ( lhs | (unsigned __int16)rhs ) );
2835 return (T)( lhs | (unsigned __int16)rhs );
2836 }
2837};
2838
2839template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int32 >
2840{
2841public:
2842 static T Or( T lhs, U rhs )
2843 {
2844 //cast forces sign extension to be zeros
2845 _SAFEINT_BINARY_ASSERT( ( lhs | rhs ) == ( lhs | (unsigned __int32)rhs ) );
2846 return (T)( lhs | (unsigned __int32)rhs );
2847 }
2848};
2849
2850template <typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryXorHelper;
2851
2852template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_OK >
2853{
2854public:
2855 static T Xor( T lhs, U rhs ){ return (T)( lhs ^ rhs ); }
2856};
2857
2858template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int8 >
2859{
2860public:
2861 static T Xor( T lhs, U rhs )
2862 {
2863 // cast forces sign extension to be zeros
2864 _SAFEINT_BINARY_ASSERT( ( lhs ^ rhs ) == ( lhs ^ (unsigned __int8)rhs ) );
2865 return (T)( lhs ^ (unsigned __int8)rhs );
2866 }
2867};
2868
2869template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int16 >
2870{
2871public:
2872 static T Xor( T lhs, U rhs )
2873 {
2874 // cast forces sign extension to be zeros
2875 _SAFEINT_BINARY_ASSERT( ( lhs ^ rhs ) == ( lhs ^ (unsigned __int16)rhs ) );
2876 return (T)( lhs ^ (unsigned __int16)rhs );
2877 }
2878};
2879
2880template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int32 >
2881{
2882public:
2883 static T Xor( T lhs, U rhs )
2884 {
2885 // cast forces sign extension to be zeros
2886 _SAFEINT_BINARY_ASSERT( ( lhs ^ rhs ) == ( lhs ^ (unsigned __int32)rhs ) );
2887 return (T)( lhs ^ (unsigned __int32)rhs );
2888 }
2889};
2890
2891#pragma warning(pop)
2892} // namespace details
2893
2894} // namespace utilities
2895
2896} // namespace msl
2897
2898#pragma pack(pop)
#define U(x)
Definition: wordpad.c:45
#define __int8
Definition: basetyps.h:25
#define __int16
Definition: basetyps.h:22
#define __int64
Definition: basetyps.h:16
#define __int32
Definition: basetyps.h:19
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
static SafeIntError Addition(const __int64 &lhs, const unsigned __int64 &rhs, __int64 &result)
static SafeIntError Divide(const T &t, const U &u, T &result)
static SafeIntError Divide(const T &t, const U &u, T &result)
static SafeIntError Divide(const T &t, const unsigned __int64 &u, T &result)
static SafeIntError RegMultiply(signed __int32 a, const signed __int64 &b, signed __int32 &ret)
static SafeIntError RegMultiply(signed __int32 a, const unsigned __int64 &b, signed __int32 &ret)
static SafeIntError RegMultiply(const signed __int64 &a, signed __int32 b, signed __int64 &ret)
static SafeIntError RegMultiply(const signed __int64 &a, const signed __int64 &b, signed __int64 &ret)
static SafeIntError RegMultiply(const signed __int64 &a, unsigned __int32 b, signed __int64 &ret)
static SafeIntError RegMultiply(const signed __int64 &a, const unsigned __int64 &b, signed __int64 &ret)
static SafeIntError RegMultiply(unsigned __int32 a, const signed __int64 &b, unsigned __int32 &ret)
static SafeIntError RegMultiply(unsigned __int32 a, const unsigned __int64 &b, unsigned __int32 &ret)
static SafeIntError RegMultiply(const unsigned __int64 &a, signed __int32 b, unsigned __int64 &ret)
static SafeIntError RegMultiply(const unsigned __int64 &a, signed __int64 b, unsigned __int64 &ret)
static SafeIntError RegMultiply(const unsigned __int64 &a, unsigned __int32 b, unsigned __int64 &ret)
static SafeIntError RegMultiply(const unsigned __int64 &a, const unsigned __int64 &b, unsigned __int64 &ret)
static SafeIntError Modulus(const T &t, const U &u, T &result)
static SafeIntError Modulus(const T &t, const U &u, T &result)
static SafeIntError Modulus(const T &t, const U &u, T &result)
static SafeIntError Modulus(const T &t, const U &u, T &result)
static SafeIntError Modulus(const T &t, const U &u, T &result)
static SafeIntError Multiply(const __int64 &t, const U &u, __int64 &ret)
static SafeIntError Multiply(const __int64 &t, const __int64 &u, __int64 &ret)
static SafeIntError Multiply(const __int64 &t, const unsigned __int64 &u, __int64 &ret)
static SafeIntError Multiply(const unsigned __int64 &t, const U &u, unsigned __int64 &ret)
static SafeIntError Multiply(const unsigned __int64 &t, const U &u, unsigned __int64 &ret)
static SafeIntError Multiply(const unsigned __int64 &t, const __int64 &u, unsigned __int64 &ret)
static SafeIntError Multiply(const unsigned __int64 &t, const unsigned __int64 &u, unsigned __int64 &ret)
static SafeIntError Subtract(const T &lhs, const U &rhs, U &result)
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
static SafeIntError Subtract(const __int64 &lhs, const unsigned __int64 &rhs, unsigned __int64 &result)
static SafeIntError Subtract(const __int64 &lhs, const unsigned __int64 &rhs, __int64 &result)
#define _ASSERTE(expr)
Definition: crtdbg.h:114
static const WCHAR E[]
Definition: oid.c:1253
unsigned char
Definition: typeof.h:29
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned long
Definition: typeof.h:102
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
method
Definition: dragdrop.c:54
GLdouble GLdouble t
Definition: gl.h:2047
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
boolean suppress
Definition: jpeglib.h:1006
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
#define T
Definition: mbstring.h:31
static const struct update_accum a1
Definition: msg.c:578
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:573
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:89
static unsigned(__cdecl *hash_bstr)(bstr_t s)
static float(__cdecl *square_half_float)(float x
int details
Definition: msacm.c:1366
@ SafeIntDivideByZero
Definition: safeint.h:274
@ SafeIntArithmeticOverflow
Definition: safeint.h:273
Definition: safeint.h:265
#define bool
Definition: nsiface.idl:72
#define signed
Definition: prototyp.h:114
#define _SAFEINT_UNSIGNED_NEGATION_BEHAVIOR()
Definition: safeint.h:253
#define _SAFEINT_BINARY_ASSERT(x)
Definition: safeint.h:242
__WCHAR_TYPE__ wchar_t
Definition: stddef.h:311
#define warning(s)
Definition: debug.h:83
#define true
Definition: stdbool.h:36
#define false
Definition: stdbool.h:37
Definition: pdh_main.c:96
int ret