STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
safeint.h
Go to the documentation of this file.
1 /***
2 *safeint.h - SafeInt class and free-standing functions used to prevent arithmetic overflows
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 *
8 * The SafeInt class is designed to have as low an overhead as possible
9 * while still ensuring that all integer operations are conducted safely.
10 * Nearly every operator has been overloaded, with a very few exceptions.
11 *
12 * A usability-safety trade-off has been made to help ensure safety. This
13 * requires that every operation return either a SafeInt or a bool. If we
14 * allowed an operator to return a base integer type T, then the following
15 * can happen:
16 *
17 * char i = SafeInt<char>(32) * 2 + SafeInt<char>(16) * 4;
18 *
19 * The * operators take precedence, get overloaded, return a char, and then
20 * you have:
21 *
22 * char i = (char)64 + (char)64; //overflow!
23 *
24 * This situation would mean that safety would depend on usage, which isn't
25 * acceptable.
26 *
27 * One key operator that is missing is an implicit cast to type T. The reason for
28 * this is that if there is an implicit cast operator, then we end up with
29 * an ambiguous compile-time precedence. Because of this amiguity, there
30 * are two methods that are provided:
31 *
32 * Casting operators for every native integer type
33 *
34 * SafeInt::Ptr() - returns the address of the internal integer
35 *
36 * The SafeInt class should be used in any circumstances where ensuring
37 * integrity of the calculations is more important than performance. See Performance
38 * Notes below for additional information.
39 *
40 * Many of the conditionals will optimize out or be inlined for a release
41 * build (especially with /Ox), but it does have significantly more overhead,
42 * especially for signed numbers. If you do not _require_ negative numbers, use
43 * unsigned integer types - certain types of problems cannot occur, and this class
44 * performs most efficiently.
45 *
46 * Here's an example of when the class should ideally be used -
47 *
48 * void* AllocateMemForStructs(int StructSize, int HowMany)
49 * {
50 * SafeInt<unsigned long> s(StructSize);
51 *
52 * s *= HowMany;
53 *
54 * return malloc(s);
55 *
56 * }
57 *
58 * Here's when it should NOT be used:
59 *
60 * void foo()
61 * {
62 * int i;
63 *
64 * for(i = 0; i < 0xffff; i++)
65 * ....
66 * }
67 *
68 * Error handling - a SafeInt class will throw exceptions if something
69 * objectionable happens. The exceptions are SafeIntException classes,
70 * which contain an enum as a code.
71 *
72 * Typical usage might be:
73 *
74 * bool foo()
75 * {
76 * SafeInt<unsigned long> s; //note that s == 0 unless set
77 *
78 * try{
79 * s *= 23;
80 * ....
81 * }
82 * catch(SafeIntException err)
83 * {
84 * //handle errors here
85 * }
86 * }
87 *
88 * SafeInt accepts an error policy as an optional template parameter.
89 * We provide two error policy along with SafeInt: SafeIntErrorPolicy_SafeIntException, which
90 * throws SafeIntException in case of error, and SafeIntErrorPolicy_InvalidParameter, which
91 * calls _invalid_parameter to terminate the program.
92 *
93 * You can replace the error policy class with any class you like. This is accomplished by:
94 * 1) Create a class that has the following interface:
95 *
96 * struct YourSafeIntErrorPolicy
97 * {
98 * static __declspec(noreturn) void __stdcall SafeIntOnOverflow()
99 * {
100 * throw YourException( YourSafeIntArithmeticOverflowError );
101 * // or do something else which will terminate the program
102 * }
103 *
104 * static __declspec(noreturn) void __stdcall SafeIntOnDivZero()
105 * {
106 * throw YourException( YourSafeIntDivideByZeroError );
107 * // or do something else which will terminate the program
108 * }
109 * };
110 *
111 * Note that you don't have to throw C++ exceptions, you can throw Win32 exceptions, or do
112 * anything you like, just don't return from the call back into the code.
113 *
114 * 2) Either explicitly declare SafeInts like so:
115 * SafeInt< int, YourSafeIntErrorPolicy > si;
116 * or, before including SafeInt:
117 * #define _SAFEINT_DEFAULT_ERROR_POLICY ::YourSafeIntErrorPolicy
118 *
119 * Performance:
120 *
121 * Due to the highly nested nature of this class, you can expect relatively poor
122 * performance in unoptimized code. In tests of optimized code vs. correct inline checks
123 * in native code, this class has been found to take approximately 8% more CPU time (this varies),
124 * most of which is due to exception handling.
125 *
126 * Binary Operators:
127 *
128 * All of the binary operators have certain assumptions built into the class design.
129 * This is to ensure correctness. Notes on each class of operator follow:
130 *
131 * Arithmetic Operators (*,/,+,-,%)
132 * There are three possible variants:
133 * SafeInt< T, E > op SafeInt< T, E >
134 * SafeInt< T, E > op U
135 * U op SafeInt< T, E >
136 *
137 * The SafeInt< T, E > op SafeInt< U, E > variant is explicitly not supported, and if you try to do
138 * this the compiler with throw the following error:
139 *
140 * error C2593: 'operator *' is ambiguous
141 *
142 * This is because the arithmetic operators are required to return a SafeInt of some type.
143 * The compiler cannot know whether you'd prefer to get a type T or a type U returned. If
144 * you need to do this, you need to extract the value contained within one of the two using
145 * the casting operator. For example:
146 *
147 * SafeInt< T, E > t, result;
148 * SafeInt< U, E > u;
149 *
150 * result = t * (U)u;
151 *
152 * Comparison Operators:
153 *
154 * Because each of these operators return type bool, mixing SafeInts of differing types is
155 * allowed.
156 *
157 * Shift Operators:
158 *
159 * Shift operators always return the type on the left hand side of the operator. Mixed type
160 * operations are allowed because the return type is always known.
161 *
162 * Boolean Operators:
163 *
164 * Like comparison operators, these overloads always return type bool, and mixed-type SafeInts
165 * are allowed. Additionally, specific overloads exist for type bool on both sides of the
166 * operator.
167 *
168 * Binary Operators:
169 *
170 * Mixed-type operations are discouraged, however some provision has been made in order to
171 * enable things like:
172 *
173 * SafeInt<char> c = 2;
174 *
175 * if(c & 0x02)
176 * ...
177 *
178 * The "0x02" is actually an int, and it needs to work.
179 * In the case of binary operations on integers smaller than 32-bit, or of mixed type, corner
180 * cases do exist where you could get unexpected results. In any case where SafeInt returns a different
181 * result than the underlying operator, it will call _ASSERTE(). You should examine your code and cast things
182 * properly so that you are not programming with side effects.
183 *
184 * Comparison Operators and ANSI Conversions:
185 *
186 * The comparison operator behavior in this class varies from the ANSI definition.
187 * As an example, consider the following:
188 *
189 * unsigned int l = 0xffffffff;
190 * char c = -1;
191 *
192 * if(c == l)
193 * printf("Why is -1 equal to 4 billion???\n");
194 *
195 * The problem here is that c gets cast to an int, now has a value of 0xffffffff, and then gets
196 * cast again to an unsigned int, losing the true value. This behavior is despite the fact that
197 * an __int64 exists, and the following code will yield a different (and intuitively correct)
198 * answer:
199 *
200 * if((__int64)c == (__int64)l))
201 * printf("Why is -1 equal to 4 billion???\n");
202 * else
203 * printf("Why doesn't the compiler upcast to 64-bits when needed?\n");
204 *
205 * Note that combinations with smaller integers won't display the problem - if you
206 * changed "unsigned int" above to "unsigned short", you'd get the right answer.
207 *
208 * If you prefer to retain the ANSI standard behavior insert, before including safeint.h:
209 *
210 * #define _SAFEINT_ANSI_CONVERSIONS 1
211 *
212 * into your source. Behavior differences occur in the following cases:
213 * 8, 16, and 32-bit signed int, unsigned 32-bit int
214 * any signed int, unsigned 64-bit int
215 * Note - the signed int must be negative to show the problem
216 *
217 ****/
218 
219 #pragma once
220 
221 #include <corecrt.h>
222 #include <crtdbg.h>
223 
224 #if !defined (_SAFEINT_DEFAULT_ERROR_POLICY)
225 #define _SAFEINT_DEFAULT_ERROR_POLICY SafeIntErrorPolicy_SafeIntException
226 #endif /* !defined (_SAFEINT_DEFAULT_ERROR_POLICY) */
227 
228 #if !defined (_SAFEINT_SHIFT_ASSERT)
229 #define _SAFEINT_SHIFT_ASSERT(x) _ASSERTE(x)
230 #endif /* !defined (_SAFEINT_SHIFT_ASSERT) */
231 
232 #if !defined (_SAFEINT_BINARY_ASSERT)
233 #define _SAFEINT_BINARY_ASSERT(x) _ASSERTE(x)
234 #endif /* !defined (_SAFEINT_BINARY_ASSERT) */
235 
236 #if !defined (_SAFEINT_EXCEPTION_ASSERT)
237 #define _SAFEINT_EXCEPTION_ASSERT()
238 #endif /* !defined (_SAFEINT_EXCEPTION_ASSERT) */
239 
240 // by default, SafeInt will accept negation of an unsigned int;
241 // if you wish to disable it or assert, you can define the following
242 // macro to be a static assert or a runtime assert
243 #if !defined (_SAFEINT_UNSIGNED_NEGATION_BEHAVIOR)
244 #define _SAFEINT_UNSIGNED_NEGATION_BEHAVIOR()
245 #endif /* !defined (_SAFEINT_UNSIGNED_NEGATION_BEHAVIOR) */
246 
247 // See above "Comparison Operators and ANSI Conversions" for an explanation
248 // of _SAFEINT_USE_ANSI_CONVERSIONS
249 #if !defined (_SAFEINT_USE_ANSI_CONVERSIONS)
250 #define _SAFEINT_USE_ANSI_CONVERSIONS 0
251 #endif /* !defined (_SAFEINT_USE_ANSI_CONVERSIONS) */
252 
253 #pragma pack(push, _CRT_PACKING)
254 
255 namespace msl
256 {
257 
258 namespace utilities
259 {
260 
262 {
266 };
267 
268 } // namespace utilities
269 
270 } // namespace msl
271 
272 #include "safeint_internal.h"
273 
274 namespace msl
275 {
276 
277 namespace utilities
278 {
279 
281 {
282 public:
285  {
286  m_code = code;
287  }
289 };
290 
292 {
293  static __declspec(noreturn) void SafeIntOnOverflow()
294  {
297  }
298 
299  static __declspec(noreturn) void SafeIntOnDivZero()
300  {
303  }
304 };
305 
307 {
308  static __declspec(noreturn) void SafeIntOnOverflow()
309  {
311  _CRT_SECURE_INVALID_PARAMETER("SafeInt Arithmetic Overflow");
312  }
313 
314  static __declspec(noreturn) void SafeIntOnDivZero()
315  {
317  _CRT_SECURE_INVALID_PARAMETER("SafeInt Divide By Zero");
318  }
319 };
320 
321 // Free-standing functions that can be used where you only need to check one operation
322 // non-class helper function so that you can check for a cast's validity
323 // and handle errors how you like
324 
325 template < typename T, typename U >
326 inline bool SafeCast( const T From, U& To ) throw()
327 {
328  return (details::SafeCastHelper< U, T,
329  details::SafeIntErrorPolicy_NoThrow >::Cast( From, To ) == SafeIntNoError);
330 }
331 
332 template < typename T, typename U >
333 inline bool SafeEquals( const T t, const U u ) throw()
334 {
336 }
337 
338 template < typename T, typename U >
339 inline bool SafeNotEquals( const T t, const U u ) throw()
340 {
342 }
343 
344 template < typename T, typename U >
345 inline bool SafeGreaterThan( const T t, const U u ) throw()
346 {
348 }
349 
350 template < typename T, typename U >
351 inline bool SafeGreaterThanEquals( const T t, const U u ) throw()
352 {
354 }
355 
356 template < typename T, typename U >
357 inline bool SafeLessThan( const T t, const U u ) throw()
358 {
360 }
361 
362 template < typename T, typename U >
363 inline bool SafeLessThanEquals( const T t, const U u ) throw()
364 {
366 }
367 
368 template < typename T, typename U >
369 inline bool SafeModulus( const T& t, const U& u, T& result ) throw()
370 {
372 }
373 
374 template < typename T, typename U >
375 inline bool SafeMultiply( T t, U u, T& result ) throw()
376 {
377  return ( details::MultiplicationHelper< T, U,
378  details::SafeIntErrorPolicy_NoThrow >::Multiply( t, u, result ) == SafeIntNoError );
379 }
380 
381 template < typename T, typename U >
382 inline bool SafeDivide( T t, U u, T& result ) throw()
383 {
384  return ( details::DivisionHelper< T, U,
385  details::SafeIntErrorPolicy_NoThrow >::Divide( t, u, result ) == SafeIntNoError );
386 }
387 
388 template < typename T, typename U >
389 inline bool SafeAdd( T t, U u, T& result ) throw()
390 {
391  return ( details::AdditionHelper< T, U,
392  details::SafeIntErrorPolicy_NoThrow >::Addition( t, u, result ) == SafeIntNoError );
393 }
394 
395 template < typename T, typename U >
396 inline bool SafeSubtract( T t, U u, T& result ) throw()
397 {
398  return ( details::SubtractionHelper< T, U,
399  details::SafeIntErrorPolicy_NoThrow >::Subtract( t, u, result ) == SafeIntNoError );
400 }
401 
402 // SafeInt class
403 template < typename T, typename E = _SAFEINT_DEFAULT_ERROR_POLICY >
404 class SafeInt
405 {
406 public:
407  SafeInt() throw()
408  {
409  static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
410  m_int = 0;
411  }
412 
413  // Having a constructor for every type of int
414  // avoids having the compiler evade our checks when doing implicit casts -
415  // e.g., SafeInt<char> s = 0x7fffffff;
416  SafeInt( const T& i ) throw()
417  {
418  static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
419  //always safe
420  m_int = i;
421  }
422 
423  // provide explicit boolean converter
424  SafeInt( bool b ) throw()
425  {
426  static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
427  m_int = b ? 1 : 0;
428  }
429 
430  template < typename U >
432  {
433  static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
434  *this = SafeInt< T, E >( (U)u );
435  }
436 
437  template < typename U >
438  SafeInt( const U& i )
439  {
440  static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
441  // SafeCast will throw exceptions if i won't fit in type T
443  }
444 
445  // now start overloading operators
446  // assignment operator
447  // constructors exist for all int types and will ensure safety
448 
449  template < typename U >
450  SafeInt< T, E >& operator =( const U& rhs )
451  {
452  // use constructor to test size
453  // constructor is optimized to do minimal checking based
454  // on whether T can contain U
455  // note - do not change this
456  *this = SafeInt< T, E >( rhs );
457  return *this;
458  }
459 
460  SafeInt< T, E >& operator =( const T& rhs ) throw()
461  {
462  m_int = rhs;
463  return *this;
464  }
465 
466  template < typename U >
468  {
470  return *this;
471  }
472 
474  {
475  m_int = rhs.m_int;
476  return *this;
477  }
478 
479  // Casting operators
480 
481  operator bool() const throw()
482  {
483  return !!m_int;
484  }
485 
486  operator char() const
487  {
488  char val;
490  return val;
491  }
492 
493  operator signed char() const
494  {
495  signed char val;
497  return val;
498  }
499 
500  operator unsigned char() const
501  {
502  unsigned char val;
504  return val;
505  }
506 
507  operator __int16() const
508  {
509  __int16 val;
511  return val;
512  }
513 
514  operator unsigned __int16() const
515  {
516  unsigned __int16 val;
518  return val;
519  }
520 
521  operator __int32() const
522  {
523  __int32 val;
525  return val;
526  }
527 
528  operator unsigned __int32() const
529  {
530  unsigned __int32 val;
532  return val;
533  }
534 
535  // The compiler knows that int == __int32
536  // but not that long == __int32
537  operator long() const
538  {
539  long val;
541  return val;
542  }
543 
544  operator unsigned long() const
545  {
546  unsigned long val;
548  return val;
549  }
550 
551  operator __int64() const
552  {
553  __int64 val;
555  return val;
556  }
557 
558  operator unsigned __int64() const
559  {
560  unsigned __int64 val;
562  return val;
563  }
564 
565 #ifdef _NATIVE_WCHAR_T_DEFINED
566  operator wchar_t() const
567  {
568  unsigned __int16 val;
570  return val;
571  }
572 #endif /* _NATIVE_WCHAR_T_DEFINED */
573 
574  // If you need a pointer to the data
575  // this could be dangerous, but allows you to correctly pass
576  // instances of this class to APIs that take a pointer to an integer
577  // also see overloaded address-of operator below
578  T* Ptr() throw() { return &m_int; }
579  const T* Ptr() const throw() { return &m_int; }
580  const T& Ref() const throw() { return m_int; }
581 
582  // Unary operators
583  bool operator !() const throw() { return (!m_int) ? true : false; }
584 
585  // operator + (unary)
586  // note - normally, the '+' and '-' operators will upcast to a signed int
587  // for T < 32 bits. This class changes behavior to preserve type
588  const SafeInt< T, E >& operator +() const throw() { return *this; };
589 
590  //unary -
592  {
593  // Note - unsigned still performs the bitwise manipulation
594  // will warn at level 2 or higher if the value is 32-bit or larger
595  T tmp;
597  return SafeInt< T, E >( tmp );
598  }
599 
600  // prefix increment operator
602  {
604  {
605  ++m_int;
606  return *this;
607  }
608  E::SafeIntOnOverflow();
609  }
610 
611  // prefix decrement operator
613  {
615  {
616  --m_int;
617  return *this;
618  }
619  E::SafeIntOnOverflow();
620  }
621 
622  // note that postfix operators have inherently worse perf
623  // characteristics
624 
625  // postfix increment operator
626  SafeInt< T, E > operator ++( int ) // dummy arg to comply with spec
627  {
629  {
630  SafeInt< T, E > tmp( m_int );
631 
632  m_int++;
633  return tmp;
634  }
635  E::SafeIntOnOverflow();
636  }
637 
638  // postfix decrement operator
639  SafeInt< T, E > operator --( int ) // dummy arg to comply with spec
640  {
642  {
643  SafeInt< T, E > tmp( m_int );
644  m_int--;
645  return tmp;
646  }
647  E::SafeIntOnOverflow();
648  }
649 
650  // One's complement
651  // Note - this operator will normally change size to an int
652  // cast in return improves perf and maintains type
653  SafeInt< T, E > operator ~() const throw() { return SafeInt< T, E >( (T)~m_int ); }
654 
655  // Binary operators
656  //
657  // arithmetic binary operators
658  // % modulus
659  // * multiplication
660  // / division
661  // + addition
662  // - subtraction
663  //
664  // For each of the arithmetic operators, you will need to
665  // use them as follows:
666  //
667  // SafeInt<char> c = 2;
668  // SafeInt<int> i = 3;
669  //
670  // SafeInt<int> i2 = i op (char)c;
671  // OR
672  // SafeInt<char> i2 = (int)i op c;
673  //
674  // The base problem is that if the lhs and rhs inputs are different SafeInt types
675  // it is not possible in this implementation to determine what type of SafeInt
676  // should be returned. You have to let the class know which of the two inputs
677  // need to be the return type by forcing the other value to the base integer type.
678  //
679  // Note - as per feedback from Scott Meyers, I'm exploring how to get around this.
680  // 3.0 update - I'm still thinking about this. It can be done with template metaprogramming,
681  // but it is tricky, and there's a perf vs. correctness tradeoff where the right answer
682  // is situational.
683  //
684  // The case of:
685  //
686  // SafeInt< T, E > i, j, k;
687  // i = j op k;
688  //
689  // works just fine and no unboxing is needed because the return type is not ambiguous.
690 
691  // Modulus
692  // Modulus has some convenient properties -
693  // first, the magnitude of the return can never be
694  // larger than the lhs operand, and it must be the same sign
695  // as well. It does, however, suffer from the same promotion
696  // problems as comparisons, division and other operations
697  template < typename U >
699  {
700  T result;
702  return SafeInt< T, E >( result );
703  }
704 
706  {
707  T result;
709  return SafeInt< T, E >( result );
710  }
711 
712  // Modulus assignment
713  template < typename U >
715  {
717  return *this;
718  }
719 
720  template < typename U >
722  {
724  return *this;
725  }
726 
727  // Multiplication
728  template < typename U >
730  {
731  T ret( 0 );
733  return SafeInt< T, E >( ret );
734  }
735 
737  {
738  T ret( 0 );
740  return SafeInt< T, E >( ret );
741  }
742 
743  // Multiplication assignment
745  {
747  return *this;
748  }
749 
750  template < typename U >
752  {
754  return *this;
755  }
756 
757  template < typename U >
759  {
761  return *this;
762  }
763 
764  // Division
765  template < typename U >
767  {
768  T ret( 0 );
770  return SafeInt< T, E >( ret );
771  }
772 
774  {
775  T ret( 0 );
777  return SafeInt< T, E >( ret );
778  }
779 
780  // Division assignment
782  {
784  return *this;
785  }
786 
787  template < typename U > SafeInt< T, E >& operator /=( U i )
788  {
790  return *this;
791  }
792 
793  template < typename U > SafeInt< T, E >& operator /=( SafeInt< U, E > i )
794  {
796  return *this;
797  }
798 
799  // For addition and subtraction
800 
801  // Addition
803  {
804  T ret( 0 );
806  return SafeInt< T, E >( ret );
807  }
808 
809  template < typename U >
811  {
812  T ret( 0 );
814  return SafeInt< T, E >( ret );
815  }
816 
817  //addition assignment
819  {
821  return *this;
822  }
823 
824  template < typename U >
826  {
828  return *this;
829  }
830 
831  template < typename U >
833  {
835  return *this;
836  }
837 
838  // Subtraction
839  template < typename U >
841  {
842  T ret( 0 );
844  return SafeInt< T, E >( ret );
845  }
846 
848  {
849  T ret( 0 );
851  return SafeInt< T, E >( ret );
852  }
853 
854  // Subtraction assignment
856  {
858  return *this;
859  }
860 
861  template < typename U >
863  {
865  return *this;
866  }
867 
868  template < typename U >
870  {
872  return *this;
873  }
874 
875  // Comparison operators
876  // Additional overloads defined outside the class
877  // to allow for cases where the SafeInt is the rhs value
878 
879  // Less than
880  template < typename U >
881  bool operator <( U rhs ) const throw()
882  {
884  }
885 
886  bool operator <( SafeInt< T, E > rhs ) const throw()
887  {
888  return m_int < (T)rhs;
889  }
890 
891  // Greater than or eq.
892  template < typename U >
893  bool operator >=( U rhs ) const throw()
894  {
896  }
897 
898  bool operator >=( SafeInt< T, E > rhs ) const throw()
899  {
900  return m_int >= (T)rhs;
901  }
902 
903  // Greater than
904  template < typename U >
905  bool operator >( U rhs ) const throw()
906  {
908  }
909 
910  bool operator >( SafeInt< T, E > rhs ) const throw()
911  {
912  return m_int > (T)rhs;
913  }
914 
915  // Less than or eq.
916  template < typename U >
917  bool operator <=( U rhs ) const throw()
918  {
920  }
921 
922  bool operator <=( SafeInt< T, E > rhs ) const throw()
923  {
924  return m_int <= (T)rhs;
925  }
926 
927  // Equality
928  template < typename U >
929  bool operator ==( U rhs ) const throw()
930  {
932  }
933 
934  // Need an explicit override for type bool
935  bool operator ==( bool rhs ) const throw()
936  {
937  return ( m_int == 0 ? false : true ) == rhs;
938  }
939 
940  bool operator ==( SafeInt< T, E > rhs ) const throw() { return m_int == (T)rhs; }
941 
942  // != operators
943  template < typename U >
944  bool operator !=( U rhs ) const throw()
945  {
947  }
948 
949  bool operator !=( bool b ) const throw()
950  {
951  return ( m_int == 0 ? false : true ) != b;
952  }
953 
954  bool operator !=( SafeInt< T, E > rhs ) const throw() { return m_int != (T)rhs; }
955 
956  // Shift operators
957  // Note - shift operators ALWAYS return the same type as the lhs
958  // specific version for SafeInt< T, E > not needed -
959  // code path is exactly the same as for SafeInt< U, E > as rhs
960 
961  // Left shift
962  // Also, shifting > bitcount is undefined - trap in debug (check _SAFEINT_SHIFT_ASSERT)
963 
964  template < typename U >
965  SafeInt< T, E > operator <<( U bits ) const throw()
966  {
969 
970  return SafeInt< T, E >( (T)( m_int << bits ) );
971  }
972 
973  template < typename U >
974  SafeInt< T, E > operator <<( SafeInt< U, E > bits ) const throw()
975  {
978 
979  return SafeInt< T, E >( (T)( m_int << (U)bits ) );
980  }
981 
982  // Left shift assignment
983 
984  template < typename U >
985  SafeInt< T, E >& operator <<=( U bits ) throw()
986  {
989 
990  m_int <<= bits;
991  return *this;
992  }
993 
994  template < typename U >
995  SafeInt< T, E >& operator <<=( SafeInt< U, E > bits ) throw()
996  {
999 
1000  m_int <<= (U)bits;
1001  return *this;
1002  }
1003 
1004  // Right shift
1005  template < typename U >
1006  SafeInt< T, E > operator >>( U bits ) const throw()
1007  {
1010 
1011  return SafeInt< T, E >( (T)( m_int >> bits ) );
1012  }
1013 
1014  template < typename U >
1016  {
1019 
1020  return SafeInt< T, E >( (T)(m_int >> (U)bits) );
1021  }
1022 
1023  // Right shift assignment
1024  template < typename U >
1025  SafeInt< T, E >& operator >>=( U bits ) throw()
1026  {
1029 
1030  m_int >>= bits;
1031  return *this;
1032  }
1033 
1034  template < typename U >
1036  {
1039 
1040  m_int >>= (U)bits;
1041  return *this;
1042  }
1043 
1044  // Bitwise operators
1045  // This only makes sense if we're dealing with the same type and size
1046  // demand a type T, or something that fits into a type T
1047 
1048  // Bitwise &
1050  {
1051  return SafeInt< T, E >( m_int & (T)rhs );
1052  }
1053 
1054  template < typename U >
1055  SafeInt< T, E > operator &( U rhs ) const throw()
1056  {
1057  // we want to avoid setting bits by surprise
1058  // consider the case of lhs = int, value = 0xffffffff
1059  // rhs = char, value = 0xff
1060  //
1061  // programmer intent is to get only the lower 8 bits
1062  // normal behavior is to upcast both sides to an int
1063  // which then sign extends rhs, setting all the bits
1064 
1065  // If you land in the assert, this is because the bitwise operator
1066  // was causing unexpected behavior. Fix is to properly cast your inputs
1067  // so that it works like you meant, not unexpectedly
1068 
1070  }
1071 
1072  // Bitwise & assignment
1074  {
1075  m_int &= (T)rhs;
1076  return *this;
1077  }
1078 
1079  template < typename U >
1080  SafeInt< T, E >& operator &=( U rhs ) throw()
1081  {
1083  return *this;
1084  }
1085 
1086  template < typename U >
1088  {
1090  return *this;
1091  }
1092 
1093  // XOR
1095  {
1096  return SafeInt< T, E >( (T)( m_int ^ (T)rhs ) );
1097  }
1098 
1099  template < typename U >
1100  SafeInt< T, E > operator ^( U rhs ) const throw()
1101  {
1102  // If you land in the assert, this is because the bitwise operator
1103  // was causing unexpected behavior. Fix is to properly cast your inputs
1104  // so that it works like you meant, not unexpectedly
1105 
1107  }
1108 
1109  // XOR assignment
1111  {
1112  m_int ^= (T)rhs;
1113  return *this;
1114  }
1115 
1116  template < typename U >
1117  SafeInt< T, E >& operator ^=( U rhs ) throw()
1118  {
1120  return *this;
1121  }
1122 
1123  template < typename U >
1125  {
1127  return *this;
1128  }
1129 
1130  // bitwise OR
1132  {
1133  return SafeInt< T, E >( (T)( m_int | (T)rhs ) );
1134  }
1135 
1136  template < typename U >
1137  SafeInt< T, E > operator |( U rhs ) const throw()
1138  {
1140  }
1141 
1142  // bitwise OR assignment
1144  {
1145  m_int |= (T)rhs;
1146  return *this;
1147  }
1148 
1149  template < typename U >
1150  SafeInt< T, E >& operator |=( U rhs ) throw()
1151  {
1153  return *this;
1154  }
1155 
1156  template < typename U >
1158  {
1160  return *this;
1161  }
1162 
1163  // Miscellaneous helper functions
1165  {
1166  T tmp = test < m_int ? test : m_int;
1167  return tmp < floor ? floor : tmp;
1168  }
1169 
1171  {
1172  T tmp = test > m_int ? test : m_int;
1173  return tmp > upper ? upper : tmp;
1174  }
1175 
1176  void Swap( SafeInt< T, E >& with ) throw()
1177  {
1178  T temp( m_int );
1179  m_int = with.m_int;
1180  with.m_int = temp;
1181  }
1182 
1183  template < int bits >
1185  {
1186  // Zero is always aligned
1187  if( m_int == 0 )
1188  return *this;
1189 
1190  // We don't support aligning negative numbers at this time
1191  // Can't align unsigned numbers on bitCount (e.g., 8 bits = 256, unsigned char max = 255)
1192  // or signed numbers on bitCount-1 (e.g., 7 bits = 128, signed char max = 127).
1193  // Also makes no sense to try to align on negative or no bits.
1194 
1197  bits >= 0 && ( !details::IntTraits<T>::isSigned || m_int > 0 ) );
1198 
1199  const T AlignValue = ( (T)1 << bits ) - 1;
1200 
1201  m_int = ( m_int + AlignValue ) & ~AlignValue;
1202 
1203  if( m_int <= 0 )
1204  E::SafeIntOnOverflow();
1205 
1206  return *this;
1207  }
1208 
1209  // Commonly needed alignments:
1210  const SafeInt< T, E >& Align2() { return Align< 1 >(); }
1211  const SafeInt< T, E >& Align4() { return Align< 2 >(); }
1212  const SafeInt< T, E >& Align8() { return Align< 3 >(); }
1213  const SafeInt< T, E >& Align16() { return Align< 4 >(); }
1214  const SafeInt< T, E >& Align32() { return Align< 5 >(); }
1215  const SafeInt< T, E >& Align64() { return Align< 6 >(); }
1216 
1217 private:
1219 };
1220 
1221 // Externally defined functions for the case of U op SafeInt< T, E >
1222 template < typename T, typename U, typename E >
1223 bool operator <( U lhs, SafeInt< T, E > rhs ) throw()
1224 {
1225  return details::GreaterThanTest< T, U >::GreaterThan( (T)rhs, lhs );
1226 }
1227 
1228 template < typename T, typename U, typename E >
1229 bool operator <( SafeInt< U, E > lhs, SafeInt< T, E > rhs ) throw()
1230 {
1231  return details::GreaterThanTest< T, U >::GreaterThan( (T)rhs, (U)lhs );
1232 }
1233 
1234 // Greater than
1235 template < typename T, typename U, typename E >
1236 bool operator >( U lhs, SafeInt< T, E > rhs ) throw()
1237 {
1238  return details::GreaterThanTest< U, T >::GreaterThan( lhs, (T)rhs );
1239 }
1240 
1241 template < typename T, typename U, typename E >
1243 {
1244  return details::GreaterThanTest< T, U >::GreaterThan( (T)lhs, (U)rhs );
1245 }
1246 
1247 // Greater than or equal
1248 template < typename T, typename U, typename E >
1249 bool operator >=( U lhs, SafeInt< T, E > rhs ) throw()
1250 {
1251  return !details::GreaterThanTest< T, U >::GreaterThan( (T)rhs, lhs );
1252 }
1253 
1254 template < typename T, typename U, typename E >
1256 {
1257  return !details::GreaterThanTest< U, T >::GreaterThan( (U)rhs, (T)lhs );
1258 }
1259 
1260 // Less than or equal
1261 template < typename T, typename U, typename E >
1262 bool operator <=( U lhs, SafeInt< T, E > rhs ) throw()
1263 {
1264  return !details::GreaterThanTest< U, T >::GreaterThan( lhs, (T)rhs );
1265 }
1266 
1267 template < typename T, typename U, typename E >
1268 bool operator <=( SafeInt< T, E > lhs, SafeInt< U, E > rhs ) throw()
1269 {
1270  return !details::GreaterThanTest< T, U >::GreaterThan( (T)lhs, (U)rhs );
1271 }
1272 
1273 // equality
1274 // explicit overload for bool
1275 template < typename T, typename E >
1276 bool operator ==( bool lhs, SafeInt< T, E > rhs ) throw()
1277 {
1278  return lhs == ( (T)rhs == 0 ? false : true );
1279 }
1280 
1281 template < typename T, typename U, typename E >
1282 bool operator ==( U lhs, SafeInt< T, E > rhs ) throw()
1283 {
1284  return details::EqualityTest< T, U >::IsEquals((T)rhs, lhs);
1285 }
1286 
1287 template < typename T, typename U, typename E >
1289 {
1290  return details::EqualityTest< T, U >::IsEquals( (T)lhs, (U)rhs );
1291 }
1292 
1293 //not equals
1294 template < typename T, typename U, typename E >
1295 bool operator !=( U lhs, SafeInt< T, E > rhs ) throw()
1296 {
1297  return !details::EqualityTest< T, U >::IsEquals( rhs, lhs );
1298 }
1299 
1300 template < typename T, typename E >
1301 bool operator !=( bool lhs, SafeInt< T, E > rhs ) throw()
1302 {
1303  return ( (T)rhs == 0 ? false : true ) != lhs;
1304 }
1305 
1306 template < typename T, typename U, typename E >
1308 {
1309  return !details::EqualityTest< T, U >::IsEquals( lhs, rhs );
1310 }
1311 
1312 // Modulus
1313 template < typename T, typename U, typename E >
1315 {
1316  // Value of return depends on sign of lhs
1317  // This one may not be safe - bounds check in constructor
1318  // if lhs is negative and rhs is unsigned, this will throw an exception.
1319 
1320  // Fast-track the simple case
1321  // same size and same sign
1322 #pragma warning(suppress:4127 6326)
1323  if( sizeof(T) == sizeof(U) && details::IntTraits< T >::isSigned == details::IntTraits< U >::isSigned )
1324  {
1325  if( rhs != 0 )
1326  {
1327  if( details::IntTraits< T >::isSigned && (T)rhs == -1 )
1328  return 0;
1329 
1330  return SafeInt< T, E >( (T)( lhs % (T)rhs ) );
1331  }
1332 
1333  E::SafeIntOnDivZero();
1334  }
1335 
1336  return SafeInt< T, E >( ( SafeInt< U, E >( lhs ) % (T)rhs ) );
1337 }
1338 
1339 // Multiplication
1340 template < typename T, typename U, typename E >
1342 {
1343  T ret( 0 );
1345  return SafeInt< T, E >(ret);
1346 }
1347 
1348 // Division
1349 template < typename T, typename U, typename E > SafeInt< T, E > operator /( U lhs, SafeInt< T, E > rhs )
1350 {
1351 #pragma warning(push)
1352 #pragma warning(disable: 4127 4146 4307 4310 6326)
1353  // Corner case - has to be handled separately
1355  {
1356  if( (T)rhs > 0 )
1357  return SafeInt< T, E >( lhs/(T)rhs );
1358 
1359  // Now rhs is either negative, or zero
1360  if( (T)rhs != 0 )
1361  {
1362  if( sizeof( U ) >= 4 && sizeof( T ) <= sizeof( U ) )
1363  {
1364  // Problem case - normal casting behavior changes meaning
1365  // flip rhs to positive
1366  // any operator casts now do the right thing
1367  U tmp;
1368  if( sizeof(T) == 4 )
1369  tmp = lhs/(U)(unsigned __int32)( -(T)rhs );
1370  else
1371  tmp = lhs/(U)( -(T)rhs );
1372 
1373  if( tmp <= details::IntTraits< T >::maxInt )
1374  return SafeInt< T, E >( -( (T)tmp ) );
1375 
1376  // Corner case
1377  // Note - this warning happens because we're not using partial
1378  // template specialization in this case. For any real cases where
1379  // this block isn't optimized out, the warning won't be present.
1380  if( tmp == (U)details::IntTraits< T >::maxInt + 1 )
1382 
1383  E::SafeIntOnOverflow();
1384  }
1385 
1386  return SafeInt< T, E >(lhs/(T)rhs);
1387  }
1388 
1389  E::SafeIntOnDivZero();
1390  } // method == DivisionState_UnsignedSigned
1391 
1393  {
1394  if( lhs == details::IntTraits< U >::minInt && (T)rhs == -1 )
1395  {
1396  // corner case of a corner case - lhs = min int, rhs = -1,
1397  // but rhs is the return type, so in essence, we can return -lhs
1398  // if rhs is a larger type than lhs
1399  if( sizeof( U ) < sizeof( T ) )
1400  {
1401  return SafeInt< T, E >( (T)( -(T)details::IntTraits< U >::minInt ) );
1402  }
1403 
1404  // If rhs is smaller or the same size int, then -minInt won't work
1405  E::SafeIntOnOverflow();
1406  }
1407  }
1408 
1409  // Otherwise normal logic works with addition of bounds check when casting from U->T
1410  U ret;
1411  details::DivisionHelper< U, T, E >::Divide( lhs, (T)rhs, ret );
1412  return SafeInt< T, E >( ret );
1413 #pragma warning(pop)
1414 }
1415 
1416 // Addition
1417 template < typename T, typename U, typename E >
1419 {
1420  T ret( 0 );
1422  return SafeInt< T, E >( ret );
1423 }
1424 
1425 // Subtraction
1426 template < typename T, typename U, typename E >
1428 {
1429  T ret( 0 );
1431 
1432  return SafeInt< T, E >( ret );
1433 }
1434 
1435 // Overrides designed to deal with cases where a SafeInt is assigned out
1436 // to a normal int - this at least makes the last operation safe
1437 // +=
1438 template < typename T, typename U, typename E >
1439 T& operator +=( T& lhs, SafeInt< U, E > rhs )
1440 {
1441  T ret( 0 );
1443  lhs = ret;
1444  return lhs;
1445 }
1446 
1447 template < typename T, typename U, typename E >
1448 T& operator -=( T& lhs, SafeInt< U, E > rhs )
1449 {
1450  T ret( 0 );
1452  lhs = ret;
1453  return lhs;
1454 }
1455 
1456 template < typename T, typename U, typename E >
1457 T& operator *=( T& lhs, SafeInt< U, E > rhs )
1458 {
1459  T ret( 0 );
1461  lhs = ret;
1462  return lhs;
1463 }
1464 
1465 template < typename T, typename U, typename E >
1466 T& operator /=( T& lhs, SafeInt< U, E > rhs )
1467 {
1468  T ret( 0 );
1469  details::DivisionHelper< T, U, E >::Divide( lhs, (U)rhs, ret );
1470  lhs = ret;
1471  return lhs;
1472 }
1473 
1474 template < typename T, typename U, typename E >
1475 T& operator %=( T& lhs, SafeInt< U, E > rhs )
1476 {
1477  T ret( 0 );
1478  details::ModulusHelper< T, U, E >::Modulus( lhs, (U)rhs, ret );
1479  lhs = ret;
1480  return lhs;
1481 }
1482 
1483 template < typename T, typename U, typename E >
1484 T& operator &=( T& lhs, SafeInt< U, E > rhs ) throw()
1485 {
1486  lhs = details::BinaryAndHelper< T, U >::And( lhs, (U)rhs );
1487  return lhs;
1488 }
1489 
1490 template < typename T, typename U, typename E >
1491 T& operator ^=( T& lhs, SafeInt< U, E > rhs ) throw()
1492 {
1493  lhs = details::BinaryXorHelper< T, U >::Xor( lhs, (U)rhs );
1494  return lhs;
1495 }
1496 
1497 template < typename T, typename U, typename E >
1498 T& operator |=( T& lhs, SafeInt< U, E > rhs ) throw()
1499 {
1500  lhs = details::BinaryOrHelper< T, U >::Or( lhs, (U)rhs );
1501  return lhs;
1502 }
1503 
1504 template < typename T, typename U, typename E >
1505 T& operator <<=( T& lhs, SafeInt< U, E > rhs ) throw()
1506 {
1507  lhs = (T)( SafeInt< T, E >( lhs ) << (U)rhs );
1508  return lhs;
1509 }
1510 
1511 template < typename T, typename U, typename E >
1512 T& operator >>=( T& lhs, SafeInt< U, E > rhs ) throw()
1513 {
1514  lhs = (T)( SafeInt< T, E >( lhs ) >> (U)rhs );
1515  return lhs;
1516 }
1517 
1518 // Specific pointer overrides
1519 // Note - this function makes no attempt to ensure
1520 // that the resulting pointer is still in the buffer, only
1521 // that no int overflows happened on the way to getting the new pointer
1522 template < typename T, typename U, typename E >
1523 T*& operator +=( T*& lhs, SafeInt< U, E > rhs )
1524 {
1525  // Cast the pointer to a number so we can do arithmetic
1526  SafeInt< uintptr_t, E > ptr_val = reinterpret_cast< uintptr_t >( lhs );
1527  // Check first that rhs is valid for the type of ptrdiff_t
1528  // and that multiplying by sizeof( T ) doesn't overflow a ptrdiff_t
1529  // Next, we need to add 2 SafeInts of different types, so unbox the ptr_diff
1530  // Finally, cast the number back to a pointer of the correct type
1531  lhs = reinterpret_cast< T* >( (uintptr_t)( ptr_val + (ptrdiff_t)( SafeInt< ptrdiff_t, E >( rhs ) * sizeof( T ) ) ) );
1532  return lhs;
1533 }
1534 
1535 template < typename T, typename U, typename E >
1536 T*& operator -=( T*& lhs, SafeInt< U, E > rhs )
1537 {
1538  // Cast the pointer to a number so we can do arithmetic
1539  SafeInt< size_t, E > ptr_val = reinterpret_cast< uintptr_t >( lhs );
1540  // See above for comments
1541  lhs = reinterpret_cast< T* >( (uintptr_t)( ptr_val - (ptrdiff_t)( SafeInt< ptrdiff_t, E >( rhs ) * sizeof( T ) ) ) );
1542  return lhs;
1543 }
1544 
1545 template < typename T, typename U, typename E >
1546 T*& operator *=( T* lhs, SafeInt< U, E > rhs )
1547 {
1548  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1549  return lhs;
1550 }
1551 
1552 template < typename T, typename U, typename E >
1553 T*& operator /=( T* lhs, SafeInt< U, E > rhs )
1554 {
1555  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1556  return lhs;
1557 }
1558 
1559 template < typename T, typename U, typename E >
1560 T*& operator %=( T* lhs, SafeInt< U, E > rhs )
1561 {
1562  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1563  return lhs;
1564 }
1565 
1566 template < typename T, typename U, typename E >
1567 T*& operator &=( T* lhs, SafeInt< U, E > rhs )
1568 {
1569  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1570  return lhs;
1571 }
1572 
1573 template < typename T, typename U, typename E >
1574 T*& operator ^=( T* lhs, SafeInt< U, E > rhs )
1575 {
1576  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1577  return lhs;
1578 }
1579 
1580 template < typename T, typename U, typename E >
1581 T*& operator |=( T* lhs, SafeInt< U, E > rhs )
1582 {
1583  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1584  return lhs;
1585 }
1586 
1587 template < typename T, typename U, typename E >
1588 T*& operator <<=( T* lhs, SafeInt< U, E > rhs )
1589 {
1590  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1591  return lhs;
1592 }
1593 
1594 template < typename T, typename U, typename E >
1595 T*& operator >>=( T* lhs, SafeInt< U, E > rhs )
1596 {
1597  static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1598  return lhs;
1599 }
1600 
1601 // Shift operators
1602 // NOTE - shift operators always return the type of the lhs argument
1603 
1604 // Left shift
1605 template < typename T, typename U, typename E >
1606 SafeInt< U, E > operator <<( U lhs, SafeInt< T, E > bits ) throw()
1607 {
1610 
1611  return SafeInt< U, E >( (U)( lhs << (T)bits ) );
1612 }
1613 
1614 // Right shift
1615 template < typename T, typename U, typename E >
1617 {
1620 
1621  return SafeInt< U, E >( (U)( lhs >> (T)bits ) );
1622 }
1623 
1624 // Bitwise operators
1625 // This only makes sense if we're dealing with the same type and size
1626 // demand a type T, or something that fits into a type T.
1627 
1628 // Bitwise &
1629 template < typename T, typename U, typename E >
1631 {
1632  return SafeInt< T, E >( details::BinaryAndHelper< T, U >::And( (T)rhs, lhs ) );
1633 }
1634 
1635 // Bitwise XOR
1636 template < typename T, typename U, typename E >
1638 {
1640 }
1641 
1642 // Bitwise OR
1643 template < typename T, typename U, typename E >
1645 {
1646  return SafeInt< T, E >( details::BinaryOrHelper< T, U >::Or( (T)rhs, lhs ) );
1647 }
1648 
1649 } // namespace utilities
1650 
1651 } // namespace msl
1652 
1653 #pragma pack(pop)
const SafeInt< T, E > & Align()
Definition: safeint.h:1184
SafeIntException()
Definition: safeint.h:283
const T & Ref() const
Definition: safeint.h:580
const T * Ptr() const
Definition: safeint.h:579
T & operator^=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1491
T & operator/=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1466
SafeInt()
Definition: safeint.h:407
SafeInt< T, E > & operator/=(SafeInt< T, E > i)
Definition: safeint.h:781
bool operator>=(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1249
SafeInt< T, E > operator&(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1630
Definition: safeint_internal.h:780
static __declspec(noreturn) void SafeIntOnOverflow()
Definition: safeint.h:308
Definition: safeint_internal.h:585
bool operator<(U rhs) const
Definition: safeint.h:881
SafeInt< T, E > operator>>(U bits) const
Definition: safeint.h:1006
SafeInt(bool b)
Definition: safeint.h:424
bool SafeEquals(const T t, const U u)
Definition: safeint.h:333
SafeInt< T, E > & operator-=(SafeInt< T, E > rhs)
Definition: safeint.h:855
static __declspec(noreturn) void SafeIntOnOverflow()
Definition: safeint.h:293
Definition: safeint.h:255
bool operator>(U rhs) const
Definition: safeint.h:905
static __declspec(noreturn) void SafeIntOnDivZero()
Definition: safeint.h:299
SafeInt< T, E > & operator*=(SafeInt< T, E > rhs)
Definition: safeint.h:744
Definition: safeint_internal.h:531
bool SafeLessThanEquals(const T t, const U u)
Definition: safeint.h:363
const SafeInt< T, E > & Align16()
Definition: safeint.h:1213
_In_ long
Definition: corecrt_wstdlib.h:88
Definition: safeint.h:404
bool operator!=(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1295
T * Ptr()
Definition: safeint.h:578
SafeInt< T, E > operator~() const
Definition: safeint.h:653
Definition: safeint_internal.h:479
bool operator>=(U rhs) const
Definition: safeint.h:893
Definition: safeint_internal.h:57
bool SafeGreaterThan(const T t, const U u)
Definition: safeint.h:345
bool SafeCast(const T From, U &To)
Definition: safeint.h:326
bool operator!=(U rhs) const
Definition: safeint.h:944
bool SafeLessThan(const T t, const U u)
Definition: safeint.h:357
SafeInt< T, E > operator%(U rhs) const
Definition: safeint.h:698
bool SafeNotEquals(const T t, const U u)
Definition: safeint.h:339
Definition: safeint_internal.h:31
int ptrdiff_t
Definition: vcruntime.h:199
SafeInt< T, E > Max(SafeInt< T, E > test, SafeInt< T, E > upper=SafeInt< T, E >(details::IntTraits< T >::maxInt)) const
Definition: safeint.h:1170
T & operator+=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1439
SafeInt(const T &i)
Definition: safeint.h:416
SafeInt(const SafeInt< U, E > &u)
Definition: safeint.h:431
Definition: safeint.h:280
SafeInt< T, E > operator-(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1427
SafeInt< T, E > operator/(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1349
T & operator>>=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1512
bool operator<=(U rhs) const
Definition: safeint.h:917
bool SafeGreaterThanEquals(const T t, const U u)
Definition: safeint.h:351
#define _CRT_SECURE_INVALID_PARAMETER(expr)
Definition: corecrt.h:274
const SafeInt< T, E > & Align64()
Definition: safeint.h:1215
T & operator&=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1484
unsigned int uintptr_t
Definition: vadefs.h:30
const SafeInt< T, E > & Align2()
Definition: safeint.h:1210
bool operator==(U rhs) const
Definition: safeint.h:929
SafeInt< T, E > operator|(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1644
int i[4]
Definition: dvec.h:68
SafeInt< T, E > & operator^=(SafeInt< T, E > rhs)
Definition: safeint.h:1110
Definition: safeint.h:265
T & operator*=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1457
bool SafeMultiply(T t, U u, T &result)
Definition: safeint.h:375
SafeInt< T, E > operator-() const
Definition: safeint.h:591
#define _SAFEINT_EXCEPTION_ASSERT()
Definition: safeint.h:237
Definition: safeint_internal.h:2768
SafeInt< T, E > operator+(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1418
#define bool
Definition: stdbool.h:15
SafeInt< T, E > & operator>>=(U bits)
Definition: safeint.h:1025
Definition: safeint_internal.h:104
SafeInt< T, E > operator*(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1341
SafeInt< T, E > operator&(SafeInt< T, E > rhs) const
Definition: safeint.h:1049
SafeIntError m_code
Definition: safeint.h:288
SafeInt< T, E > operator/(U rhs) const
Definition: safeint.h:766
bool operator>(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1236
SafeInt< T, E > & operator=(const U &rhs)
Definition: safeint.h:450
unsigned char
Definition: mbstring.h:107
_CRT_BEGIN_C_HEADER typedef void(__CRTDECL *terminate_handler)()
Definition: safeint_internal.h:1515
SafeInt< T, E > operator<<(U bits) const
Definition: safeint.h:965
T & operator%=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1475
T & operator|=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1498
SafeInt< T, E > & operator+=(SafeInt< T, E > rhs)
Definition: safeint.h:818
const SafeInt< T, E > & Align32()
Definition: safeint.h:1214
Definition: safeint_internal.h:1531
SafeIntError
Definition: safeint.h:261
SafeInt< T, E > & operator|=(SafeInt< T, E > rhs)
Definition: safeint.h:1143
SafeInt< T, E > operator^(SafeInt< T, E > rhs) const
Definition: safeint.h:1094
Definition: safeint_internal.h:1734
Definition: safeint.h:263
bool SafeSubtract(T t, U u, T &result)
Definition: safeint.h:396
unsigned short wchar_t
Definition: sourceannotations.h:25
SafeInt< U, E > operator>>(U lhs, SafeInt< T, E > bits)
Definition: safeint.h:1616
Definition: safeint_internal.h:2809
SafeIntException(SafeIntError code)
Definition: safeint.h:284
Definition: safeint_internal.h:33
SafeInt(const U &i)
Definition: safeint.h:438
T m_int
Definition: safeint.h:1218
SafeInt< T, E > operator%(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1314
const SafeInt< T, E > & Align4()
Definition: safeint.h:1211
SafeInt< T, E > & operator++()
Definition: safeint.h:601
bool SafeDivide(T t, U u, T &result)
Definition: safeint.h:382
float floor(float _X) __GPU_ONLY
Calculates the floor of the argument
Definition: amp_math.h:527
const SafeInt< T, E > & operator+() const
Definition: safeint.h:588
SafeInt< T, E > Min(SafeInt< T, E > test, SafeInt< T, E > floor=SafeInt< T, E >(details::IntTraits< T >::minInt)) const
Definition: safeint.h:1164
SafeInt< T, E > operator|(SafeInt< T, E > rhs) const
Definition: safeint.h:1131
Definition: safeint_internal.h:331
SafeInt< T, E > & operator<<=(U bits)
Definition: safeint.h:985
void Swap(SafeInt< T, E > &with)
Definition: safeint.h:1176
Definition: safeint_internal.h:248
bool operator==(bool lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1276
Definition: safeint_internal.h:2179
bool operator!() const
Definition: safeint.h:583
SafeInt< T, E > & operator&=(SafeInt< T, E > rhs)
Definition: safeint.h:1073
SafeInt< T, E > operator*(U rhs) const
Definition: safeint.h:729
bool SafeAdd(T t, U u, T &result)
Definition: safeint.h:389
#define _SAFEINT_SHIFT_ASSERT(x)
Definition: safeint.h:229
SafeInt< T, E > operator^(U lhs, SafeInt< T, E > rhs)
Definition: safeint.h:1637
Definition: safeint_internal.h:2850
bool SafeModulus(const T &t, const U &u, T &result)
Definition: safeint.h:369
static __declspec(noreturn) void SafeIntOnDivZero()
Definition: safeint.h:314
T & operator-=(T &lhs, SafeInt< U, E > rhs)
Definition: safeint.h:1448
SafeInt< T, E > & operator%=(U rhs)
Definition: safeint.h:714
SafeInt< T, E > & operator--()
Definition: safeint.h:612
const SafeInt< T, E > & Align8()
Definition: safeint.h:1212