15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef BASE_SAFE_CONVERSIONS_IMPL_H_ 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define BASE_SAFE_CONVERSIONS_IMPL_H_ 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <limits> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/macros.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/template_util.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace base { 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace internal { 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// The std library doesn't provide a binary max_exponent for integers, however 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// we can compute one by adding one to the number of non-sign bits. This allows 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// for accurate range comparisons between floating point and integer types. 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename NumericType> 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct MaxExponent { 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const int value = std::numeric_limits<NumericType>::is_iec559 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? std::numeric_limits<NumericType>::max_exponent 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : (sizeof(NumericType) * 8 + 1 - 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::numeric_limits<NumericType>::is_signed); 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)enum IntegerRepresentation { 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_UNSIGNED, 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_SIGNED 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// A range for a given nunmeric Src type is contained for a given numeric Dst 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true. 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// We implement this as template specializations rather than simple static 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// comparisons to ensure type correctness in our comparisons. 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)enum NumericRangeRepresentation { 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUMERIC_RANGE_NOT_CONTAINED, 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUMERIC_RANGE_CONTAINED 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Helper templates to statically determine if our destination type can contain 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// maximum and minimum values represented by the source type. 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template < 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typename Dst, 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typename Src, 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? INTEGER_REPRESENTATION_SIGNED 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : INTEGER_REPRESENTATION_UNSIGNED, 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IntegerRepresentation SrcSign = 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::numeric_limits<Src>::is_signed 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? INTEGER_REPRESENTATION_SIGNED 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : INTEGER_REPRESENTATION_UNSIGNED > 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct StaticDstRangeRelationToSrcRange; 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Same sign: Dst is guaranteed to contain Src only if its range is equal or 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// larger. 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename Dst, typename Src, IntegerRepresentation Sign> 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign> { 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const NumericRangeRepresentation value = 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MaxExponent<Dst>::value >= MaxExponent<Src>::value 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? NUMERIC_RANGE_CONTAINED 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : NUMERIC_RANGE_NOT_CONTAINED; 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Unsigned to signed: Dst is guaranteed to contain source only if its range is 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// larger. 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct StaticDstRangeRelationToSrcRange<Dst, 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Src, 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_SIGNED, 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_UNSIGNED> { 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const NumericRangeRepresentation value = 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MaxExponent<Dst>::value > MaxExponent<Src>::value 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? NUMERIC_RANGE_CONTAINED 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : NUMERIC_RANGE_NOT_CONTAINED; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Signed to unsigned: Dst cannot be statically determined to contain Src. 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct StaticDstRangeRelationToSrcRange<Dst, 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Src, 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_UNSIGNED, 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_SIGNED> { 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)enum RangeConstraint { 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RANGE_VALID = 0x0, // Value can be represented by the destination type. 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RANGE_UNDERFLOW = 0x1, // Value would overflow. 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RANGE_OVERFLOW = 0x2, // Value would underflow. 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN). 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Helper function for coercing an int back to a RangeContraint. 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)inline RangeConstraint GetRangeConstraint(int integer_range_constraint) { 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(integer_range_constraint >= RANGE_VALID && 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) integer_range_constraint <= RANGE_INVALID); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return static_cast<RangeConstraint>(integer_range_constraint); 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This function creates a RangeConstraint from an upper and lower bound 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// check by taking advantage of the fact that only NaN can be out of range in 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// both directions at once. 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_in_lower_bound) { 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) | 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (is_in_lower_bound ? 0 : RANGE_UNDERFLOW)); 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template < 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typename Dst, 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typename Src, 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? INTEGER_REPRESENTATION_SIGNED 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : INTEGER_REPRESENTATION_UNSIGNED, 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? INTEGER_REPRESENTATION_SIGNED 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : INTEGER_REPRESENTATION_UNSIGNED, 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NumericRangeRepresentation DstRange = 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StaticDstRangeRelationToSrcRange<Dst, Src>::value > 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct DstRangeRelationToSrcRangeImpl; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The following templates are for ranges that must be verified at runtime. We 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// split it into checks based on signedness to avoid confusing casts and 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// compiler warnings on signed an unsigned comparisons. 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Dst range is statically determined to contain Src: Nothing to check. 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename Dst, 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typename Src, 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IntegerRepresentation DstSign, 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IntegerRepresentation SrcSign> 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct DstRangeRelationToSrcRangeImpl<Dst, 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Src, 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DstSign, 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SrcSign, 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUMERIC_RANGE_CONTAINED> { 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static RangeConstraint Check(Src value) { return RANGE_VALID; } 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Signed to signed narrowing: Both the upper and lower boundaries may be 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// exceeded. 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct DstRangeRelationToSrcRangeImpl<Dst, 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Src, 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_SIGNED, 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_SIGNED, 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUMERIC_RANGE_NOT_CONTAINED> { 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static RangeConstraint Check(Src value) { 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::numeric_limits<Dst>::is_iec559 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value >= -std::numeric_limits<Dst>::max()) 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value >= std::numeric_limits<Dst>::min()); 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded. 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct DstRangeRelationToSrcRangeImpl<Dst, 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Src, 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_UNSIGNED, 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_UNSIGNED, 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUMERIC_RANGE_NOT_CONTAINED> { 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static RangeConstraint Check(Src value) { 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), true); 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Unsigned to signed: The upper boundary may be exceeded. 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct DstRangeRelationToSrcRangeImpl<Dst, 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Src, 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_SIGNED, 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_UNSIGNED, 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUMERIC_RANGE_NOT_CONTAINED> { 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static RangeConstraint Check(Src value) { 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return sizeof(Dst) > sizeof(Src) 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? RANGE_VALID 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : GetRangeConstraint( 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value <= static_cast<Src>(std::numeric_limits<Dst>::max()), 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) true); 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst, 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// and any negative value exceeds the lower boundary. 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct DstRangeRelationToSrcRangeImpl<Dst, 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Src, 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_UNSIGNED, 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) INTEGER_REPRESENTATION_SIGNED, 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUMERIC_RANGE_NOT_CONTAINED> { 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static RangeConstraint Check(Src value) { 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return (MaxExponent<Dst>::value >= MaxExponent<Src>::value) 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? GetRangeConstraint(true, value >= static_cast<Src>(0)) 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : GetRangeConstraint( 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value <= static_cast<Src>(std::numeric_limits<Dst>::max()), 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value >= static_cast<Src>(0)); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)inline RangeConstraint DstRangeRelationToSrcRange(Src value) { 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) COMPILE_ASSERT(std::numeric_limits<Src>::is_specialized, 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) argument_must_be_numeric); 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) COMPILE_ASSERT(std::numeric_limits<Dst>::is_specialized, 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result_must_be_numeric); 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value); 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace internal 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace base 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // BASE_SAFE_CONVERSIONS_IMPL_H_ 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 218