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

Side by Side Diff: src/base/safe_conversions_impl.h

Issue 336183003: Add safe numerics classes, imported from Chromium (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: changes required for V8 Created 6 years, 6 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/base/safe_conversions.h ('k') | src/base/safe_math.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 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Slightly adapted for inclusion in V8.
6 // Copyright 2014 the V8 project authors. All rights reserved.
7
8 #ifndef BASE_SAFE_CONVERSIONS_IMPL_H_
jochen (gone - plz use gerrit) 2014/06/16 14:25:46 please use V8_BASE_SAFE_CONVERSIONS_IMPL_H_
Jakob Kummerow 2014/06/17 13:53:20 Done.
9 #define BASE_SAFE_CONVERSIONS_IMPL_H_
10
11 #include <limits>
12
13 #include "src/base/macros.h"
14
15 namespace v8 {
16 namespace internal {
jochen (gone - plz use gerrit) 2014/06/16 14:25:46 please use namespace v8::base in the base library
Jakob Kummerow 2014/06/17 13:53:20 Done.
17
18 // The std library doesn't provide a binary max_exponent for integers, however
19 // we can compute one by adding one to the number of non-sign bits. This allows
20 // for accurate range comparisons between floating point and integer types.
21 template <typename NumericType>
22 struct MaxExponent {
23 static const int value = std::numeric_limits<NumericType>::is_iec559
24 ? std::numeric_limits<NumericType>::max_exponent
25 : (sizeof(NumericType) * 8 + 1 -
26 std::numeric_limits<NumericType>::is_signed);
27 };
28
29 enum IntegerRepresentation {
30 INTEGER_REPRESENTATION_UNSIGNED,
31 INTEGER_REPRESENTATION_SIGNED
32 };
33
34 // A range for a given nunmeric Src type is contained for a given numeric Dst
35 // type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and
36 // numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true.
37 // We implement this as template specializations rather than simple static
38 // comparisons to ensure type correctness in our comparisons.
39 enum NumericRangeRepresentation {
40 NUMERIC_RANGE_NOT_CONTAINED,
41 NUMERIC_RANGE_CONTAINED
42 };
43
44 // Helper templates to statically determine if our destination type can contain
45 // maximum and minimum values represented by the source type.
46
47 template <
48 typename Dst,
49 typename Src,
50 IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
51 ? INTEGER_REPRESENTATION_SIGNED
52 : INTEGER_REPRESENTATION_UNSIGNED,
53 IntegerRepresentation SrcSign =
54 std::numeric_limits<Src>::is_signed
55 ? INTEGER_REPRESENTATION_SIGNED
56 : INTEGER_REPRESENTATION_UNSIGNED >
57 struct StaticDstRangeRelationToSrcRange;
58
59 // Same sign: Dst is guaranteed to contain Src only if its range is equal or
60 // larger.
61 template <typename Dst, typename Src, IntegerRepresentation Sign>
62 struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign> {
63 static const NumericRangeRepresentation value =
64 MaxExponent<Dst>::value >= MaxExponent<Src>::value
65 ? NUMERIC_RANGE_CONTAINED
66 : NUMERIC_RANGE_NOT_CONTAINED;
67 };
68
69 // Unsigned to signed: Dst is guaranteed to contain source only if its range is
70 // larger.
71 template <typename Dst, typename Src>
72 struct StaticDstRangeRelationToSrcRange<Dst,
73 Src,
74 INTEGER_REPRESENTATION_SIGNED,
75 INTEGER_REPRESENTATION_UNSIGNED> {
76 static const NumericRangeRepresentation value =
77 MaxExponent<Dst>::value > MaxExponent<Src>::value
78 ? NUMERIC_RANGE_CONTAINED
79 : NUMERIC_RANGE_NOT_CONTAINED;
80 };
81
82 // Signed to unsigned: Dst cannot be statically determined to contain Src.
83 template <typename Dst, typename Src>
84 struct StaticDstRangeRelationToSrcRange<Dst,
85 Src,
86 INTEGER_REPRESENTATION_UNSIGNED,
87 INTEGER_REPRESENTATION_SIGNED> {
88 static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
89 };
90
91 enum RangeConstraint {
92 RANGE_VALID = 0x0, // Value can be represented by the destination type.
93 RANGE_UNDERFLOW = 0x1, // Value would overflow.
94 RANGE_OVERFLOW = 0x2, // Value would underflow.
95 RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
96 };
97
98 // Helper function for coercing an int back to a RangeContraint.
99 inline RangeConstraint GetRangeConstraint(int integer_range_constraint) {
100 // TODO(jochen/jkummerow): Re-enable this when checks.h is available in base.
101 // ASSERT(integer_range_constraint >= RANGE_VALID &&
102 // integer_range_constraint <= RANGE_INVALID);
103 return static_cast<RangeConstraint>(integer_range_constraint);
104 }
105
106 // This function creates a RangeConstraint from an upper and lower bound
107 // check by taking advantage of the fact that only NaN can be out of range in
108 // both directions at once.
109 inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound,
110 bool is_in_lower_bound) {
111 return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) |
112 (is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
113 }
114
115 template <
116 typename Dst,
117 typename Src,
118 IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
119 ? INTEGER_REPRESENTATION_SIGNED
120 : INTEGER_REPRESENTATION_UNSIGNED,
121 IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
122 ? INTEGER_REPRESENTATION_SIGNED
123 : INTEGER_REPRESENTATION_UNSIGNED,
124 NumericRangeRepresentation DstRange =
125 StaticDstRangeRelationToSrcRange<Dst, Src>::value >
126 struct DstRangeRelationToSrcRangeImpl;
127
128 // The following templates are for ranges that must be verified at runtime. We
129 // split it into checks based on signedness to avoid confusing casts and
130 // compiler warnings on signed an unsigned comparisons.
131
132 // Dst range is statically determined to contain Src: Nothing to check.
133 template <typename Dst,
134 typename Src,
135 IntegerRepresentation DstSign,
136 IntegerRepresentation SrcSign>
137 struct DstRangeRelationToSrcRangeImpl<Dst,
138 Src,
139 DstSign,
140 SrcSign,
141 NUMERIC_RANGE_CONTAINED> {
142 static RangeConstraint Check(Src value) { return RANGE_VALID; }
143 };
144
145 // Signed to signed narrowing: Both the upper and lower boundaries may be
146 // exceeded.
147 template <typename Dst, typename Src>
148 struct DstRangeRelationToSrcRangeImpl<Dst,
149 Src,
150 INTEGER_REPRESENTATION_SIGNED,
151 INTEGER_REPRESENTATION_SIGNED,
152 NUMERIC_RANGE_NOT_CONTAINED> {
153 static RangeConstraint Check(Src value) {
154 return std::numeric_limits<Dst>::is_iec559
155 ? GetRangeConstraint(value <= std::numeric_limits<Dst>::max(),
156 value >= -std::numeric_limits<Dst>::max())
157 : GetRangeConstraint(value <= std::numeric_limits<Dst>::max(),
158 value >= std::numeric_limits<Dst>::min());
159 }
160 };
161
162 // Unsigned to unsigned narrowing: Only the upper boundary can be exceeded.
163 template <typename Dst, typename Src>
164 struct DstRangeRelationToSrcRangeImpl<Dst,
165 Src,
166 INTEGER_REPRESENTATION_UNSIGNED,
167 INTEGER_REPRESENTATION_UNSIGNED,
168 NUMERIC_RANGE_NOT_CONTAINED> {
169 static RangeConstraint Check(Src value) {
170 return GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), true);
171 }
172 };
173
174 // Unsigned to signed: The upper boundary may be exceeded.
175 template <typename Dst, typename Src>
176 struct DstRangeRelationToSrcRangeImpl<Dst,
177 Src,
178 INTEGER_REPRESENTATION_SIGNED,
179 INTEGER_REPRESENTATION_UNSIGNED,
180 NUMERIC_RANGE_NOT_CONTAINED> {
181 static RangeConstraint Check(Src value) {
182 return sizeof(Dst) > sizeof(Src)
183 ? RANGE_VALID
184 : GetRangeConstraint(
185 value <= static_cast<Src>(std::numeric_limits<Dst>::max()),
186 true);
187 }
188 };
189
190 // Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
191 // and any negative value exceeds the lower boundary.
192 template <typename Dst, typename Src>
193 struct DstRangeRelationToSrcRangeImpl<Dst,
194 Src,
195 INTEGER_REPRESENTATION_UNSIGNED,
196 INTEGER_REPRESENTATION_SIGNED,
197 NUMERIC_RANGE_NOT_CONTAINED> {
198 static RangeConstraint Check(Src value) {
199 return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
200 ? GetRangeConstraint(true, value >= static_cast<Src>(0))
201 : GetRangeConstraint(
202 value <= static_cast<Src>(std::numeric_limits<Dst>::max()),
203 value >= static_cast<Src>(0));
204 }
205 };
206
207 template <typename Dst, typename Src>
208 inline RangeConstraint DstRangeRelationToSrcRange(Src value) {
209 // Both source and destination must be numeric.
210 STATIC_ASSERT(std::numeric_limits<Src>::is_specialized);
211 STATIC_ASSERT(std::numeric_limits<Dst>::is_specialized);
212 return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value);
213 }
214
215 } // namespace internal
216 } // namespace v8
217
218 #endif // BASE_SAFE_CONVERSIONS_IMPL_H_
OLDNEW
« no previous file with comments | « src/base/safe_conversions.h ('k') | src/base/safe_math.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698