safe_conversions.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*
  2. * Copyright 2014 The WebRTC Project Authors. All rights reserved.
  3. *
  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
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. // Borrowed from Chromium's src/base/numerics/safe_conversions.h.
  11. #ifndef RTC_BASE_NUMERICS_SAFE_CONVERSIONS_H_
  12. #define RTC_BASE_NUMERICS_SAFE_CONVERSIONS_H_
  13. #include <limits>
  14. #include "rtc_base/checks.h"
  15. #include "rtc_base/numerics/safe_conversions_impl.h"
  16. namespace rtc {
  17. // Convenience function that returns true if the supplied value is in range
  18. // for the destination type.
  19. template <typename Dst, typename Src>
  20. inline constexpr bool IsValueInRangeForNumericType(Src value) {
  21. return internal::RangeCheck<Dst>(value) == internal::TYPE_VALID;
  22. }
  23. // checked_cast<> and dchecked_cast<> are analogous to static_cast<> for
  24. // numeric types, except that they [D]CHECK that the specified numeric
  25. // conversion will not overflow or underflow. NaN source will always trigger
  26. // the [D]CHECK.
  27. template <typename Dst, typename Src>
  28. inline constexpr Dst checked_cast(Src value) {
  29. RTC_CHECK(IsValueInRangeForNumericType<Dst>(value));
  30. return static_cast<Dst>(value);
  31. }
  32. template <typename Dst, typename Src>
  33. inline constexpr Dst dchecked_cast(Src value) {
  34. RTC_DCHECK(IsValueInRangeForNumericType<Dst>(value));
  35. return static_cast<Dst>(value);
  36. }
  37. // saturated_cast<> is analogous to static_cast<> for numeric types, except
  38. // that the specified numeric conversion will saturate rather than overflow or
  39. // underflow. NaN assignment to an integral will trigger a RTC_CHECK condition.
  40. template <typename Dst, typename Src>
  41. inline constexpr Dst saturated_cast(Src value) {
  42. // Optimization for floating point values, which already saturate.
  43. if (std::numeric_limits<Dst>::is_iec559)
  44. return static_cast<Dst>(value);
  45. switch (internal::RangeCheck<Dst>(value)) {
  46. case internal::TYPE_VALID:
  47. return static_cast<Dst>(value);
  48. case internal::TYPE_UNDERFLOW:
  49. return std::numeric_limits<Dst>::min();
  50. case internal::TYPE_OVERFLOW:
  51. return std::numeric_limits<Dst>::max();
  52. // Should fail only on attempting to assign NaN to a saturated integer.
  53. case internal::TYPE_INVALID:
  54. FATAL();
  55. return std::numeric_limits<Dst>::max();
  56. }
  57. FATAL();
  58. return static_cast<Dst>(value);
  59. }
  60. } // namespace rtc
  61. #endif // RTC_BASE_NUMERICS_SAFE_CONVERSIONS_H_