Home | History | Annotate | Download | only in base
      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 
     21 namespace rtc {
     22 
     23 // Convenience function that returns true if the supplied value is in range
     24 // for the destination type.
     25 template <typename Dst, typename Src>
     26 inline 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.
     33 template <typename Dst, typename Src>
     34 inline 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.
     42 template <typename Dst, typename Src>
     43 inline 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