blob: d246d4ffce1110e3720a155354e724bbfc623566 [file] [log] [blame]
jiayl@webrtc.org13a42bc2014-01-29 17:45:53 +00001/*
2 * libjingle
3 * Copyright 2014, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28// Borrowed from Chromium's src/base/numerics/safe_conversions.h.
29
30#ifndef TALK_BASE_SAFE_CONVERSIONS_H_
31#define TALK_BASE_SAFE_CONVERSIONS_H_
32
33#include <limits>
34
35#include "talk/base/common.h"
36#include "talk/base/logging.h"
37#include "talk/base/safe_conversions_impl.h"
38
39namespace talk_base {
40
41inline void Check(bool condition) {
42 if (!condition) {
43 LOG(LS_ERROR) << "CHECK failed.";
44 Break();
45 // The program should have crashed at this point.
46 }
47}
48
49// Convenience function that returns true if the supplied value is in range
50// for the destination type.
51template <typename Dst, typename Src>
52inline bool IsValueInRangeForNumericType(Src value) {
53 return internal::RangeCheck<Dst>(value) == internal::TYPE_VALID;
54}
55
56// checked_cast<> is analogous to static_cast<> for numeric types,
57// except that it CHECKs that the specified numeric conversion will not
58// overflow or underflow. NaN source will always trigger a CHECK.
59template <typename Dst, typename Src>
60inline Dst checked_cast(Src value) {
61 Check(IsValueInRangeForNumericType<Dst>(value));
62 return static_cast<Dst>(value);
63}
64
65// saturated_cast<> is analogous to static_cast<> for numeric types, except
66// that the specified numeric conversion will saturate rather than overflow or
67// underflow. NaN assignment to an integral will trigger a CHECK condition.
68template <typename Dst, typename Src>
69inline Dst saturated_cast(Src value) {
70 // Optimization for floating point values, which already saturate.
71 if (std::numeric_limits<Dst>::is_iec559)
72 return static_cast<Dst>(value);
73
74 switch (internal::RangeCheck<Dst>(value)) {
75 case internal::TYPE_VALID:
76 return static_cast<Dst>(value);
77
78 case internal::TYPE_UNDERFLOW:
79 return std::numeric_limits<Dst>::min();
80
81 case internal::TYPE_OVERFLOW:
82 return std::numeric_limits<Dst>::max();
83
84 // Should fail only on attempting to assign NaN to a saturated integer.
85 case internal::TYPE_INVALID:
86 Check(false);
87 return std::numeric_limits<Dst>::max();
88 }
89
90 Check(false); // NOTREACHED();
91 return static_cast<Dst>(value);
92}
93
94} // namespace talk_base
95
96#endif // TALK_BASE_SAFE_CONVERSIONS_H_