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

Side by Side Diff: src/utils/SkTFitsIn.h

Issue 18503009: Fix SkTFits in to work properly with signed/unsigned mixtures. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Address comments by adding comments and assertions. Created 7 years, 5 months 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 | Annotate | Revision Log
« no previous file with comments | « src/ports/SkOSFile_win.cpp ('k') | src/utils/SkTLogic.h » ('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 /*
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 /** SkTHasMoreDigits::type = (digits(A) >= digits(B)) ? SkTrue : SkFalse. */
19 template<typename A, typename B> struct SkTHasMoreDigits {
20 typedef SkTBool<std::numeric_limits<A>::digits >= std::numeric_limits<B>::di gits> type;
21 };
22
23 /** A high or low side predicate which is used when it is statically known
24 * that source values are in the range of the Destination.
25 */
26 template <typename S> struct SkTOutOfRange_False {
27 typedef SkFalse can_be_true;
28 typedef S source_type;
29 static bool apply(S s) {
30 return false;
31 }
32 };
33
34 /** A low side predicate which tests if the source value < Min(D).
35 * Assumes that Min(S) <= Min(D).
36 */
37 template <typename D, typename S> struct SkTOutOfRange_LT_MinD {
38 typedef SkTrue can_be_true;
39 typedef S source_type;
40 static bool apply(S s) {
41 typedef typename SkTHasMoreDigits<S, D>::type precondition;
42 SK_COMPILE_ASSERT(precondition::value, SkTOutOfRange_LT_MinD__minS_gt_mi nD);
43
44 return s < static_cast<S>((std::numeric_limits<D>::min)());
45 }
46 };
47
48 /** A low side predicate which tests if the source value is less than 0. */
49 template <typename D, typename S> struct SkTOutOfRange_LT_Zero {
50 typedef SkTrue can_be_true;
51 typedef S source_type;
52 static bool apply(S s) {
53 return s < static_cast<S>(0);
54 }
55 };
56
57 /** A high side predicate which tests if the source value > Max(D).
58 * Assumes that Max(S) >= Max(D).
59 */
60 template <typename D, typename S> struct SkTOutOfRange_GT_MaxD {
61 typedef SkTrue can_be_true;
62 typedef S source_type;
63 static bool apply(S s) {
64 typedef typename SkTHasMoreDigits<S, D>::type precondition;
65 SK_COMPILE_ASSERT(precondition::value, SkTOutOfRange_GT_MaxD__maxS_lt_ma xD);
66
67 return s > static_cast<S>((std::numeric_limits<D>::max)());
68 }
69 };
70
71 /** Composes two SkTOutOfRange predicates.
72 * First checks OutOfRange_Low then, if in range, OutOfRange_High.
73 */
74 template<class OutOfRange_Low, class OutOfRange_High> struct SkTOutOfRange_Eithe r {
75 typedef SkTrue can_be_true;
76 typedef typename OutOfRange_Low::source_type source_type;
77 static bool apply(source_type s) {
78 bool outOfRange = OutOfRange_Low::apply(s);
79 if (!outOfRange) {
80 outOfRange = OutOfRange_High::apply(s);
81 }
82 return outOfRange;
83 }
84 };
85
86 /** SkTCombineOutOfRange::type is an SkTOutOfRange_XXX type which is the
87 * optimal combination of OutOfRange_Low and OutOfRange_High.
88 */
89 template<class OutOfRange_Low, class OutOfRange_High> struct SkTCombineOutOfRang e {
90 typedef SkTOutOfRange_Either<OutOfRange_Low, OutOfRange_High> Both;
91 typedef SkTOutOfRange_False<typename OutOfRange_Low::source_type> Neither;
92
93 typedef typename OutOfRange_Low::can_be_true apply_low;
94 typedef typename OutOfRange_High::can_be_true apply_high;
95
96 typedef typename SkTMux<apply_low, apply_high,
97 Both, OutOfRange_Low, OutOfRange_High, Neither>::typ e type;
98 };
99
100 template<typename D, typename S, class OutOfRange_Low, class OutOfRange_High>
101 struct SkTRangeChecker {
102 /** This is the method which is called at runtime to do the range check. */
103 static bool OutOfRange(S s) {
104 typedef typename SkTCombineOutOfRange<OutOfRange_Low, OutOfRange_High>:: type Combined;
105 return Combined::apply(s);
106 }
107 };
108
109 /** SkTFitsIn_Unsigned2Unsiged::type is an SkTRangeChecker with an OutOfRange(S s) method
110 * the implementation of which is tailored for the source and destination types .
111 * Assumes that S and D are unsigned integer types.
112 */
113 template<typename D, typename S> struct SkTFitsIn_Unsigned2Unsiged {
114 typedef SkTOutOfRange_False<S> OutOfRange_Low;
115 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
116
117 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> HighSideOnlyC heck;
118 typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck;
119
120 // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, noth ing to check.
121 // This also protects the precondition of SkTOutOfRange_GT_MaxD.
122 typedef typename SkTHasMoreDigits<D, S>::type sourceFitsInDesitination;
123 typedef typename SkTIf<sourceFitsInDesitination, NoCheck, HighSideOnlyCheck> ::type type;
124 };
125
126 /** SkTFitsIn_Signed2Signed::type is an SkTRangeChecker with an OutOfRange(S s) method
127 * the implementation of which is tailored for the source and destination types .
128 * Assumes that S and D are signed integer types.
129 */
130 template<typename D, typename S> struct SkTFitsIn_Signed2Signed {
131 typedef SkTOutOfRange_LT_MinD<D, S> OutOfRange_Low;
132 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
133
134 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> FullCheck;
135 typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck;
136
137 // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, noth ing to check.
138 // This also protects the precondition of SkTOutOfRange_LT_MinD and SkTOutOf Range_GT_MaxD.
139 typedef typename SkTHasMoreDigits<D, S>::type sourceFitsInDesitination;
140 typedef typename SkTIf<sourceFitsInDesitination, NoCheck, FullCheck>::type t ype;
141 };
142
143 /** SkTFitsIn_Signed2Unsigned::type is an SkTRangeChecker with an OutOfRange(S s ) method
144 * the implementation of which is tailored for the source and destination types .
145 * Assumes that S is a signed integer type and D is an unsigned integer type.
146 */
147 template<typename D, typename S> struct SkTFitsIn_Signed2Unsigned {
148 typedef SkTOutOfRange_LT_Zero<D, S> OutOfRange_Low;
149 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
150
151 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> FullCheck;
152 typedef SkTRangeChecker<D, S, OutOfRange_Low, SkTOutOfRange_False<S> > LowSi deOnlyCheck;
153
154 // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(),
155 // no need to check the high side. (Until C++11, assume more digits means gr eater max.)
156 // This also protects the precondition of SkTOutOfRange_GT_MaxD.
157 typedef typename SkTHasMoreDigits<D, S>::type sourceCannotExceedDesitination ;
158 typedef typename SkTIf<sourceCannotExceedDesitination, LowSideOnlyCheck, Ful lCheck>::type type;
159 };
160
161 /** SkTFitsIn_Unsigned2Signed::type is an SkTRangeChecker with an OutOfRange(S s ) method
162 * the implementation of which is tailored for the source and destination types .
163 * Assumes that S is an usigned integer type and D is a signed integer type.
164 */
165 template<typename D, typename S> struct SkTFitsIn_Unsigned2Signed {
166 typedef SkTOutOfRange_False<S> OutOfRange_Low;
167 typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
168
169 typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> HighSideOnlyC heck;
170 typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck;
171
172 // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(), nothin g to check.
173 // (Until C++11, assume more digits means greater max.)
174 // This also protects the precondition of SkTOutOfRange_GT_MaxD.
175 typedef typename SkTHasMoreDigits<D, S>::type sourceCannotExceedDesitination ;
176 typedef typename SkTIf<sourceCannotExceedDesitination, NoCheck, HighSideOnly Check>::type type;
177 };
178
179 /** SkTFitsIn::type is an SkTRangeChecker with an OutOfRange(S s) method
180 * the implementation of which is tailored for the source and destination types .
181 * Assumes that S and D are integer types.
182 */
183 template<typename D, typename S> struct SkTFitsIn {
184 // One of the following will be the 'selector' type.
185 typedef SkTFitsIn_Signed2Signed<D, S> S2S;
186 typedef SkTFitsIn_Signed2Unsigned<D, S> S2U;
187 typedef SkTFitsIn_Unsigned2Signed<D, S> U2S;
188 typedef SkTFitsIn_Unsigned2Unsiged<D, S> U2U;
189
190 typedef SkTBool<std::numeric_limits<S>::is_signed> S_is_signed;
191 typedef SkTBool<std::numeric_limits<D>::is_signed> D_is_signed;
192
193 typedef typename SkTMux<S_is_signed, D_is_signed, S2S, S2U, U2S, U2U>::type selector;
194 // This type is an SkTRangeChecker.
195 typedef typename selector::type type;
196 };
197
198 } // namespace Private
199 } // namespace sktfitsin
200
201 /** Returns true if the integer source value 's' will fit in the integer destina tion type 'D'. */
202 template <typename D, typename S> inline bool SkTFitsIn(S s) {
203 SK_COMPILE_ASSERT(std::numeric_limits<S>::is_integer, SkTFitsIn_source_must_ be_integer);
204 SK_COMPILE_ASSERT(std::numeric_limits<D>::is_integer, SkTFitsIn_destination_ must_be_integer);
205
206 return !sktfitsin::Private::SkTFitsIn<D, S>::type::OutOfRange(s);
207 }
208
209 #endif
OLDNEW
« no previous file with comments | « src/ports/SkOSFile_win.cpp ('k') | src/utils/SkTLogic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698