STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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 
19 namespace msl
20 {
21 
22 namespace utilities
23 {
24 
25 namespace details
26 {
27 #pragma warning(push)
28 #pragma warning(disable:4702)
29 
30 template < typename T >
31 class DependentFalse { public: enum{ value = false }; };
32 
33 template < typename T > class NumericType;
34 
35 template <> class NumericType<bool> { public: enum{ isBool = true, isFloat = false, isInt = false }; };
36 template <> class NumericType<char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
37 template <> class NumericType<unsigned char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
38 template <> class NumericType<signed char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
39 template <> class NumericType<short> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
40 template <> class NumericType<unsigned short> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
41 #ifdef _NATIVE_WCHAR_T_DEFINED
42 template <> class NumericType<wchar_t> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
43 #endif /* _NATIVE_WCHAR_T_DEFINED */
44 template <> class NumericType<int> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
45 template <> class NumericType<unsigned int> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
46 template <> class NumericType<long> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
47 template <> class NumericType<unsigned long> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
48 template <> class NumericType<__int64> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
49 template <> class NumericType<unsigned __int64> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
50 template <> class NumericType<float> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
51 template <> class NumericType<double> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
52 template <> class NumericType<long double> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
53 // Catch-all for anything not supported
54 template < typename T > class NumericType { public: enum{ isBool = false, isFloat = false, isInt = false }; };
55 
56 
57 template < typename T > class IntTraits
58 {
59 public:
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 
104 template < typename T, typename U > class SafeIntCompare
105 {
106 public:
107  enum
108  {
112  isCastOK = ((isLikeSigned && sizeof(T) >= sizeof(U)) ||
113  (IntTraits< T >::isSigned && sizeof(T) > sizeof(U))),
116  };
117 };
118 
119 template < typename U > class SafeIntCompare< float, U >
120 {
121 public:
122  enum
123  {
125  isBothUnsigned = false,
127  isCastOK = true
128  };
129 };
130 
131 template < typename U > class SafeIntCompare< double, U >
132 {
133 public:
134  enum
135  {
137  isBothUnsigned = false,
139  isCastOK = true
140  };
141 };
142 
143 template < typename U > class SafeIntCompare< long double, U >
144 {
145 public:
146  enum
147  {
149  isBothUnsigned = false,
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 
161 template < typename T, typename U > class IntRegion
162 {
163 public:
164  enum
165  {
166  //unsigned-unsigned zone
172  //unsigned-signed
173  IntZone_UintLT32_IntLT32 = !IntTraits< T >::isSigned && IntTraits< U >::isSigned && SafeIntCompare< T,U >::isBothLT32Bit,
178  IntZone_Uint64_Int64 = IntTraits< T >::isUint64 && IntTraits< U >::isInt64,
179  //signed-signed
184  IntZone_Int64_Int = SafeIntCompare< T,U >::isBothSigned && IntTraits< T >::is64Bit && IntTraits< U >::isLT64Bit,
186  //signed-unsigned
187  IntZone_IntLT32_UintLT32 = IntTraits< T >::isSigned && !IntTraits< U >::isSigned && SafeIntCompare< T,U >::isBothLT32Bit,
193  };
194 };
195 
196 // useful function to help with getting the magnitude of a negative number
198 {
202 };
203 
204 template < typename T >
206 {
207 public:
208  enum
209  {
212  };
213 };
214 
215 template < typename T, int Method = GetAbsMethod< T >::method > class AbsValueHelper;
216 
217 template < typename T > class AbsValueHelper < T, AbsMethodInt >
218 {
219 public:
220  static unsigned __int32 Abs( T t ) throw()
221  {
222  _ASSERTE( t < 0 );
223  return (unsigned __int32)-t;
224  }
225 };
226 
227 template < typename T > class AbsValueHelper < T, AbsMethodInt64 >
228 {
229 public:
230  static unsigned __int64 Abs( T t ) throw()
231  {
232  _ASSERTE( t < 0 );
233  return (unsigned __int64)-t;
234  }
235 };
236 
237 template < typename T > class AbsValueHelper < T, AbsMethodNoop >
238 {
239 public:
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 
248 template < typename T, typename E, bool fSigned > class NegationHelper;
249 
250 template < typename T, typename E > class NegationHelper < T, E, true > // Signed
251 {
252 public:
253  static SafeIntError Negative( T t, T& ret )
254  {
255  // corner case
256  if( t != IntTraits< T >::minInt )
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 
268 template < typename T, typename E > class NegationHelper < T, E, false > // unsigned
269 {
270 public:
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 {
287  CastOK = 0,
295 };
296 
297 template < typename ToType, typename FromType >
299 {
300 public:
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 
330 template < typename T, typename U, typename E,
332 
333 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastOK >
334 {
335 public:
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
345 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastFromFloat >
346 {
347 public:
348  static SafeIntError Cast( U u, T& t )
349  {
350  if( u <= (U)IntTraits< T >::maxInt &&
351  u >= (U)IntTraits< T >::minInt )
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
363 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastFromBool >
364 {
365 public:
366  static SafeIntError Cast( bool b, T& t ) throw()
367  {
368  t = (T)( b ? 1 : 0 );
369  return SafeIntNoError;
370  }
371 };
372 
373 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastToBool >
374 {
375 public:
376  static SafeIntError Cast( T t, bool& b ) throw()
377  {
378  b = !!t;
379  return SafeIntNoError;
380  }
381 };
382 
383 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckLTZero >
384 {
385 public:
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 
399 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckGTMax >
400 {
401 public:
402  static SafeIntError Cast( U u, T& t )
403  {
404  if( u > IntTraits< T >::maxInt )
405  {
406  E::SafeIntOnOverflow();
408  }
409 
410  t = (T)u;
411  return SafeIntNoError;
412  }
413 };
414 
415 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckMinMaxUnsigned >
416 {
417 public:
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 
432 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckMinMaxSigned >
433 {
434 public:
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 {
457 };
458 
459 template < typename T, typename U >
461 {
462 public:
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 ) ||
472  ( IntTraits< U >::isSigned && sizeof(T) < 8 ) ) ? ComparisonMethod_CastInt64 :
475 #endif /* _SAFEINT_USE_ANSI_CONVERSIONS */
476  };
477 };
478 
479 template <typename T, typename U, int Method = ValidComparison< T, U >::method > class EqualityTest;
480 
481 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_Ok >
482 {
483 public:
484  static bool IsEquals( const T t, const U u ) throw() { return ( t == u ); }
485 };
486 
487 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_CastInt >
488 {
489 public:
490  static bool IsEquals( const T t, const U u ) throw() { return ( (int)t == (int)u ); }
491 };
492 
493 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_CastInt64 >
494 {
495 public:
496  static bool IsEquals( const T t, const U u ) throw() { return ( (__int64)t == (__int64)u ); }
497 };
498 
499 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_UnsignedT >
500 {
501 public:
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 
515 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_UnsignedU>
516 {
517 public:
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 
531 template <typename T, typename U, int Method = ValidComparison< T, U >::method > class GreaterThanTest;
532 
533 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_Ok >
534 {
535 public:
536  static bool GreaterThan( const T t, const U u ) throw() { return ( t > u ); }
537 };
538 
539 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_CastInt >
540 {
541 public:
542  static bool GreaterThan( const T t, const U u ) throw() { return ( (int)t > (int)u ); }
543 };
544 
545 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_CastInt64 >
546 {
547 public:
548  static bool GreaterThan( const T t, const U u ) throw() { return ( (__int64)t > (__int64)u ); }
549 };
550 
551 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_UnsignedT >
552 {
553 public:
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 
567 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_UnsignedU >
568 {
569 public:
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
585 template <typename T, typename U, typename E, int Method = ValidComparison< T, U >::method > class ModulusHelper;
586 
587 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_Ok>
588 {
589 public:
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 
614 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_CastInt>
615 {
616 public:
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 
641 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_CastInt64>
642 {
643 public:
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
667 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_UnsignedT>
668 {
669 public:
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  {
682  result = (T)(t % AbsValueHelper< U >::Abs(u));
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
694 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_UnsignedU>
695 {
696 public:
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
739 };
740 
741 template < typename T, typename U >
743 {
744 public:
745  enum
746  {
747  // unsigned-unsigned
755  // unsigned-signed
762  // signed-signed
769  // signed-unsigned
777  };
778 };
779 
780 template <typename T, typename U, typename E, int Method = MultiplicationMethod< T, U >::method > class MultiplicationHelper;
781 
782 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastInt>
783 {
784 public:
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 
801 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastUint >
802 {
803 public:
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 
820 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastInt64>
821 {
822 public:
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 
828  if(tmp > (__int64)IntTraits< T >::maxInt || tmp < (__int64)IntTraits< T >::minInt)
829  {
830  E::SafeIntOnOverflow();
832  }
833 
834  ret = (T)tmp;
835  return SafeIntNoError;
836  }
837 };
838 
839 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastUint64>
840 {
841 public:
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
860 template < typename T, typename U, typename E > class LargeIntRegMultiply;
861 
862 template< typename E > class LargeIntRegMultiply< unsigned __int64, unsigned __int64, E >
863 {
864 public:
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 
929 template< typename E > class LargeIntRegMultiply< unsigned __int64, unsigned __int32, E >
930 {
931 public:
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 
975 template< typename E > class LargeIntRegMultiply< unsigned __int64, signed __int32, E >
976 {
977 public:
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 
990 template< typename E > class LargeIntRegMultiply< unsigned __int64, signed __int64, E >
991 {
992 public:
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 
1005 template< typename E > class LargeIntRegMultiply< signed __int32, unsigned __int64, E >
1006 {
1007 public:
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 
1059 template < typename E > class LargeIntRegMultiply< unsigned __int32, unsigned __int64, E >
1060 {
1061 public:
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 
1089 template < typename E > class LargeIntRegMultiply< unsigned __int32, signed __int64, E >
1090 {
1091 public:
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 
1104 template < typename E > class LargeIntRegMultiply< signed __int64, signed __int64, E >
1105 {
1106 public:
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 
1157 template < typename E > class LargeIntRegMultiply< signed __int64, unsigned __int32, E >
1158 {
1159 public:
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 
1200 template < typename E > class LargeIntRegMultiply< signed __int64, signed __int32, E >
1201 {
1202 public:
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 
1253 template < typename E > class LargeIntRegMultiply< signed __int32, signed __int64, E >
1254 {
1255 public:
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 
1306 template < typename E > class LargeIntRegMultiply< signed __int64, unsigned __int64, E >
1307 {
1308 public:
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 
1351 template < typename E > class MultiplicationHelper< unsigned __int64, unsigned __int64, E, MultiplicationState_Uint64Uint64 >
1352 {
1353 public:
1354  static SafeIntError Multiply( const unsigned __int64& t, const unsigned __int64& u, unsigned __int64& ret )
1355  {
1357  }
1358 };
1359 
1360 template < typename U, typename E > class MultiplicationHelper<unsigned __int64, U, E, MultiplicationState_Uint64Uint >
1361 {
1362 public:
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
1371 template < typename T, typename E > class MultiplicationHelper< T, unsigned __int64, E, MultiplicationState_UintUint64 >
1372 {
1373 public:
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 
1390 template < typename U, typename E > class MultiplicationHelper< unsigned __int64, U, E, MultiplicationState_Uint64Int >
1391 {
1392 public:
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 
1400 template < typename E > class MultiplicationHelper<unsigned __int64, __int64, E, MultiplicationState_Uint64Int64 >
1401 {
1402 public:
1403  static SafeIntError Multiply(const unsigned __int64& t, const __int64& u, unsigned __int64& ret)
1404  {
1406  }
1407 };
1408 
1409 template < typename T, typename E > class MultiplicationHelper< T, __int64, E, MultiplicationState_UintInt64 >
1410 {
1411 public:
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 
1428 template < typename U, typename E > class MultiplicationHelper<__int64, U, E, MultiplicationState_Int64Uint >
1429 {
1430 public:
1431  //U is unsigned up to 32-bit
1432  static SafeIntError Multiply( const __int64& t, const U& u, __int64& ret )
1433  {
1434  return LargeIntRegMultiply< __int64, unsigned __int32, E >::RegMultiply( t, (unsigned __int32)u, ret );
1435  }
1436 };
1437 
1438 template < typename E > class MultiplicationHelper<__int64, __int64, E, MultiplicationState_Int64Int64 >
1439 {
1440 public:
1441  static SafeIntError Multiply( const __int64& t, const __int64& u, __int64& ret )
1442  {
1444  }
1445 };
1446 
1447 template < typename U, typename E > class MultiplicationHelper<__int64, U, E, MultiplicationState_Int64Int>
1448 {
1449 public:
1450  //U is signed up to 32-bit
1451  static SafeIntError Multiply( const __int64& t, U u, __int64& ret )
1452  {
1453  return LargeIntRegMultiply< __int64, __int32, E >::RegMultiply( t, (__int32)u, ret );
1454  }
1455 };
1456 
1457 template < typename T, typename E > class MultiplicationHelper< T, unsigned __int64, E, MultiplicationState_IntUint64 >
1458 {
1459 public:
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 
1476 template < typename E > class MultiplicationHelper<__int64, unsigned __int64, E, MultiplicationState_Int64Uint64>
1477 {
1478 public:
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 
1486 template < typename T, typename E > class MultiplicationHelper< T, __int64, E, MultiplicationState_IntInt64>
1487 {
1488 public:
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 {
1513 };
1514 
1515 template < typename T, typename U > class DivisionMethod
1516 {
1517 public:
1518  enum
1519  {
1528  };
1529 };
1530 
1531 template < typename T, typename U, typename E, int Method = DivisionMethod< T, U >::method > class DivisionHelper;
1532 
1533 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_OK >
1534 {
1535 public:
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 
1549 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_UnsignedSigned>
1550 {
1551 public:
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 
1579 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedUnsigned32 >
1580 {
1581 public:
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 
1602 template < typename T, typename E > class DivisionHelper< T, unsigned __int64, E, DivisionState_SignedUnsigned64 >
1603 {
1604 public:
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
1623  if( t == IntTraits< T >::minInt && u == (unsigned __int64)IntTraits< T >::minInt )
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 
1636 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedUnsigned>
1637 {
1638 public:
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 
1654 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedSigned>
1655 {
1656 public:
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 {
1695 };
1696 
1697 template< typename T, typename U >
1699 {
1700 public:
1701  enum
1702  {
1703  //unsigned-unsigned
1709  //unsigned-signed
1716  //signed-signed
1723  //signed-unsigned
1731  };
1732 };
1733 
1734 template < typename T, typename U, typename E, int Method = AdditionMethod< T, U >::method > class AdditionHelper;
1735 
1736 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastIntCheckMax >
1737 {
1738 public:
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 
1755 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUintCheckOverflow >
1756 {
1757 public:
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 
1774 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUintCheckOverflowMax>
1775 {
1776 public:
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 
1793 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckOverflow>
1794 {
1795 public:
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 
1813 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckOverflowMax >
1814 {
1815 public:
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 
1833 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastIntCheckMinMax >
1834 {
1835 public:
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 
1841  if( tmp <= (__int32)IntTraits< T >::maxInt && tmp >= (__int32)IntTraits< T >::minInt )
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)
1854 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckMinMax >
1855 {
1856 public:
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 
1862  if( tmp <= (__int64)IntTraits< T >::maxInt && tmp >= (__int64)IntTraits< T >::minInt )
1863  {
1864  result = (T)tmp;
1865  return SafeIntNoError;
1866  }
1867 
1868  E::SafeIntOnOverflow();
1870  // return E::SafeIntOnOverflow2();
1871  }
1872 };
1873 #pragma warning(pop)
1874 
1875 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckMax >
1876 {
1877 public:
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 
1894 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckMinMax >
1895 {
1896 public:
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 
1931 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckMinMax2>
1932 {
1933 public:
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 
1963 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflow>
1964 {
1965 public:
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 
1995 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflowMinMax>
1996 {
1997 public:
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 
2017 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflowMax >
2018 {
2019 public:
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 
2036 template < typename E > class AdditionHelper < __int64, unsigned __int64, E, AdditionState_ManualCheckInt64Uint64 >
2037 {
2038 public:
2039  static SafeIntError Addition( const __int64& lhs, const unsigned __int64& rhs, __int64& result ) throw()
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 
2055 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_ManualCheck >
2056 {
2057 public:
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
2104 };
2105 
2106 template < typename T, typename U > class SubtractionMethod
2107 {
2108 public:
2109  enum
2110  {
2111  // unsigned-unsigned
2117  // unsigned-signed
2124  // signed-signed
2131  // signed-unsigned
2139  };
2140 };
2141 
2142 // this is for the case of U - SafeInt< T, E >
2143 template < typename T, typename U > class SubtractionMethod2
2144 {
2145 public:
2146  enum
2147  {
2148  // unsigned-unsigned
2154  // unsigned-signed
2161  // signed-signed
2168  // signed-unsigned
2176  };
2177 };
2178 
2179 template < typename T, typename U, typename E, int Method = SubtractionMethod< T, U >::method > class SubtractionHelper;
2180 
2181 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_BothUnsigned >
2182 {
2183 public:
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 
2198 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_BothUnsigned2 >
2199 {
2200 public:
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);
2208  return SafeCastHelper< U, T, E>::Cast( tmp, result);
2209  }
2210 
2211  E::SafeIntOnOverflow();
2213  }
2214 };
2215 
2216 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastIntCheckMinMax >
2217 {
2218 public:
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 
2236 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_CastIntCheckMinMax2 >
2237 {
2238 public:
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 
2245  return SafeCastHelper< T, __int32, E >::Cast( tmp, result );
2246  }
2247 };
2248 
2249 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastIntCheckMin >
2250 {
2251 public:
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 
2269 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastInt64CheckMinMax >
2270 {
2271 public:
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 
2278  return SafeCastHelper< T, __int64, E >::Cast( tmp, result );
2279  }
2280 };
2281 
2282 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_CastInt64CheckMinMax2 >
2283 {
2284 public:
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 
2291  return SafeCastHelper< T, __int64, E >::Cast( tmp, result );
2292  }
2293 };
2294 
2295 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastInt64CheckMin >
2296 {
2297 public:
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 
2315 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Uint64Int >
2316 {
2317 public:
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 
2347 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Uint64Int2 >
2348 {
2349 public:
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 
2392 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_UintInt64 >
2393 {
2394 public:
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 
2427 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_UintInt642 >
2428 {
2429 public:
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 
2457 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Int64Int >
2458 {
2459 public:
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 
2487 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Int64Int2 >
2488 {
2489 public:
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 
2531 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_IntInt64 >
2532 {
2533 public:
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 
2595 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_IntInt642 >
2596 {
2597 public:
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 
2616 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Int64Uint >
2617 {
2618 public:
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 
2636 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Int64Uint2 >
2637 {
2638 public:
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 
2655 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_IntUint64 >
2656 {
2657 public:
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 
2689 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_IntUint642 >
2690 {
2691 public:
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 
2706 template < typename E > class SubtractionHelper< __int64, unsigned __int64, E, SubtractionState_Int64Uint64 >
2707 {
2708 public:
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 
2724 template < typename E > class SubtractionHelper< __int64, unsigned __int64, E, SubtractionState_Int64Uint642 >
2725 {
2726 public:
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 {
2748 };
2749 
2750 template < typename T, typename U > class BinaryMethod
2751 {
2752 public:
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 ) ||
2765  };
2766 };
2767 
2768 template < typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryAndHelper;
2769 
2770 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_OK >
2771 {
2772 public:
2773  static T And( T lhs, U rhs ){ return (T)( lhs & rhs ); }
2774 };
2775 
2776 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int8 >
2777 {
2778 public:
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 
2787 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int16 >
2788 {
2789 public:
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 
2798 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int32 >
2799 {
2800 public:
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 
2809 template < typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryOrHelper;
2810 
2811 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_OK >
2812 {
2813 public:
2814  static T Or( T lhs, U rhs ){ return (T)( lhs | rhs ); }
2815 };
2816 
2817 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int8 >
2818 {
2819 public:
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 
2828 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int16 >
2829 {
2830 public:
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 
2839 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int32 >
2840 {
2841 public:
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 
2850 template <typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryXorHelper;
2851 
2852 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_OK >
2853 {
2854 public:
2855  static T Xor( T lhs, U rhs ){ return (T)( lhs ^ rhs ); }
2856 };
2857 
2858 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int8 >
2859 {
2860 public:
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 
2869 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int16 >
2870 {
2871 public:
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 
2880 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int32 >
2881 {
2882 public:
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)
AdditionState
Definition: safeint_internal.h:1677
Definition: safeint_internal.h:70
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2272
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2790
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:644
static unsigned __int64 Abs(T t)
Definition: safeint_internal.h:230
static const T maxInt
Definition: safeint_internal.h:87
Definition: safeint_internal.h:1694
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2430
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:548
Definition: safeint_internal.h:64
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:402
static T Abs(T t)
Definition: safeint_internal.h:240
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2298
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1966
Definition: safeint_internal.h:2100
Definition: safeint_internal.h:780
Definition: safeint_internal.h:585
Definition: safeint_internal.h:205
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1878
Definition: safeint_internal.h:1693
Definition: safeint_internal.h:1507
Definition: safeint_internal.h:77
DivisionState
Definition: safeint_internal.h:1505
Definition: safeint.h:255
Definition: safeint_internal.h:66
Definition: safeint_internal.h:287
static SafeIntError Negative(T t, T &ret)
Definition: safeint_internal.h:271
static SafeIntError Cast(bool b, T &t)
Definition: safeint_internal.h:366
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2692
Definition: safeint_internal.h:2089
Definition: safeint_internal.h:76
Definition: safeint_internal.h:531
Definition: safeint_internal.h:2103
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1582
Definition: safeint_internal.h:215
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1998
Definition: safeint_internal.h:1512
_In_ long
Definition: corecrt_wstdlib.h:88
Definition: safeint_internal.h:2096
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:617
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2814
Definition: safeint_internal.h:479
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1796
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:518
Definition: safeint_internal.h:57
Definition: safeint_internal.h:199
Definition: safeint_internal.h:67
Definition: safeint_internal.h:742
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:348
Definition: safeint_internal.h:460
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:590
Definition: safeint_internal.h:2085
static SafeIntError RegMultiply(const unsigned __int64 &a, unsigned __int32 b, unsigned __int64 &ret)
Definition: safeint_internal.h:932
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2318
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2861
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:805
Definition: safeint_internal.h:293
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:435
Definition: safeint_internal.h:31
static SafeIntError Subtract(const __int64 &lhs, const unsigned __int64 &rhs, __int64 &result)
Definition: safeint_internal.h:2709
Definition: safeint_internal.h:2090
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:536
Definition: safeint_internal.h:54
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1857
Definition: safeint_internal.h:54
static SafeIntError Cast(T t, bool &b)
Definition: safeint_internal.h:376
Definition: safeint_internal.h:468
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2619
Definition: safeint_internal.h:75
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2831
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1758
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:554
static SafeIntError RegMultiply(const unsigned __int64 &a, const unsigned __int64 &b, unsigned __int64 &ret)
Definition: safeint_internal.h:865
Definition: safeint_internal.h:738
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2883
Definition: safeint_internal.h:2746
static SafeIntError Subtract(const T &lhs, const U &rhs, U &result)
Definition: safeint_internal.h:2201
static SafeIntError RegMultiply(const signed __int64 &a, const signed __int64 &b, signed __int64 &ret)
Definition: safeint_internal.h:1107
Definition: safeint_internal.h:79
MultiplicationState
Definition: safeint_internal.h:720
Definition: safeint_internal.h:2744
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2285
static SafeIntError Multiply(const unsigned __int64 &t, const U &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1364
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2779
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:824
#define _ASSERTE(expr)
Definition: crtdbg.h:707
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1641
static SafeIntError Multiply(const __int64 &t, const __int64 &u, __int64 &ret)
Definition: safeint_internal.h:1441
Definition: safeint_internal.h:112
Definition: safeint.h:265
Definition: safeint_internal.h:454
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2820
Definition: safeint_internal.h:2086
Definition: safeint_internal.h:2768
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1739
Definition: safeint_internal.h:200
static SafeIntError RegMultiply(const unsigned __int64 &a, signed __int64 b, unsigned __int64 &ret)
Definition: safeint_internal.h:993
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:843
static void SafeIntOnDivZero()
Definition: safeint_internal.h:99
Definition: safeint_internal.h:2101
Definition: safeint_internal.h:74
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:496
Definition: safeint_internal.h:289
#define bool
Definition: stdbool.h:15
Definition: safeint_internal.h:2097
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1836
Definition: safeint_internal.h:2745
static SafeIntError Divide(const T &t, const unsigned __int64 &u, T &result)
Definition: safeint_internal.h:1605
Definition: safeint_internal.h:104
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:484
Definition: safeint_internal.h:71
Definition: safeint_internal.h:453
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:490
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2490
unsigned char
Definition: mbstring.h:107
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2855
char int *typedef int(__CRTDECL *_CRT_REPORT_HOOKW)(int
Definition: crtdbg.h:45
static SafeIntError RegMultiply(const unsigned __int64 &a, signed __int32 b, unsigned __int64 &ret)
Definition: safeint_internal.h:978
static unsigned __int32 Abs(T t)
Definition: safeint_internal.h:220
Definition: safeint_internal.h:72
Definition: safeint_internal.h:1515
Definition: safeint_internal.h:54
static SafeIntError Multiply(const T &t, const __int64 &u, T &ret)
Definition: safeint_internal.h:1413
#define false
Definition: stdbool.h:16
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2058
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2395
Definition: safeint_internal.h:298
Definition: safeint_internal.h:292
static SafeIntError Addition(const __int64 &lhs, const unsigned __int64 &rhs, __int64 &result)
Definition: safeint_internal.h:2039
static SafeIntError Multiply(const unsigned __int64 &t, const __int64 &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1403
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2773
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2219
Definition: safeint_internal.h:1531
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2184
BinaryState
Definition: safeint_internal.h:2742
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:670
static SafeIntError Subtract(const __int64 &lhs, const unsigned __int64 &rhs, unsigned __int64 &result)
Definition: safeint_internal.h:2729
SafeIntError
Definition: safeint.h:261
Definition: safeint_internal.h:294
Definition: safeint_internal.h:65
Definition: safeint_internal.h:31
Definition: safeint_internal.h:1734
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1552
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2658
Definition: safeint_internal.h:291
static SafeIntError Negative(T t, T &ret)
Definition: safeint_internal.h:253
static SafeIntError RegMultiply(signed __int32 a, const unsigned __int64 &b, signed __int32 &ret)
Definition: safeint_internal.h:1008
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2801
static void SafeIntOnOverflow()
Definition: safeint_internal.h:95
Definition: safeint_internal.h:2088
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:697
Definition: safeint_internal.h:2098
static const T minInt
Definition: safeint_internal.h:88
Definition: safeint.h:263
Definition: safeint_internal.h:455
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:502
Definition: safeint_internal.h:161
AbsMethod
Definition: safeint_internal.h:197
Definition: safeint_internal.h:2143
Definition: safeint_internal.h:860
unsigned short wchar_t
Definition: sourceannotations.h:25
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1934
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:542
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:386
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1816
static SafeIntError Multiply(const __int64 &t, U u, __int64 &ret)
Definition: safeint_internal.h:1451
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1897
static SafeIntError RegMultiply(const signed __int64 &a, const unsigned __int64 &b, signed __int64 &ret)
Definition: safeint_internal.h:1309
Definition: safeint_internal.h:2809
Definition: safeint_internal.h:303
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1536
Definition: safeint_internal.h:456
Definition: safeint_internal.h:33
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:570
Definition: safeint_internal.h:68
static SafeIntError RegMultiply(const signed __int64 &a, signed __int32 b, signed __int64 &ret)
Definition: safeint_internal.h:1203
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2252
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2598
static SafeIntError Multiply(const __int64 &t, const U &u, __int64 &ret)
Definition: safeint_internal.h:1432
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:336
Definition: safeint_internal.h:1698
static SafeIntError RegMultiply(const signed __int64 &a, unsigned __int32 b, signed __int64 &ret)
Definition: safeint_internal.h:1160
Definition: safeint_internal.h:2750
Definition: safeint_internal.h:210
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2239
static SafeIntError RegMultiply(unsigned __int32 a, const unsigned __int64 &b, unsigned __int32 &ret)
Definition: safeint_internal.h:1062
Definition: safeint_internal.h:331
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2350
static SafeIntError RegMultiply(signed __int32 a, const signed __int64 &b, signed __int32 &ret)
Definition: safeint_internal.h:1256
Definition: safeint_internal.h:201
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:786
ComparisonMethod
Definition: safeint_internal.h:450
Definition: safeint_internal.h:69
Definition: safeint_internal.h:248
Definition: safeint_internal.h:288
static SafeIntError Multiply(T t, const __int64 &u, T &ret)
Definition: safeint_internal.h:1490
static SafeIntError Multiply(const unsigned __int64 &t, const unsigned __int64 &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1354
static SafeIntError Multiply(const unsigned __int64 &t, const U &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1394
Definition: safeint_internal.h:2179
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1657
Definition: safeint_internal.h:81
SubtractionState
Definition: safeint_internal.h:2078
Definition: safeint_internal.h:78
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1777
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2640
Definition: safeint_internal.h:290
static SafeIntError Multiply(T t, const unsigned __int64 &u, T &ret)
Definition: safeint_internal.h:1461
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:418
Definition: safeint_internal.h:2087
#define true
Definition: stdbool.h:17
Definition: safeint_internal.h:2747
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2020
static SafeIntError Multiply(const __int64 &t, const unsigned __int64 &u, __int64 &ret)
Definition: safeint_internal.h:1480
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2842
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2534
CastMethod
Definition: safeint_internal.h:285
Definition: safeint_internal.h:2106
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2872
#define _SAFEINT_UNSIGNED_NEGATION_BEHAVIOR()
Definition: safeint.h:244
Definition: safeint_internal.h:2099
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2460
static SafeIntError Multiply(const T &t, const unsigned __int64 &u, T &ret)
Definition: safeint_internal.h:1375
Definition: safeint_internal.h:452
Definition: safeint_internal.h:2850
static SafeIntError RegMultiply(unsigned __int32 a, const signed __int64 &b, unsigned __int32 &ret)
Definition: safeint_internal.h:1092
#define _SAFEINT_BINARY_ASSERT(x)
Definition: safeint.h:233
Definition: safeint_internal.h:73