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

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

Powered by Google App Engine
This is Rietveld 408576698