| 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 |