OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2017 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2017 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 ""); | 135 ""); |
136 }; | 136 }; |
137 | 137 |
138 // Specialization for when both types are integral. | 138 // Specialization for when both types are integral. |
139 template <typename T1, typename T2> | 139 template <typename T1, typename T2> |
140 struct MType<T1, T2, true, true> { | 140 struct MType<T1, T2, true, true> { |
141 // The type with the lowest minimum value. In case of a tie, the type with | 141 // The type with the lowest minimum value. In case of a tie, the type with |
142 // the lowest maximum value. In case that too is a tie, the types have the | 142 // the lowest maximum value. In case that too is a tie, the types have the |
143 // same range, and we arbitrarily pick T1. | 143 // same range, and we arbitrarily pick T1. |
144 using min_t = typename std::conditional< | 144 using min_t = typename std::conditional< |
145 safe_cmp::Lt(Limits<T1>::lowest, Limits<T2>::lowest), | 145 SafeLt(Limits<T1>::lowest, Limits<T2>::lowest), |
146 T1, | 146 T1, |
147 typename std::conditional< | 147 typename std::conditional< |
148 safe_cmp::Gt(Limits<T1>::lowest, Limits<T2>::lowest), | 148 SafeGt(Limits<T1>::lowest, Limits<T2>::lowest), |
149 T2, | 149 T2, |
150 typename std::conditional<safe_cmp::Le(Limits<T1>::max, | 150 typename std::conditional<SafeLe(Limits<T1>::max, Limits<T2>::max), |
151 Limits<T2>::max), | |
152 T1, | 151 T1, |
153 T2>::type>::type>::type; | 152 T2>::type>::type>::type; |
154 static_assert(std::is_same<min_t, T1>::value || | 153 static_assert(std::is_same<min_t, T1>::value || |
155 std::is_same<min_t, T2>::value, | 154 std::is_same<min_t, T2>::value, |
156 ""); | 155 ""); |
157 | 156 |
158 // The type with the highest maximum value. In case of a tie, the types have | 157 // The type with the highest maximum value. In case of a tie, the types have |
159 // the same range (because in C++, integer types with the same maximum also | 158 // the same range (because in C++, integer types with the same maximum also |
160 // have the same minimum). | 159 // have the same minimum). |
161 static_assert(safe_cmp::Ne(Limits<T1>::max, Limits<T2>::max) || | 160 static_assert(SafeNe(Limits<T1>::max, Limits<T2>::max) || |
162 safe_cmp::Eq(Limits<T1>::lowest, Limits<T2>::lowest), | 161 SafeEq(Limits<T1>::lowest, Limits<T2>::lowest), |
163 "integer types with the same max should have the same min"); | 162 "integer types with the same max should have the same min"); |
164 using max_t = typename std:: | 163 using max_t = typename std:: |
165 conditional<safe_cmp::Ge(Limits<T1>::max, Limits<T2>::max), T1, T2>::type; | 164 conditional<SafeGe(Limits<T1>::max, Limits<T2>::max), T1, T2>::type; |
166 static_assert(std::is_same<max_t, T1>::value || | 165 static_assert(std::is_same<max_t, T1>::value || |
167 std::is_same<max_t, T2>::value, | 166 std::is_same<max_t, T2>::value, |
168 ""); | 167 ""); |
169 }; | 168 }; |
170 | 169 |
171 // A dummy type that we pass around at compile time but never actually use. | 170 // A dummy type that we pass around at compile time but never actually use. |
172 // Declared but not defined. | 171 // Declared but not defined. |
173 struct DefaultType; | 172 struct DefaultType; |
174 | 173 |
175 // ::type is A, except we fall back to B if A is DefaultType. We static_assert | 174 // ::type is A, except we fall back to B if A is DefaultType. We static_assert |
176 // that the chosen type can hold all values that B can hold. | 175 // that the chosen type can hold all values that B can hold. |
177 template <typename A, typename B> | 176 template <typename A, typename B> |
178 struct TypeOr { | 177 struct TypeOr { |
179 using type = typename std:: | 178 using type = typename std:: |
180 conditional<std::is_same<A, DefaultType>::value, B, A>::type; | 179 conditional<std::is_same<A, DefaultType>::value, B, A>::type; |
181 static_assert(safe_cmp::Le(Limits<type>::lowest, Limits<B>::lowest) && | 180 static_assert(SafeLe(Limits<type>::lowest, Limits<B>::lowest) && |
182 safe_cmp::Ge(Limits<type>::max, Limits<B>::max), | 181 SafeGe(Limits<type>::max, Limits<B>::max), |
183 "The specified type isn't large enough"); | 182 "The specified type isn't large enough"); |
184 static_assert(IsIntlike<type>::value == IsIntlike<B>::value && | 183 static_assert(IsIntlike<type>::value == IsIntlike<B>::value && |
185 std::is_floating_point<type>::value == | 184 std::is_floating_point<type>::value == |
186 std::is_floating_point<type>::value, | 185 std::is_floating_point<type>::value, |
187 "float<->int conversions not allowed"); | 186 "float<->int conversions not allowed"); |
188 }; | 187 }; |
189 | 188 |
190 } // namespace safe_minmax_impl | 189 } // namespace safe_minmax_impl |
191 | 190 |
192 template < | 191 template < |
193 typename R = safe_minmax_impl::DefaultType, | 192 typename R = safe_minmax_impl::DefaultType, |
194 typename T1 = safe_minmax_impl::DefaultType, | 193 typename T1 = safe_minmax_impl::DefaultType, |
195 typename T2 = safe_minmax_impl::DefaultType, | 194 typename T2 = safe_minmax_impl::DefaultType, |
196 typename R2 = typename safe_minmax_impl::TypeOr< | 195 typename R2 = typename safe_minmax_impl::TypeOr< |
197 R, | 196 R, |
198 typename safe_minmax_impl::MType< | 197 typename safe_minmax_impl::MType< |
199 typename safe_minmax_impl::UnderlyingType<T1>::type, | 198 typename safe_minmax_impl::UnderlyingType<T1>::type, |
200 typename safe_minmax_impl::UnderlyingType<T2>::type>::min_t>::type> | 199 typename safe_minmax_impl::UnderlyingType<T2>::type>::min_t>::type> |
201 constexpr R2 SafeMin(T1 a, T2 b) { | 200 constexpr R2 SafeMin(T1 a, T2 b) { |
202 static_assert(IsIntlike<T1>::value || std::is_floating_point<T1>::value, | 201 static_assert(IsIntlike<T1>::value || std::is_floating_point<T1>::value, |
203 "The first argument must be integral or floating-point"); | 202 "The first argument must be integral or floating-point"); |
204 static_assert(IsIntlike<T2>::value || std::is_floating_point<T2>::value, | 203 static_assert(IsIntlike<T2>::value || std::is_floating_point<T2>::value, |
205 "The second argument must be integral or floating-point"); | 204 "The second argument must be integral or floating-point"); |
206 return safe_cmp::Lt(a, b) ? static_cast<R2>(a) : static_cast<R2>(b); | 205 return SafeLt(a, b) ? static_cast<R2>(a) : static_cast<R2>(b); |
207 } | 206 } |
208 | 207 |
209 template < | 208 template < |
210 typename R = safe_minmax_impl::DefaultType, | 209 typename R = safe_minmax_impl::DefaultType, |
211 typename T1 = safe_minmax_impl::DefaultType, | 210 typename T1 = safe_minmax_impl::DefaultType, |
212 typename T2 = safe_minmax_impl::DefaultType, | 211 typename T2 = safe_minmax_impl::DefaultType, |
213 typename R2 = typename safe_minmax_impl::TypeOr< | 212 typename R2 = typename safe_minmax_impl::TypeOr< |
214 R, | 213 R, |
215 typename safe_minmax_impl::MType< | 214 typename safe_minmax_impl::MType< |
216 typename safe_minmax_impl::UnderlyingType<T1>::type, | 215 typename safe_minmax_impl::UnderlyingType<T1>::type, |
217 typename safe_minmax_impl::UnderlyingType<T2>::type>::max_t>::type> | 216 typename safe_minmax_impl::UnderlyingType<T2>::type>::max_t>::type> |
218 constexpr R2 SafeMax(T1 a, T2 b) { | 217 constexpr R2 SafeMax(T1 a, T2 b) { |
219 static_assert(IsIntlike<T1>::value || std::is_floating_point<T1>::value, | 218 static_assert(IsIntlike<T1>::value || std::is_floating_point<T1>::value, |
220 "The first argument must be integral or floating-point"); | 219 "The first argument must be integral or floating-point"); |
221 static_assert(IsIntlike<T2>::value || std::is_floating_point<T2>::value, | 220 static_assert(IsIntlike<T2>::value || std::is_floating_point<T2>::value, |
222 "The second argument must be integral or floating-point"); | 221 "The second argument must be integral or floating-point"); |
223 return safe_cmp::Gt(a, b) ? static_cast<R2>(a) : static_cast<R2>(b); | 222 return SafeGt(a, b) ? static_cast<R2>(a) : static_cast<R2>(b); |
224 } | 223 } |
225 | 224 |
226 namespace safe_minmax_impl { | 225 namespace safe_minmax_impl { |
227 | 226 |
228 // Given three types T, L, and H, let ::type be a suitable return value for | 227 // Given three types T, L, and H, let ::type be a suitable return value for |
229 // SafeClamp(T, L, H). See the docs at the top of this file for details. | 228 // SafeClamp(T, L, H). See the docs at the top of this file for details. |
230 template <typename T, | 229 template <typename T, |
231 typename L, | 230 typename L, |
232 typename H, | 231 typename H, |
233 bool int1 = IsIntlike<T>::value, | 232 bool int1 = IsIntlike<T>::value, |
(...skipping 24 matching lines...) Expand all Loading... |
258 // Is the given type an acceptable return type? (That is, can it represent | 257 // Is the given type an acceptable return type? (That is, can it represent |
259 // all possible return values, and is it no larger than the largest of the | 258 // all possible return values, and is it no larger than the largest of the |
260 // input types?) | 259 // input types?) |
261 template <typename A> | 260 template <typename A> |
262 struct AcceptableType { | 261 struct AcceptableType { |
263 private: | 262 private: |
264 static constexpr bool not_too_large = sizeof(A) <= sizeof(L) || | 263 static constexpr bool not_too_large = sizeof(A) <= sizeof(L) || |
265 sizeof(A) <= sizeof(H) || | 264 sizeof(A) <= sizeof(H) || |
266 sizeof(A) <= sizeof(T); | 265 sizeof(A) <= sizeof(T); |
267 static constexpr bool range_contained = | 266 static constexpr bool range_contained = |
268 safe_cmp::Le(Limits<A>::lowest, r_min) && | 267 SafeLe(Limits<A>::lowest, r_min) && SafeLe(r_max, Limits<A>::max); |
269 safe_cmp::Le(r_max, Limits<A>::max); | |
270 | 268 |
271 public: | 269 public: |
272 static constexpr bool value = not_too_large && range_contained; | 270 static constexpr bool value = not_too_large && range_contained; |
273 }; | 271 }; |
274 | 272 |
275 using best_signed_type = typename std::conditional< | 273 using best_signed_type = typename std::conditional< |
276 AcceptableType<int8_t>::value, | 274 AcceptableType<int8_t>::value, |
277 int8_t, | 275 int8_t, |
278 typename std::conditional< | 276 typename std::conditional< |
279 AcceptableType<int16_t>::value, | 277 AcceptableType<int16_t>::value, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 typename safe_minmax_impl::UnderlyingType<L>::type, | 318 typename safe_minmax_impl::UnderlyingType<L>::type, |
321 typename safe_minmax_impl::UnderlyingType<H>::type>::type>::type> | 319 typename safe_minmax_impl::UnderlyingType<H>::type>::type>::type> |
322 R2 SafeClamp(T x, L min, H max) { | 320 R2 SafeClamp(T x, L min, H max) { |
323 static_assert(IsIntlike<H>::value || std::is_floating_point<H>::value, | 321 static_assert(IsIntlike<H>::value || std::is_floating_point<H>::value, |
324 "The first argument must be integral or floating-point"); | 322 "The first argument must be integral or floating-point"); |
325 static_assert(IsIntlike<T>::value || std::is_floating_point<T>::value, | 323 static_assert(IsIntlike<T>::value || std::is_floating_point<T>::value, |
326 "The second argument must be integral or floating-point"); | 324 "The second argument must be integral or floating-point"); |
327 static_assert(IsIntlike<L>::value || std::is_floating_point<L>::value, | 325 static_assert(IsIntlike<L>::value || std::is_floating_point<L>::value, |
328 "The third argument must be integral or floating-point"); | 326 "The third argument must be integral or floating-point"); |
329 RTC_DCHECK_LE(min, max); | 327 RTC_DCHECK_LE(min, max); |
330 return safe_cmp::Le(x, min) | 328 return SafeLe(x, min) |
331 ? static_cast<R2>(min) | 329 ? static_cast<R2>(min) |
332 : safe_cmp::Ge(x, max) ? static_cast<R2>(max) : static_cast<R2>(x); | 330 : SafeGe(x, max) ? static_cast<R2>(max) : static_cast<R2>(x); |
333 } | 331 } |
334 | 332 |
335 } // namespace rtc | 333 } // namespace rtc |
336 | 334 |
337 #endif // WEBRTC_BASE_SAFE_MINMAX_H_ | 335 #endif // WEBRTC_BASE_SAFE_MINMAX_H_ |
OLD | NEW |