mfbt/IntegerTypeTraits.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mfbt/IntegerTypeTraits.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,119 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* Helpers to manipulate integer types that don't fit in TypeTraits.h */
    1.11 +
    1.12 +#ifndef mozilla_IntegerTypeTraits_h
    1.13 +#define mozilla_IntegerTypeTraits_h
    1.14 +
    1.15 +#include "mozilla/TypeTraits.h"
    1.16 +#include <stdint.h>
    1.17 +
    1.18 +namespace mozilla {
    1.19 +
    1.20 +namespace detail {
    1.21 +
    1.22 +/**
    1.23 + * StdintTypeForSizeAndSignedness returns the stdint integer type
    1.24 + * of given size (can be 1, 2, 4 or 8) and given signedness
    1.25 + * (false means unsigned, true means signed).
    1.26 + */
    1.27 +template<size_t Size, bool Signedness>
    1.28 +struct StdintTypeForSizeAndSignedness;
    1.29 +
    1.30 +template<>
    1.31 +struct StdintTypeForSizeAndSignedness<1, true>
    1.32 +{ typedef int8_t   Type; };
    1.33 +
    1.34 +template<>
    1.35 +struct StdintTypeForSizeAndSignedness<1, false>
    1.36 +{ typedef uint8_t  Type; };
    1.37 +
    1.38 +template<>
    1.39 +struct StdintTypeForSizeAndSignedness<2, true>
    1.40 +{ typedef int16_t  Type; };
    1.41 +
    1.42 +template<>
    1.43 +struct StdintTypeForSizeAndSignedness<2, false>
    1.44 +{ typedef uint16_t Type; };
    1.45 +
    1.46 +template<>
    1.47 +struct StdintTypeForSizeAndSignedness<4, true>
    1.48 +{ typedef int32_t  Type; };
    1.49 +
    1.50 +template<>
    1.51 +struct StdintTypeForSizeAndSignedness<4, false>
    1.52 +{ typedef uint32_t Type; };
    1.53 +
    1.54 +template<>
    1.55 +struct StdintTypeForSizeAndSignedness<8, true>
    1.56 +{ typedef int64_t  Type; };
    1.57 +
    1.58 +template<>
    1.59 +struct StdintTypeForSizeAndSignedness<8, false>
    1.60 +{ typedef uint64_t Type; };
    1.61 +
    1.62 +} // namespace detail
    1.63 +
    1.64 +template<size_t Size>
    1.65 +struct UnsignedStdintTypeForSize
    1.66 +  : detail::StdintTypeForSizeAndSignedness<Size, false>
    1.67 +{};
    1.68 +
    1.69 +template<typename IntegerType>
    1.70 +struct PositionOfSignBit
    1.71 +{
    1.72 +  static_assert(IsIntegral<IntegerType>::value, "PositionOfSignBit is only for integral types");
    1.73 +  // 8 here should be CHAR_BIT from limits.h, but the world has moved on.
    1.74 +  static const size_t value = 8 * sizeof(IntegerType) - 1;
    1.75 +};
    1.76 +
    1.77 +/**
    1.78 + * MinValue returns the minimum value of the given integer type as a
    1.79 + * compile-time constant, which std::numeric_limits<IntegerType>::min()
    1.80 + * cannot do in c++98.
    1.81 + */
    1.82 +template<typename IntegerType>
    1.83 +struct MinValue
    1.84 +{
    1.85 +  private:
    1.86 +    static_assert(IsIntegral<IntegerType>::value, "MinValue is only for integral types");
    1.87 +
    1.88 +    typedef typename MakeUnsigned<IntegerType>::Type UnsignedIntegerType;
    1.89 +    static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;
    1.90 +
    1.91 +  public:
    1.92 +    // Bitwise ops may return a larger type, that's why we cast explicitly.
    1.93 +    // In C++, left bit shifts on signed values is undefined by the standard
    1.94 +    // unless the shifted value is representable.
    1.95 +    // Notice that signed-to-unsigned conversions are always well-defined in
    1.96 +    // the standard as the value congruent to 2**n, as expected. By contrast,
    1.97 +    // unsigned-to-signed is only well-defined if the value is representable.
    1.98 +    static const IntegerType value =
    1.99 +        IsSigned<IntegerType>::value
   1.100 +        ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
   1.101 +        : IntegerType(0);
   1.102 +};
   1.103 +
   1.104 +/**
   1.105 + * MaxValue returns the maximum value of the given integer type as a
   1.106 + * compile-time constant, which std::numeric_limits<IntegerType>::max()
   1.107 + * cannot do in c++98.
   1.108 + */
   1.109 +template<typename IntegerType>
   1.110 +struct MaxValue
   1.111 +{
   1.112 +    static_assert(IsIntegral<IntegerType>::value, "MaxValue is only for integral types");
   1.113 +
   1.114 +    // Tricksy, but covered by the CheckedInt unit test.
   1.115 +    // Relies on the type of MinValue<IntegerType>::value
   1.116 +    // being IntegerType.
   1.117 +    static const IntegerType value = ~MinValue<IntegerType>::value;
   1.118 +};
   1.119 +
   1.120 +} // namespace mozilla
   1.121 +
   1.122 +#endif // mozilla_IntegerTypeTraits_h

mercurial