blob: f6cb24e412698625a92df9aa6b1bfe44a17a0dbe [file] [log] [blame]
henrike@webrtc.org47be73b2014-05-13 18:00:26 +00001/*
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/common.h"
19#include "webrtc/base/logging.h"
20#include "webrtc/base/safe_conversions_impl.h"
21
22namespace rtc {
23
24inline void Check(bool condition) {
25 if (!condition) {
26 LOG(LS_ERROR) << "CHECK failed.";
27 Break();
28 // The program should have crashed at this point.
29 }
30}
31
32// Convenience function that returns true if the supplied value is in range
33// for the destination type.
34template <typename Dst, typename Src>
35inline bool IsValueInRangeForNumericType(Src value) {
36 return internal::RangeCheck<Dst>(value) == internal::TYPE_VALID;
37}
38
39// checked_cast<> is analogous to static_cast<> for numeric types,
40// except that it CHECKs that the specified numeric conversion will not
41// overflow or underflow. NaN source will always trigger a CHECK.
42template <typename Dst, typename Src>
43inline Dst checked_cast(Src value) {
44 Check(IsValueInRangeForNumericType<Dst>(value));
45 return static_cast<Dst>(value);
46}
47
48// saturated_cast<> is analogous to static_cast<> for numeric types, except
49// that the specified numeric conversion will saturate rather than overflow or
50// underflow. NaN assignment to an integral will trigger a CHECK condition.
51template <typename Dst, typename Src>
52inline Dst saturated_cast(Src value) {
53 // Optimization for floating point values, which already saturate.
54 if (std::numeric_limits<Dst>::is_iec559)
55 return static_cast<Dst>(value);
56
57 switch (internal::RangeCheck<Dst>(value)) {
58 case internal::TYPE_VALID:
59 return static_cast<Dst>(value);
60
61 case internal::TYPE_UNDERFLOW:
62 return std::numeric_limits<Dst>::min();
63
64 case internal::TYPE_OVERFLOW:
65 return std::numeric_limits<Dst>::max();
66
67 // Should fail only on attempting to assign NaN to a saturated integer.
68 case internal::TYPE_INVALID:
69 Check(false);
70 return std::numeric_limits<Dst>::max();
71 }
72
73 Check(false); // NOTREACHED();
74 return static_cast<Dst>(value);
75}
76
77} // namespace rtc
78
79#endif // WEBRTC_BASE_SAFE_CONVERSIONS_H_