chromium/third_party/webrtc/rtc_base/numerics/safe_conversions_impl.h

/*
 *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// Borrowed from Chromium's src/base/numerics/safe_conversions_impl.h.

#ifndef RTC_BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
#define RTC_BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_

#include <limits>

namespace rtc {
namespace internal {

enum DstSign {};

enum SrcSign {};

enum DstRange {};

// Helper templates to statically determine if our destination type can contain
// all values represented by the source type.

template <typename Dst,
          typename Src,
          DstSign IsDstSigned =
              std::numeric_limits<Dst>::is_signed ? DST_SIGNED : DST_UNSIGNED,
          SrcSign IsSrcSigned =
              std::numeric_limits<Src>::is_signed ? SRC_SIGNED : SRC_UNSIGNED>
struct StaticRangeCheck {};

StaticRangeCheck<Dst, Src, DST_SIGNED, SRC_SIGNED>;

StaticRangeCheck<Dst, Src, DST_UNSIGNED, SRC_UNSIGNED>;

StaticRangeCheck<Dst, Src, DST_SIGNED, SRC_UNSIGNED>;

StaticRangeCheck<Dst, Src, DST_UNSIGNED, SRC_SIGNED>;

enum RangeCheckResult {};

// This macro creates a RangeCheckResult from an upper and lower bound
// check by taking advantage of the fact that only NaN can be out of range in
// both directions at once.
#define BASE_NUMERIC_RANGE_CHECK_RESULT(is_in_upper_bound, is_in_lower_bound)

template <typename Dst,
          typename Src,
          DstSign IsDstSigned =
              std::numeric_limits<Dst>::is_signed ? DST_SIGNED : DST_UNSIGNED,
          SrcSign IsSrcSigned =
              std::numeric_limits<Src>::is_signed ? SRC_SIGNED : SRC_UNSIGNED,
          DstRange IsSrcRangeContained = StaticRangeCheck<Dst, Src>::value>
struct RangeCheckImpl {};

// The following templates are for ranges that must be verified at runtime. We
// split it into checks based on signedness to avoid confusing casts and
// compiler warnings on signed an unsigned comparisons.

// Dst range always contains the result: nothing to check.
RangeCheckImpl<Dst, Src, IsDstSigned, IsSrcSigned, CONTAINS_RANGE>;

// Signed to signed narrowing.
RangeCheckImpl<Dst, Src, DST_SIGNED, SRC_SIGNED, OVERLAPS_RANGE>;

// Unsigned to unsigned narrowing.
RangeCheckImpl<Dst, Src, DST_UNSIGNED, SRC_UNSIGNED, OVERLAPS_RANGE>;

// Unsigned to signed.
RangeCheckImpl<Dst, Src, DST_SIGNED, SRC_UNSIGNED, OVERLAPS_RANGE>;

// Signed to unsigned.
RangeCheckImpl<Dst, Src, DST_UNSIGNED, SRC_SIGNED, OVERLAPS_RANGE>;

template <typename Dst, typename Src>
inline constexpr RangeCheckResult RangeCheck(Src value) {}

}  // namespace internal
}  // namespace rtc

#endif  // RTC_BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_