gfx/skia/trunk/src/utils/SkTFitsIn.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/utils/SkTFitsIn.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,209 @@
     1.4 +/*
     1.5 + * Copyright 2013 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#ifndef SkTFitsIn_DEFINED
    1.12 +#define SkTFitsIn_DEFINED
    1.13 +
    1.14 +#include "SkTypes.h"
    1.15 +#include "SkTLogic.h"
    1.16 +#include <limits>
    1.17 +
    1.18 +namespace sktfitsin {
    1.19 +namespace Private {
    1.20 +
    1.21 +/** SkTHasMoreDigits::type = (digits(A) >= digits(B)) ? SkTrue : SkFalse. */
    1.22 +template<typename A, typename B> struct SkTHasMoreDigits {
    1.23 +    typedef SkTBool<std::numeric_limits<A>::digits >= std::numeric_limits<B>::digits> type;
    1.24 +};
    1.25 +
    1.26 +/** A high or low side predicate which is used when it is statically known
    1.27 + *  that source values are in the range of the Destination.
    1.28 + */
    1.29 +template <typename S> struct SkTOutOfRange_False {
    1.30 +    typedef SkFalse can_be_true;
    1.31 +    typedef S source_type;
    1.32 +    static bool apply(S s) {
    1.33 +        return false;
    1.34 +    }
    1.35 +};
    1.36 +
    1.37 +/** A low side predicate which tests if the source value < Min(D).
    1.38 + *  Assumes that Min(S) <= Min(D).
    1.39 + */
    1.40 +template <typename D, typename S> struct SkTOutOfRange_LT_MinD {
    1.41 +    typedef SkTrue can_be_true;
    1.42 +    typedef S source_type;
    1.43 +    static bool apply(S s) {
    1.44 +        typedef typename SkTHasMoreDigits<S, D>::type precondition;
    1.45 +        SK_COMPILE_ASSERT(precondition::value, SkTOutOfRange_LT_MinD__minS_gt_minD);
    1.46 +
    1.47 +        return s < static_cast<S>((std::numeric_limits<D>::min)());
    1.48 +    }
    1.49 +};
    1.50 +
    1.51 +/** A low side predicate which tests if the source value is less than 0. */
    1.52 +template <typename D, typename S> struct SkTOutOfRange_LT_Zero {
    1.53 +    typedef SkTrue can_be_true;
    1.54 +    typedef S source_type;
    1.55 +    static bool apply(S s) {
    1.56 +        return s < static_cast<S>(0);
    1.57 +    }
    1.58 +};
    1.59 +
    1.60 +/** A high side predicate which tests if the source value > Max(D).
    1.61 + *  Assumes that Max(S) >= Max(D).
    1.62 + */
    1.63 +template <typename D, typename S> struct SkTOutOfRange_GT_MaxD {
    1.64 +    typedef SkTrue can_be_true;
    1.65 +    typedef S source_type;
    1.66 +    static bool apply(S s) {
    1.67 +        typedef typename SkTHasMoreDigits<S, D>::type precondition;
    1.68 +        SK_COMPILE_ASSERT(precondition::value, SkTOutOfRange_GT_MaxD__maxS_lt_maxD);
    1.69 +
    1.70 +        return s > static_cast<S>((std::numeric_limits<D>::max)());
    1.71 +    }
    1.72 +};
    1.73 +
    1.74 +/** Composes two SkTOutOfRange predicates.
    1.75 + *  First checks OutOfRange_Low then, if in range, OutOfRange_High.
    1.76 + */
    1.77 +template<class OutOfRange_Low, class OutOfRange_High> struct SkTOutOfRange_Either {
    1.78 +    typedef SkTrue can_be_true;
    1.79 +    typedef typename OutOfRange_Low::source_type source_type;
    1.80 +    static bool apply(source_type s) {
    1.81 +        bool outOfRange = OutOfRange_Low::apply(s);
    1.82 +        if (!outOfRange) {
    1.83 +            outOfRange = OutOfRange_High::apply(s);
    1.84 +        }
    1.85 +        return outOfRange;
    1.86 +    }
    1.87 +};
    1.88 +
    1.89 +/** SkTCombineOutOfRange::type is an SkTOutOfRange_XXX type which is the
    1.90 + *  optimal combination of OutOfRange_Low and OutOfRange_High.
    1.91 + */
    1.92 +template<class OutOfRange_Low, class OutOfRange_High> struct SkTCombineOutOfRange {
    1.93 +    typedef SkTOutOfRange_Either<OutOfRange_Low, OutOfRange_High> Both;
    1.94 +    typedef SkTOutOfRange_False<typename OutOfRange_Low::source_type> Neither;
    1.95 +
    1.96 +    typedef typename OutOfRange_Low::can_be_true apply_low;
    1.97 +    typedef typename OutOfRange_High::can_be_true apply_high;
    1.98 +
    1.99 +    typedef typename SkTMux<apply_low, apply_high,
   1.100 +                            Both, OutOfRange_Low, OutOfRange_High, Neither>::type type;
   1.101 +};
   1.102 +
   1.103 +template<typename D, typename S, class OutOfRange_Low, class OutOfRange_High>
   1.104 +struct SkTRangeChecker {
   1.105 +    /** This is the method which is called at runtime to do the range check. */
   1.106 +    static bool OutOfRange(S s) {
   1.107 +        typedef typename SkTCombineOutOfRange<OutOfRange_Low, OutOfRange_High>::type Combined;
   1.108 +        return Combined::apply(s);
   1.109 +    }
   1.110 +};
   1.111 +
   1.112 +/** SkTFitsIn_Unsigned2Unsiged::type is an SkTRangeChecker with an OutOfRange(S s) method
   1.113 + *  the implementation of which is tailored for the source and destination types.
   1.114 + *  Assumes that S and D are unsigned integer types.
   1.115 + */
   1.116 +template<typename D, typename S> struct SkTFitsIn_Unsigned2Unsiged {
   1.117 +    typedef SkTOutOfRange_False<S> OutOfRange_Low;
   1.118 +    typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
   1.119 +
   1.120 +    typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> HighSideOnlyCheck;
   1.121 +    typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck;
   1.122 +
   1.123 +    // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, nothing to check.
   1.124 +    // This also protects the precondition of SkTOutOfRange_GT_MaxD.
   1.125 +    typedef typename SkTHasMoreDigits<D, S>::type sourceFitsInDesitination;
   1.126 +    typedef typename SkTIf<sourceFitsInDesitination, NoCheck, HighSideOnlyCheck>::type type;
   1.127 +};
   1.128 +
   1.129 +/** SkTFitsIn_Signed2Signed::type is an SkTRangeChecker with an OutOfRange(S s) method
   1.130 + *  the implementation of which is tailored for the source and destination types.
   1.131 + *  Assumes that S and D are signed integer types.
   1.132 + */
   1.133 +template<typename D, typename S> struct SkTFitsIn_Signed2Signed {
   1.134 +    typedef SkTOutOfRange_LT_MinD<D, S> OutOfRange_Low;
   1.135 +    typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
   1.136 +
   1.137 +    typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> FullCheck;
   1.138 +    typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck;
   1.139 +
   1.140 +    // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, nothing to check.
   1.141 +    // This also protects the precondition of SkTOutOfRange_LT_MinD and SkTOutOfRange_GT_MaxD.
   1.142 +    typedef typename SkTHasMoreDigits<D, S>::type sourceFitsInDesitination;
   1.143 +    typedef typename SkTIf<sourceFitsInDesitination, NoCheck, FullCheck>::type type;
   1.144 +};
   1.145 +
   1.146 +/** SkTFitsIn_Signed2Unsigned::type is an SkTRangeChecker with an OutOfRange(S s) method
   1.147 + *  the implementation of which is tailored for the source and destination types.
   1.148 + *  Assumes that S is a signed integer type and D is an unsigned integer type.
   1.149 + */
   1.150 +template<typename D, typename S> struct SkTFitsIn_Signed2Unsigned {
   1.151 +    typedef SkTOutOfRange_LT_Zero<D, S> OutOfRange_Low;
   1.152 +    typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
   1.153 +
   1.154 +    typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> FullCheck;
   1.155 +    typedef SkTRangeChecker<D, S, OutOfRange_Low, SkTOutOfRange_False<S> > LowSideOnlyCheck;
   1.156 +
   1.157 +    // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(),
   1.158 +    // no need to check the high side. (Until C++11, assume more digits means greater max.)
   1.159 +    // This also protects the precondition of SkTOutOfRange_GT_MaxD.
   1.160 +    typedef typename SkTHasMoreDigits<D, S>::type sourceCannotExceedDesitination;
   1.161 +    typedef typename SkTIf<sourceCannotExceedDesitination, LowSideOnlyCheck, FullCheck>::type type;
   1.162 +};
   1.163 +
   1.164 +/** SkTFitsIn_Unsigned2Signed::type is an SkTRangeChecker with an OutOfRange(S s) method
   1.165 + *  the implementation of which is tailored for the source and destination types.
   1.166 + *  Assumes that S is an usigned integer type and D is a signed integer type.
   1.167 + */
   1.168 +template<typename D, typename S> struct SkTFitsIn_Unsigned2Signed {
   1.169 +    typedef SkTOutOfRange_False<S> OutOfRange_Low;
   1.170 +    typedef SkTOutOfRange_GT_MaxD<D, S> OutOfRange_High;
   1.171 +
   1.172 +    typedef SkTRangeChecker<D, S, OutOfRange_Low, OutOfRange_High> HighSideOnlyCheck;
   1.173 +    typedef SkTRangeChecker<D, S, SkTOutOfRange_False<S>, SkTOutOfRange_False<S> > NoCheck;
   1.174 +
   1.175 +    // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(), nothing to check.
   1.176 +    // (Until C++11, assume more digits means greater max.)
   1.177 +    // This also protects the precondition of SkTOutOfRange_GT_MaxD.
   1.178 +    typedef typename SkTHasMoreDigits<D, S>::type sourceCannotExceedDesitination;
   1.179 +    typedef typename SkTIf<sourceCannotExceedDesitination, NoCheck, HighSideOnlyCheck>::type type;
   1.180 +};
   1.181 +
   1.182 +/** SkTFitsIn::type is an SkTRangeChecker with an OutOfRange(S s) method
   1.183 + *  the implementation of which is tailored for the source and destination types.
   1.184 + *  Assumes that S and D are integer types.
   1.185 + */
   1.186 +template<typename D, typename S> struct SkTFitsIn {
   1.187 +    // One of the following will be the 'selector' type.
   1.188 +    typedef SkTFitsIn_Signed2Signed<D, S> S2S;
   1.189 +    typedef SkTFitsIn_Signed2Unsigned<D, S> S2U;
   1.190 +    typedef SkTFitsIn_Unsigned2Signed<D, S> U2S;
   1.191 +    typedef SkTFitsIn_Unsigned2Unsiged<D, S> U2U;
   1.192 +
   1.193 +    typedef SkTBool<std::numeric_limits<S>::is_signed> S_is_signed;
   1.194 +    typedef SkTBool<std::numeric_limits<D>::is_signed> D_is_signed;
   1.195 +
   1.196 +    typedef typename SkTMux<S_is_signed, D_is_signed, S2S, S2U, U2S, U2U>::type selector;
   1.197 +    // This type is an SkTRangeChecker.
   1.198 +    typedef typename selector::type type;
   1.199 +};
   1.200 +
   1.201 +} // namespace Private
   1.202 +} // namespace sktfitsin
   1.203 +
   1.204 +/** Returns true if the integer source value 's' will fit in the integer destination type 'D'. */
   1.205 +template <typename D, typename S> inline bool SkTFitsIn(S s) {
   1.206 +    SK_COMPILE_ASSERT(std::numeric_limits<S>::is_integer, SkTFitsIn_source_must_be_integer);
   1.207 +    SK_COMPILE_ASSERT(std::numeric_limits<D>::is_integer, SkTFitsIn_destination_must_be_integer);
   1.208 +
   1.209 +    return !sktfitsin::Private::SkTFitsIn<D, S>::type::OutOfRange(s);
   1.210 +}
   1.211 +
   1.212 +#endif

mercurial