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

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: Remove enable_if, use SK_COMPILE_ASSERT instead. 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
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 /** 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
OLDNEW
« no previous file with comments | « src/ports/SkOSFile_win.cpp ('k') | src/utils/SkTLogic.h » ('j') | src/utils/SkTLogic.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698