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_H_ 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define BASE_SAFE_CONVERSIONS_H_ 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <limits> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions_impl.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace base { 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Convenience function that returns true if the supplied value is in range 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// for the destination type. 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)inline bool IsValueInRangeForNumericType(Src value) { 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return internal::DstRangeRelationToSrcRange<Dst>(value) == 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) internal::RANGE_VALID; 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// checked_cast<> is analogous to static_cast<> for numeric types, 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// except that it CHECKs that the specified numeric conversion will not 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// overflow or underflow. NaN source will always trigger a CHECK. 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)inline Dst checked_cast(Src value) { 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK(IsValueInRangeForNumericType<Dst>(value)); 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<Dst>(value); 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// saturated_cast<> is analogous to static_cast<> for numeric types, except 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// that the specified numeric conversion will saturate rather than overflow or 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// underflow. NaN assignment to an integral will trigger a CHECK condition. 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src> 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)inline Dst saturated_cast(Src value) { 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Optimization for floating point values, which already saturate. 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (std::numeric_limits<Dst>::is_iec559) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<Dst>(value); 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (internal::DstRangeRelationToSrcRange<Dst>(value)) { 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case internal::RANGE_VALID: 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<Dst>(value); 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case internal::RANGE_UNDERFLOW: 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::numeric_limits<Dst>::min(); 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case internal::RANGE_OVERFLOW: 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::numeric_limits<Dst>::max(); 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Should fail only on attempting to assign NaN to a saturated integer. 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case internal::RANGE_INVALID: 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK(false); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::numeric_limits<Dst>::max(); 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<Dst>(value); 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace base 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // BASE_SAFE_CONVERSIONS_H_ 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 65