diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/utils/SkTFitsIn.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/utils/SkTFitsIn.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,209 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkTFitsIn_DEFINED +#define SkTFitsIn_DEFINED + +#include "SkTypes.h" +#include "SkTLogic.h" +#include + +namespace sktfitsin { +namespace Private { + +/** SkTHasMoreDigits::type = (digits(A) >= digits(B)) ? SkTrue : SkFalse. */ +template struct SkTHasMoreDigits { + typedef SkTBool::digits >= std::numeric_limits::digits> type; +}; + +/** A high or low side predicate which is used when it is statically known + * that source values are in the range of the Destination. + */ +template struct SkTOutOfRange_False { + typedef SkFalse can_be_true; + typedef S source_type; + static bool apply(S s) { + return false; + } +}; + +/** A low side predicate which tests if the source value < Min(D). + * Assumes that Min(S) <= Min(D). + */ +template struct SkTOutOfRange_LT_MinD { + typedef SkTrue can_be_true; + typedef S source_type; + static bool apply(S s) { + typedef typename SkTHasMoreDigits::type precondition; + SK_COMPILE_ASSERT(precondition::value, SkTOutOfRange_LT_MinD__minS_gt_minD); + + return s < static_cast((std::numeric_limits::min)()); + } +}; + +/** A low side predicate which tests if the source value is less than 0. */ +template struct SkTOutOfRange_LT_Zero { + typedef SkTrue can_be_true; + typedef S source_type; + static bool apply(S s) { + return s < static_cast(0); + } +}; + +/** A high side predicate which tests if the source value > Max(D). + * Assumes that Max(S) >= Max(D). + */ +template struct SkTOutOfRange_GT_MaxD { + typedef SkTrue can_be_true; + typedef S source_type; + static bool apply(S s) { + typedef typename SkTHasMoreDigits::type precondition; + SK_COMPILE_ASSERT(precondition::value, SkTOutOfRange_GT_MaxD__maxS_lt_maxD); + + return s > static_cast((std::numeric_limits::max)()); + } +}; + +/** Composes two SkTOutOfRange predicates. + * First checks OutOfRange_Low then, if in range, OutOfRange_High. + */ +template struct SkTOutOfRange_Either { + typedef SkTrue can_be_true; + typedef typename OutOfRange_Low::source_type source_type; + static bool apply(source_type s) { + bool outOfRange = OutOfRange_Low::apply(s); + if (!outOfRange) { + outOfRange = OutOfRange_High::apply(s); + } + return outOfRange; + } +}; + +/** SkTCombineOutOfRange::type is an SkTOutOfRange_XXX type which is the + * optimal combination of OutOfRange_Low and OutOfRange_High. + */ +template struct SkTCombineOutOfRange { + typedef SkTOutOfRange_Either Both; + typedef SkTOutOfRange_False Neither; + + typedef typename OutOfRange_Low::can_be_true apply_low; + typedef typename OutOfRange_High::can_be_true apply_high; + + typedef typename SkTMux::type type; +}; + +template +struct SkTRangeChecker { + /** This is the method which is called at runtime to do the range check. */ + static bool OutOfRange(S s) { + typedef typename SkTCombineOutOfRange::type Combined; + return Combined::apply(s); + } +}; + +/** SkTFitsIn_Unsigned2Unsiged::type is an SkTRangeChecker with an OutOfRange(S s) method + * the implementation of which is tailored for the source and destination types. + * Assumes that S and D are unsigned integer types. + */ +template struct SkTFitsIn_Unsigned2Unsiged { + typedef SkTOutOfRange_False OutOfRange_Low; + typedef SkTOutOfRange_GT_MaxD OutOfRange_High; + + typedef SkTRangeChecker HighSideOnlyCheck; + typedef SkTRangeChecker, SkTOutOfRange_False > NoCheck; + + // If std::numeric_limits::digits >= std::numeric_limits::digits, nothing to check. + // This also protects the precondition of SkTOutOfRange_GT_MaxD. + typedef typename SkTHasMoreDigits::type sourceFitsInDesitination; + typedef typename SkTIf::type type; +}; + +/** SkTFitsIn_Signed2Signed::type is an SkTRangeChecker with an OutOfRange(S s) method + * the implementation of which is tailored for the source and destination types. + * Assumes that S and D are signed integer types. + */ +template struct SkTFitsIn_Signed2Signed { + typedef SkTOutOfRange_LT_MinD OutOfRange_Low; + typedef SkTOutOfRange_GT_MaxD OutOfRange_High; + + typedef SkTRangeChecker FullCheck; + typedef SkTRangeChecker, SkTOutOfRange_False > NoCheck; + + // If std::numeric_limits::digits >= std::numeric_limits::digits, nothing to check. + // This also protects the precondition of SkTOutOfRange_LT_MinD and SkTOutOfRange_GT_MaxD. + typedef typename SkTHasMoreDigits::type sourceFitsInDesitination; + typedef typename SkTIf::type type; +}; + +/** SkTFitsIn_Signed2Unsigned::type is an SkTRangeChecker with an OutOfRange(S s) method + * the implementation of which is tailored for the source and destination types. + * Assumes that S is a signed integer type and D is an unsigned integer type. + */ +template struct SkTFitsIn_Signed2Unsigned { + typedef SkTOutOfRange_LT_Zero OutOfRange_Low; + typedef SkTOutOfRange_GT_MaxD OutOfRange_High; + + typedef SkTRangeChecker FullCheck; + typedef SkTRangeChecker > LowSideOnlyCheck; + + // If std::numeric_limits::max() >= std::numeric_limits::max(), + // no need to check the high side. (Until C++11, assume more digits means greater max.) + // This also protects the precondition of SkTOutOfRange_GT_MaxD. + typedef typename SkTHasMoreDigits::type sourceCannotExceedDesitination; + typedef typename SkTIf::type type; +}; + +/** SkTFitsIn_Unsigned2Signed::type is an SkTRangeChecker with an OutOfRange(S s) method + * the implementation of which is tailored for the source and destination types. + * Assumes that S is an usigned integer type and D is a signed integer type. + */ +template struct SkTFitsIn_Unsigned2Signed { + typedef SkTOutOfRange_False OutOfRange_Low; + typedef SkTOutOfRange_GT_MaxD OutOfRange_High; + + typedef SkTRangeChecker HighSideOnlyCheck; + typedef SkTRangeChecker, SkTOutOfRange_False > NoCheck; + + // If std::numeric_limits::max() >= std::numeric_limits::max(), nothing to check. + // (Until C++11, assume more digits means greater max.) + // This also protects the precondition of SkTOutOfRange_GT_MaxD. + typedef typename SkTHasMoreDigits::type sourceCannotExceedDesitination; + typedef typename SkTIf::type type; +}; + +/** SkTFitsIn::type is an SkTRangeChecker with an OutOfRange(S s) method + * the implementation of which is tailored for the source and destination types. + * Assumes that S and D are integer types. + */ +template struct SkTFitsIn { + // One of the following will be the 'selector' type. + typedef SkTFitsIn_Signed2Signed S2S; + typedef SkTFitsIn_Signed2Unsigned S2U; + typedef SkTFitsIn_Unsigned2Signed U2S; + typedef SkTFitsIn_Unsigned2Unsiged U2U; + + typedef SkTBool::is_signed> S_is_signed; + typedef SkTBool::is_signed> D_is_signed; + + typedef typename SkTMux::type selector; + // This type is an SkTRangeChecker. + typedef typename selector::type type; +}; + +} // namespace Private +} // namespace sktfitsin + +/** Returns true if the integer source value 's' will fit in the integer destination type 'D'. */ +template inline bool SkTFitsIn(S s) { + SK_COMPILE_ASSERT(std::numeric_limits::is_integer, SkTFitsIn_source_must_be_integer); + SK_COMPILE_ASSERT(std::numeric_limits::is_integer, SkTFitsIn_destination_must_be_integer); + + return !sktfitsin::Private::SkTFitsIn::type::OutOfRange(s); +} + +#endif