Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: Source/core/html/canvas/CheckedInt.h

Issue 55833005: Move CheckedInt.h to Source/platform (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/core.gypi ('k') | Source/core/html/canvas/DataView.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /* Provides checked integers, detecting integer overflow and divide-by-0. */
7
8 // Necessary modifications are made to the original CheckedInt.h file when
9 // incorporating it into WebKit:
10 // 1) Comment out #define MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
11 // 2) Comment out #include "mozilla/StandardInteger.h"
12 // 3) Define MOZ_DELETE
13 // 4) Change namespace mozilla to namespace WebCore
14
15 #ifndef mozilla_CheckedInt_h_
16 #define mozilla_CheckedInt_h_
17
18 /*
19 * Build options. Comment out these #defines to disable the corresponding
20 * optional feature. Disabling features may be useful for code using
21 * CheckedInt outside of Mozilla (e.g. WebKit)
22 */
23
24 // Enable usage of MOZ_STATIC_ASSERT to check for unsupported types.
25 // If disabled, static asserts are replaced by regular assert().
26 // #define MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
27
28 /*
29 * End of build options
30 */
31
32 #ifdef MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
33 # include "mozilla/Assertions.h"
34 #else
35 # ifndef MOZ_STATIC_ASSERT
36 # include <cassert>
37 # define MOZ_STATIC_ASSERT(cond, reason) assert((cond) && reason)
38 # define MOZ_ASSERT(cond, reason) assert((cond) && reason)
39 # endif
40 #endif
41
42 // #include "mozilla/StandardInteger.h"
43
44 #ifndef MOZ_DELETE
45 #define MOZ_DELETE
46 #endif
47
48 #include <climits>
49 #include <cstddef>
50
51 namespace WebCore {
52
53 namespace detail {
54
55 /*
56 * Step 1: manually record supported types
57 *
58 * What's nontrivial here is that there are different families of integer
59 * types: basic integer types and stdint types. It is merrily undefined which
60 * types from one family may be just typedefs for a type from another family.
61 *
62 * For example, on GCC 4.6, aside from the basic integer types, the only other
63 * type that isn't just a typedef for some of them, is int8_t.
64 */
65
66 struct UnsupportedType {};
67
68 template<typename IntegerType>
69 struct IsSupportedPass2
70 {
71 static const bool value = false;
72 };
73
74 template<typename IntegerType>
75 struct IsSupported
76 {
77 static const bool value = IsSupportedPass2<IntegerType>::value;
78 };
79
80 template<>
81 struct IsSupported<int8_t>
82 { static const bool value = true; };
83
84 template<>
85 struct IsSupported<uint8_t>
86 { static const bool value = true; };
87
88 template<>
89 struct IsSupported<int16_t>
90 { static const bool value = true; };
91
92 template<>
93 struct IsSupported<uint16_t>
94 { static const bool value = true; };
95
96 template<>
97 struct IsSupported<int32_t>
98 { static const bool value = true; };
99
100 template<>
101 struct IsSupported<uint32_t>
102 { static const bool value = true; };
103
104 template<>
105 struct IsSupported<int64_t>
106 { static const bool value = true; };
107
108 template<>
109 struct IsSupported<uint64_t>
110 { static const bool value = true; };
111
112
113 template<>
114 struct IsSupportedPass2<char>
115 { static const bool value = true; };
116
117 template<>
118 struct IsSupportedPass2<unsigned char>
119 { static const bool value = true; };
120
121 template<>
122 struct IsSupportedPass2<short>
123 { static const bool value = true; };
124
125 template<>
126 struct IsSupportedPass2<unsigned short>
127 { static const bool value = true; };
128
129 template<>
130 struct IsSupportedPass2<int>
131 { static const bool value = true; };
132
133 template<>
134 struct IsSupportedPass2<unsigned int>
135 { static const bool value = true; };
136
137 template<>
138 struct IsSupportedPass2<long>
139 { static const bool value = true; };
140
141 template<>
142 struct IsSupportedPass2<unsigned long>
143 { static const bool value = true; };
144
145
146 /*
147 * Step 2: some integer-traits kind of stuff.
148 */
149
150 template<size_t Size, bool Signedness>
151 struct StdintTypeForSizeAndSignedness
152 {};
153
154 template<>
155 struct StdintTypeForSizeAndSignedness<1, true>
156 { typedef int8_t Type; };
157
158 template<>
159 struct StdintTypeForSizeAndSignedness<1, false>
160 { typedef uint8_t Type; };
161
162 template<>
163 struct StdintTypeForSizeAndSignedness<2, true>
164 { typedef int16_t Type; };
165
166 template<>
167 struct StdintTypeForSizeAndSignedness<2, false>
168 { typedef uint16_t Type; };
169
170 template<>
171 struct StdintTypeForSizeAndSignedness<4, true>
172 { typedef int32_t Type; };
173
174 template<>
175 struct StdintTypeForSizeAndSignedness<4, false>
176 { typedef uint32_t Type; };
177
178 template<>
179 struct StdintTypeForSizeAndSignedness<8, true>
180 { typedef int64_t Type; };
181
182 template<>
183 struct StdintTypeForSizeAndSignedness<8, false>
184 { typedef uint64_t Type; };
185
186 template<typename IntegerType>
187 struct UnsignedType
188 {
189 typedef typename StdintTypeForSizeAndSignedness<sizeof(IntegerType),
190 false>::Type Type;
191 };
192
193 template<typename IntegerType>
194 struct IsSigned
195 {
196 static const bool value = IntegerType(-1) <= IntegerType(0);
197 };
198
199 template<typename IntegerType, size_t Size = sizeof(IntegerType)>
200 struct TwiceBiggerType
201 {
202 typedef typename StdintTypeForSizeAndSignedness<
203 sizeof(IntegerType) * 2,
204 IsSigned<IntegerType>::value
205 >::Type Type;
206 };
207
208 template<typename IntegerType>
209 struct TwiceBiggerType<IntegerType, 8>
210 {
211 typedef UnsupportedType Type;
212 };
213
214 template<typename IntegerType>
215 struct PositionOfSignBit
216 {
217 static const size_t value = CHAR_BIT * sizeof(IntegerType) - 1;
218 };
219
220 template<typename IntegerType>
221 struct MinValue
222 {
223 private:
224 typedef typename UnsignedType<IntegerType>::Type UnsignedIntegerType;
225 static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;
226
227 public:
228 // Bitwise ops may return a larger type, that's why we cast explicitly.
229 // In C++, left bit shifts on signed values is undefined by the standard
230 // unless the shifted value is representable.
231 // Notice that signed-to-unsigned conversions are always well-defined in
232 // the standard as the value congruent to 2**n, as expected. By contrast,
233 // unsigned-to-signed is only well-defined if the value is representable.
234 static const IntegerType value =
235 IsSigned<IntegerType>::value
236 ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
237 : IntegerType(0);
238 };
239
240 template<typename IntegerType>
241 struct MaxValue
242 {
243 // Tricksy, but covered by the unit test.
244 // Relies heavily on the type of MinValue<IntegerType>::value
245 // being IntegerType.
246 static const IntegerType value = ~MinValue<IntegerType>::value;
247 };
248
249 /*
250 * Step 3: Implement the actual validity checks.
251 *
252 * Ideas taken from IntegerLib, code different.
253 */
254
255 template<typename T>
256 inline bool
257 HasSignBit(T x)
258 {
259 // In C++, right bit shifts on negative values is undefined by the standard.
260 // Notice that signed-to-unsigned conversions are always well-defined in the
261 // standard, as the value congruent modulo 2**n as expected. By contrast,
262 // unsigned-to-signed is only well-defined if the value is representable.
263 return bool(typename UnsignedType<T>::Type(x)
264 >> PositionOfSignBit<T>::value);
265 }
266
267 // Bitwise ops may return a larger type, so it's good to use this inline
268 // helper guaranteeing that the result is really of type T.
269 template<typename T>
270 inline T
271 BinaryComplement(T x)
272 {
273 return ~x;
274 }
275
276 template<typename T,
277 typename U,
278 bool IsTSigned = IsSigned<T>::value,
279 bool IsUSigned = IsSigned<U>::value>
280 struct DoesRangeContainRange
281 {
282 };
283
284 template<typename T, typename U, bool Signedness>
285 struct DoesRangeContainRange<T, U, Signedness, Signedness>
286 {
287 static const bool value = sizeof(T) >= sizeof(U);
288 };
289
290 template<typename T, typename U>
291 struct DoesRangeContainRange<T, U, true, false>
292 {
293 static const bool value = sizeof(T) > sizeof(U);
294 };
295
296 template<typename T, typename U>
297 struct DoesRangeContainRange<T, U, false, true>
298 {
299 static const bool value = false;
300 };
301
302 template<typename T,
303 typename U,
304 bool IsTSigned = IsSigned<T>::value,
305 bool IsUSigned = IsSigned<U>::value,
306 bool DoesTRangeContainURange = DoesRangeContainRange<T, U>::value>
307 struct IsInRangeImpl {};
308
309 template<typename T, typename U, bool IsTSigned, bool IsUSigned>
310 struct IsInRangeImpl<T, U, IsTSigned, IsUSigned, true>
311 {
312 static bool run(U)
313 {
314 return true;
315 }
316 };
317
318 template<typename T, typename U>
319 struct IsInRangeImpl<T, U, true, true, false>
320 {
321 static bool run(U x)
322 {
323 return x <= MaxValue<T>::value && x >= MinValue<T>::value;
324 }
325 };
326
327 template<typename T, typename U>
328 struct IsInRangeImpl<T, U, false, false, false>
329 {
330 static bool run(U x)
331 {
332 return x <= MaxValue<T>::value;
333 }
334 };
335
336 template<typename T, typename U>
337 struct IsInRangeImpl<T, U, true, false, false>
338 {
339 static bool run(U x)
340 {
341 return sizeof(T) > sizeof(U) || x <= U(MaxValue<T>::value);
342 }
343 };
344
345 template<typename T, typename U>
346 struct IsInRangeImpl<T, U, false, true, false>
347 {
348 static bool run(U x)
349 {
350 return sizeof(T) >= sizeof(U)
351 ? x >= 0
352 : x >= 0 && x <= U(MaxValue<T>::value);
353 }
354 };
355
356 template<typename T, typename U>
357 inline bool
358 IsInRange(U x)
359 {
360 return IsInRangeImpl<T, U>::run(x);
361 }
362
363 template<typename T>
364 inline bool
365 IsAddValid(T x, T y)
366 {
367 // Addition is valid if the sign of x+y is equal to either that of x or that
368 // of y. Since the value of x+y is undefined if we have a signed type, we
369 // compute it using the unsigned type of the same size.
370 // Beware! These bitwise operations can return a larger integer type,
371 // if T was a small type like int8_t, so we explicitly cast to T.
372
373 typename UnsignedType<T>::Type ux = x;
374 typename UnsignedType<T>::Type uy = y;
375 typename UnsignedType<T>::Type result = ux + uy;
376 return IsSigned<T>::value
377 ? HasSignBit(BinaryComplement(T((result ^ x) & (result ^ y))))
378 : BinaryComplement(x) >= y;
379 }
380
381 template<typename T>
382 inline bool
383 IsSubValid(T x, T y)
384 {
385 // Subtraction is valid if either x and y have same sign, or x-y and x have
386 // same sign. Since the value of x-y is undefined if we have a signed type,
387 // we compute it using the unsigned type of the same size.
388 typename UnsignedType<T>::Type ux = x;
389 typename UnsignedType<T>::Type uy = y;
390 typename UnsignedType<T>::Type result = ux - uy;
391
392 return IsSigned<T>::value
393 ? HasSignBit(BinaryComplement(T((result ^ x) & (x ^ y))))
394 : x >= y;
395 }
396
397 template<typename T,
398 bool IsSigned = IsSigned<T>::value,
399 bool TwiceBiggerTypeIsSupported =
400 IsSupported<typename TwiceBiggerType<T>::Type>::value>
401 struct IsMulValidImpl {};
402
403 template<typename T, bool IsSigned>
404 struct IsMulValidImpl<T, IsSigned, true>
405 {
406 static bool run(T x, T y)
407 {
408 typedef typename TwiceBiggerType<T>::Type TwiceBiggerType;
409 TwiceBiggerType product = TwiceBiggerType(x) * TwiceBiggerType(y);
410 return IsInRange<T>(product);
411 }
412 };
413
414 template<typename T>
415 struct IsMulValidImpl<T, true, false>
416 {
417 static bool run(T x, T y)
418 {
419 const T max = MaxValue<T>::value;
420 const T min = MinValue<T>::value;
421
422 if (x == 0 || y == 0)
423 return true;
424
425 if (x > 0) {
426 return y > 0
427 ? x <= max / y
428 : y >= min / x;
429 }
430
431 // If we reach this point, we know that x < 0.
432 return y > 0
433 ? x >= min / y
434 : y >= max / x;
435 }
436 };
437
438 template<typename T>
439 struct IsMulValidImpl<T, false, false>
440 {
441 static bool run(T x, T y)
442 {
443 return y == 0 || x <= MaxValue<T>::value / y;
444 }
445 };
446
447 template<typename T>
448 inline bool
449 IsMulValid(T x, T y)
450 {
451 return IsMulValidImpl<T>::run(x, y);
452 }
453
454 template<typename T>
455 inline bool
456 IsDivValid(T x, T y)
457 {
458 // Keep in mind that in the signed case, min/-1 is invalid because abs(min)>ma x.
459 return y != 0 &&
460 !(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1));
461 }
462
463 // This is just to shut up msvc warnings about negating unsigned ints.
464 template<typename T, bool IsSigned = IsSigned<T>::value>
465 struct OppositeIfSignedImpl
466 {
467 static T run(T x) { return -x; }
468 };
469 template<typename T>
470 struct OppositeIfSignedImpl<T, false>
471 {
472 static T run(T x) { return x; }
473 };
474 template<typename T>
475 inline T
476 OppositeIfSigned(T x)
477 {
478 return OppositeIfSignedImpl<T>::run(x);
479 }
480
481 } // namespace detail
482
483
484 /*
485 * Step 4: Now define the CheckedInt class.
486 */
487
488 /**
489 * @class CheckedInt
490 * @brief Integer wrapper class checking for integer overflow and other errors
491 * @param T the integer type to wrap. Can be any type among the following:
492 * - any basic integer type such as |int|
493 * - any stdint type such as |int8_t|
494 *
495 * This class implements guarded integer arithmetic. Do a computation, check
496 * that isValid() returns true, you then have a guarantee that no problem, such
497 * as integer overflow, happened during this computation, and you can call
498 * value() to get the plain integer value.
499 *
500 * The arithmetic operators in this class are guaranteed not to raise a signal
501 * (e.g. in case of a division by zero).
502 *
503 * For example, suppose that you want to implement a function that computes
504 * (x+y)/z, that doesn't crash if z==0, and that reports on error (divide by
505 * zero or integer overflow). You could code it as follows:
506 @code
507 bool computeXPlusYOverZ(int x, int y, int z, int *result)
508 {
509 CheckedInt<int> checkedResult = (CheckedInt<int>(x) + y) / z;
510 if (checkedResult.isValid()) {
511 *result = checkedResult.value();
512 return true;
513 } else {
514 return false;
515 }
516 }
517 @endcode
518 *
519 * Implicit conversion from plain integers to checked integers is allowed. The
520 * plain integer is checked to be in range before being casted to the
521 * destination type. This means that the following lines all compile, and the
522 * resulting CheckedInts are correctly detected as valid or invalid:
523 * @code
524 // 1 is of type int, is found to be in range for uint8_t, x is valid
525 CheckedInt<uint8_t> x(1);
526 // -1 is of type int, is found not to be in range for uint8_t, x is invalid
527 CheckedInt<uint8_t> x(-1);
528 // -1 is of type int, is found to be in range for int8_t, x is valid
529 CheckedInt<int8_t> x(-1);
530 // 1000 is of type int16_t, is found not to be in range for int8_t,
531 // x is invalid
532 CheckedInt<int8_t> x(int16_t(1000));
533 // 3123456789 is of type uint32_t, is found not to be in range for int32_t,
534 // x is invalid
535 CheckedInt<int32_t> x(uint32_t(3123456789));
536 * @endcode
537 * Implicit conversion from
538 * checked integers to plain integers is not allowed. As shown in the
539 * above example, to get the value of a checked integer as a normal integer,
540 * call value().
541 *
542 * Arithmetic operations between checked and plain integers is allowed; the
543 * result type is the type of the checked integer.
544 *
545 * Checked integers of different types cannot be used in the same arithmetic
546 * expression.
547 *
548 * There are convenience typedefs for all stdint types, of the following form
549 * (these are just 2 examples):
550 @code
551 typedef CheckedInt<int32_t> CheckedInt32;
552 typedef CheckedInt<uint16_t> CheckedUint16;
553 @endcode
554 */
555 template<typename T>
556 class CheckedInt
557 {
558 protected:
559 T mValue;
560 bool mIsValid;
561
562 template<typename U>
563 CheckedInt(U value, bool isValid) : mValue(value), mIsValid(isValid)
564 {
565 MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
566 "This type is not supported by CheckedInt");
567 }
568
569 public:
570 /**
571 * Constructs a checked integer with given @a value. The checked integer is
572 * initialized as valid or invalid depending on whether the @a value
573 * is in range.
574 *
575 * This constructor is not explicit. Instead, the type of its argument is a
576 * separate template parameter, ensuring that no conversion is performed
577 * before this constructor is actually called. As explained in the above
578 * documentation for class CheckedInt, this constructor checks that its
579 * argument is valid.
580 */
581 template<typename U>
582 CheckedInt(U value)
583 : mValue(T(value)),
584 mIsValid(detail::IsInRange<T>(value))
585 {
586 MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
587 "This type is not supported by CheckedInt");
588 }
589
590 /** Constructs a valid checked integer with initial value 0 */
591 CheckedInt() : mValue(0), mIsValid(true)
592 {
593 MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
594 "This type is not supported by CheckedInt");
595 }
596
597 /** @returns the actual value */
598 T value() const
599 {
600 MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
601 return mValue;
602 }
603
604 /**
605 * @returns true if the checked integer is valid, i.e. is not the result
606 * of an invalid operation or of an operation involving an invalid checked
607 * integer
608 */
609 bool isValid() const
610 {
611 return mIsValid;
612 }
613
614 template<typename U>
615 friend CheckedInt<U> operator +(const CheckedInt<U>& lhs,
616 const CheckedInt<U>& rhs);
617 template<typename U>
618 CheckedInt& operator +=(U rhs);
619 template<typename U>
620 friend CheckedInt<U> operator -(const CheckedInt<U>& lhs,
621 const CheckedInt<U> &rhs);
622 template<typename U>
623 CheckedInt& operator -=(U rhs);
624 template<typename U>
625 friend CheckedInt<U> operator *(const CheckedInt<U>& lhs,
626 const CheckedInt<U> &rhs);
627 template<typename U>
628 CheckedInt& operator *=(U rhs);
629 template<typename U>
630 friend CheckedInt<U> operator /(const CheckedInt<U>& lhs,
631 const CheckedInt<U> &rhs);
632 template<typename U>
633 CheckedInt& operator /=(U rhs);
634
635 CheckedInt operator -() const
636 {
637 // Circumvent msvc warning about - applied to unsigned int.
638 // if we're unsigned, the only valid case anyway is 0
639 // in which case - is a no-op.
640 T result = detail::OppositeIfSigned(mValue);
641 /* Help the compiler perform RVO (return value optimization). */
642 return CheckedInt(result,
643 mIsValid && detail::IsSubValid(T(0),
644 mValue));
645 }
646
647 /**
648 * @returns true if the left and right hand sides are valid
649 * and have the same value.
650 *
651 * Note that these semantics are the reason why we don't offer
652 * a operator!=. Indeed, we'd want to have a!=b be equivalent to !(a==b)
653 * but that would mean that whenever a or b is invalid, a!=b
654 * is always true, which would be very confusing.
655 *
656 * For similar reasons, operators <, >, <=, >= would be very tricky to
657 * specify, so we just avoid offering them.
658 *
659 * Notice that these == semantics are made more reasonable by these facts:
660 * 1. a==b implies equality at the raw data level
661 * (the converse is false, as a==b is never true among invalids)
662 * 2. This is similar to the behavior of IEEE floats, where a==b
663 * means that a and b have the same value *and* neither is NaN.
664 */
665 bool operator ==(const CheckedInt& other) const
666 {
667 return mIsValid && other.mIsValid && mValue == other.mValue;
668 }
669
670 /** prefix ++ */
671 CheckedInt& operator++()
672 {
673 *this += 1;
674 return *this;
675 }
676
677 /** postfix ++ */
678 CheckedInt operator++(int)
679 {
680 CheckedInt tmp = *this;
681 *this += 1;
682 return tmp;
683 }
684
685 /** prefix -- */
686 CheckedInt& operator--()
687 {
688 *this -= 1;
689 return *this;
690 }
691
692 /** postfix -- */
693 CheckedInt operator--(int)
694 {
695 CheckedInt tmp = *this;
696 *this -= 1;
697 return tmp;
698 }
699
700 private:
701 /**
702 * The !=, <, <=, >, >= operators are disabled:
703 * see the comment on operator==.
704 */
705 template<typename U>
706 bool operator !=(U other) const MOZ_DELETE;
707 template<typename U>
708 bool operator <(U other) const MOZ_DELETE;
709 template<typename U>
710 bool operator <=(U other) const MOZ_DELETE;
711 template<typename U>
712 bool operator >(U other) const MOZ_DELETE;
713 template<typename U>
714 bool operator >=(U other) const MOZ_DELETE;
715 };
716
717 #define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \
718 template<typename T> \
719 inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, \
720 const CheckedInt<T> &rhs) \
721 { \
722 if (!detail::Is##NAME##Valid(lhs.mValue, rhs.mValue)) \
723 return CheckedInt<T>(0, false); \
724 \
725 return CheckedInt<T>(lhs.mValue OP rhs.mValue, \
726 lhs.mIsValid && rhs.mIsValid); \
727 }
728
729 MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
730 MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
731 MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
732 MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /)
733
734 #undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
735
736 // Implement castToCheckedInt<T>(x), making sure that
737 // - it allows x to be either a CheckedInt<T> or any integer type
738 // that can be casted to T
739 // - if x is already a CheckedInt<T>, we just return a reference to it,
740 // instead of copying it (optimization)
741
742 namespace detail {
743
744 template<typename T, typename U>
745 struct CastToCheckedIntImpl
746 {
747 typedef CheckedInt<T> ReturnType;
748 static CheckedInt<T> run(U u) { return u; }
749 };
750
751 template<typename T>
752 struct CastToCheckedIntImpl<T, CheckedInt<T> >
753 {
754 typedef const CheckedInt<T>& ReturnType;
755 static const CheckedInt<T>& run(const CheckedInt<T>& u) { return u; }
756 };
757
758 } // namespace detail
759
760 template<typename T, typename U>
761 inline typename detail::CastToCheckedIntImpl<T, U>::ReturnType
762 castToCheckedInt(U u)
763 {
764 return detail::CastToCheckedIntImpl<T, U>::run(u);
765 }
766
767 #define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \
768 template<typename T> \
769 template<typename U> \
770 CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U rhs) \
771 { \
772 *this = *this OP castToCheckedInt<T>(rhs); \
773 return *this; \
774 } \
775 template<typename T, typename U> \
776 inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, U rhs) \
777 { \
778 return lhs OP castToCheckedInt<T>(rhs); \
779 } \
780 template<typename T, typename U> \
781 inline CheckedInt<T> operator OP(U lhs, const CheckedInt<T> &rhs) \
782 { \
783 return castToCheckedInt<T>(lhs) OP rhs; \
784 }
785
786 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
787 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
788 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
789 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
790
791 #undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS
792
793 template<typename T, typename U>
794 inline bool
795 operator ==(const CheckedInt<T> &lhs, U rhs)
796 {
797 return lhs == castToCheckedInt<T>(rhs);
798 }
799
800 template<typename T, typename U>
801 inline bool
802 operator ==(U lhs, const CheckedInt<T> &rhs)
803 {
804 return castToCheckedInt<T>(lhs) == rhs;
805 }
806
807 // Convenience typedefs.
808 typedef CheckedInt<int8_t> CheckedInt8;
809 typedef CheckedInt<uint8_t> CheckedUint8;
810 typedef CheckedInt<int16_t> CheckedInt16;
811 typedef CheckedInt<uint16_t> CheckedUint16;
812 typedef CheckedInt<int32_t> CheckedInt32;
813 typedef CheckedInt<uint32_t> CheckedUint32;
814 typedef CheckedInt<int64_t> CheckedInt64;
815 typedef CheckedInt<uint64_t> CheckedUint64;
816
817 } // namespace WebCore
818
819 #endif /* mozilla_CheckedInt_h_ */
OLDNEW
« no previous file with comments | « Source/core/core.gypi ('k') | Source/core/html/canvas/DataView.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698