Move some numeric utility code from rtc_base/ to rtc_base/numerics/

Specifically, I'm moving

  safe_compare.h
  safe_conversions.h
  safe_minmax.h

They shouldn't be part of the API, and moving them to an appropriate
subdirectory of rtc_base/ is a good way to keep track of that.

BUG=webrtc:8445

Change-Id: I458531aeb30bcf4291c4bec3bf22a2fffbf054ff
Reviewed-on: https://webrtc-review.googlesource.com/20860
Commit-Queue: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20829}
diff --git a/rtc_base/numerics/safe_conversions_impl.h b/rtc_base/numerics/safe_conversions_impl.h
new file mode 100644
index 0000000..9b4f1c6
--- /dev/null
+++ b/rtc_base/numerics/safe_conversions_impl.h
@@ -0,0 +1,175 @@
+/*
+ *  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 { DST_UNSIGNED, DST_SIGNED };
+
+enum SrcSign { SRC_UNSIGNED, SRC_SIGNED };
+
+enum DstRange { OVERLAPS_RANGE, CONTAINS_RANGE };
+
+// 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 {};
+
+template <typename Dst, typename Src>
+struct StaticRangeCheck<Dst, Src, DST_SIGNED, SRC_SIGNED> {
+  typedef std::numeric_limits<Dst> DstLimits;
+  typedef std::numeric_limits<Src> SrcLimits;
+  // Compare based on max_exponent, which we must compute for integrals.
+  static const size_t kDstMaxExponent =
+      DstLimits::is_iec559 ? DstLimits::max_exponent : (sizeof(Dst) * 8 - 1);
+  static const size_t kSrcMaxExponent =
+      SrcLimits::is_iec559 ? SrcLimits::max_exponent : (sizeof(Src) * 8 - 1);
+  static const DstRange value =
+      kDstMaxExponent >= kSrcMaxExponent ? CONTAINS_RANGE : OVERLAPS_RANGE;
+};
+
+template <typename Dst, typename Src>
+struct StaticRangeCheck<Dst, Src, DST_UNSIGNED, SRC_UNSIGNED> {
+  static const DstRange value =
+      sizeof(Dst) >= sizeof(Src) ? CONTAINS_RANGE : OVERLAPS_RANGE;
+};
+
+template <typename Dst, typename Src>
+struct StaticRangeCheck<Dst, Src, DST_SIGNED, SRC_UNSIGNED> {
+  typedef std::numeric_limits<Dst> DstLimits;
+  typedef std::numeric_limits<Src> SrcLimits;
+  // Compare based on max_exponent, which we must compute for integrals.
+  static const size_t kDstMaxExponent =
+      DstLimits::is_iec559 ? DstLimits::max_exponent : (sizeof(Dst) * 8 - 1);
+  static const size_t kSrcMaxExponent = sizeof(Src) * 8;
+  static const DstRange value =
+      kDstMaxExponent >= kSrcMaxExponent ? CONTAINS_RANGE : OVERLAPS_RANGE;
+};
+
+template <typename Dst, typename Src>
+struct StaticRangeCheck<Dst, Src, DST_UNSIGNED, SRC_SIGNED> {
+  static const DstRange value = OVERLAPS_RANGE;
+};
+
+enum RangeCheckResult {
+  TYPE_VALID = 0,      // Value can be represented by the destination type.
+  TYPE_UNDERFLOW = 1,  // Value would overflow.
+  TYPE_OVERFLOW = 2,   // Value would underflow.
+  TYPE_INVALID = 3     // Source value is invalid (i.e. NaN).
+};
+
+// 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) \
+  RangeCheckResult(((is_in_upper_bound) ? 0 : TYPE_OVERFLOW) |                \
+                   ((is_in_lower_bound) ? 0 : TYPE_UNDERFLOW))
+
+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.
+template <typename Dst, typename Src, DstSign IsDstSigned, SrcSign IsSrcSigned>
+struct RangeCheckImpl<Dst, Src, IsDstSigned, IsSrcSigned, CONTAINS_RANGE> {
+  static RangeCheckResult Check(Src value) { return TYPE_VALID; }
+};
+
+// Signed to signed narrowing.
+template <typename Dst, typename Src>
+struct RangeCheckImpl<Dst, Src, DST_SIGNED, SRC_SIGNED, OVERLAPS_RANGE> {
+  static RangeCheckResult Check(Src value) {
+    typedef std::numeric_limits<Dst> DstLimits;
+    return DstLimits::is_iec559
+               ? BASE_NUMERIC_RANGE_CHECK_RESULT(
+                     value <= static_cast<Src>(DstLimits::max()),
+                     value >= static_cast<Src>(DstLimits::max() * -1))
+               : BASE_NUMERIC_RANGE_CHECK_RESULT(
+                     value <= static_cast<Src>(DstLimits::max()),
+                     value >= static_cast<Src>(DstLimits::min()));
+  }
+};
+
+// Unsigned to unsigned narrowing.
+template <typename Dst, typename Src>
+struct RangeCheckImpl<Dst, Src, DST_UNSIGNED, SRC_UNSIGNED, OVERLAPS_RANGE> {
+  static RangeCheckResult Check(Src value) {
+    typedef std::numeric_limits<Dst> DstLimits;
+    return BASE_NUMERIC_RANGE_CHECK_RESULT(
+        value <= static_cast<Src>(DstLimits::max()), true);
+  }
+};
+
+// Unsigned to signed.
+template <typename Dst, typename Src>
+struct RangeCheckImpl<Dst, Src, DST_SIGNED, SRC_UNSIGNED, OVERLAPS_RANGE> {
+  static RangeCheckResult Check(Src value) {
+    typedef std::numeric_limits<Dst> DstLimits;
+    return sizeof(Dst) > sizeof(Src)
+               ? TYPE_VALID
+               : BASE_NUMERIC_RANGE_CHECK_RESULT(
+                     value <= static_cast<Src>(DstLimits::max()), true);
+  }
+};
+
+// Signed to unsigned.
+template <typename Dst, typename Src>
+struct RangeCheckImpl<Dst, Src, DST_UNSIGNED, SRC_SIGNED, OVERLAPS_RANGE> {
+  static RangeCheckResult Check(Src value) {
+    typedef std::numeric_limits<Dst> DstLimits;
+    typedef std::numeric_limits<Src> SrcLimits;
+    // Compare based on max_exponent, which we must compute for integrals.
+    static const size_t kDstMaxExponent = sizeof(Dst) * 8;
+    static const size_t kSrcMaxExponent =
+        SrcLimits::is_iec559 ? SrcLimits::max_exponent : (sizeof(Src) * 8 - 1);
+    return (kDstMaxExponent >= kSrcMaxExponent)
+               ? BASE_NUMERIC_RANGE_CHECK_RESULT(true,
+                                                 value >= static_cast<Src>(0))
+               : BASE_NUMERIC_RANGE_CHECK_RESULT(
+                     value <= static_cast<Src>(DstLimits::max()),
+                     value >= static_cast<Src>(0));
+  }
+};
+
+template <typename Dst, typename Src>
+inline RangeCheckResult RangeCheck(Src value) {
+  static_assert(std::numeric_limits<Src>::is_specialized,
+                "argument must be numeric");
+  static_assert(std::numeric_limits<Dst>::is_specialized,
+                "result must be numeric");
+  return RangeCheckImpl<Dst, Src>::Check(value);
+}
+
+}  // namespace internal
+}  // namespace rtc
+
+#endif  // RTC_BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_