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
11// Borrowed from Chromium's src/base/numerics/safe_conversions.h.
12
13#ifndef WEBRTC_BASE_SAFE_CONVERSIONS_H_
14#define WEBRTC_BASE_SAFE_CONVERSIONS_H_
15
16#include <limits>
17
18#include "webrtc/base/checks.h"
19#include "webrtc/base/safe_conversions_impl.h"
20
21namespace rtc {
22
23// Convenience function that returns true if the supplied value is in range
24// for the destination type.
25template <typename Dst, typename Src>
26inline bool IsValueInRangeForNumericType(Src value) {
27  return internal::RangeCheck<Dst>(value) == internal::TYPE_VALID;
28}
29
30// checked_cast<> is analogous to static_cast<> for numeric types,
31// except that it CHECKs that the specified numeric conversion will not
32// overflow or underflow. NaN source will always trigger a CHECK.
33template <typename Dst, typename Src>
34inline Dst checked_cast(Src value) {
35  RTC_CHECK(IsValueInRangeForNumericType<Dst>(value));
36  return static_cast<Dst>(value);
37}
38
39// saturated_cast<> is analogous to static_cast<> for numeric types, except
40// that the specified numeric conversion will saturate rather than overflow or
41// underflow. NaN assignment to an integral will trigger a RTC_CHECK condition.
42template <typename Dst, typename Src>
43inline Dst saturated_cast(Src value) {
44  // Optimization for floating point values, which already saturate.
45  if (std::numeric_limits<Dst>::is_iec559)
46    return static_cast<Dst>(value);
47
48  switch (internal::RangeCheck<Dst>(value)) {
49    case internal::TYPE_VALID:
50      return static_cast<Dst>(value);
51
52    case internal::TYPE_UNDERFLOW:
53      return std::numeric_limits<Dst>::min();
54
55    case internal::TYPE_OVERFLOW:
56      return std::numeric_limits<Dst>::max();
57
58    // Should fail only on attempting to assign NaN to a saturated integer.
59    case internal::TYPE_INVALID:
60      FATAL();
61      return std::numeric_limits<Dst>::max();
62  }
63
64  FATAL();
65  return static_cast<Dst>(value);
66}
67
68}  // namespace rtc
69
70#endif  // WEBRTC_BASE_SAFE_CONVERSIONS_H_
71