1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_SAFE_CONVERSIONS_H_
6#define BASE_SAFE_CONVERSIONS_H_
7
8#include <limits>
9
10#include "base/logging.h"
11#include "base/numerics/safe_conversions_impl.h"
12
13namespace base {
14
15// Convenience function that returns true if the supplied value is in range
16// for the destination type.
17template <typename Dst, typename Src>
18inline bool IsValueInRangeForNumericType(Src value) {
19  return internal::DstRangeRelationToSrcRange<Dst>(value) ==
20         internal::RANGE_VALID;
21}
22
23// checked_cast<> is analogous to static_cast<> for numeric types,
24// except that it CHECKs that the specified numeric conversion will not
25// overflow or underflow. NaN source will always trigger a CHECK.
26template <typename Dst, typename Src>
27inline Dst checked_cast(Src value) {
28  CHECK(IsValueInRangeForNumericType<Dst>(value));
29  return static_cast<Dst>(value);
30}
31
32// saturated_cast<> is analogous to static_cast<> for numeric types, except
33// that the specified numeric conversion will saturate rather than overflow or
34// underflow. NaN assignment to an integral will trigger a CHECK condition.
35template <typename Dst, typename Src>
36inline Dst saturated_cast(Src value) {
37  // Optimization for floating point values, which already saturate.
38  if (std::numeric_limits<Dst>::is_iec559)
39    return static_cast<Dst>(value);
40
41  switch (internal::DstRangeRelationToSrcRange<Dst>(value)) {
42    case internal::RANGE_VALID:
43      return static_cast<Dst>(value);
44
45    case internal::RANGE_UNDERFLOW:
46      return std::numeric_limits<Dst>::min();
47
48    case internal::RANGE_OVERFLOW:
49      return std::numeric_limits<Dst>::max();
50
51    // Should fail only on attempting to assign NaN to a saturated integer.
52    case internal::RANGE_INVALID:
53      CHECK(false);
54      return std::numeric_limits<Dst>::max();
55  }
56
57  NOTREACHED();
58  return static_cast<Dst>(value);
59}
60
61}  // namespace base
62
63#endif  // BASE_SAFE_CONVERSIONS_H_
64
65