Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2013 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #ifndef SkTFitsIn_DEFINED | |
| 9 #define SkTFitsIn_DEFINED | |
| 10 | |
| 11 #include "SkTypes.h" | |
| 12 #include "SkTLogic.h" | |
| 13 #include <limits> | |
| 14 | |
| 15 namespace sktfitsin { | |
| 16 namespace Private { | |
| 17 | |
| 18 /** A high or low side predicate which is used when it is statically known | |
| 19 * that source values are in the range of the Destination. | |
| 20 */ | |
| 21 template <typename S> struct SkTOutOfRange_False { | |
| 22 typedef SkFalse can_be_true; | |
| 23 typedef S source_type; | |
| 24 static bool apply(S s) { | |
| 25 return false; | |
| 26 } | |
| 27 }; | |
| 28 | |
| 29 /** A low side predicate which tests if the source value < Min(D). | |
| 30 * Assumes that Min(S) <= Min(D). | |
| 31 */ | |
| 32 template <typename D, typename S> struct SkTOutOfRange_LT_MinD { | |
| 33 typedef SkTrue can_be_true; | |
| 34 typedef S source_type; | |
| 35 static bool apply(S s) { | |
| 36 return s < static_cast<S>((std::numeric_limits<D>::min)()); | |
| 37 } | |
| 38 }; | |
| 39 | |
| 40 /** A low side predicate which tests if the source value is less than 0. */ | |
| 41 template <typename D, typename S> struct SkTOutOfRange_LT_Zero { | |
| 42 typedef SkTrue can_be_true; | |
| 43 typedef S source_type; | |
| 44 static bool apply(S s) { | |
| 45 return s < static_cast<S>(0); | |
| 46 } | |
| 47 }; | |
| 48 | |
| 49 /** A high side predicate which tests if the source value > Max(D). | |
| 50 * Assumes that Max(S) >= Max(D). | |
| 51 */ | |
| 52 template <typename D, typename S> struct SkTOutOfRange_GT_MaxD { | |
| 53 typedef SkTrue can_be_true; | |
| 54 typedef S source_type; | |
| 55 static bool apply(S s) { | |
| 56 return s > static_cast<S>((std::numeric_limits<D>::max)()); | |
| 57 } | |
| 58 }; | |
| 59 | |
| 60 /** Composes two SkTOutOfRange predicates: first 'Low' then, if in range, 'High' . */ | |
| 61 template<class OutOfRange_Low, class OutOfRange_High> struct SkTOutOfRange_Eithe r { | |
| 62 typedef SkTrue can_be_true; | |
| 63 typedef typename OutOfRange_Low::source_type source_type; | |
| 64 static bool apply(source_type s) { | |
| 65 bool outOfRange = OutOfRange_Low::apply(s); | |
| 66 if (!outOfRange) { | |
| 67 outOfRange = OutOfRange_High::apply(s); | |
| 68 } | |
| 69 return outOfRange; | |
| 70 } | |
| 71 }; | |
| 72 | |
| 73 /** Optimally combines low and high OutOfRange predicates. */ | |
| 74 template<class OutOfRange_Low, class OutOfRange_High> struct SkTCombineOutOfRang e { | |
| 75 typedef SkTOutOfRange_Either<OutOfRange_Low, OutOfRange_High> Both; | |
| 76 typedef SkTOutOfRange_False<typename OutOfRange_Low::source_type> Neither; | |
| 77 | |
| 78 typedef typename OutOfRange_Low::can_be_true apply_low; | |
| 79 typedef typename OutOfRange_High::can_be_true apply_high; | |
| 80 | |
| 81 typedef typename SkTMux<apply_low, apply_high, | |
| 82 Both, OutOfRange_Low, OutOfRange_High, Neither>::typ e type; | |
| 83 }; | |
| 84 | |
| 85 template<typename D, typename S, class OutOfRange_Low, class OutOfRange_High> | |
| 86 struct SkTRangeChecker { | |
| 87 /** This is the method which is called at runtime to do the range check. */ | |
| 88 static bool OutOfRange(S s) { | |
| 89 typedef typename SkTCombineOutOfRange<OutOfRange_Low, OutOfRange_High>:: type Combined; | |
| 90 return Combined::apply(s); | |
| 91 } | |
| 92 }; | |
| 93 | |
| 94 /** SkTrue if D has the same or more magnitude digits than S. */ | |
| 95 template<typename D, typename S> struct SkTHasMoreDigits { | |
| 96 typedef SkTBool<std::numeric_limits<D>::digits >= std::numeric_limits<S>::di gits> type; | |
| 97 }; | |
| 98 | |
| 99 template<typename D, typename S> struct SkTFitsIn_Unsigned2Unsiged { | |
|
mtklein
2013/07/11 14:56:57
Can you add a comment for each of these four remin
bungeman-skia
2013/07/11 20:22:03
Hmmm... yes. So the reason I have for these tests
| |
| 100 typedef SkTOutOfRange_False<S> OutOfRange_Low; | |
| 101 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High; | |
| 102 | |
| 103 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> HighSideOnlyC heck; | |
| 104 typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck; | |
| 105 | |
| 106 // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, noth ing to check. | |
| 107 typedef typename SkTHasMoreDigits<D, S>::type sourceFitsInDesitination; | |
| 108 typedef typename SkTIf<sourceFitsInDesitination, NoCheck, HighSideOnlyCheck> ::type type; | |
| 109 }; | |
| 110 | |
| 111 template<typename D, typename S> struct SkTFitsIn_Signed2Signed { | |
| 112 typedef SkTOutOfRange_LT_MinD<D, S> OutOfRange_Low; | |
| 113 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High; | |
| 114 | |
| 115 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> FullCheck; | |
| 116 typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck; | |
| 117 | |
| 118 // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, noth ing to check. | |
| 119 typedef typename SkTHasMoreDigits<D, S>::type sourceFitsInDesitination; | |
| 120 typedef typename SkTIf<sourceFitsInDesitination, NoCheck, FullCheck>::type t ype; | |
| 121 }; | |
| 122 | |
| 123 template<typename D, typename S> struct SkTFitsIn_Signed2Unsigned { | |
| 124 typedef SkTOutOfRange_LT_Zero<D, S> OutOfRange_Low; | |
| 125 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High; | |
| 126 | |
| 127 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> FullCheck; | |
| 128 typedef SkTRangeChecker<D, S, OutOfRange_Low, SkTOutOfRange_False<S> > LowSi deOnlyCheck; | |
| 129 | |
| 130 // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(), | |
| 131 // no need to check the high side. (Until C++11, assume more digits means gr eater max.) | |
| 132 typedef typename SkTHasMoreDigits<D, S>::type sourceCannotExceedDesitination ; | |
| 133 typedef typename SkTIf<sourceCannotExceedDesitination, LowSideOnlyCheck, Ful lCheck>::type type; | |
| 134 }; | |
| 135 | |
| 136 template<typename D, typename S> struct SkTFitsIn_Unsigned2Signed { | |
| 137 typedef SkTOutOfRange_False<S> OutOfRange_Low; | |
| 138 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High; | |
| 139 | |
| 140 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> HighSideOnlyC heck; | |
| 141 typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck; | |
| 142 | |
| 143 // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(), nothin g to check. | |
| 144 // (Until C++11, assume more digits means greater max.) | |
| 145 typedef typename SkTHasMoreDigits<D, S>::type sourceCannotExceedDesitination ; | |
| 146 typedef typename SkTIf<sourceCannotExceedDesitination, NoCheck, HighSideOnly Check>::type type; | |
| 147 }; | |
| 148 | |
| 149 template<typename D, typename S> struct SkTFitsIn { | |
| 150 // One of the following will be the 'selector' type. | |
| 151 typedef SkTFitsIn_Signed2Signed<D, S> S2S; | |
| 152 typedef SkTFitsIn_Signed2Unsigned<D, S> S2U; | |
| 153 typedef SkTFitsIn_Unsigned2Signed<D, S> U2S; | |
| 154 typedef SkTFitsIn_Unsigned2Unsiged<D, S> U2U; | |
| 155 | |
| 156 typedef SkTBool<std::numeric_limits<S>::is_signed> S_is_signed; | |
| 157 typedef SkTBool<std::numeric_limits<D>::is_signed> D_is_signed; | |
| 158 | |
| 159 typedef typename SkTMux<S_is_signed, D_is_signed, S2S, S2U, U2S, U2U>::type selector; | |
| 160 // This type is an SkTRangeChecker. | |
| 161 typedef typename selector::type type; | |
| 162 }; | |
| 163 | |
| 164 } | |
|
mtklein
2013/07/11 14:56:57
Do you mind tacking on
// namespace Private
//
bungeman-skia
2013/07/11 20:22:03
Done.
| |
| 165 } | |
| 166 | |
| 167 /** Returns true if the integer source value 's' will fit in the integer destina tion type 'D'. */ | |
| 168 template <typename D, typename S> inline bool SkTFitsIn(S s) { | |
| 169 SK_COMPILE_ASSERT(std::numeric_limits<S>::is_integer, SkTFitsIn_source_must_ be_integer); | |
| 170 SK_COMPILE_ASSERT(std::numeric_limits<D>::is_integer, SkTFitsIn_destination_ must_be_integer); | |
| 171 | |
| 172 return !sktfitsin::Private::SkTFitsIn<D, S>::type::OutOfRange(s); | |
| 173 } | |
| 174 | |
| 175 #endif | |
| OLD | NEW |